1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
//! # prov-graph
//!
//! The read core of a [prov](https://docs.rs/prov) workspace: plaintext
//! documents, the links declared in their own embedded metadata, and the
//! traversal over them.
//!
//! ## What this crate is for
//!
//! A prov workspace describes itself. Follow the links in a document's
//! frontmatter and body and the whole structure unfolds — no index to trust
//! instead of the documents, no sidecar folder that has to be kept in step.
//! This crate is that unfolding, and *only* that.
//!
//! Everything here reads. The filesystem port it asks for
//! ([`fs::ReadStorage`]) has no method that writes a byte; the id index it asks
//! for ([`index::IdIndex`]) has no method that changes a registration. Nor is
//! the vocabulary for writing merely unused — it is *absent*, declared a layer
//! up in `prov-store` instead. So a consumer that must not modify a workspace —
//! a language server, a static renderer, a browser viewer — can depend on this
//! crate and be *unable* to, rather than merely intending not to. That is the
//! whole reason the split exists, and it is why the write halves are not here
//! behind a feature flag someone could leave switched on.
//!
//! The write surface is `prov-store`: `Storage`, the metadata editor, and the
//! `IndexStore` registries. The verbs are `prov`: creating, renaming, deleting,
//! attaching, the change/journal machinery that makes a mutation crash-atomic,
//! the config layer, the validation and repair passes.
//! `prov` owns one [`Graph`] and forwards every read to it, so the two are the
//! same traversal — not a reimplementation that can drift.
//!
//! `prov-views` is what that promise looks like taken up: a whole view engine —
//! parse a declared view, resolve its scope by walking the spanning relation,
//! group the documents it reaches — built on this crate and nothing else, and
//! therefore unable to modify a byte of what it reads.
//!
//! ## The shape of it
//!
//! - [`Document`] — a plaintext file split into its embedded metadata block and
//! its body.
//! - [`relation::RelationSet`] — which metadata fields are links. Exactly one
//! may be **spanning**: the single-parent tree that gives a workspace its
//! discovery spine. Every other relation may be many-to-many, so the tree is a
//! backbone, never a ceiling.
//! - [`Graph`] — a root, a [`fs::ReadStorage`], an [`index::IdIndex`], and the
//! [`graph::ReadSettings`] that say how links are spelled. Its two walks are
//! the [`census`](Graph::census) (every forward link, flat, each tagged with
//! where it is written and how it resolves) and the [`tree`](Graph::tree)
//! (the spanning relation only, as a materialized outline).
//!
//! The census is ground truth. Reachability, the backlinks map, and prov's own
//! validation findings are all views over it, and any stored index heals
//! *toward* it, never the reverse.
// At least one embedded-metadata format backend must be compiled in, otherwise
// nothing here can parse a document at all. The format features (`yaml`,
// `json`, `toml`, `fig-lang`) forward to the matching `fig` parser.
compile_error!;
pub use ;
pub use ;
pub use ;
pub use block_on;
pub use ExtKind;
pub use Format;
pub use Fixity;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ReadScope;
pub use ;
pub use ;
pub use ;
pub use ;
/// The body-prose parser, re-exported whole.
///
/// [`content`] uses twig to answer prov's own two questions — render a body to
/// HTML ([`render_html`]) and find the spans a parser calls code
/// ([`code_spans`]) — and both hand back plain strings and offsets. That is the
/// whole of what prov needs, and for a long time it was the whole of what
/// anyone could reach: twig was an implementation detail with no path out.
///
/// It is re-exported because the consumers this crate was built for — a
/// language server, a static renderer, a browser viewer — need the *tree*, not
/// a rendering of it. A static site generator filtering `:::vis{...}` regions
/// by audience, or an editor addressing a node to splice it, is asking twig
/// questions prov has no opinion about and should not grow one about.
///
/// Without this they would depend on `twig-doc` directly, pin it themselves,
/// and resolve to a different [`twig::Document`] than the one [`content`]
/// parses with — two AST vocabularies in one build, disagreeing silently about
/// what a document is.
///
/// **This makes `twig-doc` a public dependency**, which is a real cost and the
/// reason it was not done sooner: twig's major version is now part of prov's
/// semver contract, so a twig 4 is a breaking change for prov whether or not
/// prov's own surface moves. Accepted deliberately — the alternative is not
/// "no coupling", it is the same coupling spelled separately by every
/// downstream crate and enforced by nobody.
///
/// ```
/// use prov_graph::twig::{Document, Format, MarkdownExtensions};
///
/// // What [`content`] cannot ask for: an opt-in extension. prov parses with
/// // defaults, so a consumer that needs directives reaches past it — and,
/// // through this re-export, reaches the same twig.
/// let directives = MarkdownExtensions { directives: true, ..Default::default() };
/// let mut doc = Document::parse_str_with(
/// ":::vis{.public}\nHello\n:::\n",
/// Format::Markdown,
/// directives,
/// )?;
/// // The directive's name becomes the element tag and its attributes ride
/// // along — which is also why a consumer publishing HTML unwraps these
/// // rather than rendering them.
/// let html = String::from_utf8(doc.render_html()?).unwrap();
/// assert!(html.contains("<vis class=\"public\">"), "{html}");
/// # Ok::<(), prov_graph::twig::Error>(())
/// ```
pub use twig;