Repository navigation
Releases: sonalect/serde_markdown
Release list
v0.5.1
Added
- Ready for crates.io: keywords, categories, and the license text in both
packages, a README forserde_markdown_derive, and docs.rs builds
serde_markdownwith every feature (thebuffaandtokiomodules).
serde_markdownrequires its ownserde_markdown_deriveby exact
version. - CI builds and tests
serde_markdownandserde_markdown_derivewith
the minimum Rust version, read fromrust-version.
Changed
-
The minimum Rust version (
rust-version) is 1.88 (it was 1.99.0), the
oldest rustc that builds and tests the published crates. -
The workspace takes its dependencies as caret ranges instead of exact
pins (serde = "1.0.229", was"=1.0.229"), so a consumer is not held to
one version of serde, buffa, tokio, or the format crates.Cargo.lock
still fixes the versions this repository builds and tests; Renovate moves
it within the ranges. -
The README takes
serde_markdownfrom crates.io
(serde_markdown = "0.5") and links to GitHub by absolute URLs. -
Dependencies: at least
serde_json1.0.154,syn3.0.9, andtokio
1.53.3. -
Tooling:
bazel_utils_*v0.4.0, Buf CLI v1.74.0, and
bazel-contrib/setup-bazel0.19.1 in CI. Buildifier, markdownlint, buf
lint, and cargo audit now also run on Windows (amd64 and arm64), so every
test but the doc tests runs on all six CI platforms; rules_rust cannot link
doc tests on Windows (LNK1181).
v0.5.0
Added
- Bazel test targets for the builds with only
tokioand onlybuffa
(serde_markdown_tokio_only,serde_markdown_buffa_only), next to the
all-features,no_json,no_toml,no_yaml, andminimalbuilds.
Changed
- Breaking: a key of the fields block that is named like a body field is
ErrorKind::Typeon read (the message names the key). Before, the key was
dropped without a word, even from a type withdeny_unknown_fields. - Breaking: a number that is not finite (
.inf,.nan,inf,nan) is
an error on read:ErrorKind::FrontMatterin the fields block,
ErrorKind::Bodyin a structured body section. Before, it read as an
absent value (None). The writer refuses such a number in every language
(JSON used to writenull):ErrorKind::FrontMatterin the fields block,
ErrorKind::Bodyin a structured body section. - Breaking: the writer refuses a fields block that a reader would not
read back as written:ErrorKind::FrontMatterwith no source. In the bare
layout this is a string holding a---, fence, or HTML comment line, or
any value whose encoding the reader would split or take for body; the
message says to write it withFieldsLayout::Fenced. - Breaking: a
Markdown::BODY_FIELDSname that the value never
serializes (not even skipped) isErrorKind::Typeat write. A manual impl
that named a missing field silently lost its section before. - Breaking:
#[derive(Markdown)]rejects a body field that carries
#[serde(skip)],skip_serializing, orskip_deserializing(compile
error); useskip_serializing_ifanddefaultfor an optional body field. - Breaking: the constructors
Error::syntax,Error::front_matter,
Error::body,Error::body_source,Error::type_error,
Error::format_disabled, andError::ioare no longer public. Errors are
made by the crate; read them withkind(),offset(),Display, and
source(). To make one in your ownSerializeorDeserializecode, use
serde'sError::custom, which givesErrorKind::Type.?on an
std::io::Errorstill converts, throughFrom<io::Error>. - Breaking:
ErrorKindis#[non_exhaustive]. Amatchon it needs a
_arm, so a kind added later does not break your build. - Format sniffing is strict.
{is JSON. TOML is chosen only for a table
header ([key],[[key]]) or akey = valuefirst line whose value
starts like a TOML value. A bare first slice that starts with[and is
not a table header (a Markdown link, a list) is body, with no decoder
run; an unlabeled fence starting with[is still JSON. A body-only
document starting with[text](url) moreorE = mc² is famousno longer
fails withErrorKind::FrontMatter. - A map key that is not a string (
BTreeMap<u32, _>,i64,bool) reads
in every language. Reading goes throughserde_json::Valueas the
deserializer. - A
Vec<u8>body is no longer decoded as a document to find out whether it
is a list, unless it starts like one ([or-after whitespace and#
comment lines). A body-only document is no longer decoded as YAML unless
its first line can start a mapping (it has a:, or starts with?,{,
!,&,*, or%). Results are the same; a 6 MB body is read and
written about twice as fast. - The CommonMark parser stops after the last separator that splits the
earlier body fields, so the verbatim last body field is not parsed. A 6 MB
last field reads about three times as fast. serde_markdown::PROTO_INCLUDEis for Cargo builds; under Bazel a build
script takes the directory from the annotated filegroup (README, "The
option in Bazel").- DESIGN.md, README, and ROADMAP.md match the code (sniffing, the fields
fence, errors, tests, M15 and M16 done).
Removed
- Breaking:
serde_markdown::DESIGN, the constant holding the file name
DESIGN.md. It had no use in code.
Fixed
- A fenced fields block whose encoded text has a line of backticks (a YAML
or TOML string holding a fence) closed early and read back with no error
as different data. The fence is now longer than any such run. FieldsLayout::Barewith TOML and every field absent wrote a stray
---and read back the body shifted. An empty bare block is now no block.- A bare TOML block that starts with a table (
[meta]) was sniffed as JSON
and failed to read back. - A newtype body field (
struct Title(String)) was read through the YAML
parser ("# Title\n\n- item"came back as"item"), and acharbody
field#,-, or~failed. Both are now raw section text; a newtype
around a struct or a number is still read in the fence language. - A body-only document that needs an explicit empty fields block, written by
a build without that language, wrote a block its own reader refuses. It
is nowErrorKind::FormatDisabledat write.
v0.4.1
v0.4.0
Added
- Feature
tokio(off by default) addsserde_markdown::tokio, the async
twin of every function under the same name:to_string,
to_string_with_format,to_string_with,to_vec,to_writer(tokio
AsyncWrite),from_str,from_slice,from_reader(tokio
AsyncRead). It writes and reads the same documents as the sync form. It
is native: the same steps, with a cooperative yield between them when the
task's budget is spent; no thread and nospawn_blocking, so an async
caller awaits it as it is. - The runnable example
example-tokio(rust/examples/tokio): the async
form on a tokio runtime, with a file round-trip overtokio::fsand
pages rendered in parallel tasks.
Changed
- The README is rewritten for users of the crate: how to depend on it, the
document shape, body fields, language and layout, errors, the async API
(with a file round-trip overtokio::fs), and protobuf messages; the
development notes moved to the end. Its examples are checked against the
crate. - When a required body section and front-matter keys are both missing,
the error is the first missing field in declaration order:
ErrorKind::Typefor a front-matter key. Before, the missing body
section (ErrorKind::Body) was reported first. markdown/options.proto, the(markdown.body)option, moved into the crate:
rust/markdown/proto/markdown/options.proto. The import path is the same,
markdown/options.proto. The Cargo dependency now brings the option too, so
a consumer needs no second channel for it.PROTO_INCLUDEpoints into the crate (<crate>/proto), so it works for a
crate fetched alone, not only from a checkout of this repository.
Removed
- The Bazel label
@serde_markdown//proto/markdown:options.proto. A Bazel
consumer drops itsbazel_depandgit_overrideofserde_markdownand
reaches the file through its crate_universe hub with an annotation
(additive_build_file_contentplusextra_aliased_targets); the README
shows it. With one dependency the proto and the crate can no longer drift
to different versions. - The fixtures crate
serde_markdown-proto(not published) no longer carries
the generatedmarkdown.bodyextension constant.
Fixed
- Enum fields read back. A field of an enum type (Serde's default,
externally tagged form) failed to read withErrorKind::Type, in the
fields block and in a body section. Unit variants and variants with
content now round-trip in YAML, JSON, and TOML; a unit variant in a body
section is its raw name. #[derive(Markdown)]follows the struct's#[serde(rename_all = "...")]
(andrename_all(serialize = ..., deserialize = ...)) and drops ther#
of a raw identifier. Before, a body field of such a struct was written
into the fields block, with no error. A body field whose serialize and
deserialize names differ is now a compile error.- A
Vec<u8>body whose text reads as a YAML or JSON list ([1, 2],
- a) reads back as its bytes; before, it read as the list's numbers or
failed. AVec<u8>whose text reads as an empty list ([]) is
ErrorKind::Bodyon write, since it cannot be told from an empty list. - A body field with
#[serde(default)]may be missing from the document:
a field without a section is no longer handed to the value, so Serde
applies its default (orNone). A required one is still
ErrorKind::Body. - A TOML date-time in the fields block (
when = 1979-05-27T07:32:00Z)
reads into a string orTimestampfield; before,ErrorKind::Type. - Built without the
yamlfeature, a document whose first slice is prose
reads as body, and a body-only document is written with no empty fields
block. Before, reading failed withErrorKind::FormatDisabledand writing
added an empty JSON or TOML block. - Leading
---lines are skipped in linear time. A document of many of
them took quadratic time (40 000 lines: 1.4 s). - Every feature set builds and tests, none at all included.
v0.3.1
v0.3.0
Changed
- The last body field is the rest of the document, verbatim: it is never
parsed or trimmed, so it may hold top-level---lines, setext underlines,
tables, and fences. Before, such a body was written and then refused on read
(found 2 sections) or cut. - Body text is verbatim in both directions: no line break is added at the end
of the document or removed from a section. Documents written by 0.3.0 end
with the last byte of the last section. - The presence of the last body field is its separator: no separator is
None, a separator followed by nothing isSome(""), and""after it is
literal text. The""convention forSome("")remains only for optional
body fields that are not the last. - Front-matter keys are written in declaration order (proto field order for
buffa messages) in YAML, JSON, and TOML, not alphabetically. No dependency
was added. - A bare first slice that is not a mapping is body from its first byte; the
leading whitespace and---prefix is discarded only before fields.
Added
- A body value that is not the last and holds a top-level
---line, an
unclosed fence, or a trailing carriage return isErrorKind::Bodyat write
time, instead of a document that cannot be read back.
v0.2.3
Fixed
- A fenced code block inside a list item or a block quote was reported as an
unclosed fence (Syntax) although its closing line was there: the check
allowed at most three spaces before the closer on the raw line, and no>
marker. The closer is now judged against the opener's column, after the
container prefix. Bare YAML fields whose first key is a list read the rest
of the mapping as that list item, so a multi-line string holding a fenced
block was written byFieldsLayout::Bareand then refused on read.
v0.2.2
v0.2.1
Changed
- Updated all
bazel_utils_*modules tov0.2.11. - Updated
bazel_utils_*git remotes to use sonalect forks. - Protobuf well-known types now sourced locally via
proto/third_partyinstead
of remote Buf dependency. - Updated
buf.yamlto remove remote wellknowntypes dependency.
v0.2.0
Changed
- Reorganized workspace structure: renamed
rust/serde_markdown→
rust/markdown,rust/serde_markdown_derive→rust/markdown_derive, and
consolidated generated code into a newrust/protomodule (replacing
rust/generated). - Updated all
bazel_utils_*modules tov0.2.10. - Updated
protobuftov36.2.