feat: process video question md into html (#38667)
* feat: process video question md into html * test: mdToHTML * fix: use dedicated prism component
This commit is contained in:
committed by
Mrugesh Mohapatra
parent
04412cbf6f
commit
de0bec88a3
@ -10,3 +10,19 @@ Object {
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`tests-to-data plugin should match the video snapshot 1`] = `
|
||||
Object {
|
||||
"question": Object {
|
||||
"answers": Array [
|
||||
"<p>inline <code>code</code></p>",
|
||||
"<p>some <em>italics</em></p>",
|
||||
"<p><code> code in </code> code tags</p>",
|
||||
],
|
||||
"solution": 3,
|
||||
"text": "<p>Question line one</p>
|
||||
<pre><code class=\\"language-js\\"> var x = 'y';
|
||||
</code></pre>",
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
197
tools/challenge-md-parser/fixtures/video-challenge-md-ast.json
Normal file
197
tools/challenge-md-parser/fixtures/video-challenge-md-ast.json
Normal file
@ -0,0 +1,197 @@
|
||||
{
|
||||
"type": "root",
|
||||
"children": [
|
||||
{
|
||||
"type": "yaml",
|
||||
"value": "id: 5e9a093a74c4063ca6f7c151\ntitle: Jupyter Notebooks Importing and Exporting Data\nchallengeType: 11\nvideoId: k1msxD3JIxE",
|
||||
"position": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 1,
|
||||
"offset": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 6,
|
||||
"column": 4,
|
||||
"offset": 129
|
||||
},
|
||||
"indent": [
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "heading",
|
||||
"depth": 2,
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"value": "Description",
|
||||
"position": {
|
||||
"start": {
|
||||
"line": 8,
|
||||
"column": 4,
|
||||
"offset": 134
|
||||
},
|
||||
"end": {
|
||||
"line": 8,
|
||||
"column": 15,
|
||||
"offset": 145
|
||||
},
|
||||
"indent": []
|
||||
}
|
||||
}
|
||||
],
|
||||
"position": {
|
||||
"start": {
|
||||
"line": 8,
|
||||
"column": 1,
|
||||
"offset": 131
|
||||
},
|
||||
"end": {
|
||||
"line": 8,
|
||||
"column": 15,
|
||||
"offset": 145
|
||||
},
|
||||
"indent": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "html",
|
||||
"value": "<section id='description'>\n</section>",
|
||||
"position": {
|
||||
"start": {
|
||||
"line": 9,
|
||||
"column": 1,
|
||||
"offset": 146
|
||||
},
|
||||
"end": {
|
||||
"line": 10,
|
||||
"column": 11,
|
||||
"offset": 183
|
||||
},
|
||||
"indent": [
|
||||
1
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "heading",
|
||||
"depth": 2,
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"value": "Tests",
|
||||
"position": {
|
||||
"start": {
|
||||
"line": 12,
|
||||
"column": 4,
|
||||
"offset": 188
|
||||
},
|
||||
"end": {
|
||||
"line": 12,
|
||||
"column": 9,
|
||||
"offset": 193
|
||||
},
|
||||
"indent": []
|
||||
}
|
||||
}
|
||||
],
|
||||
"position": {
|
||||
"start": {
|
||||
"line": 12,
|
||||
"column": 1,
|
||||
"offset": 185
|
||||
},
|
||||
"end": {
|
||||
"line": 12,
|
||||
"column": 9,
|
||||
"offset": 193
|
||||
},
|
||||
"indent": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "html",
|
||||
"value": "<section id='tests'>",
|
||||
"position": {
|
||||
"start": {
|
||||
"line": 13,
|
||||
"column": 1,
|
||||
"offset": 194
|
||||
},
|
||||
"end": {
|
||||
"line": 13,
|
||||
"column": 21,
|
||||
"offset": 214
|
||||
},
|
||||
"indent": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "code",
|
||||
"lang": "yml",
|
||||
"value": "question:\n text: |\n Question line one\n ```js\n var x = 'y';\n ```\n\n answers:\n - inline `code`\n - some *italics*\n - <code> code in </code> code tags\n solution: 3",
|
||||
"position": {
|
||||
"start": {
|
||||
"line": 15,
|
||||
"column": 1,
|
||||
"offset": 216
|
||||
},
|
||||
"end": {
|
||||
"line": 28,
|
||||
"column": 4,
|
||||
"offset": 411
|
||||
},
|
||||
"indent": [
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "html",
|
||||
"value": "</section>",
|
||||
"position": {
|
||||
"start": {
|
||||
"line": 30,
|
||||
"column": 1,
|
||||
"offset": 413
|
||||
},
|
||||
"end": {
|
||||
"line": 30,
|
||||
"column": 11,
|
||||
"offset": 423
|
||||
},
|
||||
"indent": []
|
||||
}
|
||||
}
|
||||
],
|
||||
"position": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 1,
|
||||
"offset": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 32,
|
||||
"column": 1,
|
||||
"offset": 425
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,20 @@
|
||||
const visit = require('unist-util-visit');
|
||||
const YAML = require('js-yaml');
|
||||
const unified = require('unified');
|
||||
const markdown = require('remark-parse');
|
||||
const remark2rehype = require('remark-rehype');
|
||||
const html = require('rehype-stringify');
|
||||
const raw = require('rehype-raw');
|
||||
|
||||
const processor = unified()
|
||||
.use(markdown)
|
||||
.use(remark2rehype, { allowDangerousHTML: true })
|
||||
.use(raw)
|
||||
.use(html);
|
||||
|
||||
function mdToHTML(str) {
|
||||
return processor.processSync(str).toString();
|
||||
}
|
||||
|
||||
function plugin() {
|
||||
return transformer;
|
||||
@ -11,6 +26,12 @@ function plugin() {
|
||||
const { lang, value } = node;
|
||||
if (lang === 'yml') {
|
||||
const tests = YAML.load(value);
|
||||
if (tests.question) {
|
||||
tests.question.answers = tests.question.answers.map(answer =>
|
||||
mdToHTML(answer)
|
||||
);
|
||||
tests.question.text = mdToHTML(tests.question.text);
|
||||
}
|
||||
file.data = {
|
||||
...file.data,
|
||||
...tests
|
||||
@ -21,3 +42,4 @@ function plugin() {
|
||||
}
|
||||
|
||||
module.exports = plugin;
|
||||
module.exports.mdToHTML = mdToHTML;
|
||||
|
@ -1,7 +1,23 @@
|
||||
/* global describe it expect beforeEach */
|
||||
const mockAST = require('./fixtures/challenge-md-ast.json');
|
||||
const mockVideoAST = require('./fixtures/video-challenge-md-ast.json');
|
||||
const testsToData = require('./tests-to-data');
|
||||
|
||||
const { mdToHTML } = testsToData;
|
||||
|
||||
describe('mdToHTML', () => {
|
||||
it('converts Markdown to HTML', () => {
|
||||
// a line of text on its own is parsed as a paragraph, hence the p tags
|
||||
expect(mdToHTML('*it*')).toBe('<p><em>it</em></p>');
|
||||
});
|
||||
|
||||
it('preserves code language', () => {
|
||||
expect(mdToHTML('```js\n var x = "y";\n```')).toBe(
|
||||
'<pre><code class="language-js"> var x = "y";\n</code></pre>'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('tests-to-data plugin', () => {
|
||||
const plugin = testsToData();
|
||||
let file = { data: {} };
|
||||
@ -29,8 +45,40 @@ describe('tests-to-data plugin', () => {
|
||||
expect(testObject).toHaveProperty('text');
|
||||
});
|
||||
|
||||
it('should generate a question object from a video challenge AST', () => {
|
||||
expect.assertions(4);
|
||||
plugin(mockVideoAST, file);
|
||||
const testObject = file.data.question;
|
||||
expect(Object.keys(testObject).length).toBe(3);
|
||||
expect(testObject).toHaveProperty('text');
|
||||
expect(testObject).toHaveProperty('solution');
|
||||
expect(testObject).toHaveProperty('answers');
|
||||
});
|
||||
|
||||
it('should convert question and answer markdown into html', () => {
|
||||
plugin(mockVideoAST, file);
|
||||
const testObject = file.data.question;
|
||||
expect(Object.keys(testObject).length).toBe(3);
|
||||
expect(testObject.text).toBe(
|
||||
'<p>Question line one</p>\n' +
|
||||
`<pre><code class="language-js"> var x = 'y';\n` +
|
||||
'</code></pre>'
|
||||
);
|
||||
expect(testObject.solution).toBe(3);
|
||||
expect(testObject.answers[0]).toBe('<p>inline <code>code</code></p>');
|
||||
expect(testObject.answers[1]).toBe('<p>some <em>italics</em></p>');
|
||||
expect(testObject.answers[2]).toBe(
|
||||
'<p><code> code in </code> code tags</p>'
|
||||
);
|
||||
});
|
||||
|
||||
it('should have an output to match the snapshot', () => {
|
||||
plugin(mockAST, file);
|
||||
expect(file.data).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match the video snapshot', () => {
|
||||
plugin(mockVideoAST, file);
|
||||
expect(file.data).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
Reference in New Issue
Block a user