Implement abstract syntax tree compilation of the new syntax
This commit is contained in:
@@ -193,6 +193,7 @@ pub enum Node {
|
||||
Break(Break),
|
||||
/// Code (phrasing).
|
||||
InlineCode(InlineCode),
|
||||
Task(Task),
|
||||
/// Math (phrasing).
|
||||
InlineMath(InlineMath),
|
||||
/// Delete.
|
||||
@@ -269,6 +270,7 @@ impl fmt::Debug for Node {
|
||||
Node::Yaml(x) => x.fmt(f),
|
||||
Node::Break(x) => x.fmt(f),
|
||||
Node::InlineCode(x) => x.fmt(f),
|
||||
Node::Task(x) => x.fmt(f),
|
||||
Node::InlineMath(x) => x.fmt(f),
|
||||
Node::Delete(x) => x.fmt(f),
|
||||
Node::Emphasis(x) => x.fmt(f),
|
||||
@@ -330,6 +332,7 @@ impl ToString for Node {
|
||||
Node::Toml(x) => x.value.clone(),
|
||||
Node::Yaml(x) => x.value.clone(),
|
||||
Node::InlineCode(x) => x.value.clone(),
|
||||
Node::Task(x) => x.value.clone(),
|
||||
Node::InlineMath(x) => x.value.clone(),
|
||||
Node::MdxTextExpression(x) => x.value.clone(),
|
||||
Node::Html(x) => x.value.clone(),
|
||||
@@ -414,6 +417,7 @@ impl Node {
|
||||
Node::Yaml(x) => x.position.as_ref(),
|
||||
Node::Break(x) => x.position.as_ref(),
|
||||
Node::InlineCode(x) => x.position.as_ref(),
|
||||
Node::Task(x) => x.position.as_ref(),
|
||||
Node::InlineMath(x) => x.position.as_ref(),
|
||||
Node::Delete(x) => x.position.as_ref(),
|
||||
Node::Emphasis(x) => x.position.as_ref(),
|
||||
@@ -453,6 +457,7 @@ impl Node {
|
||||
Node::Yaml(x) => x.position.as_mut(),
|
||||
Node::Break(x) => x.position.as_mut(),
|
||||
Node::InlineCode(x) => x.position.as_mut(),
|
||||
Node::Task(x) => x.position.as_mut(),
|
||||
Node::InlineMath(x) => x.position.as_mut(),
|
||||
Node::Delete(x) => x.position.as_mut(),
|
||||
Node::Emphasis(x) => x.position.as_mut(),
|
||||
@@ -492,6 +497,7 @@ impl Node {
|
||||
Node::Yaml(x) => x.position = position,
|
||||
Node::Break(x) => x.position = position,
|
||||
Node::InlineCode(x) => x.position = position,
|
||||
Node::Task(x) => x.position = position,
|
||||
Node::InlineMath(x) => x.position = position,
|
||||
Node::Delete(x) => x.position = position,
|
||||
Node::Emphasis(x) => x.position = position,
|
||||
@@ -892,6 +898,23 @@ pub struct InlineCode {
|
||||
pub position: Option<Position>,
|
||||
}
|
||||
|
||||
/// Code (phrasing).
|
||||
///
|
||||
/// ```markdown
|
||||
/// > | `a`
|
||||
/// ^^^
|
||||
/// ```
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct Task {
|
||||
// Text.
|
||||
/// Content model.
|
||||
pub value: String,
|
||||
/// Positional info.
|
||||
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
|
||||
pub position: Option<Position>,
|
||||
}
|
||||
|
||||
/// Math (phrasing).
|
||||
///
|
||||
/// ```markdown
|
||||
|
||||
+18
-1
@@ -333,6 +333,7 @@ fn enter(context: &mut CompileContext) {
|
||||
Name::CodeIndented => on_enter_code_indented(context),
|
||||
Name::CodeFenced | Name::MathFlow => on_enter_raw_flow(context),
|
||||
Name::CodeText | Name::MathText => on_enter_raw_text(context),
|
||||
Name::Task => on_enter_task(context),
|
||||
Name::Definition => on_enter_definition(context),
|
||||
Name::DefinitionDestinationString => on_enter_definition_destination_string(context),
|
||||
Name::Emphasis => on_enter_emphasis(context),
|
||||
@@ -371,7 +372,7 @@ fn exit(context: &mut CompileContext) {
|
||||
on_exit_drop(context);
|
||||
}
|
||||
Name::MdxEsm | Name::MdxFlowExpression | Name::MdxJsxFlowTag => on_exit_drop_slurp(context),
|
||||
Name::CharacterEscapeValue | Name::CodeTextData | Name::Data | Name::MathTextData => {
|
||||
Name::CharacterEscapeValue | Name::CodeTextData | Name::TaskContent | Name::Data | Name::MathTextData => {
|
||||
on_exit_data(context);
|
||||
}
|
||||
Name::AutolinkEmail => on_exit_autolink_email(context),
|
||||
@@ -391,6 +392,7 @@ fn exit(context: &mut CompileContext) {
|
||||
Name::CodeFencedFenceInfo => on_exit_raw_flow_fence_info(context),
|
||||
Name::CodeFlowChunk | Name::MathFlowChunk => on_exit_raw_flow_chunk(context),
|
||||
Name::CodeText | Name::MathText => on_exit_raw_text(context),
|
||||
Name::Task => on_exit_task(context),
|
||||
Name::Definition => on_exit_definition(context),
|
||||
Name::DefinitionDestinationString => on_exit_definition_destination_string(context),
|
||||
Name::DefinitionLabelString => on_exit_definition_label_string(context),
|
||||
@@ -455,6 +457,13 @@ fn on_enter_block_quote(context: &mut CompileContext) {
|
||||
context.push("<blockquote>");
|
||||
}
|
||||
|
||||
/// Handle [`Enter`][Kind::Enter]:[`Task`][Name::Task].
|
||||
fn on_enter_task(context: &mut CompileContext) {
|
||||
context.tight_stack.push(false);
|
||||
// context.line_ending_if_needed();
|
||||
context.push("<task-todo>");
|
||||
}
|
||||
|
||||
/// Handle [`Enter`][Kind::Enter]:[`CodeIndented`][Name::CodeIndented].
|
||||
fn on_enter_code_indented(context: &mut CompileContext) {
|
||||
context.raw_flow_seen_data = Some(false);
|
||||
@@ -757,6 +766,14 @@ fn on_exit_block_quote(context: &mut CompileContext) {
|
||||
context.push("</blockquote>");
|
||||
}
|
||||
|
||||
/// Handle [`Exit`][Kind::Exit]:[`Task`][Name::Task].
|
||||
fn on_exit_task(context: &mut CompileContext) {
|
||||
context.tight_stack.pop();
|
||||
// context.line_ending_if_needed();
|
||||
// context.slurp_one_line_ending = false;
|
||||
context.push("</task-todo>");
|
||||
}
|
||||
|
||||
/// Handle [`Exit`][Kind::Exit]:[`CharacterReferenceMarker`][Name::CharacterReferenceMarker].
|
||||
fn on_exit_character_reference_marker(context: &mut CompileContext) {
|
||||
context.character_reference_marker = Some(b'&');
|
||||
|
||||
+37
-1
@@ -7,7 +7,7 @@ use crate::mdast::{
|
||||
ImageReference, InlineCode, InlineMath, Link, LinkReference, List, ListItem, Math,
|
||||
MdxFlowExpression, MdxJsxAttribute, MdxJsxExpressionAttribute, MdxJsxFlowElement,
|
||||
MdxJsxTextElement, MdxTextExpression, MdxjsEsm, Node, Paragraph, ReferenceKind, Root, Strong,
|
||||
Table, TableCell, TableRow, Text, ThematicBreak, Toml, Yaml,
|
||||
Table, TableCell, TableRow, Text, Task, ThematicBreak, Toml, Yaml,
|
||||
};
|
||||
use crate::message;
|
||||
use crate::unist::{Point, Position};
|
||||
@@ -267,6 +267,7 @@ fn enter(context: &mut CompileContext) -> Result<(), message::Message> {
|
||||
| Name::CharacterReference
|
||||
| Name::CodeFlowChunk
|
||||
| Name::CodeTextData
|
||||
| Name::TaskContent
|
||||
| Name::Data
|
||||
| Name::FrontmatterChunk
|
||||
| Name::HtmlFlowData
|
||||
@@ -291,6 +292,7 @@ fn enter(context: &mut CompileContext) -> Result<(), message::Message> {
|
||||
Name::CodeFenced => on_enter_code_fenced(context),
|
||||
Name::CodeIndented => on_enter_code_indented(context),
|
||||
Name::CodeText => on_enter_code_text(context),
|
||||
Name::Task => on_enter_task(context),
|
||||
Name::Definition => on_enter_definition(context),
|
||||
Name::Emphasis => on_enter_emphasis(context),
|
||||
Name::Frontmatter => on_enter_frontmatter(context),
|
||||
@@ -359,6 +361,7 @@ fn exit(context: &mut CompileContext) -> Result<(), message::Message> {
|
||||
Name::CharacterEscapeValue
|
||||
| Name::CodeFlowChunk
|
||||
| Name::CodeTextData
|
||||
| Name::TaskContent
|
||||
| Name::Data
|
||||
| Name::FrontmatterChunk
|
||||
| Name::HtmlFlowData
|
||||
@@ -387,6 +390,7 @@ fn exit(context: &mut CompileContext) -> Result<(), message::Message> {
|
||||
Name::CodeFenced | Name::MathFlow => on_exit_raw_flow(context)?,
|
||||
Name::CodeIndented => on_exit_code_indented(context)?,
|
||||
Name::CodeText | Name::MathText => on_exit_raw_text(context)?,
|
||||
Name::Task => on_exit_task(context)?,
|
||||
Name::DefinitionDestinationString => on_exit_definition_destination_string(context),
|
||||
Name::DefinitionLabelString | Name::GfmFootnoteDefinitionLabelString => {
|
||||
on_exit_definition_id(context);
|
||||
@@ -501,6 +505,15 @@ fn on_enter_code_text(context: &mut CompileContext) {
|
||||
context.buffer();
|
||||
}
|
||||
|
||||
/// Handle [`Enter`][Kind::Enter]:[`Task`][Name::Task].
|
||||
fn on_enter_task(context: &mut CompileContext) {
|
||||
context.tail_push(Node::Task(Task {
|
||||
value: String::new(),
|
||||
position: None,
|
||||
}));
|
||||
context.buffer();
|
||||
}
|
||||
|
||||
/// Handle [`Enter`][Kind::Enter]:[`MathText`][Name::MathText].
|
||||
fn on_enter_math_text(context: &mut CompileContext) {
|
||||
context.tail_push(Node::InlineMath(InlineMath {
|
||||
@@ -1103,6 +1116,29 @@ fn on_exit_raw_text(context: &mut CompileContext) -> Result<(), message::Message
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Handle [`Exit`][Kind::Exit]:{[`CodeText`][Name::CodeText],[`MathText`][Name::MathText]}.
|
||||
fn on_exit_task(context: &mut CompileContext) -> Result<(), message::Message> {
|
||||
let mut value = context.resume().to_string();
|
||||
|
||||
let value_bytes = value.as_bytes();
|
||||
if value.len() > 2
|
||||
&& value_bytes[0] == b' '
|
||||
&& value_bytes[value.len() - 1] == b' '
|
||||
&& !value_bytes.iter().all(|b| *b == b' ')
|
||||
{
|
||||
value.remove(0);
|
||||
value.pop();
|
||||
}
|
||||
|
||||
match context.tail_mut() {
|
||||
Node::Task(node) => node.value = value,
|
||||
_ => unreachable!("expected task on stack for value"),
|
||||
}
|
||||
|
||||
on_exit(context)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Handle [`Exit`][Kind::Exit]:[`Data`][Name::Data] (and many text things).
|
||||
fn on_exit_data(context: &mut CompileContext) -> Result<(), message::Message> {
|
||||
let value = Slice::from_position(
|
||||
|
||||
Reference in New Issue
Block a user