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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
//! `aozora` — the public meta crate.
//!
//! Single front door for parsing Aozora Bunko notation. Downstream
//! consumers should depend on this crate alone; everything they need
//! is re-exported through this surface or accessed via [`Document`]
//! and [`AozoraTree`].
//!
//! ```no_run
//! use aozora::Document;
//!
//! let source = std::fs::read_to_string("crime_and_punishment.txt").unwrap();
//! let doc = Document::new(source);
//! let tree = doc.parse();
//! let html = tree.to_html();
//! println!("{html}");
//! ```
//!
//! Tunable parses go through the builder chain:
//!
//! ```
//! use aozora::{Document, DiagnosticPolicy};
//!
//! let doc = Document::options()
//! .arena_capacity(64 * 1024)
//! .diagnostic_policy(DiagnosticPolicy::DropInternal)
//! .build("|青梅《おうめ》");
//! let tree = doc.parse();
//! assert!(!tree.serialize().is_empty());
//! ```
//!
//! # Architecture
//!
//! [`Document`] owns the source buffer plus a `bumpalo`-backed
//! arena. [`AozoraTree`] borrows from that arena via the `&self`
//! lifetime returned by [`Document::parse`]. Every per-node
//! allocation lives inside the arena, with the
//! [`Interner`](aozora_syntax::borrowed::Interner) deduplicating
//! repeated string content; dropping the `Document` releases the
//! entire tree in a single `Bump::reset` step.
//!
//! Internal build-block crates (`aozora-spec`, `aozora-syntax`,
//! `aozora-pipeline`, `aozora-render`, `aozora-encoding`) are
//! `publish = false` and reachable only through this meta crate's
//! [`pipeline`] / [`syntax`] / [`render`] / [`encoding`] / [`wire`]
//! modules. Depend on `aozora` alone; see the
//! [Architecture chapter of the handbook](https://p4suta.github.io/aozora/arch/pipeline.html)
//! for the layered design.
pub use ;
/// Per-node HTML writer: `render_node::render(node, entering, &mut w)`.
///
/// The sanctioned surface for sibling composition layers — notably
/// `afm` (Aozora Flavored Markdown, ADR-0010) — that splice individual
/// Aozora spans into a host document at sentinel positions rather than
/// rendering a whole [`Document`] through [`html`]. Whole-document
/// callers should still use [`html`] / [`serialize`]; this promotes the
/// per-node tier to the curated front door so siblings need not reach
/// through the `render::*` wildcard module.
pub use render_node;
pub use ;
pub use ;
/// Bump-allocator arena that owns all borrowed-AST node storage.
///
/// Sibling composition layers (notably `afm`, ADR-0010) that drive
/// [`lex_into_arena`] directly construct the arena themselves via this
/// re-export, instead of going through [`Document`] (which owns its own
/// arena internally). Promoted to the curated front door alongside the
/// per-node [`render_node`] path so the two have matching entry points
/// without reaching through the `syntax::*` wildcard module.
pub use Arena;
/// Borrowed-AST node types editor surfaces match against (LSP inlay
/// hints, hover, completion, code actions, semantic tokens).
/// Re-exported so external consumers don't have to depend on
/// `aozora-syntax` directly — `aozora` is the single editor-facing
/// front door.
pub use ;
pub use ;
/// Eagerly initialise the parser's process-global lazy tables.
///
/// The *first* [`Document::parse`] then does not pay the one-time build
/// cost on its critical path.
///
/// Parsing is lazy by default: a consumer that never parses — or parses
/// no annotations — pays nothing. `prewarm` is **opt-in**. Call it once,
/// early, from a latency-sensitive front end (e.g. a WASM editor warming
/// the parser before the first keystroke). It is idempotent and
/// thread-safe; redundant calls are effectively free.
///
/// It warms the SIMD trigger-scan backend selection (Phase 1) and the
/// annotation-classifier Aho-Corasick DFA (Phase 3) — the latter is the
/// bulk of the cost (~150 microseconds; the `aozora-pipeline` `boot`
/// bench measures it).
///
/// ```
/// aozora::prewarm();
/// let doc = aozora::Document::new("|青梅《おうめ》");
/// let _ = doc.parse().to_html();
/// ```
/// Re-export of [`aozora_pipeline`] under a stable name.
///
/// Editor integrations that want per-phase access
/// (`pipeline::lexer::*` for the phase functions, `pipeline::Pipeline`
/// for the type-state machine) reach through this module so the
/// wider workspace can keep `aozora` as the single front door. The
/// `aozora-pipeline` crate is `publish = false` and only callable
/// via this re-export.
/// Re-export of [`aozora_syntax`] — AST node types, arena, interner.
///
/// External callers normally reach through [`Document`] /
/// [`AozoraTree`] for the borrowed-AST surface; this module exposes
/// the underlying types when they need to construct nodes directly
/// (visitor implementations, custom renderers).
/// Re-export of [`aozora_render`] — HTML / serialize emitters and
/// the visitor trait.
///
/// Custom downstream renderers (EPUB, plain text, LaTeX, …)
/// implement [`syntax::borrowed::AozoraVisitor`](crate::syntax::borrowed)
/// and route through this module.
/// Re-export of [`aozora_encoding`] — Shift_JIS decoding and gaiji
/// resolution.
///
/// Phase 0 of the lex pipeline runs encoding detection first;
/// callers that want to drive encoding without parsing can reach
/// through this module.
/// Lossless concrete syntax tree.
///
/// Re-export of [`aozora_cst`] under the `cst` feature. Enables
/// editor-grade surfaces (LSP servers, source-faithful
/// refactoring / formatting tools) without pulling rowan into the
/// dep tree of plain library consumers.
///
/// ```rust,ignore
/// use aozora::Document;
/// let doc = Document::new("|青梅《おうめ》");
/// let cst = aozora::cst::from_tree(&doc.parse());
/// // Walk the rowan SyntaxNode tree …
/// ```
/// Tree-sitter-flavoured pattern queries over the CST.
///
/// Re-export of [`aozora_query`] under the `query` feature.
/// Editor surfaces (`textDocument/documentHighlight`, "find all
/// ruby annotations") compose against the DSL instead of
/// re-implementing tree walks.
///
/// ```rust,ignore
/// use aozora::Document;
/// use aozora::query::compile;
///
/// let doc = Document::new("|青梅《おうめ》");
/// let cst = aozora::cst::from_tree(&doc.parse());
/// let q = compile("(Construct @ruby)").unwrap();
/// let captures = q.captures(&cst);
/// ```
/// Aozora-shaped `proptest` strategies.
///
/// Downstream renderer / visitor authors writing their own property
/// tests reach through this module instead of pulling
/// `aozora-proptest` directly. Enabled by the `proptest` Cargo
/// feature on the `aozora` crate; both `aozora::proptest::*` and
/// the `proptest` crate itself are then in scope for the consumer.
///
/// The generators here cover the same shapes the workspace's
/// `tests/property_*` suites rely on, so any regression noticed
/// inside the parser also surfaces inside the consumer's test
/// harness.