From 9fbc5edf2a78ebc733732b7fa6fc40acd3bf978b Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Fri, 9 Sep 2022 16:19:19 +0200 Subject: Add docs for mdx expressions --- src/construct/mdx_expression_flow.rs | 44 ++++++++- src/construct/mdx_expression_text.rs | 36 +++++++- src/construct/partial_mdx_expression.rs | 84 ++++++++++++++++- src/event.rs | 159 ++++++++++++++++++++++++++++---- 4 files changed, 293 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/construct/mdx_expression_flow.rs b/src/construct/mdx_expression_flow.rs index 0faea31..ef3ca41 100644 --- a/src/construct/mdx_expression_flow.rs +++ b/src/construct/mdx_expression_flow.rs @@ -1,4 +1,38 @@ -//! To do. +//! MDX expression (flow) occurs in the [flow][] content type. +//! +//! ## Grammar +//! +//! MDX expression (flow) forms with the following BNF +//! (see [construct][crate::construct] for character groups): +//! +//! ```bnf +//! mdx_expression_flow ::= mdx_expression *space_or_tab +//! +//! ; See the `partial_mdx_expression` construct for the BNF of that part. +//! ``` +//! +//! As this construct occurs in flow, like all flow constructs, it must be +//! followed by an eol (line ending) or eof (end of file). +//! +//! See [`mdx_expression`][mdx_expression] for more info. +//! +//! ## Tokens +//! +//! * [`MdxFlowExpression`][Name::MdxFlowExpression] +//! * [`SpaceOrTab`][Name::SpaceOrTab] +//! * see [`mdx_expression`][mdx_expression] for more +//! +//! ## Recommendation +//! +//! See [`mdx_expression`][mdx_expression] for recommendations. +//! +//! ## References +//! +//! * [`syntax.js` in `micromark-extension-mdx-expression`](https://github.com/micromark/micromark-extension-mdx-expression/blob/main/packages/micromark-extension-mdx-expression/dev/lib/syntax.js) +//! * [`mdxjs.com`](https://mdxjs.com) +//! +//! [flow]: crate::construct::flow +//! [mdx_expression]: crate::construct::partial_mdx_expression use crate::construct::partial_space_or_tab::{space_or_tab, space_or_tab_min_max}; use crate::event::Name; @@ -6,7 +40,7 @@ use crate::state::{Name as StateName, State}; use crate::tokenizer::Tokenizer; use crate::util::constant::TAB_SIZE; -/// Start of MDX: expression (flow). +/// Start of an MDX expression (flow). /// /// ```markdown /// > | {Math.PI} @@ -35,7 +69,7 @@ pub fn start(tokenizer: &mut Tokenizer) -> State { } } -/// After optional whitespace, before of MDX expression (flow). +/// After optional whitespace, before expression. /// /// ```markdown /// > | {Math.PI} @@ -50,7 +84,7 @@ pub fn before(tokenizer: &mut Tokenizer) -> State { } } -/// After an MDX expression (flow). +/// After expression. /// /// ```markdown /// > | {Math.PI} @@ -66,7 +100,7 @@ pub fn after(tokenizer: &mut Tokenizer) -> State { } } -/// After an MDX expression (flow), after optional whitespace. +/// After expression, after optional whitespace. /// /// ```markdown /// > | {Math.PI}␠␊ diff --git a/src/construct/mdx_expression_text.rs b/src/construct/mdx_expression_text.rs index 8d061eb..53160a0 100644 --- a/src/construct/mdx_expression_text.rs +++ b/src/construct/mdx_expression_text.rs @@ -1,10 +1,40 @@ -//! To do. +//! MDX expression (text) occurs in the [text][] content type. +//! +//! ## Grammar +//! +//! MDX expression (text) forms with the following BNF +//! (see [construct][crate::construct] for character groups): +//! +//! ```bnf +//! mdx_expression_text ::= mdx_expression +//! +//! ; See the `partial_mdx_expression` construct for the BNF of that part. +//! ``` +//! +//! See [`mdx_expression`][mdx_expression] for more info. +//! +//! ## Tokens +//! +//! * [`MdxTextExpression`][Name::MdxTextExpression] +//! * see [`mdx_expression`][mdx_expression] for more +//! +//! ## Recommendation +//! +//! See [`mdx_expression`][mdx_expression] for recommendations. +//! +//! ## References +//! +//! * [`syntax.js` in `micromark-extension-mdx-expression`](https://github.com/micromark/micromark-extension-mdx-expression/blob/main/packages/micromark-extension-mdx-expression/dev/lib/syntax.js) +//! * [`mdxjs.com`](https://mdxjs.com) +//! +//! [text]: crate::construct::text +//! [mdx_expression]: crate::construct::partial_mdx_expression use crate::event::Name; use crate::state::{Name as StateName, State}; use crate::tokenizer::Tokenizer; -/// Start of MDX: expression (text). +/// Start of an MDX expression (text). /// /// ```markdown /// > | a {Math.PI} c @@ -22,7 +52,7 @@ pub fn start(tokenizer: &mut Tokenizer) -> State { } } -/// After an MDX expression (text) tag. +/// After expression. /// /// ```markdown /// > | a {Math.PI} c diff --git a/src/construct/partial_mdx_expression.rs b/src/construct/partial_mdx_expression.rs index aeea52e..31a9af8 100644 --- a/src/construct/partial_mdx_expression.rs +++ b/src/construct/partial_mdx_expression.rs @@ -1,4 +1,61 @@ -//! To do. +//! MDX expression occurs in [MDX expression (flow)][mdx_expression_flow] and +//! [MDX expression (text)][mdx_expression_text]. +//! +//! ## Grammar +//! +//! MDX expression forms with the following BNF +//! (see [construct][crate::construct] for character groups): +//! +//! ```bnf +//! mdx_expression ::= '{' *(expression_text | expression) '}' +//! expression_text ::= char - '{' - '}' +//! ``` +//! +//! ## Tokens +//! +//! * [`LineEnding`][Name::LineEnding] +//! * [`SpaceOrTab`][Name::SpaceOrTab] +//! * [`MdxExpressionMarker`][Name::MdxExpressionMarker] +//! * [`MdxExpressionData`][Name::MdxExpressionData] +//! +//! ## Recommendation +//! +//! When authoring markdown with JavaScript, keep in mind that MDX is a +//! whitespace sensitive and line-based language, while JavaScript is +//! insensitive to whitespace. +//! This affects how markdown and JavaScript interleave with eachother in MDX. +//! For more info on how it works, see [§ Interleaving][interleaving] on the +//! MDX site. +//! +//! ## Errors +//! +//! ### Unexpected end of file in expression, expected a corresponding closing brace for `{` +//! +//! This error occurs if a `{` was seen without a `}`. +//! For example: +//! +//! ```markdown +//! a { b +//! ``` +//! +//! ### Unexpected lazy line in expression in container, expected line to be prefixed with `>` when in a block quote, whitespace when in a list, etc +//! +//! This error occurs if a a lazy line (of a container) is found in an expression. +//! For example: +//! +//! ```markdown +//! > {a + +//! b} +//! ``` +//! +//! ## References +//! +//! * [`micromark-factory-mdx-expression`](https://github.com/micromark/micromark-extension-mdx-expression/blob/main/packages/micromark-factory-mdx-expression/dev/index.js) +//! * [`mdxjs.com`](https://mdxjs.com) +//! +//! [mdx_expression_flow]: crate::construct::mdx_expression_flow +//! [mdx_expression_text]: crate::construct::mdx_expression_text +//! [interleaving]: https://mdxjs.com/docs/what-is-mdx/#interleaving use crate::construct::partial_space_or_tab::space_or_tab_min_max; use crate::event::Name; @@ -6,7 +63,7 @@ use crate::state::{Name as StateName, State}; use crate::tokenizer::Tokenizer; use alloc::format; -/// Start of MDX: expression. +/// Start of an MDX expression. /// /// ```markdown /// > | a {Math.PI} c @@ -21,6 +78,12 @@ pub fn start(tokenizer: &mut Tokenizer) -> State { State::Next(StateName::MdxExpressionBefore) } +/// Before data. +/// +/// ```markdown +/// > | a {Math.PI} c +/// ^ +/// ``` pub fn before(tokenizer: &mut Tokenizer) -> State { match tokenizer.current { None => { @@ -38,7 +101,7 @@ pub fn before(tokenizer: &mut Tokenizer) -> State { Some(b'}') if tokenizer.tokenize_state.size == 0 => { if tokenizer.tokenize_state.token_1 == Name::MdxJsxTagAttributeValueExpression && !tokenizer.tokenize_state.seen { State::Error(format!( - "{}:{}: Unexpected empty in expression, expected a value between braces", + "{}:{}: Unexpected empty expression, expected a value between braces", tokenizer.point.line, tokenizer.point.column )) } else { @@ -58,6 +121,12 @@ pub fn before(tokenizer: &mut Tokenizer) -> State { } } +/// In data. +/// +/// ```markdown +/// > | a {Math.PI} c +/// ^ +/// ``` pub fn inside(tokenizer: &mut Tokenizer) -> State { if matches!(tokenizer.current, None | Some(b'\n')) || (tokenizer.current == Some(b'}') && tokenizer.tokenize_state.size == 0) @@ -77,8 +146,15 @@ pub fn inside(tokenizer: &mut Tokenizer) -> State { } } +/// After eol. +/// +/// ```markdown +/// | a {b + +/// > | c} d +/// ^ +/// ``` pub fn eol_after(tokenizer: &mut Tokenizer) -> State { - // Lazy continuation in a flow expression (or in a flow tag) is a syntax error. + // Lazy continuation in a flow expression (or flow tag) is a syntax error. if (tokenizer.tokenize_state.token_1 == Name::MdxFlowExpression || tokenizer.tokenize_state.token_2 == Name::MdxJsxFlowTag) && tokenizer.lazy diff --git a/src/event.rs b/src/event.rs index 2375369..6ea52fb 100644 --- a/src/event.rs +++ b/src/event.rs @@ -523,7 +523,7 @@ pub enum Name { /// ## Info /// /// * **Context**: - /// [`CodeText`][Name::CodeText], + /// [`CodeText`][Name::CodeText] /// * **Content model**: /// void /// * **Construct**: @@ -541,7 +541,7 @@ pub enum Name { /// ## Info /// /// * **Context**: - /// [`CodeText`][Name::CodeText], + /// [`CodeText`][Name::CodeText] /// * **Content model**: /// void /// * **Construct**: @@ -1692,7 +1692,7 @@ pub enum Name { /// ## Info /// /// * **Context**: - /// [`HeadingAtx`][Name::HeadingAtx], + /// [`HeadingAtx`][Name::HeadingAtx] /// * **Content model**: /// [text content][crate::construct::text] /// * **Construct**: @@ -1791,7 +1791,7 @@ pub enum Name { /// ## Info /// /// * **Context**: - /// [`HtmlFlow`][Name::HtmlFlow], + /// [`HtmlFlow`][Name::HtmlFlow] /// * **Content model**: /// void /// * **Construct**: @@ -2062,7 +2062,7 @@ pub enum Name { /// /// * **Context**: /// [`ListOrdered`][Name::ListOrdered], - /// [`ListUnordered`][Name::ListUnordered], + /// [`ListUnordered`][Name::ListUnordered] /// * **Content model**: /// [`ListItemPrefix`][Name::ListItemPrefix], /// [flow content][crate::construct::flow] @@ -2320,7 +2320,7 @@ pub enum Name { /// ## Info /// /// * **Context**: - /// [`MathText`][Name::MathText], + /// [`MathText`][Name::MathText] /// * **Content model**: /// void /// * **Construct**: @@ -2351,6 +2351,90 @@ pub enum Name { /// ^ ^ /// ``` MathTextSequence, + /// MDX extension: expression marker. + /// + /// ## Info + /// + /// * **Context**: + /// [`MdxFlowExpression`][Name::MdxFlowExpression], + /// [`MdxTextExpression`][Name::MdxTextExpression], + /// [`MdxJsxTagAttributeExpression`][Name::MdxJsxTagAttributeExpression], + /// [`MdxJsxTagAttributeValueExpression`][Name::MdxJsxTagAttributeValueExpression] + /// * **Content model**: + /// void + /// * **Construct**: + /// [`partial_mdx_expression`][crate::construct::partial_mdx_expression] + /// + /// ## Example + /// + /// ```markdown + /// > | {Math.PI} + /// ^ ^ + /// ``` + MdxExpressionMarker, + /// MDX extension: expression data. + /// + /// ## Info + /// + /// * **Context**: + /// [`MdxFlowExpression`][Name::MdxFlowExpression], + /// [`MdxTextExpression`][Name::MdxTextExpression], + /// [`MdxJsxTagAttributeExpression`][Name::MdxJsxTagAttributeExpression], + /// [`MdxJsxTagAttributeValueExpression`][Name::MdxJsxTagAttributeValueExpression] + /// * **Content model**: + /// void + /// * **Construct**: + /// [`partial_mdx_expression`][crate::construct::partial_mdx_expression] + /// + /// ## Example + /// + /// ```markdown + /// > | {Math.PI} + /// ^^^^^^^ + /// ``` + MdxExpressionData, + /// MDX extension: expression (flow). + /// + /// ## Info + /// + /// * **Context**: + /// [flow content][crate::construct::flow] + /// * **Content model**: + /// [`LineEnding`][Name::LineEnding], + /// [`SpaceOrTab`][Name::SpaceOrTab], + /// [`MdxExpressionMarker`][Name::MdxExpressionMarker], + /// [`MdxExpressionData`][Name::MdxExpressionData] + /// * **Construct**: + /// [`mdx_expression_flow`][crate::construct::mdx_expression_flow] + /// + /// ## Example + /// + /// ```markdown + /// > | {Math.PI} + /// ^^^^^^^^^ + /// ``` + MdxFlowExpression, + /// MDX extension: expression (text). + /// + /// ## Info + /// + /// * **Context**: + /// [flow content][crate::construct::flow] + /// * **Content model**: + /// [`LineEnding`][Name::LineEnding], + /// [`SpaceOrTab`][Name::SpaceOrTab], + /// [`MdxExpressionMarker`][Name::MdxExpressionMarker], + /// [`MdxExpressionData`][Name::MdxExpressionData] + /// * **Construct**: + /// [`mdx_expression_text`][crate::construct::mdx_expression_text] + /// + /// ## Example + /// + /// ```markdown + /// > | a {Math.PI} b + /// ^^^^^^^^^ + /// ``` + MdxTextExpression, /// MDX extension: JSX (flow). /// /// ## Info @@ -2364,7 +2448,7 @@ pub enum Name { /// [`MdxJsxTagClosingMarker`][Name::MdxJsxTagClosingMarker], /// [`MdxJsxTagName`][Name::MdxJsxTagName], /// [`MdxJsxTagAttribute`][Name::MdxJsxTagAttribute], - /// to do: attribute expression, + /// [`MdxJsxTagAttributeExpression`][Name::MdxJsxTagAttributeExpression], /// [`MdxJsxTagSelfClosingMarker`][Name::MdxJsxTagSelfClosingMarker] /// * **Construct**: /// [`mdx_jsx_flow`][crate::construct::mdx_jsx_flow] @@ -2389,7 +2473,7 @@ pub enum Name { /// [`MdxJsxTagClosingMarker`][Name::MdxJsxTagClosingMarker], /// [`MdxJsxTagName`][Name::MdxJsxTagName], /// [`MdxJsxTagAttribute`][Name::MdxJsxTagAttribute], - /// to do: attribute expression, + /// [`MdxJsxTagAttributeExpression`][Name::MdxJsxTagAttributeExpression], /// [`MdxJsxTagSelfClosingMarker`][Name::MdxJsxTagSelfClosingMarker] /// * **Construct**: /// [`mdx_jsx_text`][crate::construct::mdx_jsx_text] @@ -2597,7 +2681,7 @@ pub enum Name { /// [`MdxJsxTagAttributeName`][Name::MdxJsxTagAttributeName], /// [`MdxJsxTagAttributeInitializerMarker`][Name::MdxJsxTagAttributeInitializerMarker], /// [`MdxJsxTagAttributeValueLiteral`][Name::MdxJsxTagAttributeValueLiteral], - /// to do: attribute value expression, + /// [`MdxJsxTagAttributeValueExpression`][Name::MdxJsxTagAttributeValueExpression] /// * **Construct**: /// [`partial_mdx_jsx`][crate::construct::partial_mdx_jsx] /// @@ -2612,6 +2696,28 @@ pub enum Name { /// ^^^^^ /// ``` MdxJsxTagAttribute, + /// MDX extension: JSX tag attribute expression. + /// + /// ## Info + /// + /// * **Context**: + /// [`MdxJsxFlowTag`][Name::MdxJsxFlowTag], + /// [`MdxJsxTextTag`][Name::MdxJsxTextTag] + /// * **Content model**: + /// [`LineEnding`][Name::LineEnding], + /// [`SpaceOrTab`][Name::SpaceOrTab], + /// [`MdxExpressionMarker`][Name::MdxExpressionMarker], + /// [`MdxExpressionData`][Name::MdxExpressionData] + /// * **Construct**: + /// [`partial_mdx_jsx`][crate::construct::partial_mdx_jsx] + /// + /// ## Example + /// + /// ```markdown + /// > | a c + /// ^^^^^^^^^ + /// ``` + MdxJsxTagAttributeExpression, /// MDX extension: JSX: attribute name. /// /// ## Info @@ -2623,7 +2729,7 @@ pub enum Name { /// [`MdxJsxEsWhitespace`][Name::MdxJsxEsWhitespace], /// [`MdxJsxTagAttributePrimaryName`][Name::MdxJsxTagAttributePrimaryName], /// [`MdxJsxTagAttributeNamePrefixMarker`][Name::MdxJsxTagAttributeNamePrefixMarker], - /// [`MdxJsxTagAttributeNameLocal`][Name::MdxJsxTagAttributeNameLocal], + /// [`MdxJsxTagAttributeNameLocal`][Name::MdxJsxTagAttributeNameLocal] /// * **Construct**: /// [`partial_mdx_jsx`][crate::construct::partial_mdx_jsx] /// @@ -2710,6 +2816,28 @@ pub enum Name { /// ^ /// ``` MdxJsxTagAttributeInitializerMarker, + /// MDX extension: JSX tag attribute value expression. + /// + /// ## Info + /// + /// * **Context**: + /// [`MdxJsxFlowTag`][Name::MdxJsxFlowTag], + /// [`MdxJsxTextTag`][Name::MdxJsxTextTag] + /// * **Content model**: + /// [`LineEnding`][Name::LineEnding], + /// [`SpaceOrTab`][Name::SpaceOrTab], + /// [`MdxExpressionMarker`][Name::MdxExpressionMarker], + /// [`MdxExpressionData`][Name::MdxExpressionData] + /// * **Construct**: + /// [`partial_mdx_jsx`][crate::construct::partial_mdx_jsx] + /// + /// ## Example + /// + /// ```markdown + /// > | a d + /// ^^^^^^^^^ + /// ``` + MdxJsxTagAttributeValueExpression, /// MDX extension: JSX: attribute value literal. /// /// ## Info @@ -3166,17 +3294,10 @@ pub enum Name { /// ^ ^ ^ /// ``` ThematicBreakSequence, - - MdxFlowExpression, - MdxTextExpression, - MdxExpressionMarker, // void - MdxExpressionData, // void - MdxJsxTagAttributeValueExpression, - MdxJsxTagAttributeExpression, } /// List of void events, used to make sure everything is working well. -pub const VOID_EVENTS: [Name; 73] = [ +pub const VOID_EVENTS: [Name; 75] = [ Name::AttentionSequence, Name::AutolinkEmail, Name::AutolinkMarker, @@ -3231,6 +3352,8 @@ pub const VOID_EVENTS: [Name; 73] = [ Name::MathFlowChunk, Name::MathTextData, Name::MathTextSequence, + Name::MdxExpressionMarker, + Name::MdxExpressionData, Name::MdxJsxTagMarker, Name::MdxJsxTagClosingMarker, Name::MdxJsxTagNamePrimary, -- cgit