From 71dbc8c0189d6b2032f3d8f21cbfffa3f8fe0f12 Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Fri, 9 Sep 2022 10:18:24 +0200 Subject: Add docs to mdx jsx --- src/construct/partial_mdx_jsx.rs | 163 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 162 insertions(+), 1 deletion(-) (limited to 'src/construct/partial_mdx_jsx.rs') diff --git a/src/construct/partial_mdx_jsx.rs b/src/construct/partial_mdx_jsx.rs index ac4b7d8..1a51608 100644 --- a/src/construct/partial_mdx_jsx.rs +++ b/src/construct/partial_mdx_jsx.rs @@ -1,4 +1,165 @@ -//! To do. +//! MDX JSX occurs in [MDX JSX (flow)][mdx_jsx_flow] and +//! [MDX JSX (text)][mdx_jsx_text]. +//! +//! ## Grammar +//! +//! MDX JSX forms with the following BNF +//! (see [construct][crate::construct] for character groups): +//! +//! ```bnf +//! ; constraint: markdown whitespace (`space_or_tab | eol`) is NOT +//! ; allowed directly after `<` in order to allow `1 < 3` in markdown. +//! mdx_jsx ::= +//! '<' [closing] +//! [*whitespace name [attributes_after_identifier] [closing]] +//! *whitespace '>' +//! +//! attributes_after_identifier ::= +//! 1*whitespace (attributes_boolean | attributes_value) | +//! *whitespace attributes_expression | +//! attributes_after_value ::= +//! *whitespace (attributes_boolean | attributes_expression | attributes_value) +//! attributes_boolean ::= key [attributes_after_identifier] +//! ; Note: in gnostic mode the value of the expression must instead be a single valid ES spread +//! ; expression +//! attributes_expression ::= expression [attributes_after_value] +//! attributes_value ::= key initializer [attributes_after_value] +//! +//! closing ::= *whitespace '/' +//! +//! name ::= identifier [local | members] +//! key ::= identifier [local] +//! local ::= *whitespace ':' *whitespace identifier +//! members ::= member *member +//! member ::= *whitespace '.' *whitespace identifier +//! +//! identifier ::= identifier_start *identifier_part +//! initializer ::= *whitespace '=' *whitespace value +//! value ::= double_quoted | single_quoted | expression +//! ; Note: in gnostic mode the value must instead be a single valid ES expression +//! expression ::= '{' *(expression_text | expression) '}' +//! +//! double_quoted ::= '"' *double_quoted_text '"' +//! single_quoted ::= "'" *single_quoted_text "'" +//! +//! text ::= char - '<' - '{' +//! whitespace ::= es_whitespace +//! double_quoted_text ::= char - '"' +//! single_quoted_text ::= char - "'" +//! expression_text ::= char - '{' - '}' +//! identifier_start ::= es_identifier_start +//! identifier_part ::= es_identifier_part | '-' +//! +//! ; ECMAScript +//! ; See “Identifier_start”: +//! es_identifier_start ::= ? +//! ; See “Identifier_part”: +//! es_identifier_part ::= ? +//! ; See “Whitespace”: +//! es_whitespace ::= ? +//! ``` +//! +//! The grammar for JSX in markdown is much stricter than that of HTML in +//! markdown. +//! The primary benefit of this is that tags are parsed into tokens, and thus +//! can be processed. +//! Another, arguable, benefit of this is that it comes with syntax errors: if +//! an author types something that is nonsensical, an error is thrown with +//! information about where it happened, what occurred, and what was expected +//! instead. +//! +//! ## Tokens +//! +//! * [`LineEnding`][Name::LineEnding] +//! * [`MdxJsxEsWhitespace`][Name::MdxJsxEsWhitespace] +//! * [`MdxJsxTagMarker`][Name::MdxJsxTagMarker] +//! * [`MdxJsxTagClosingMarker`][Name::MdxJsxTagClosingMarker] +//! * [`MdxJsxTagName`][Name::MdxJsxTagName] +//! * [`MdxJsxTagNamePrimary`][Name::MdxJsxTagNamePrimary] +//! * [`MdxJsxTagNameMemberMarker`][Name::MdxJsxTagNameMemberMarker] +//! * [`MdxJsxTagNamePrefixMarker`][Name::MdxJsxTagNamePrefixMarker] +//! * [`MdxJsxTagNameMember`][Name::MdxJsxTagNameMember] +//! * [`MdxJsxTagNameLocal`][Name::MdxJsxTagNameLocal] +//! * [`MdxJsxTagAttribute`][Name::MdxJsxTagAttribute] +//! * [`MdxJsxTagAttributeName`][Name::MdxJsxTagAttributeName] +//! * [`MdxJsxTagAttributePrimaryName`][Name::MdxJsxTagAttributePrimaryName] +//! * [`MdxJsxTagAttributeNamePrefixMarker`][Name::MdxJsxTagAttributeNamePrefixMarker] +//! * [`MdxJsxTagAttributeNameLocal`][Name::MdxJsxTagAttributeNameLocal] +//! * [`MdxJsxTagAttributeInitializerMarker`][Name::MdxJsxTagAttributeInitializerMarker] +//! * [`MdxJsxTagAttributeValueLiteral`][Name::MdxJsxTagAttributeValueLiteral] +//! * [`MdxJsxTagAttributeValueLiteralMarker`][Name::MdxJsxTagAttributeValueLiteralMarker] +//! * [`MdxJsxTagAttributeValueLiteralValue`][Name::MdxJsxTagAttributeValueLiteralValue] +//! * [`MdxJsxTagSelfClosingMarker`][Name::MdxJsxTagSelfClosingMarker] +//! +//! ## Recommendation +//! +//! When authoring markdown with JSX, keep in mind that MDX is a whitespace +//! sensitive and line-based language, while JavaScript is insensitive to +//! whitespace. +//! This affects how markdown and JSX interleave with eachother in MDX. +//! For more info on how it works, see [§ Interleaving][interleaving] on the +//! MDX site. +//! +//! ###### Comments inside tags +//! +//! JavaScript comments in JSX are not supported. +//! +//! Incorrect: +//! +//! ```jsx +//! +//! +//! ``` +//! +//! Correct: +//! +//! ```jsx +//! +//! +//! ``` +//! +//! A PR that adds support for them would be accepted. +//! +//! ###### Element or fragment attribute values +//! +//! JSX elements or JSX fragments as attribute values are not supported. +//! The reason for this change is that it would be confusing whether markdown +//! would work. +//! +//! Incorrect: +//! +//! ```jsx +//! Venus /> +//! Pluto /> +//! ``` +//! +//! Correct: +//! +//! ```jsx +//! +//! Jupiter} /> +//! ``` +//! +//! ###### Greater than (`>`) and right curly brace (`}`) +//! +//! JSX does not allow U+003E GREATER THAN (`>`) or U+007D RIGHT CURLY BRACE +//! (`}`) literally in text, they need to be encoded as character references +//! (or expressions). +//! There is no good reason for this (some JSX parsers agree with us and don’t +//! crash either). +//! Therefore, in MDX, U+003E GREATER THAN (`>`) and U+007D RIGHT CURLY BRACE +//! (`}`) are fine literally and don’t need to be encoded. +//! +//! ## References +//! +//! * [`jsx-flow.js` in `micromark-extension-mdx-jsx`](https://github.com/micromark/micromark-extension-mdx-jsx/blob/main/dev/lib/jsx-flow.js) +//! * [`mdxjs.com`](https://mdxjs.com) +//! +//! [mdx_jsx_flow]: crate::construct::mdx_jsx_flow +//! [mdx_jsx_text]: crate::construct::mdx_jsx_text +//! [interleaving]: https://mdxjs.com/docs/what-is-mdx/#interleaving use crate::event::Name; use crate::state::{Name as StateName, State}; -- cgit