Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion packages/parser/src/dast-normalize/normalize-dast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 `<document>` element.
Expand All @@ -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);
}
Expand All @@ -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),
);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very interesting strategy. It's certainly quick for now, but I think it would be better to convert the AST directly so we have full control over the nodes created (e.g, in code blocks, etc.)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean that it's possible we'll be using Markdown not just with text nodes, but in other places (inside code blocks, for example)? If so, then your comment below makes a lot of sense -- define where Markdown belongs and where it doesn't.

// 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.
*/
Expand Down
11 changes: 11 additions & 0 deletions packages/parser/test/dast-basic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down Expand Up @@ -470,4 +471,14 @@ describe("DAST", async () => {
}
`);
});
it("converts Markdown text to HTML", () => {
let source: string;
let dast: ReturnType<typeof lezerToDast>;

source = `*hi*\n\n# there!`;
dast = lezerToDast(source);
expect(toXml(normalizeDocumentDast(dast))).toEqual(
"<document><p><em>hi</em></p><h1>there!</h1></document>",
);
});
});
10 changes: 6 additions & 4 deletions packages/test-viewer/src/test/testCode.doenet
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
**test**

<graph>
<point name="P" x="3" y="1" />
<rectangle width="40" height="40" center="(0,0)" filled name="R" />
Expand All @@ -17,8 +19,8 @@
<p>A lovely section.</p>
<problem>
<p>
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.
</p>
</problem>
</section>
Expand All @@ -27,8 +29,8 @@
<p>Another section!</p>
<problem includeParentNumber="true">
<p>
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.
</p>
</problem>
</section>
Expand Down