Implement abstract syntax tree compilation of the new syntax
This commit is contained in:
@@ -193,6 +193,7 @@ pub enum Node {
|
|||||||
Break(Break),
|
Break(Break),
|
||||||
/// Code (phrasing).
|
/// Code (phrasing).
|
||||||
InlineCode(InlineCode),
|
InlineCode(InlineCode),
|
||||||
|
Task(Task),
|
||||||
/// Math (phrasing).
|
/// Math (phrasing).
|
||||||
InlineMath(InlineMath),
|
InlineMath(InlineMath),
|
||||||
/// Delete.
|
/// Delete.
|
||||||
@@ -269,6 +270,7 @@ impl fmt::Debug for Node {
|
|||||||
Node::Yaml(x) => x.fmt(f),
|
Node::Yaml(x) => x.fmt(f),
|
||||||
Node::Break(x) => x.fmt(f),
|
Node::Break(x) => x.fmt(f),
|
||||||
Node::InlineCode(x) => x.fmt(f),
|
Node::InlineCode(x) => x.fmt(f),
|
||||||
|
Node::Task(x) => x.fmt(f),
|
||||||
Node::InlineMath(x) => x.fmt(f),
|
Node::InlineMath(x) => x.fmt(f),
|
||||||
Node::Delete(x) => x.fmt(f),
|
Node::Delete(x) => x.fmt(f),
|
||||||
Node::Emphasis(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::Toml(x) => x.value.clone(),
|
||||||
Node::Yaml(x) => x.value.clone(),
|
Node::Yaml(x) => x.value.clone(),
|
||||||
Node::InlineCode(x) => x.value.clone(),
|
Node::InlineCode(x) => x.value.clone(),
|
||||||
|
Node::Task(x) => x.value.clone(),
|
||||||
Node::InlineMath(x) => x.value.clone(),
|
Node::InlineMath(x) => x.value.clone(),
|
||||||
Node::MdxTextExpression(x) => x.value.clone(),
|
Node::MdxTextExpression(x) => x.value.clone(),
|
||||||
Node::Html(x) => x.value.clone(),
|
Node::Html(x) => x.value.clone(),
|
||||||
@@ -414,6 +417,7 @@ impl Node {
|
|||||||
Node::Yaml(x) => x.position.as_ref(),
|
Node::Yaml(x) => x.position.as_ref(),
|
||||||
Node::Break(x) => x.position.as_ref(),
|
Node::Break(x) => x.position.as_ref(),
|
||||||
Node::InlineCode(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::InlineMath(x) => x.position.as_ref(),
|
||||||
Node::Delete(x) => x.position.as_ref(),
|
Node::Delete(x) => x.position.as_ref(),
|
||||||
Node::Emphasis(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::Yaml(x) => x.position.as_mut(),
|
||||||
Node::Break(x) => x.position.as_mut(),
|
Node::Break(x) => x.position.as_mut(),
|
||||||
Node::InlineCode(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::InlineMath(x) => x.position.as_mut(),
|
||||||
Node::Delete(x) => x.position.as_mut(),
|
Node::Delete(x) => x.position.as_mut(),
|
||||||
Node::Emphasis(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::Yaml(x) => x.position = position,
|
||||||
Node::Break(x) => x.position = position,
|
Node::Break(x) => x.position = position,
|
||||||
Node::InlineCode(x) => x.position = position,
|
Node::InlineCode(x) => x.position = position,
|
||||||
|
Node::Task(x) => x.position = position,
|
||||||
Node::InlineMath(x) => x.position = position,
|
Node::InlineMath(x) => x.position = position,
|
||||||
Node::Delete(x) => x.position = position,
|
Node::Delete(x) => x.position = position,
|
||||||
Node::Emphasis(x) => x.position = position,
|
Node::Emphasis(x) => x.position = position,
|
||||||
@@ -892,6 +898,23 @@ pub struct InlineCode {
|
|||||||
pub position: Option<Position>,
|
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).
|
/// Math (phrasing).
|
||||||
///
|
///
|
||||||
/// ```markdown
|
/// ```markdown
|
||||||
|
|||||||
+18
-1
@@ -333,6 +333,7 @@ fn enter(context: &mut CompileContext) {
|
|||||||
Name::CodeIndented => on_enter_code_indented(context),
|
Name::CodeIndented => on_enter_code_indented(context),
|
||||||
Name::CodeFenced | Name::MathFlow => on_enter_raw_flow(context),
|
Name::CodeFenced | Name::MathFlow => on_enter_raw_flow(context),
|
||||||
Name::CodeText | Name::MathText => on_enter_raw_text(context),
|
Name::CodeText | Name::MathText => on_enter_raw_text(context),
|
||||||
|
Name::Task => on_enter_task(context),
|
||||||
Name::Definition => on_enter_definition(context),
|
Name::Definition => on_enter_definition(context),
|
||||||
Name::DefinitionDestinationString => on_enter_definition_destination_string(context),
|
Name::DefinitionDestinationString => on_enter_definition_destination_string(context),
|
||||||
Name::Emphasis => on_enter_emphasis(context),
|
Name::Emphasis => on_enter_emphasis(context),
|
||||||
@@ -371,7 +372,7 @@ fn exit(context: &mut CompileContext) {
|
|||||||
on_exit_drop(context);
|
on_exit_drop(context);
|
||||||
}
|
}
|
||||||
Name::MdxEsm | Name::MdxFlowExpression | Name::MdxJsxFlowTag => on_exit_drop_slurp(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);
|
on_exit_data(context);
|
||||||
}
|
}
|
||||||
Name::AutolinkEmail => on_exit_autolink_email(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::CodeFencedFenceInfo => on_exit_raw_flow_fence_info(context),
|
||||||
Name::CodeFlowChunk | Name::MathFlowChunk => on_exit_raw_flow_chunk(context),
|
Name::CodeFlowChunk | Name::MathFlowChunk => on_exit_raw_flow_chunk(context),
|
||||||
Name::CodeText | Name::MathText => on_exit_raw_text(context),
|
Name::CodeText | Name::MathText => on_exit_raw_text(context),
|
||||||
|
Name::Task => on_exit_task(context),
|
||||||
Name::Definition => on_exit_definition(context),
|
Name::Definition => on_exit_definition(context),
|
||||||
Name::DefinitionDestinationString => on_exit_definition_destination_string(context),
|
Name::DefinitionDestinationString => on_exit_definition_destination_string(context),
|
||||||
Name::DefinitionLabelString => on_exit_definition_label_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>");
|
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].
|
/// Handle [`Enter`][Kind::Enter]:[`CodeIndented`][Name::CodeIndented].
|
||||||
fn on_enter_code_indented(context: &mut CompileContext) {
|
fn on_enter_code_indented(context: &mut CompileContext) {
|
||||||
context.raw_flow_seen_data = Some(false);
|
context.raw_flow_seen_data = Some(false);
|
||||||
@@ -757,6 +766,14 @@ fn on_exit_block_quote(context: &mut CompileContext) {
|
|||||||
context.push("</blockquote>");
|
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].
|
/// Handle [`Exit`][Kind::Exit]:[`CharacterReferenceMarker`][Name::CharacterReferenceMarker].
|
||||||
fn on_exit_character_reference_marker(context: &mut CompileContext) {
|
fn on_exit_character_reference_marker(context: &mut CompileContext) {
|
||||||
context.character_reference_marker = Some(b'&');
|
context.character_reference_marker = Some(b'&');
|
||||||
|
|||||||
+37
-1
@@ -7,7 +7,7 @@ use crate::mdast::{
|
|||||||
ImageReference, InlineCode, InlineMath, Link, LinkReference, List, ListItem, Math,
|
ImageReference, InlineCode, InlineMath, Link, LinkReference, List, ListItem, Math,
|
||||||
MdxFlowExpression, MdxJsxAttribute, MdxJsxExpressionAttribute, MdxJsxFlowElement,
|
MdxFlowExpression, MdxJsxAttribute, MdxJsxExpressionAttribute, MdxJsxFlowElement,
|
||||||
MdxJsxTextElement, MdxTextExpression, MdxjsEsm, Node, Paragraph, ReferenceKind, Root, Strong,
|
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::message;
|
||||||
use crate::unist::{Point, Position};
|
use crate::unist::{Point, Position};
|
||||||
@@ -267,6 +267,7 @@ fn enter(context: &mut CompileContext) -> Result<(), message::Message> {
|
|||||||
| Name::CharacterReference
|
| Name::CharacterReference
|
||||||
| Name::CodeFlowChunk
|
| Name::CodeFlowChunk
|
||||||
| Name::CodeTextData
|
| Name::CodeTextData
|
||||||
|
| Name::TaskContent
|
||||||
| Name::Data
|
| Name::Data
|
||||||
| Name::FrontmatterChunk
|
| Name::FrontmatterChunk
|
||||||
| Name::HtmlFlowData
|
| Name::HtmlFlowData
|
||||||
@@ -291,6 +292,7 @@ fn enter(context: &mut CompileContext) -> Result<(), message::Message> {
|
|||||||
Name::CodeFenced => on_enter_code_fenced(context),
|
Name::CodeFenced => on_enter_code_fenced(context),
|
||||||
Name::CodeIndented => on_enter_code_indented(context),
|
Name::CodeIndented => on_enter_code_indented(context),
|
||||||
Name::CodeText => on_enter_code_text(context),
|
Name::CodeText => on_enter_code_text(context),
|
||||||
|
Name::Task => on_enter_task(context),
|
||||||
Name::Definition => on_enter_definition(context),
|
Name::Definition => on_enter_definition(context),
|
||||||
Name::Emphasis => on_enter_emphasis(context),
|
Name::Emphasis => on_enter_emphasis(context),
|
||||||
Name::Frontmatter => on_enter_frontmatter(context),
|
Name::Frontmatter => on_enter_frontmatter(context),
|
||||||
@@ -359,6 +361,7 @@ fn exit(context: &mut CompileContext) -> Result<(), message::Message> {
|
|||||||
Name::CharacterEscapeValue
|
Name::CharacterEscapeValue
|
||||||
| Name::CodeFlowChunk
|
| Name::CodeFlowChunk
|
||||||
| Name::CodeTextData
|
| Name::CodeTextData
|
||||||
|
| Name::TaskContent
|
||||||
| Name::Data
|
| Name::Data
|
||||||
| Name::FrontmatterChunk
|
| Name::FrontmatterChunk
|
||||||
| Name::HtmlFlowData
|
| Name::HtmlFlowData
|
||||||
@@ -387,6 +390,7 @@ fn exit(context: &mut CompileContext) -> Result<(), message::Message> {
|
|||||||
Name::CodeFenced | Name::MathFlow => on_exit_raw_flow(context)?,
|
Name::CodeFenced | Name::MathFlow => on_exit_raw_flow(context)?,
|
||||||
Name::CodeIndented => on_exit_code_indented(context)?,
|
Name::CodeIndented => on_exit_code_indented(context)?,
|
||||||
Name::CodeText | Name::MathText => on_exit_raw_text(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::DefinitionDestinationString => on_exit_definition_destination_string(context),
|
||||||
Name::DefinitionLabelString | Name::GfmFootnoteDefinitionLabelString => {
|
Name::DefinitionLabelString | Name::GfmFootnoteDefinitionLabelString => {
|
||||||
on_exit_definition_id(context);
|
on_exit_definition_id(context);
|
||||||
@@ -501,6 +505,15 @@ fn on_enter_code_text(context: &mut CompileContext) {
|
|||||||
context.buffer();
|
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].
|
/// Handle [`Enter`][Kind::Enter]:[`MathText`][Name::MathText].
|
||||||
fn on_enter_math_text(context: &mut CompileContext) {
|
fn on_enter_math_text(context: &mut CompileContext) {
|
||||||
context.tail_push(Node::InlineMath(InlineMath {
|
context.tail_push(Node::InlineMath(InlineMath {
|
||||||
@@ -1103,6 +1116,29 @@ fn on_exit_raw_text(context: &mut CompileContext) -> Result<(), message::Message
|
|||||||
Ok(())
|
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).
|
/// Handle [`Exit`][Kind::Exit]:[`Data`][Name::Data] (and many text things).
|
||||||
fn on_exit_data(context: &mut CompileContext) -> Result<(), message::Message> {
|
fn on_exit_data(context: &mut CompileContext) -> Result<(), message::Message> {
|
||||||
let value = Slice::from_position(
|
let value = Slice::from_position(
|
||||||
|
|||||||
Reference in New Issue
Block a user