diff --git a/compiler/src/knitr/__test__/knitr.test.ts b/compiler/src/knitr/__test__/knitr.test.ts index 7eddc865..7daeabaa 100644 --- a/compiler/src/knitr/__test__/knitr.test.ts +++ b/compiler/src/knitr/__test__/knitr.test.ts @@ -240,7 +240,7 @@ describe('knitr', () => { expect(ignoreWhitespace(md)).toContain( ignoreWhitespace(` - \`\`\`{.r-error} + \`\`\`{.r-error-output} Error in "120" + "5": non-numeric argument to binary operator \`\`\` `) @@ -284,7 +284,7 @@ describe('knitr', () => {
print(a)
-
+
Python Console
Error in py_call_impl(callable, dots$args, dots$keywords): NameError: name 'a' is not defined
         Detailed traceback:
@@ -301,7 +301,7 @@ describe('knitr', () => {
       
b
-
+
R Console
Error in eval(expr, envir, enclos): object 'b' not found
diff --git a/compiler/src/knitr/index.ts b/compiler/src/knitr/index.ts index 8f7c5fe4..a38efd3a 100644 --- a/compiler/src/knitr/index.ts +++ b/compiler/src/knitr/index.ts @@ -84,10 +84,10 @@ function reportErrors(response: string, file: VFile) { async function formatResponse(response: string) { let md = response; md = removeCustomPythonBinNotice(md); - md = removeHashSigns(md); md = addCodeBlockClasses(md); - md = removeEmptyLog(md); md = addErrorCodeBlock(md); + md = removeHashSigns(md); + md = removeEmptyLog(md); md = addNewLineAfterKable(md); return md; } @@ -96,16 +96,13 @@ function removeCustomPythonBinNotice(md: string) { return md.replace(/^\$python\s\[1\]\s"\S+"/, ''); } -function removeHashSigns(md: string) { - let insideCodeBlock = false; +function addCodeBlockClasses(md: string) { return md .split('\n') .reduce((acc: string[], line) => { - if (line.startsWith('```')) { - insideCodeBlock = !insideCodeBlock; - } - if (insideCodeBlock) { - acc.push(line.replace(/^##\s+/, '')); + if (line.startsWith('```{.knitr-output}')) { + const lang = findLanguageForOutput(acc); + acc.push(`\`\`\`{.${lang}-output}`); } else { acc.push(line); } @@ -114,13 +111,18 @@ function removeHashSigns(md: string) { .join('\n'); } -function addCodeBlockClasses(md: string) { +function removeHashSigns(md: string) { + let insideCodeResponse = false; + let openingLine = ''; return md .split('\n') .reduce((acc: string[], line) => { - if (line.startsWith('```{.knitr-output}')) { - const lang = findLanguageForOutput(acc); - acc.push(`\`\`\`{.${lang}-output}`); + if (line.startsWith('```')) { + insideCodeResponse = !insideCodeResponse; + openingLine = insideCodeResponse ? line : ''; + } + if (insideCodeResponse && openingLine.endsWith('-output}')) { + acc.push(line.replace(/^##\s+/, '')); } else { acc.push(line); } @@ -137,9 +139,9 @@ function addErrorCodeBlock(md: string) { return md .split('\n') .reduce((acc: string[], line, idx) => { - if (line.startsWith('Error') && acc[idx - 1].startsWith('```')) { + if (line.startsWith('## Error') && acc[idx - 1].startsWith('```')) { const lang = findLanguageForOutput(acc.slice(0, -1)); - acc[acc.length - 1] = `\`\`\`{.${lang}-error}`; + acc[acc.length - 1] = `\`\`\`{.${lang}-error-output}`; } acc.push(line); return acc; diff --git a/compiler/src/mdast/__test__/escaping.test.ts b/compiler/src/mdast/__test__/escaping.test.ts new file mode 100644 index 00000000..9de85fc7 --- /dev/null +++ b/compiler/src/mdast/__test__/escaping.test.ts @@ -0,0 +1,22 @@ +import { + testProcessor, + unindentString, +} from '../../test-utils/test-processor'; + +describe('example', () => { + it('should allow the author to use sample markdown headings', async () => { + const { html } = await testProcessor(` + \`\`\` + ## This is a subsection + \`\`\` + `); + + const expected = unindentString(` +
+
## This is a subsection
+
+ `); + + expect(html).toBe(expected); + }); +}); diff --git a/compiler/src/mdast/code-blocks.ts b/compiler/src/mdast/code-blocks.ts index e2c3e47f..27e48c11 100644 --- a/compiler/src/mdast/code-blocks.ts +++ b/compiler/src/mdast/code-blocks.ts @@ -73,7 +73,7 @@ function customCode(node: Code, ctx: Context, file: VFile) { } function addConsoleHeading(klass: string) { - if (klass === 'r-output' || klass === 'r-error') { + if (klass === 'r-output' || klass === 'r-error-output') { return { type: 'element', tagName: 'h6', @@ -88,7 +88,7 @@ function addConsoleHeading(klass: string) { ], }; } - if (klass === 'python-output' || klass === 'python-error') { + if (klass === 'python-output' || klass === 'python-error-output') { return { type: 'element', tagName: 'h6', diff --git a/template/src/styles/code.scss b/template/src/styles/code.scss index 462287f3..326662e3 100644 --- a/template/src/styles/code.scss +++ b/template/src/styles/code.scss @@ -32,7 +32,7 @@ code { background: transparent; } - &[class$="error"] { + &[class$="error-output"] { background: var(--errorColor); color: white; & > h6.console-heading {