pub struct Config<'a> {
pub schemas: Arc<dyn SchemaSource + Send + Sync>,
pub variables: Option<Variables>,
pub functions: Arc<IndexMap<String, ConfigFunction>>,
pub partials: Arc<IndexMap<String, Node<'a>>>,
pub validation: ValidationOptions<'a>,
}Expand description
Everything the validator and the transformer read.
The lifetime is the source text that partials and
ValidationOptions::parents borrow. A config holding neither – the
ordinary case for a host that registers schemas once and reuses them – is a
Config<'static>, and Rust’s variance lets that be passed wherever a
Config<'a> is wanted. That is deliberate: a schema registry that could
only validate documents of its own lifetime would have to be rebuilt per
page.
§Why three fields are behind an Arc
A config is cloned on a hot path and only one field differs between the
original and the copy: {% partial %} scopes a partial’s body by cloning
the whole config to replace variables. Everything
else – the schemas, the functions, the parsed partials – is registered
once and read many times, so copying it per expansion charges the caller for
the site’s whole partial corpus on every partial in every page, which
compounds exactly where partials earn their keep.
So those three are shared rather than copied. Reads are unchanged
(Arc derefs). The two maps have copy-on-write mutators
(functions_mut and
partials_mut) for assembly; the schema source
does not, because a trait object cannot be copied on write. A host fills a
MapSchemaSource and shares it with with_schemas,
so the sharing is explicit rather than clever.
Fields§
§schemas: Arc<dyn SchemaSource + Send + Sync>Where a schema comes from.
The only mechanism: there is no map beside it and so no precedence rule
to remember. Config::new starts it empty and
builtins::config at Markdoc’s own.
variables: Option<Variables>Variables a $name reference resolves against.
None switches variable checking off; Some of an empty map switches
it on with nothing defined.
functions: Arc<IndexMap<String, ConfigFunction>>Functions a f() call resolves against.
Shared: see the note on Config. Use
functions_mut to edit one in place.
partials: Arc<IndexMap<String, Node<'a>>>Parsed partial documents, keyed by the name {% partial file=... %}
uses.
Parsed, not raw: this crate performs no I/O, so a host reads the file and parses it. That is why the config carries a lifetime.
Shared: see the note on Config, where this field is the one that
made the sharing worth doing. Use
partials_mut to edit the map in place.
validation: ValidationOptions<'a>Switches and context for the validation pass.
Implementations§
Source§impl<'a> Config<'a>
impl<'a> Config<'a>
Sourcepub fn new() -> Config<'a>
pub fn new() -> Config<'a>
An empty config: no schemas, no variables, no functions, no partials.
Every node then reports node-undefined or tag-undefined, which is the
correct answer rather than a degenerate one – upstream’s own validate
merges its built-in schemas in before it gets here, and a host that skips
that step has genuinely defined nothing.
Sourcepub fn with_schemas(
self,
schemas: Arc<dyn SchemaSource + Send + Sync>,
) -> Config<'a>
pub fn with_schemas( self, schemas: Arc<dyn SchemaSource + Send + Sync>, ) -> Config<'a>
Replace the schema source.
Chainable, for the registering case: fill a MapSchemaSource and hand
it over in one expression. The source is shared, not copied, so a host
with one registry and many configs pays for it once.
Sourcepub fn functions_mut(&mut self) -> &mut IndexMap<String, ConfigFunction>
pub fn functions_mut(&mut self) -> &mut IndexMap<String, ConfigFunction>
The functions, for in-place edit.
Copy-on-write: the map is copied only if another Config is sharing it,
which is what makes registering once and scoping many times cheap.
Sourcepub fn partials_mut(&mut self) -> &mut IndexMap<String, Node<'a>>
pub fn partials_mut(&mut self) -> &mut IndexMap<String, Node<'a>>
The parsed partials, for in-place edit. Copy-on-write, as
functions_mut is.
Sourcepub fn find_schema(&self, node: &Node<'_>) -> Option<&Schema>
pub fn find_schema(&self, node: &Node<'_>) -> Option<&Schema>
The schema for a node: its tag’s if it has a tag, its type’s otherwise.
Upstream’s transformer.findSchema. It lives on the config rather than
on Node because the node is the leaf type and the config is the
stage above it; upstream’s node.findSchema(config) is the same call
with the arrow pointing the other way. The work is
SchemaSource::find’s; this only chooses the key.
Trait Implementations§
Source§impl Debug for Config<'_>
impl Debug for Config<'_>
Source§fn fmt(&self, f: &mut Formatter<'_>) -> Result
fn fmt(&self, f: &mut Formatter<'_>) -> Result
Hooks are function pointers with no useful rendering, so the derived
Debug is unavailable and this one reports what is there instead: the
names registered, which is what you want when a tag-undefined error
disagrees with what you thought you registered.
The schema names come through the source’s provided
tag_names and
node_types, and print as None for a
source that cannot enumerate – which is the truth, and different from
an empty list.