phase 1: core AST, spans, and Visitor
Define every node type in SPEC.md §6.4 — Document, 11 block variants, 15 inline variants (including the 4 link-related ones), plus ListItem / DefinitionItem / TableRow / TableCell, ListSymbol, CheckboxState, Keyword, LinkTarget, LinkKind. Every node carries a `Span` (line + column + byte offset, 0-indexed) per §6.5. Visitor: open-recursion trait with default `visit_*` bodies that delegate to `walk_*` free functions. Override at any granularity; call `walk_*` from your override to keep descending. P4 resolved by defining the trait now so Phase 5 (renderer) and Phase 7 (semantic tokens) can plug in without refactoring traversal. P3 resolved: AST string fields are owned `String`. Cow / Arc<str> can be revisited if the parser grows a zero-copy mode. Tests: visitor smoke test builds a heading + paragraph + list + table by hand and asserts exact visit counts (4 blocks, 12 inlines, 9 text leaves, 1 bold, 1 external link, 1 transclusion). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
//! Link-related AST nodes and supporting types.
|
||||
//!
|
||||
//! See SPEC.md §6.4. All nodes here are inline (`InlineNode` variants);
|
||||
//! they live in their own module because the link model has enough surface
|
||||
//! area (kinds, anchors, interwiki indirection) to warrant separation.
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use super::inline::InlineNode;
|
||||
use super::span::Span;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum LinkKind {
|
||||
Wiki,
|
||||
Interwiki,
|
||||
Diary,
|
||||
File,
|
||||
Local,
|
||||
Raw,
|
||||
AnchorOnly,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)]
|
||||
pub struct LinkTarget {
|
||||
pub kind: LinkKind,
|
||||
pub path: Option<String>,
|
||||
pub wiki_index: Option<usize>,
|
||||
pub wiki_name: Option<String>,
|
||||
pub anchor: Option<String>,
|
||||
pub is_absolute: bool,
|
||||
pub is_directory: bool,
|
||||
}
|
||||
|
||||
impl Default for LinkKind {
|
||||
fn default() -> Self {
|
||||
Self::Wiki
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct WikiLinkNode {
|
||||
pub span: Span,
|
||||
pub target: LinkTarget,
|
||||
pub description: Option<Vec<InlineNode>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct ExternalLinkNode {
|
||||
pub span: Span,
|
||||
pub url: String,
|
||||
pub description: Option<Vec<InlineNode>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct TransclusionNode {
|
||||
pub span: Span,
|
||||
pub url: String,
|
||||
pub alt: Option<String>,
|
||||
pub attrs: HashMap<String, String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct RawUrlNode {
|
||||
pub span: Span,
|
||||
pub url: String,
|
||||
}
|
||||
Reference in New Issue
Block a user