diff --git a/packages/parser/src/dast-normalize/normalize-dast.ts b/packages/parser/src/dast-normalize/normalize-dast.ts index e256fb3fb..f322f3ebc 100644 --- a/packages/parser/src/dast-normalize/normalize-dast.ts +++ b/packages/parser/src/dast-normalize/normalize-dast.ts @@ -16,6 +16,11 @@ import { selectSugar } from "./component-sugar/select"; import { postponeRenderSugar } from "./component-sugar/postponeRender"; import { pluginEnforceValidNames } from "./enforce-valid-names"; import { pretzelSugar } from "./component-sugar/pretzel"; +import { lezerToDast } from "../lezer-to-dast"; +import { Parser, HtmlRenderer } from "commonmark"; + +const commonMarkParser = new Parser(); +const commonMarkRenderer = new HtmlRenderer(); /** * Normalize the DAST tree so that it is contained in a single `` element. @@ -25,13 +30,15 @@ export function normalizeDocumentDast( dast: DastRoot, addCompatibilityNames = false, ) { + console.log(dast); let processor = unified() .use(pluginRemoveCommentsInstructionsAndDocStrings) .use(pluginChangeCdataToText) .use(pluginEnsureDocumentElement) .use(pluginConvertPretextAttributes) .use(pluginEnforceValidNames) - .use(pluginExpandAliasedElements); + .use(pluginExpandAliasedElements) + .use(pluginTextToMarkdown); if (addCompatibilityNames) { processor = processor.use(pluginAddCompatibilityNames); } @@ -54,6 +61,29 @@ const pluginChangeCdataToText: Plugin<[], DastRoot, DastRoot> = () => { }; }; +/** + * Interpret all text nodes that are children of the root node as Markdown, transforming them to HTML. + */ +const pluginTextToMarkdown: Plugin<[], DastRoot, DastRoot> = () => { + return (tree) => { + visit(tree, (node, visitInfo) => { + // All text nodes that are children of the root node are interpreted as Markdown. + if (node.type === "text" && visitInfo.parents.length === 1) { + const html = commonMarkRenderer.render( + commonMarkParser.parse(node.value), + ); + // Parse this HTML into a DAST tree, then replace the text node with the new DAST tree. + const dast = lezerToDast(html); + visitInfo.parents[0].children.splice( + visitInfo.index!, + 1, + ...(dast.children as DastElementContent[]), + ); + } + }); + }; +}; + /** * Remove all comment/instruction/docstring nodes from the DAST tree. */ diff --git a/packages/parser/test/dast-basic.test.ts b/packages/parser/test/dast-basic.test.ts index ed6c6bd12..b50d036ba 100644 --- a/packages/parser/test/dast-basic.test.ts +++ b/packages/parser/test/dast-basic.test.ts @@ -13,6 +13,7 @@ import { splitTextAtSpecialChars, splitTextNodeAt, } from "../src/lezer-to-dast/gobble-function-arguments"; +import { normalizeDocumentDast } from "../src/dast-normalize/normalize-dast"; const origLog = console.log; console.log = (...args) => { @@ -470,4 +471,14 @@ describe("DAST", async () => { } `); }); + it("converts Markdown text to HTML", () => { + let source: string; + let dast: ReturnType; + + source = `*hi*\n\n# there!`; + dast = lezerToDast(source); + expect(toXml(normalizeDocumentDast(dast))).toEqual( + "

hi

there!

", + ); + }); }); diff --git a/packages/test-viewer/src/test/testCode.doenet b/packages/test-viewer/src/test/testCode.doenet index 7925166a4..ba96a9f09 100644 --- a/packages/test-viewer/src/test/testCode.doenet +++ b/packages/test-viewer/src/test/testCode.doenet @@ -1,3 +1,5 @@ +**test** + @@ -17,8 +19,8 @@

A lovely section.

- This problem is nested inside a section. The default number does not - include the parent number. + This problem is nested inside a section. The default number does not + include the parent number.

@@ -27,8 +29,8 @@

Another section!

- This exercise is nested inside a section. Rendering of the parent section - number has been included. + This exercise is nested inside a section. Rendering of the parent section + number has been included.