refactor: remove remains of old parser

This commit is contained in:
Oliver Eyton-Williams
2021-02-03 10:42:14 +01:00
committed by Mrugesh Mohapatra
parent 2c7efe50fd
commit 9ff3a29a72
26 changed files with 323 additions and 5381 deletions

View File

@ -1,3 +0,0 @@
__snapshots__
fixtures
*.test.js

View File

@ -1,24 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`challengeSeed-to-data plugin should have an output to match the snapshot 1`] = `
Object {
"files": Object {
"indexjs": Object {
"contents": "function testFunction(arg) {
return arg;
}
testFunction('hello');
",
"editableRegionBoundaries": Array [],
"ext": "js",
"head": "console.log('before the test');
",
"key": "indexjs",
"name": "index",
"tail": "console.info('after the test');
",
},
},
}
`;

View File

@ -1,10 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`frontmatter-to-data plugin should have an output to match the snapshot 1`] = `
Object {
"challengeType": 0,
"id": "bd7123c8c441eddfaeb5bdef",
"title": "Say Hello to HTML Elements",
"videoUrl": "https://scrimba.com/p/pVMPUv/cE8Gpt2",
}
`;

View File

@ -1,23 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`challengeSeed-to-data plugin should have an output to match the snapshot 1`] = `
Object {
"solutions": Array [
Object {
"indexjs": Object {
"contents": "function testFunction(arg) {
return arg;
}
testFunction('hello');
",
"ext": "js",
"head": "",
"key": "indexjs",
"name": "index",
"tail": "",
},
},
],
}
`;

View File

@ -1,28 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`tests-to-data plugin should have an output to match the snapshot 1`] = `
Object {
"tests": Array [
Object {
"testString": "assert.isTrue((/hello(\\\\s)+world/gi).test($('h1').text()), 'Your <code>h1</code> element should have the text \\"Hello World\\".');",
"text": "<p>Your <code>h1</code> element should have the text \\"Hello World\\".</p>",
},
],
}
`;
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>",
},
}
`;

View File

@ -1,17 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`text-to-data should have an output to match the snapshot 1`] = `
Object {
"description": "<section id=\\"description\\">
<p>Welcome to freeCodeCamp's HTML coding challenges. These will walk you through web development step-by-step.</p>
<p>Lorem Ipsum with <code>some code</code></p>
<p><blockquote>
<p>Some text in a blockquote</p>
<p>Some text in a blockquote, with <code>code</code></p>
</blockquote></p>
<p><pre><code class=\\"language-html\\">&#x3C;p>We aim to preserve this&#x3C;/p>
</code></pre></p>
</section>",
"instructions": "",
}
`;

View File

@ -1,124 +0,0 @@
const visit = require('unist-util-visit');
const { selectAll, select } = require('hast-util-select');
const { sectionFilter } = require('./utils');
const seedRE = /(.+)-seed$/;
const headRE = /(.+)-setup$/;
const tailRE = /(.+)-teardown$/;
const editableRegionMarker = '--fcc-editable-region--';
function defaultFile(lang) {
return {
key: `index${lang}`,
ext: lang,
name: 'index',
contents: '',
head: '',
tail: ''
};
}
function createCodeGetter(codeKey, regEx, seeds) {
return container => {
const {
properties: { id }
} = container;
const lang = id.match(regEx)[1];
const key = `index${lang}`;
const code = select('code', container).children[0].value;
if (key in seeds) {
seeds[key] = {
...seeds[key],
[codeKey]: code
};
} else {
seeds[key] = {
...defaultFile(lang),
[codeKey]: code
};
}
};
}
// TODO: any reason to worry about CRLF?
function findRegionMarkers(file) {
const lines = file.contents.split('\n');
const editableLines = lines
.map((line, id) => (line.trim() === editableRegionMarker ? id : -1))
.filter(id => id >= 0);
if (editableLines.length > 2) {
throw Error('Editable region has too many markers' + editableLines);
}
if (editableLines.length === 0) {
return null;
} else if (editableLines.length === 1) {
throw Error(`Editable region not closed`);
} else {
return editableLines;
}
}
function removeLines(contents, toRemove) {
const lines = contents.split('\n');
return lines.filter((_, id) => !toRemove.includes(id)).join('\n');
}
function createPlugin() {
return function transformer(tree, file) {
function visitor(node) {
if (sectionFilter(node, 'challengeSeed')) {
let seeds = {};
const codeDivs = selectAll('div', node);
const seedContainers = codeDivs.filter(({ properties: { id } }) =>
seedRE.test(id)
);
seedContainers.forEach(createCodeGetter('contents', seedRE, seeds));
const headContainers = codeDivs.filter(({ properties: { id } }) =>
headRE.test(id)
);
headContainers.forEach(createCodeGetter('head', headRE, seeds));
const tailContainers = codeDivs.filter(({ properties: { id } }) =>
tailRE.test(id)
);
tailContainers.forEach(createCodeGetter('tail', tailRE, seeds));
file.data = {
...file.data,
files: seeds
};
// TODO: make this readable.
Object.keys(seeds).forEach(key => {
const fileData = seeds[key];
const editRegionMarkers = findRegionMarkers(fileData);
if (editRegionMarkers) {
fileData.contents = removeLines(
fileData.contents,
editRegionMarkers
);
if (editRegionMarkers[1] <= editRegionMarkers[0]) {
throw Error('Editable region must be non zero');
}
fileData.editableRegionBoundaries = editRegionMarkers;
} else {
fileData.editableRegionBoundaries = [];
}
});
// TODO: TESTS!
}
}
visit(tree, 'element', visitor);
};
}
exports.challengeSeedToData = createPlugin;
exports.createCodeGetter = createCodeGetter;
exports.defaultFile = defaultFile;

View File

@ -1,58 +0,0 @@
/* global describe it expect beforeEach */
const isArray = require('lodash/isArray');
const mockAST = require('./fixtures/challenge-html-ast.json');
const { challengeSeedToData } = require('./challengeSeed-to-data');
const { isObject } = require('lodash');
describe('challengeSeed-to-data plugin', () => {
const plugin = challengeSeedToData();
let file = { data: {} };
beforeEach(() => {
file = { data: {} };
});
it('returns a function', () => {
expect(typeof plugin).toEqual('function');
});
it('adds a `files` property to `file.data`', () => {
plugin(mockAST, file);
expect('files' in file.data).toBe(true);
});
it('ensures that the `files` property is an object', () => {
plugin(mockAST, file);
expect(isObject(file.data.files)).toBe(true);
});
it('adds test objects to the files array following a schema', () => {
expect.assertions(15);
plugin(mockAST, file);
const {
data: { files }
} = file;
const testObject = files.indexjs;
expect(Object.keys(testObject).length).toEqual(7);
expect(testObject).toHaveProperty('key');
expect(typeof testObject['key']).toBe('string');
expect(testObject).toHaveProperty('ext');
expect(typeof testObject['ext']).toBe('string');
expect(testObject).toHaveProperty('name');
expect(typeof testObject['name']).toBe('string');
expect(testObject).toHaveProperty('contents');
expect(typeof testObject['contents']).toBe('string');
expect(testObject).toHaveProperty('head');
expect(typeof testObject['head']).toBe('string');
expect(testObject).toHaveProperty('tail');
expect(typeof testObject['tail']).toBe('string');
expect(testObject).toHaveProperty('editableRegionBoundaries');
expect(isArray(testObject['editableRegionBoundaries'])).toBe(true);
});
it('should have an output to match the snapshot', () => {
plugin(mockAST, file);
expect(file.data).toMatchSnapshot();
});
});

View File

@ -1,284 +0,0 @@
{
"type": "root",
"children": [{
"type": "element",
"tagName": "h2",
"properties": {},
"children": [{
"type": "text",
"value": "Description",
"position": {
"start": {
"line": 1,
"column": 4,
"offset": 3
},
"end": {
"line": 1,
"column": 15,
"offset": 14
}
}
}],
"position": {
"start": {
"line": 1,
"column": 1,
"offset": 0
},
"end": {
"line": 1,
"column": 15,
"offset": 14
}
}
}, {
"type": "text",
"value": "\n"
}, {
"type": "element",
"tagName": "section",
"properties": {
"id": "description"
},
"children": [{
"type": "text",
"value": "\n",
"position": {
"start": {
"line": 3,
"column": 27,
"offset": 42
},
"end": {
"line": 4,
"column": 1,
"offset": 43
}
}
}, {
"type": "element",
"tagName": "code",
"properties": {},
"children": [{
"type": "text",
"value": "code",
"position": {
"start": {
"line": 4,
"column": 7,
"offset": 49
},
"end": {
"line": 4,
"column": 11,
"offset": 53
}
}
}],
"position": {
"start": {
"line": 4,
"column": 1,
"offset": 43
},
"end": {
"line": 4,
"column": 18,
"offset": 60
}
}
}, {
"type": "text",
"value": " ",
"position": {
"start": {
"line": 4,
"column": 18,
"offset": 60
},
"end": {
"line": 4,
"column": 19,
"offset": 61
}
}
}, {
"type": "element",
"tagName": "tag",
"properties": {},
"children": [{
"type": "text",
"value": "with more after a space",
"position": {
"start": {
"line": 4,
"column": 24,
"offset": 66
},
"end": {
"line": 4,
"column": 47,
"offset": 89
}
}
}],
"position": {
"start": {
"line": 4,
"column": 19,
"offset": 61
},
"end": {
"line": 4,
"column": 53,
"offset": 95
}
}
}, {
"type": "text",
"value": "\n"
}, {
"type": "element",
"tagName": "p",
"properties": {},
"children": [{
"type": "text",
"value": "after many new lines another pair of ",
"position": {
"start": {
"line": 9,
"column": 1,
"offset": 100
},
"end": {
"line": 9,
"column": 38,
"offset": 137
}
}
}, {
"type": "element",
"tagName": "strong",
"properties": {},
"children": [{
"type": "text",
"value": "elements",
"position": {
"start": {
"line": 9,
"column": 46,
"offset": 145
},
"end": {
"line": 9,
"column": 54,
"offset": 153
}
}
}],
"position": {
"start": {
"line": 9,
"column": 38,
"offset": 137
},
"end": {
"line": 9,
"column": 63,
"offset": 162
}
}
}, {
"type": "text",
"value": " ",
"position": {
"start": {
"line": 9,
"column": 63,
"offset": 162
},
"end": {
"line": 9,
"column": 64,
"offset": 163
}
}
}, {
"type": "element",
"tagName": "em",
"properties": {},
"children": [{
"type": "text",
"value": "with a space",
"position": {
"start": {
"line": 9,
"column": 68,
"offset": 167
},
"end": {
"line": 9,
"column": 80,
"offset": 179
}
}
}],
"position": {
"start": {
"line": 9,
"column": 64,
"offset": 163
},
"end": {
"line": 9,
"column": 85,
"offset": 184
}
}
}],
"position": {
"start": {
"line": 9,
"column": 1,
"offset": 100
},
"end": {
"line": 9,
"column": 85,
"offset": 184
}
}
}, {
"type": "text",
"value": "\n"
}],
"position": {
"start": {
"line": 3,
"column": 1,
"offset": 16
},
"end": {
"line": 10,
"column": 11,
"offset": 195
}
}
}],
"data": {
"quirksMode": false
},
"position": {
"start": {
"line": 1,
"column": 1,
"offset": 0
},
"end": {
"line": 1,
"column": 1,
"offset": 0
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,915 +0,0 @@
{
"type": "root",
"children": [
{
"type": "yaml",
"value":
"id: bd7123c8c441eddfaeb5bdef\ntitle: Say Hello to HTML Elements\nchallengeType: 0\nvideoUrl: https://scrimba.com/p/pVMPUv/cE8Gpt2",
"position": {
"start": {
"line": 1,
"column": 1,
"offset": 0
},
"end": {
"line": 6,
"column": 4,
"offset": 134
},
"indent": [1, 1, 1, 1, 1]
}
},
{
"type": "heading",
"depth": 2,
"children": [
{
"type": "text",
"value": "Description",
"position": {
"start": {
"line": 8,
"column": 4,
"offset": 139
},
"end": {
"line": 8,
"column": 15,
"offset": 150
},
"indent": []
}
}
],
"position": {
"start": {
"line": 8,
"column": 1,
"offset": 136
},
"end": {
"line": 8,
"column": 15,
"offset": 150
},
"indent": []
}
},
{
"type": "html",
"value": "<section id='description'>",
"position": {
"start": {
"line": 9,
"column": 1,
"offset": 151
},
"end": {
"line": 9,
"column": 27,
"offset": 177
},
"indent": []
}
},
{
"type": "paragraph",
"children": [
{
"type": "text",
"value":
"Welcome to freeCodeCamp's HTML coding challenges. These will walk you through web development step-by-step.",
"position": {
"start": {
"line": 11,
"column": 1,
"offset": 179
},
"end": {
"line": 11,
"column": 108,
"offset": 286
},
"indent": []
}
}
],
"position": {
"start": {
"line": 11,
"column": 1,
"offset": 179
},
"end": {
"line": 11,
"column": 108,
"offset": 286
},
"indent": []
}
},
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "Lorem Ipsum with ",
"position": {
"start": {
"line": 13,
"column": 1,
"offset": 288
},
"end": {
"line": 13,
"column": 18,
"offset": 305
},
"indent": []
}
},
{
"type": "inlineCode",
"value": "some code",
"position": {
"start": {
"line": 13,
"column": 18,
"offset": 305
},
"end": {
"line": 13,
"column": 29,
"offset": 316
},
"indent": []
}
}
],
"position": {
"start": {
"line": 13,
"column": 1,
"offset": 288
},
"end": {
"line": 13,
"column": 29,
"offset": 316
},
"indent": []
}
},
{
"type": "blockquote",
"children": [
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "Some text in a blockquote",
"position": {
"start": {
"line": 15,
"column": 3,
"offset": 320
},
"end": {
"line": 15,
"column": 28,
"offset": 345
},
"indent": []
}
}
],
"position": {
"start": {
"line": 15,
"column": 3,
"offset": 320
},
"end": {
"line": 15,
"column": 28,
"offset": 345
},
"indent": []
}
},
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "Some text in a blockquote, with ",
"position": {
"start": {
"line": 17,
"column": 3,
"offset": 349
},
"end": {
"line": 17,
"column": 35,
"offset": 381
},
"indent": []
}
},
{
"type": "inlineCode",
"value": "code",
"position": {
"start": {
"line": 17,
"column": 35,
"offset": 381
},
"end": {
"line": 17,
"column": 41,
"offset": 387
},
"indent": []
}
}
],
"position": {
"start": {
"line": 17,
"column": 3,
"offset": 349
},
"end": {
"line": 17,
"column": 41,
"offset": 387
},
"indent": []
}
}
],
"position": {
"start": {
"line": 15,
"column": 1,
"offset": 318
},
"end": {
"line": 17,
"column": 41,
"offset": 387
},
"indent": [1, 1]
}
},
{
"type": "code",
"lang": "html",
"value": "<p>We aim to preserve this</p>",
"position": {
"start": {
"line": 19,
"column": 1,
"offset": 389
},
"end": {
"line": 21,
"column": 4,
"offset": 431
},
"indent": [1, 1]
}
},
{
"type": "html",
"value": "</section>",
"position": {
"start": {
"line": 22,
"column": 1,
"offset": 432
},
"end": {
"line": 22,
"column": 11,
"offset": 442
},
"indent": []
}
},
{
"type": "heading",
"depth": 2,
"children": [
{
"type": "text",
"value": "Instructions",
"position": {
"start": {
"line": 24,
"column": 4,
"offset": 447
},
"end": {
"line": 24,
"column": 16,
"offset": 459
},
"indent": []
}
}
],
"position": {
"start": {
"line": 24,
"column": 1,
"offset": 444
},
"end": {
"line": 24,
"column": 16,
"offset": 459
},
"indent": []
}
},
{
"type": "html",
"value": "<section id='instructions'>",
"position": {
"start": {
"line": 25,
"column": 1,
"offset": 460
},
"end": {
"line": 25,
"column": 28,
"offset": 487
},
"indent": []
}
},
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "To pass the test on this challenge, change your ",
"position": {
"start": {
"line": 27,
"column": 1,
"offset": 489
},
"end": {
"line": 27,
"column": 49,
"offset": 537
},
"indent": []
}
},
{
"type": "inlineCode",
"value": "h1",
"position": {
"start": {
"line": 27,
"column": 49,
"offset": 537
},
"end": {
"line": 27,
"column": 53,
"offset": 541
},
"indent": []
}
},
{
"type": "text",
"value": " element's text to say \"Hello World\".",
"position": {
"start": {
"line": 27,
"column": 53,
"offset": 541
},
"end": {
"line": 27,
"column": 90,
"offset": 578
},
"indent": []
}
}
],
"position": {
"start": {
"line": 27,
"column": 1,
"offset": 489
},
"end": {
"line": 27,
"column": 90,
"offset": 578
},
"indent": []
}
},
{
"type": "html",
"value": "</section>",
"position": {
"start": {
"line": 29,
"column": 1,
"offset": 580
},
"end": {
"line": 29,
"column": 11,
"offset": 590
},
"indent": []
}
},
{
"type": "heading",
"depth": 2,
"children": [
{
"type": "text",
"value": "Tests",
"position": {
"start": {
"line": 31,
"column": 4,
"offset": 595
},
"end": {
"line": 31,
"column": 9,
"offset": 600
},
"indent": []
}
}
],
"position": {
"start": {
"line": 31,
"column": 1,
"offset": 592
},
"end": {
"line": 31,
"column": 9,
"offset": 600
},
"indent": []
}
},
{
"type": "html",
"value": "<section id='tests'>",
"position": {
"start": {
"line": 32,
"column": 1,
"offset": 601
},
"end": {
"line": 32,
"column": 21,
"offset": 621
},
"indent": []
}
},
{
"type": "code",
"lang": "yml",
"value":
"tests:\n - text: Your <code>h1</code> element should have the text \"Hello World\".\n testString: assert.isTrue((/hello(\\s)+world/gi).test($('h1').text()), 'Your <code>h1</code> element should have the text \"Hello World\".');",
"position": {
"start": {
"line": 34,
"column": 1,
"offset": 623
},
"end": {
"line": 38,
"column": 4,
"offset": 858
},
"indent": [1, 1, 1, 1]
}
},
{
"type": "html",
"value": "</section>",
"position": {
"start": {
"line": 40,
"column": 1,
"offset": 860
},
"end": {
"line": 40,
"column": 11,
"offset": 870
},
"indent": []
}
},
{
"type": "heading",
"depth": 2,
"children": [
{
"type": "text",
"value": "Challenge Seed",
"position": {
"start": {
"line": 42,
"column": 4,
"offset": 875
},
"end": {
"line": 42,
"column": 18,
"offset": 889
},
"indent": []
}
}
],
"position": {
"start": {
"line": 42,
"column": 1,
"offset": 872
},
"end": {
"line": 42,
"column": 18,
"offset": 889
},
"indent": []
}
},
{
"type": "html",
"value": "<section id='challengeSeed'>",
"position": {
"start": {
"line": 43,
"column": 1,
"offset": 890
},
"end": {
"line": 43,
"column": 29,
"offset": 918
},
"indent": []
}
},
{
"type": "html",
"value": "<div id='js-seed'>",
"position": {
"start": {
"line": 45,
"column": 1,
"offset": 920
},
"end": {
"line": 45,
"column": 19,
"offset": 938
},
"indent": []
}
},
{
"type": "code",
"lang": "js",
"value":
"function testFunction(arg) {\n return arg;\n}\n\ntestFunction('hello');",
"position": {
"start": {
"line": 47,
"column": 1,
"offset": 940
},
"end": {
"line": 53,
"column": 4,
"offset": 1018
},
"indent": [1, 1, 1, 1, 1, 1]
}
},
{
"type": "html",
"value": "</div>",
"position": {
"start": {
"line": 55,
"column": 1,
"offset": 1020
},
"end": {
"line": 55,
"column": 7,
"offset": 1026
},
"indent": []
}
},
{
"type": "heading",
"depth": 3,
"children": [
{
"type": "text",
"value": "Before Test",
"position": {
"start": {
"line": 57,
"column": 5,
"offset": 1032
},
"end": {
"line": 57,
"column": 16,
"offset": 1043
},
"indent": []
}
}
],
"position": {
"start": {
"line": 57,
"column": 1,
"offset": 1028
},
"end": {
"line": 57,
"column": 16,
"offset": 1043
},
"indent": []
}
},
{
"type": "html",
"value": "<div id='js-setup'>",
"position": {
"start": {
"line": 58,
"column": 1,
"offset": 1044
},
"end": {
"line": 58,
"column": 20,
"offset": 1063
},
"indent": []
}
},
{
"type": "code",
"lang": "js",
"value": "console.log('before the test');",
"position": {
"start": {
"line": 60,
"column": 1,
"offset": 1065
},
"end": {
"line": 62,
"column": 4,
"offset": 1106
},
"indent": [1, 1]
}
},
{
"type": "html",
"value": "</div>",
"position": {
"start": {
"line": 64,
"column": 1,
"offset": 1108
},
"end": {
"line": 64,
"column": 7,
"offset": 1114
},
"indent": []
}
},
{
"type": "heading",
"depth": 3,
"children": [
{
"type": "text",
"value": "After Test",
"position": {
"start": {
"line": 66,
"column": 5,
"offset": 1120
},
"end": {
"line": 66,
"column": 15,
"offset": 1130
},
"indent": []
}
}
],
"position": {
"start": {
"line": 66,
"column": 1,
"offset": 1116
},
"end": {
"line": 66,
"column": 15,
"offset": 1130
},
"indent": []
}
},
{
"type": "html",
"value": "<div id='js-teardown'>",
"position": {
"start": {
"line": 67,
"column": 1,
"offset": 1131
},
"end": {
"line": 67,
"column": 23,
"offset": 1153
},
"indent": []
}
},
{
"type": "code",
"lang": "js",
"value": "console.info('after the test');",
"position": {
"start": {
"line": 69,
"column": 1,
"offset": 1155
},
"end": {
"line": 71,
"column": 4,
"offset": 1196
},
"indent": [1, 1]
}
},
{
"type": "html",
"value": "</div>\n</section>",
"position": {
"start": {
"line": 73,
"column": 1,
"offset": 1198
},
"end": {
"line": 74,
"column": 11,
"offset": 1215
},
"indent": [1]
}
},
{
"type": "heading",
"depth": 2,
"children": [
{
"type": "text",
"value": "Solution",
"position": {
"start": {
"line": 76,
"column": 4,
"offset": 1220
},
"end": {
"line": 76,
"column": 12,
"offset": 1228
},
"indent": []
}
}
],
"position": {
"start": {
"line": 76,
"column": 1,
"offset": 1217
},
"end": {
"line": 76,
"column": 12,
"offset": 1228
},
"indent": []
}
},
{
"type": "html",
"value": "<section id='solution'>",
"position": {
"start": {
"line": 77,
"column": 1,
"offset": 1229
},
"end": {
"line": 77,
"column": 24,
"offset": 1252
},
"indent": []
}
},
{
"type": "code",
"lang": "js",
"value":
"function testFunction(arg) {\n return arg;\n}\n\ntestFunction('hello');",
"position": {
"start": {
"line": 79,
"column": 1,
"offset": 1254
},
"end": {
"line": 85,
"column": 4,
"offset": 1332
},
"indent": [1, 1, 1, 1, 1, 1]
}
},
{
"type": "html",
"value": "</section>",
"position": {
"start": {
"line": 86,
"column": 1,
"offset": 1333
},
"end": {
"line": 86,
"column": 11,
"offset": 1343
},
"indent": []
}
}
],
"position": {
"start": {
"line": 1,
"column": 1,
"offset": 0
},
"end": {
"line": 86,
"column": 11,
"offset": 1343
}
}
}

View File

@ -1,197 +0,0 @@
{
"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
}
}
}

View File

@ -1,18 +0,0 @@
const visit = require('unist-util-visit');
const YAML = require('js-yaml');
function plugin() {
return transformer;
function transformer(tree, file) {
visit(tree, 'yaml', visitor);
function visitor(node) {
const frontmatter = YAML.load(node.value);
file.data = { ...file.data, ...frontmatter };
}
}
}
module.exports = plugin;

View File

@ -1,62 +0,0 @@
/* global describe it expect beforeEach */
const { isObject } = require('lodash');
const mockAST = require('./fixtures/challenge-md-ast.json');
const frontmatterToData = require('./frontmatter-to-data');
describe('frontmatter-to-data plugin', () => {
const plugin = frontmatterToData();
let file = { data: {} };
beforeEach(() => {
file = { data: {} };
});
it('should return a plugin which is a function', () => {
expect(typeof plugin).toEqual('function');
});
it('should maintain an object for the `file.data` property', () => {
plugin(mockAST, file);
expect(isObject(file.data)).toBe(true);
});
it('should add all keys from frontmatter to the `file.data` property', () => {
const expectedKeys = ['id', 'title', 'challengeType', 'videoUrl'];
plugin(mockAST, file);
const actualKeys = Object.keys(file.data);
expect(actualKeys).toEqual(expectedKeys);
});
it('should not mutate any type held in the frontmatter', () => {
expect.assertions(4);
plugin(mockAST, file);
const { id, title, challengeType, videoUrl } = file.data;
expect(typeof id).toEqual('string');
expect(typeof title).toEqual('string');
expect(typeof challengeType).toEqual('number');
expect(typeof videoUrl).toEqual('string');
});
it('should trim extra whitespace from keys and values', () => {
expect.assertions(7);
plugin(mockAST, file);
const whitespaceRE = /(^\s\S+|\S\s$)/;
const keys = Object.keys(file.data);
keys.forEach(key => expect(whitespaceRE.test(key)).toBe(false));
const values = keys.map(key => file.data[key]);
values
.filter(value => typeof value === 'string')
.forEach(value => expect(whitespaceRE.test(value)).toBe(false));
});
it('should not mutate url strings', () => {
const expectedUrl = 'https://scrimba.com/p/pVMPUv/cE8Gpt2';
plugin(mockAST, file);
expect(file.data.videoUrl).toEqual(expectedUrl);
});
it('should have an output to match the snapshot', () => {
plugin(mockAST, file);
expect(file.data).toMatchSnapshot();
});
});

View File

@ -1,40 +0,0 @@
const unified = require('unified');
const vfile = require('to-vfile');
const markdown = require('remark-parse');
const remark2rehype = require('remark-rehype');
const html = require('rehype-stringify');
const frontmatter = require('remark-frontmatter');
const raw = require('rehype-raw');
const frontmatterToData = require('./frontmatter-to-data');
const textToData = require('./text-to-data');
const testsToData = require('./tests-to-data');
const { challengeSeedToData } = require('./challengeSeed-to-data');
const solutionsToData = require('./solution-to-data');
const processor = unified()
.use(markdown)
.use(frontmatter, ['yaml'])
.use(frontmatterToData)
.use(testsToData)
.use(remark2rehype, { allowDangerousHTML: true })
.use(raw)
.use(solutionsToData)
.use(textToData, ['description', 'instructions'])
.use(challengeSeedToData)
// the plugins below are just to stop the processor from throwing
// we need to write a compiler that can create graphql nodes
.use(html);
exports.parseMarkdown = function parseMarkdown(filename) {
return new Promise((resolve, reject) =>
processor.process(vfile.readSync(filename), function(err, file) {
if (err) {
err.message += ' in file ' + filename;
reject(err);
}
delete file.contents;
return resolve(file.data);
})
);
};

File diff suppressed because it is too large Load Diff

View File

@ -1,40 +1,37 @@
{
"name": "@freecodecamp/challenge-parser",
"version": "2.0.0",
"description": "",
"name": "challenge-parser",
"version": "0.0.1",
"description": "converts mdx files to challenge objects",
"main": "index.js",
"publishConfig": {
"access": "public"
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"devDependencies": {
"unist-util-select": "^3.0.1"
},
"dependencies": {
"hast-util-select": "^2.1.0",
"hast-util-to-html": "^7.1.1",
"js-yaml": "^3.12.0",
"lodash": "^4.17.20",
"lodash": "^4.17.19",
"mdast-builder": "^1.1.1",
"mdast-util-gfm": "^0.1.0",
"mdast-util-to-hast": "^9.1.1",
"rehype-raw": "^3.0.0",
"rehype-stringify": "^4.0.0",
"remark": "^12.0.1",
"remark-frontmatter": "^1.3.3",
"micromark-extension-gfm-strikethrough": "^0.6.1",
"micromark-extension-gfm-table": "^0.4.1",
"remark": "^13.0.0",
"remark-directive": "^1.0.1",
"remark-frontmatter": "^3.0.0",
"remark-html": "^12.0.0",
"remark-mdx": "^1.6.14",
"remark-parse": "^5.0.0",
"remark-rehype": "^3.0.2",
"remark-stringify": "^6.0.4",
"to-vfile": "^6.1.0",
"unified": "^7.1.0",
"remark-parse": "^9.0.0",
"to-vfile": "^5.0.1",
"unified": "^7.0.0",
"unist-util-find": "^1.0.1",
"unist-util-find-after": "^3.0.0",
"unist-util-find-all-after": "^3.0.1",
"unist-util-find-all-between": "^2.0.0",
"unist-util-is": "^4.0.2",
"unist-util-modify-children": "^2.0.0",
"unist-util-position": "^3.1.0",
"unist-util-remove": "^2.0.0",
"unist-util-visit": "^2.0.3",
"unist-util-visit-children": "^1.1.4"

View File

@ -1,997 +0,0 @@
{
"name": "challenge-mdx-parser",
"version": "0.0.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@types/mdast": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.3.tgz",
"integrity": "sha512-SXPBMnFVQg1s00dlMCc/jCdvPqdE4mXaMMCeRlxLDmTAEoegHT53xKtkDnzDTOcmMHUfcjyf36/YYZ6SxRdnsw==",
"requires": {
"@types/unist": "*"
}
},
"@types/node": {
"version": "14.11.10",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.10.tgz",
"integrity": "sha512-yV1nWZPlMFpoXyoknm4S56y2nlTAuFYaJuQtYRAOU7xA/FJ9RY0Xm7QOkaYMMmr8ESdHIuUb6oQgR/0+2NqlyA=="
},
"@types/unist": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz",
"integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ=="
},
"@types/vfile": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@types/vfile/-/vfile-3.0.2.tgz",
"integrity": "sha512-b3nLFGaGkJ9rzOcuXRfHkZMdjsawuDD0ENL9fzTophtBg8FJHSGbH7daXkEpcwy3v7Xol3pAvsmlYyFhR4pqJw==",
"requires": {
"@types/node": "*",
"@types/unist": "*",
"@types/vfile-message": "*"
}
},
"@types/vfile-message": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@types/vfile-message/-/vfile-message-2.0.0.tgz",
"integrity": "sha512-GpTIuDpb9u4zIO165fUy9+fXcULdD8HFRNli04GehoMVbeNq7D6OBnqSmg3lxZnC+UvgUhEWKxdKiwYUkGltIw==",
"requires": {
"vfile-message": "*"
}
},
"argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"requires": {
"sprintf-js": "~1.0.2"
}
},
"array-iterate": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-1.1.4.tgz",
"integrity": "sha512-sNRaPGh9nnmdC8Zf+pT3UqP8rnWj5Hf9wiFGsX3wUQ2yVSIhO2ShFwCoceIPpB41QF6i2OEmrHmCo36xronCVA=="
},
"bail": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz",
"integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ=="
},
"boolbase": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
"dev": true
},
"ccount": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.5.tgz",
"integrity": "sha512-MOli1W+nfbPLlKEhInaxhRdp7KVLFxLN5ykwzHgLsLI3H3gs5jjFAK4Eoj3OzzcxCtumDaI8onoVDeQyWaNTkw=="
},
"character-entities": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz",
"integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw=="
},
"character-entities-html4": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.4.tgz",
"integrity": "sha512-HRcDxZuZqMx3/a+qrzxdBKBPUpxWEq9xw2OPZ3a/174ihfrQKVsFhqtthBInFy1zZ9GgZyFXOatNujm8M+El3g=="
},
"character-entities-legacy": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz",
"integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA=="
},
"character-reference-invalid": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz",
"integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg=="
},
"collapse-white-space": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz",
"integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ=="
},
"comma-separated-tokens": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz",
"integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw=="
},
"css-selector-parser": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/css-selector-parser/-/css-selector-parser-1.4.1.tgz",
"integrity": "sha512-HYPSb7y/Z7BNDCOrakL4raGO2zltZkbeXyAd6Tg9obzix6QhzxCotdBl6VT0Dv4vZfJGVz3WL/xaEI9Ly3ul0g==",
"dev": true
},
"debug": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
"integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
"requires": {
"ms": "2.1.2"
}
},
"esprima": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
},
"extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
},
"fault": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/fault/-/fault-1.0.4.tgz",
"integrity": "sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==",
"requires": {
"format": "^0.2.0"
}
},
"format": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz",
"integrity": "sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs="
},
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
},
"has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"requires": {
"function-bind": "^1.1.1"
}
},
"hast-util-is-element": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-1.1.0.tgz",
"integrity": "sha512-oUmNua0bFbdrD/ELDSSEadRVtWZOf3iF6Lbv81naqsIV99RnSCieTbWuWCY8BAeEfKJTKl0gRdokv+dELutHGQ=="
},
"hast-util-sanitize": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-3.0.0.tgz",
"integrity": "sha512-gxsM24ARtuulsrWEj8QtVM6FNeAEHklF/t7TEIWvX1wuQcoAQtJtEUcT8t0os4uxCUqh1epX/gTi8fp8gNKvCA==",
"requires": {
"xtend": "^4.0.0"
}
},
"hast-util-to-html": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-7.1.1.tgz",
"integrity": "sha512-Ujqj0hGuo3dIQKilkbauAv5teOqPvhaSLEgs1lgApFT0812e114KiffV8XfE4ttR8dRPqxNOIJOMu6SKOVOGlg==",
"requires": {
"ccount": "^1.0.0",
"comma-separated-tokens": "^1.0.0",
"hast-util-is-element": "^1.0.0",
"hast-util-whitespace": "^1.0.0",
"html-void-elements": "^1.0.0",
"property-information": "^5.0.0",
"space-separated-tokens": "^1.0.0",
"stringify-entities": "^3.0.1",
"unist-util-is": "^4.0.0",
"xtend": "^4.0.0"
},
"dependencies": {
"property-information": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz",
"integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==",
"requires": {
"xtend": "^4.0.0"
}
}
}
},
"hast-util-whitespace": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-1.0.4.tgz",
"integrity": "sha512-I5GTdSfhYfAPNztx2xJRQpG8cuDSNt599/7YUn7Gx/WxNMsG+a835k97TDkFgk123cwjfwINaZknkKkphx/f2A=="
},
"html-void-elements": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.5.tgz",
"integrity": "sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w=="
},
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"is-alphabetical": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz",
"integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg=="
},
"is-alphanumerical": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz",
"integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==",
"requires": {
"is-alphabetical": "^1.0.0",
"is-decimal": "^1.0.0"
}
},
"is-buffer": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz",
"integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A=="
},
"is-decimal": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz",
"integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw=="
},
"is-hexadecimal": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz",
"integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw=="
},
"is-plain-obj": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
"integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA=="
},
"js-yaml": {
"version": "3.14.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz",
"integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==",
"requires": {
"argparse": "^1.0.7",
"esprima": "^4.0.0"
}
},
"lodash": {
"version": "4.17.20",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
},
"lodash.iteratee": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/lodash.iteratee/-/lodash.iteratee-4.7.0.tgz",
"integrity": "sha1-vkF32yiajMw8CZDx2ya1si/BVUw="
},
"longest-streak": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.4.tgz",
"integrity": "sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg=="
},
"markdown-table": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz",
"integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==",
"requires": {
"repeat-string": "^1.0.0"
}
},
"mdast-builder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/mdast-builder/-/mdast-builder-1.1.1.tgz",
"integrity": "sha512-a3KBk/LmYD6wKsWi8WJrGU/rXR4yuF4Men0JO0z6dSZCm5FrXXWTRDjqK0vGSqa+1M6p9edeuypZAZAzSehTUw==",
"requires": {
"@types/unist": "^2.0.3"
}
},
"mdast-util-definitions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-3.0.1.tgz",
"integrity": "sha512-BAv2iUm/e6IK/b2/t+Fx69EL/AGcq/IG2S+HxHjDJGfLJtd6i9SZUS76aC9cig+IEucsqxKTR0ot3m933R3iuA==",
"requires": {
"unist-util-visit": "^2.0.0"
}
},
"mdast-util-directive": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/mdast-util-directive/-/mdast-util-directive-1.0.0.tgz",
"integrity": "sha512-04nOvmHrQfcgPQDAn9x0gW05vhqXmkGPP9G7o8BE+7Oy16oyTAgJpJyVFTscPyEzfsP7p7LSKJAXWqTCBvPjuw==",
"requires": {
"mdast-util-to-markdown": "^0.5.0",
"parse-entities": "^2.0.0",
"repeat-string": "^1.0.0",
"stringify-entities": "^3.1.0",
"unist-util-visit-parents": "^3.0.0"
},
"dependencies": {
"unist-util-visit-parents": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz",
"integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==",
"requires": {
"@types/unist": "^2.0.0",
"unist-util-is": "^4.0.0"
}
}
}
},
"mdast-util-from-markdown": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.0.tgz",
"integrity": "sha512-x9b9ekG2IfeqHSUPhn4+o8SeXqual0/ZHzzugV/cC21L6s1KyKAwIHKBJ1NN9ZstIlY8YAefELRSWfJMby4a9Q==",
"requires": {
"@types/mdast": "^3.0.0",
"mdast-util-to-string": "^1.0.0",
"micromark": "~2.10.0",
"parse-entities": "^2.0.0"
}
},
"mdast-util-frontmatter": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/mdast-util-frontmatter/-/mdast-util-frontmatter-0.2.0.tgz",
"integrity": "sha512-FHKL4w4S5fdt1KjJCwB0178WJ0evnyyQr5kXTM3wrOVpytD0hrkvd+AOOjU9Td8onOejCkmZ+HQRT3CZ3coHHQ==",
"requires": {
"micromark-extension-frontmatter": "^0.2.0"
}
},
"mdast-util-gfm": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-0.1.0.tgz",
"integrity": "sha512-HLfygQL6HdhJhFbLta4Ki9hClrzyAxRjyRvpm5caN65QZL+NyHPmqFlnF9vm1Rn58JT2+AbLwNcEDY4MEvkk8Q==",
"requires": {
"mdast-util-gfm-autolink-literal": "^0.1.0",
"mdast-util-gfm-strikethrough": "^0.2.0",
"mdast-util-gfm-table": "^0.1.0",
"mdast-util-gfm-task-list-item": "^0.1.0"
}
},
"mdast-util-gfm-autolink-literal": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-0.1.1.tgz",
"integrity": "sha512-gJ2xSpqKCetSr22GEWpZH3f5ffb4pPn/72m4piY0v7T/S+O7n7rw+sfoPLhb2b4O7WdnERoYdALRcmD68FMtlw=="
},
"mdast-util-gfm-strikethrough": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-0.2.2.tgz",
"integrity": "sha512-T37ZbaokJcRbHROXmoVAieWnesPD5N21tv2ifYzaGRLbkh1gknItUGhZzHefUn5Zc/eaO/iTDSAFOBrn/E8kWw==",
"requires": {
"mdast-util-to-markdown": "^0.5.0"
}
},
"mdast-util-gfm-table": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-0.1.4.tgz",
"integrity": "sha512-T4xFSON9kUb/IpYA5N+KGWcsdGczAvILvKiXQwUGind6V9fvjPCR9yhZnIeaLdBWXaz3m/Gq77ZtuLMjtFR4IQ==",
"requires": {
"markdown-table": "^2.0.0",
"mdast-util-to-markdown": "^0.5.0"
}
},
"mdast-util-gfm-task-list-item": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-0.1.3.tgz",
"integrity": "sha512-9adbEPNB7oxvwiHErO6v+3D+YyM42G0LHCnBId8trm5mkvjsm8vt9zxo0yGZxih/8luk9uZq8Smf31sDIqrmkA==",
"requires": {
"mdast-util-to-markdown": "^0.5.0"
}
},
"mdast-util-to-hast": {
"version": "9.1.2",
"resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-9.1.2.tgz",
"integrity": "sha512-OpkFLBC2VnNAb2FNKcKWu9FMbJhQKog+FCT8nuKmQNIKXyT1n3SIskE7uWDep6x+cA20QXlK5AETHQtYmQmxtQ==",
"requires": {
"@types/mdast": "^3.0.0",
"@types/unist": "^2.0.0",
"mdast-util-definitions": "^3.0.0",
"mdurl": "^1.0.0",
"unist-builder": "^2.0.0",
"unist-util-generated": "^1.0.0",
"unist-util-position": "^3.0.0",
"unist-util-visit": "^2.0.0"
}
},
"mdast-util-to-markdown": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-0.5.2.tgz",
"integrity": "sha512-kPPJ98HguKsWuUgR1oVR7oyVIdcSmOEYPL2g0rGTkJLDJrV2JSEq+F6b+mPtpQCexmD7Vdd7MES34rQUGCIMTw==",
"requires": {
"@types/unist": "^2.0.0",
"longest-streak": "^2.0.0",
"mdast-util-to-string": "^1.0.0",
"parse-entities": "^2.0.0",
"repeat-string": "^1.0.0",
"zwitch": "^1.0.0"
}
},
"mdast-util-to-string": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.1.0.tgz",
"integrity": "sha512-jVU0Nr2B9X3MU4tSK7JP1CMkSvOj7X5l/GboG1tKRw52lLF1x2Ju92Ms9tNetCcbfX3hzlM73zYo2NKkWSfF/A=="
},
"mdurl": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
"integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4="
},
"micromark": {
"version": "2.10.1",
"resolved": "https://registry.npmjs.org/micromark/-/micromark-2.10.1.tgz",
"integrity": "sha512-fUuVF8sC1X7wsCS29SYQ2ZfIZYbTymp0EYr6sab3idFjigFFjGa5UwoniPlV9tAgntjuapW1t9U+S0yDYeGKHQ==",
"requires": {
"debug": "^4.0.0",
"parse-entities": "^2.0.0"
}
},
"micromark-extension-directive": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-1.0.0.tgz",
"integrity": "sha512-6FjvznI5GpUysZqGtTEMeDaC/D3FdWFVc3CC5gDZB3fBtqiaIRBhCNg4fbqvrFSC0T2eqRbO2dJ7ZFU86gAtEQ==",
"requires": {
"micromark": "~2.10.0",
"parse-entities": "^2.0.0"
}
},
"micromark-extension-frontmatter": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/micromark-extension-frontmatter/-/micromark-extension-frontmatter-0.2.2.tgz",
"integrity": "sha512-q6nPLFCMTLtfsctAuS0Xh4vaolxSFUWUWR6PZSrXXiRy+SANGllpcqdXFv2z07l0Xz/6Hl40hK0ffNCJPH2n1A==",
"requires": {
"fault": "^1.0.0"
}
},
"micromark-extension-gfm-strikethrough": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-0.6.1.tgz",
"integrity": "sha512-2+5qpceAqPysnjM0bpONY/3Jdnt7PJpns7rEtlwoThV2OOE7ReoQ07lYSAL8y/1sW5NnmF8XylvBdSlGsphEpQ==",
"requires": {
"micromark": "~2.10.0"
}
},
"micromark-extension-gfm-table": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-0.4.1.tgz",
"integrity": "sha512-xVpqOnfFaa2OtC/Y7rlt4tdVFlUHdoLH3RXAZgb/KP3DDyKsAOx6BRS3UxiiyvmD/p2l6VUpD4bMIniuP4o4JA==",
"requires": {
"micromark": "~2.10.0"
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"not": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/not/-/not-0.1.0.tgz",
"integrity": "sha1-yWkcF0bFXc++VMvYvU/wQbwrUZ0=",
"dev": true
},
"nth-check": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
"integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==",
"dev": true,
"requires": {
"boolbase": "~1.0.0"
}
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"requires": {
"wrappy": "1"
}
},
"parse-entities": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz",
"integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==",
"requires": {
"character-entities": "^1.0.0",
"character-entities-legacy": "^1.0.0",
"character-reference-invalid": "^1.0.0",
"is-alphanumerical": "^1.0.0",
"is-decimal": "^1.0.0",
"is-hexadecimal": "^1.0.0"
}
},
"remark": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/remark/-/remark-13.0.0.tgz",
"integrity": "sha512-HDz1+IKGtOyWN+QgBiAT0kn+2s6ovOxHyPAFGKVE81VSzJ+mq7RwHFledEvB5F1p4iJvOah/LOKdFuzvRnNLCA==",
"requires": {
"remark-parse": "^9.0.0",
"remark-stringify": "^9.0.0",
"unified": "^9.1.0"
},
"dependencies": {
"remark-parse": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-9.0.0.tgz",
"integrity": "sha512-geKatMwSzEXKHuzBNU1z676sGcDcFoChMK38TgdHJNAYfFtsfHDQG7MoJAjs6sgYMqyLduCYWDIWZIxiPeafEw==",
"requires": {
"mdast-util-from-markdown": "^0.8.0"
}
},
"remark-stringify": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-9.0.0.tgz",
"integrity": "sha512-8x29DpTbVzEc6Dwb90qhxCtbZ6hmj3BxWWDpMhA+1WM4dOEGH5U5/GFe3Be5Hns5MvPSFAr1e2KSVtKZkK5nUw==",
"requires": {
"mdast-util-to-markdown": "^0.5.0"
}
},
"unified": {
"version": "9.2.0",
"resolved": "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz",
"integrity": "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==",
"requires": {
"bail": "^1.0.0",
"extend": "^3.0.0",
"is-buffer": "^2.0.0",
"is-plain-obj": "^2.0.0",
"trough": "^1.0.0",
"vfile": "^4.0.0"
}
}
}
},
"remark-directive": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/remark-directive/-/remark-directive-1.0.1.tgz",
"integrity": "sha512-x6rZs0qa0zu9gW7Avd+rRxHJL2K9TGk+c51NaLfQgCNI7SxwBycRJ3w5mMkjkIjO6O9/qdx0ntu48byCSgF96Q==",
"requires": {
"mdast-util-directive": "^1.0.0",
"micromark-extension-directive": "^1.0.0"
}
},
"remark-frontmatter": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/remark-frontmatter/-/remark-frontmatter-3.0.0.tgz",
"integrity": "sha512-mSuDd3svCHs+2PyO29h7iijIZx4plX0fheacJcAoYAASfgzgVIcXGYSq9GFyYocFLftQs8IOmmkgtOovs6d4oA==",
"requires": {
"mdast-util-frontmatter": "^0.2.0",
"micromark-extension-frontmatter": "^0.2.0"
}
},
"remark-html": {
"version": "12.0.0",
"resolved": "https://registry.npmjs.org/remark-html/-/remark-html-12.0.0.tgz",
"integrity": "sha512-M104NMHs48+uswChJkCDXCdabzxAinpHikpt6kS3gmGMyIvPZ5kn53tB9shFsL2O4HUJ9DIEsah1SX1Ve5FXHA==",
"requires": {
"hast-util-sanitize": "^3.0.0",
"hast-util-to-html": "^7.0.0",
"mdast-util-to-hast": "^9.0.0",
"xtend": "^4.0.1"
}
},
"remark-parse": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-9.0.0.tgz",
"integrity": "sha512-geKatMwSzEXKHuzBNU1z676sGcDcFoChMK38TgdHJNAYfFtsfHDQG7MoJAjs6sgYMqyLduCYWDIWZIxiPeafEw==",
"requires": {
"mdast-util-from-markdown": "^0.8.0"
}
},
"repeat-string": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
"integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
},
"replace-ext": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz",
"integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs="
},
"space-separated-tokens": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz",
"integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA=="
},
"sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
},
"stringify-entities": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-3.1.0.tgz",
"integrity": "sha512-3FP+jGMmMV/ffZs86MoghGqAoqXAdxLrJP4GUdrDN1aIScYih5tuIO3eF4To5AJZ79KDZ8Fpdy7QJnK8SsL1Vg==",
"requires": {
"character-entities-html4": "^1.0.0",
"character-entities-legacy": "^1.0.0",
"xtend": "^4.0.0"
}
},
"to-vfile": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/to-vfile/-/to-vfile-5.0.3.tgz",
"integrity": "sha512-z1Lfx60yAMDMmr+f426Y4yECsHdl8GVEAE+LymjRF5oOIZ7T4N20IxWNAxXLMRzP9jSSll38Z0fKVAhVLsdLOw==",
"requires": {
"is-buffer": "^2.0.0",
"vfile": "^3.0.0"
},
"dependencies": {
"unist-util-stringify-position": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz",
"integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ=="
},
"vfile": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/vfile/-/vfile-3.0.1.tgz",
"integrity": "sha512-y7Y3gH9BsUSdD4KzHsuMaCzRjglXN0W2EcMf0gpvu6+SbsGhMje7xDc8AEoeXy6mIwCKMI6BkjMsRjzQbhMEjQ==",
"requires": {
"is-buffer": "^2.0.0",
"replace-ext": "1.0.0",
"unist-util-stringify-position": "^1.0.0",
"vfile-message": "^1.0.0"
}
},
"vfile-message": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.1.1.tgz",
"integrity": "sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==",
"requires": {
"unist-util-stringify-position": "^1.1.1"
}
}
}
},
"trim": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz",
"integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0="
},
"trim-trailing-lines": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.3.tgz",
"integrity": "sha512-4ku0mmjXifQcTVfYDfR5lpgV7zVqPg6zV9rdZmwOPqq0+Zq19xDqEgagqVbc4pOOShbncuAOIs59R3+3gcF3ZA=="
},
"trough": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz",
"integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA=="
},
"unherit": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz",
"integrity": "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==",
"requires": {
"inherits": "^2.0.0",
"xtend": "^4.0.0"
}
},
"unified": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/unified/-/unified-7.1.0.tgz",
"integrity": "sha512-lbk82UOIGuCEsZhPj8rNAkXSDXd6p0QLzIuSsCdxrqnqU56St4eyOB+AlXsVgVeRmetPTYydIuvFfpDIed8mqw==",
"requires": {
"@types/unist": "^2.0.0",
"@types/vfile": "^3.0.0",
"bail": "^1.0.0",
"extend": "^3.0.0",
"is-plain-obj": "^1.1.0",
"trough": "^1.0.0",
"vfile": "^3.0.0",
"x-is-string": "^0.1.0"
},
"dependencies": {
"is-plain-obj": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
"integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4="
},
"unist-util-stringify-position": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz",
"integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ=="
},
"vfile": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/vfile/-/vfile-3.0.1.tgz",
"integrity": "sha512-y7Y3gH9BsUSdD4KzHsuMaCzRjglXN0W2EcMf0gpvu6+SbsGhMje7xDc8AEoeXy6mIwCKMI6BkjMsRjzQbhMEjQ==",
"requires": {
"is-buffer": "^2.0.0",
"replace-ext": "1.0.0",
"unist-util-stringify-position": "^1.0.0",
"vfile-message": "^1.0.0"
}
},
"vfile-message": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.1.1.tgz",
"integrity": "sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==",
"requires": {
"unist-util-stringify-position": "^1.1.1"
}
}
}
},
"unist-builder": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz",
"integrity": "sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw=="
},
"unist-util-find": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/unist-util-find/-/unist-util-find-1.0.1.tgz",
"integrity": "sha1-EGK7tpKMepfGrcibU3RdTEbCIqI=",
"requires": {
"lodash.iteratee": "^4.5.0",
"remark": "^5.0.1",
"unist-util-visit": "^1.1.0"
},
"dependencies": {
"longest-streak": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-1.0.0.tgz",
"integrity": "sha1-0GWXxNTDG1LMsfXY+P5xSOr9aWU="
},
"markdown-table": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-0.4.0.tgz",
"integrity": "sha1-iQwsGzv+g/sA5BKbjkz+ZFJw+dE="
},
"parse-entities": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz",
"integrity": "sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==",
"requires": {
"character-entities": "^1.0.0",
"character-entities-legacy": "^1.0.0",
"character-reference-invalid": "^1.0.0",
"is-alphanumerical": "^1.0.0",
"is-decimal": "^1.0.0",
"is-hexadecimal": "^1.0.0"
}
},
"remark": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/remark/-/remark-5.1.0.tgz",
"integrity": "sha1-y0Y709vLS5l5STXu4c9x16jjBow=",
"requires": {
"remark-parse": "^1.1.0",
"remark-stringify": "^1.1.0",
"unified": "^4.1.1"
}
},
"remark-parse": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-1.1.0.tgz",
"integrity": "sha1-w8oQ+ajaBGFcKPCapOMEUQUm7CE=",
"requires": {
"collapse-white-space": "^1.0.0",
"extend": "^3.0.0",
"parse-entities": "^1.0.2",
"repeat-string": "^1.5.4",
"trim": "0.0.1",
"trim-trailing-lines": "^1.0.0",
"unherit": "^1.0.4",
"unist-util-remove-position": "^1.0.0",
"vfile-location": "^2.0.0"
}
},
"remark-stringify": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-1.1.0.tgz",
"integrity": "sha1-pxBeJbnuK/mkm3XSxCPxGwauIJI=",
"requires": {
"ccount": "^1.0.0",
"extend": "^3.0.0",
"longest-streak": "^1.0.0",
"markdown-table": "^0.4.0",
"parse-entities": "^1.0.2",
"repeat-string": "^1.5.4",
"stringify-entities": "^1.0.1",
"unherit": "^1.0.4"
}
},
"stringify-entities": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.2.tgz",
"integrity": "sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A==",
"requires": {
"character-entities-html4": "^1.0.0",
"character-entities-legacy": "^1.0.0",
"is-alphanumerical": "^1.0.0",
"is-hexadecimal": "^1.0.0"
}
},
"unified": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/unified/-/unified-4.2.1.tgz",
"integrity": "sha1-dv9Dqo2kMPbn5KVchOusKtLPzS4=",
"requires": {
"bail": "^1.0.0",
"extend": "^3.0.0",
"has": "^1.0.1",
"once": "^1.3.3",
"trough": "^1.0.0",
"vfile": "^1.0.0"
}
},
"unist-util-remove-position": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.4.tgz",
"integrity": "sha512-tLqd653ArxJIPnKII6LMZwH+mb5q+n/GtXQZo6S6csPRs5zB0u79Yw8ouR3wTw8wxvdJFhpP6Y7jorWdCgLO0A==",
"requires": {
"unist-util-visit": "^1.1.0"
}
},
"unist-util-visit": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz",
"integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==",
"requires": {
"unist-util-visit-parents": "^2.0.0"
}
},
"vfile": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/vfile/-/vfile-1.4.0.tgz",
"integrity": "sha1-wP1vpIT43r23cfaMMe112I2pf+c="
},
"vfile-location": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.6.tgz",
"integrity": "sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA=="
}
}
},
"unist-util-find-after": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-3.0.0.tgz",
"integrity": "sha512-ojlBqfsBftYXExNu3+hHLfJQ/X1jYY/9vdm4yZWjIbf0VuWF6CRufci1ZyoD/wV2TYMKxXUoNuoqwy+CkgzAiQ==",
"requires": {
"unist-util-is": "^4.0.0"
}
},
"unist-util-find-all-after": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/unist-util-find-all-after/-/unist-util-find-all-after-3.0.1.tgz",
"integrity": "sha512-0GICgc++sRJesLwEYDjFVJPJttBpVQaTNgc6Jw0Jhzvfs+jtKePEMu+uD+PqkRUrAvGQqwhpDwLGWo1PK8PDEw==",
"requires": {
"unist-util-is": "^4.0.0"
}
},
"unist-util-find-all-between": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/unist-util-find-all-between/-/unist-util-find-all-between-2.1.0.tgz",
"integrity": "sha512-OCCUtDD8UHKeODw3TPXyFDxPCbpgBzbGTTaDpR68nvxkwiVcawBqMVrokfBMvUi7ij2F5q7S4s4Jq5dvkcBt+w==",
"requires": {
"unist-util-find": "^1.0.1",
"unist-util-is": "^4.0.2"
}
},
"unist-util-generated": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.5.tgz",
"integrity": "sha512-1TC+NxQa4N9pNdayCYA1EGUOCAO0Le3fVp7Jzns6lnua/mYgwHo0tz5WUAfrdpNch1RZLHc61VZ1SDgrtNXLSw=="
},
"unist-util-is": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz",
"integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ=="
},
"unist-util-modify-children": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-2.0.0.tgz",
"integrity": "sha512-HGrj7JQo9DwZt8XFsX8UD4gGqOsIlCih9opG6Y+N11XqkBGKzHo8cvDi+MfQQgiZ7zXRUiQREYHhjOBHERTMdg==",
"requires": {
"array-iterate": "^1.0.0"
}
},
"unist-util-position": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.1.0.tgz",
"integrity": "sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA=="
},
"unist-util-remove": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-2.0.0.tgz",
"integrity": "sha512-HwwWyNHKkeg/eXRnE11IpzY8JT55JNM1YCwwU9YNCnfzk6s8GhPXrVBBZWiwLeATJbI7euvoGSzcy9M29UeW3g==",
"requires": {
"unist-util-is": "^4.0.0"
}
},
"unist-util-select": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/unist-util-select/-/unist-util-select-3.0.1.tgz",
"integrity": "sha512-VQpTuqZVJlRbosQdnLdTPIIqwZeU70YZ5aMBOqtFNGeeCdYn6ORZt/9RiaVlbl06ocuf58SVMoFa7a13CSGPMA==",
"dev": true,
"requires": {
"css-selector-parser": "^1.0.0",
"not": "^0.1.0",
"nth-check": "^1.0.0",
"unist-util-is": "^4.0.0",
"zwitch": "^1.0.0"
}
},
"unist-util-stringify-position": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz",
"integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==",
"requires": {
"@types/unist": "^2.0.2"
}
},
"unist-util-visit": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz",
"integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==",
"requires": {
"@types/unist": "^2.0.0",
"unist-util-is": "^4.0.0",
"unist-util-visit-parents": "^3.0.0"
},
"dependencies": {
"unist-util-visit-parents": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.0.tgz",
"integrity": "sha512-0g4wbluTF93npyPrp/ymd3tCDTMnP0yo2akFD2FIBAYXq/Sga3lwaU1D8OYKbtpioaI6CkDcQ6fsMnmtzt7htw==",
"requires": {
"@types/unist": "^2.0.0",
"unist-util-is": "^4.0.0"
}
}
}
},
"unist-util-visit-children": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/unist-util-visit-children/-/unist-util-visit-children-1.1.4.tgz",
"integrity": "sha512-sA/nXwYRCQVRwZU2/tQWUqJ9JSFM1X3x7JIOsIgSzrFHcfVt6NkzDtKzyxg2cZWkCwGF9CO8x4QNZRJRMK8FeQ=="
},
"unist-util-visit-parents": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz",
"integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==",
"requires": {
"unist-util-is": "^3.0.0"
},
"dependencies": {
"unist-util-is": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz",
"integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A=="
}
}
},
"vfile": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/vfile/-/vfile-4.2.0.tgz",
"integrity": "sha512-a/alcwCvtuc8OX92rqqo7PflxiCgXRFjdyoGVuYV+qbgCb0GgZJRvIgCD4+U/Kl1yhaRsaTwksF88xbPyGsgpw==",
"requires": {
"@types/unist": "^2.0.0",
"is-buffer": "^2.0.0",
"replace-ext": "1.0.0",
"unist-util-stringify-position": "^2.0.0",
"vfile-message": "^2.0.0"
}
},
"vfile-message": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz",
"integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==",
"requires": {
"@types/unist": "^2.0.0",
"unist-util-stringify-position": "^2.0.0"
}
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"x-is-string": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz",
"integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI="
},
"xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
},
"zwitch": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz",
"integrity": "sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw=="
}
}
}

View File

@ -1,39 +0,0 @@
{
"name": "challenge-parser",
"version": "0.0.1",
"description": "converts mdx files to challenge objects",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"devDependencies": {
"unist-util-select": "^3.0.1"
},
"dependencies": {
"hast-util-to-html": "^7.1.1",
"js-yaml": "^3.12.0",
"lodash": "^4.17.19",
"mdast-builder": "^1.1.1",
"mdast-util-gfm": "^0.1.0",
"mdast-util-to-hast": "^9.1.1",
"micromark-extension-gfm-strikethrough": "^0.6.1",
"micromark-extension-gfm-table": "^0.4.1",
"remark": "^13.0.0",
"remark-directive": "^1.0.1",
"remark-frontmatter": "^3.0.0",
"remark-html": "^12.0.0",
"remark-parse": "^9.0.0",
"to-vfile": "^5.0.1",
"unified": "^7.0.0",
"unist-util-find": "^1.0.1",
"unist-util-find-after": "^3.0.0",
"unist-util-find-all-after": "^3.0.1",
"unist-util-find-all-between": "^2.0.0",
"unist-util-is": "^4.0.2",
"unist-util-modify-children": "^2.0.0",
"unist-util-position": "^3.1.0",
"unist-util-remove": "^2.0.0",
"unist-util-visit": "^2.0.3",
"unist-util-visit-children": "^1.1.4"
}
}

View File

@ -1,55 +0,0 @@
const visit = require('unist-util-visit');
const { selectAll } = require('hast-util-select');
const { sectionFilter } = require('./utils');
const { createCodeGetter, defaultFile } = require('./challengeSeed-to-data');
const { isEmpty } = require('lodash');
const solutionRE = /(.+)-solution$/;
function indexByKey(obj) {
return { [obj.key]: { ...obj } };
}
function createPlugin() {
return function transformer(tree, file) {
function visitor(node) {
if (sectionFilter(node, 'solution')) {
// fallback for single-file challenges
const rawSolutions = selectAll('code', node).map(element => ({
lang: element.properties.className[0].split('-')[1],
contents: element.children[0].value
}));
const solutionFiles = {};
const codeDivs = selectAll('div', node);
const solutionContainers = codeDivs.filter(({ properties: { id } }) =>
solutionRE.test(id)
);
solutionContainers.forEach(
createCodeGetter('contents', solutionRE, solutionFiles)
);
const solutionsAsFiles = rawSolutions
.map(({ lang, contents }) => ({
...defaultFile(lang),
contents
}))
.map(indexByKey);
const solutions = isEmpty(solutionFiles)
? solutionsAsFiles
: [solutionFiles];
file.data = {
...file.data,
solutions
};
}
}
visit(tree, 'element', visitor);
};
}
module.exports = createPlugin;

View File

@ -1,38 +0,0 @@
/* global describe it expect beforeEach */
const mockAST = require('./fixtures/challenge-html-ast.json');
const solutionToData = require('./solution-to-data');
const { isObject } = require('lodash');
describe('challengeSeed-to-data plugin', () => {
const plugin = solutionToData();
let file = { data: {} };
beforeEach(() => {
file = { data: {} };
});
it('returns a function', () => {
expect(typeof plugin).toEqual('function');
});
it('adds a `solutions` property to `file.data`', () => {
plugin(mockAST, file);
expect('solutions' in file.data).toBe(true);
});
it('ensures that the `solutions` property is an array', () => {
plugin(mockAST, file);
expect(Array.isArray(file.data.solutions)).toBe(true);
});
it('each entry in the `solutions` array is an object', () => {
plugin(mockAST, file);
expect(file.data.solutions.every(el => isObject(el))).toBe(true);
});
it('should have an output to match the snapshot', () => {
plugin(mockAST, file);
expect(file.data).toMatchSnapshot();
});
});

View File

@ -1,55 +0,0 @@
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;
function transformer(tree, file) {
visit(tree, 'code', visitor);
function visitor(node) {
const { lang, value } = node;
if (lang === 'yml') {
const tests = YAML.load(value);
if (tests.question) {
// mdToHTML can not parse numbers. If an answer is a number
// (i.e. 5, not '5') it has to be converted.
tests.question.answers = tests.question.answers.map(answer =>
mdToHTML(answer.toString())
);
tests.question.text = mdToHTML(tests.question.text);
}
// since tests are overloaded (they're both a list of projects and
// actual tests), it's necessary to check which they are:
if (tests.tests && tests.tests[0] && tests.tests[0].text) {
tests.tests = tests.tests.map(({ text, testString }) => ({
text: mdToHTML(text),
testString
}));
}
file.data = {
...file.data,
...tests
};
}
}
}
}
module.exports = plugin;
module.exports.mdToHTML = mdToHTML;

View File

@ -1,84 +0,0 @@
/* 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: {} };
beforeEach(() => {
file = { data: {} };
});
it('returns a function', () => {
expect(typeof plugin).toEqual('function');
});
it('adds a `tests` property to `file.data`', () => {
plugin(mockAST, file);
expect('tests' in file.data).toBe(true);
});
it('adds test objects to the tests array following a schema', () => {
expect.assertions(3);
plugin(mockAST, file);
const testObject = file.data.tests[0];
expect(Object.keys(testObject).length).toBe(2);
expect(testObject).toHaveProperty('testString');
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();
});
});

View File

@ -1,82 +0,0 @@
const visit = require('unist-util-visit');
const toHTML = require('hast-util-to-html');
const { sectionFilter } = require('./utils');
function createPNode() {
return {
type: 'element',
tagName: 'p',
children: [],
properties: {}
};
}
function createBlankLineNode() {
return {
type: 'text',
value: '\n'
};
}
function textToData(sectionIds) {
if (!sectionIds || !Array.isArray(sectionIds) || sectionIds.length <= 0) {
throw new Error("textToData must have an array of section id's supplied");
}
function transformer(tree, file) {
visit(tree, 'element', visitor);
function visitor(node) {
sectionIds.forEach(sectionId => {
if (sectionFilter(node, sectionId)) {
const newChildren = [];
let currentParagraph = null;
node.children.forEach(child => {
if (child.type !== 'text') {
if (child.type === 'element' && child.tagName === 'p') {
newChildren.push(child);
currentParagraph = null;
} else {
if (!currentParagraph) {
currentParagraph = createPNode();
newChildren.push(currentParagraph);
}
currentParagraph.children.push(child);
}
} else {
const lines = child.value.split('\n');
if (lines.filter(Boolean).length > 0) {
lines.forEach((line, index) => {
if (line === '') {
currentParagraph = null;
} else {
if (!currentParagraph || index > 0) {
newChildren.push(createBlankLineNode());
currentParagraph = createPNode();
newChildren.push(currentParagraph);
}
currentParagraph.children.push({ ...child, value: line });
}
});
} else {
currentParagraph = null;
newChildren.push(createBlankLineNode());
}
}
});
const hasData = newChildren.some(
node => node.type !== 'text' || !/^\s*$/.test(node.value)
);
const textArray = hasData
? toHTML({ ...node, children: newChildren })
: '';
file.data = {
...file.data,
[sectionId]: textArray
};
}
});
}
}
return transformer;
}
module.exports = textToData;

View File

@ -1,90 +0,0 @@
/* global describe it expect */
const mockAST = require('./fixtures/challenge-html-ast.json');
const adjacentTagsAST = require('./fixtures/adjacent-tags-ast.json');
const textToData = require('./text-to-data');
describe('text-to-data', () => {
const expectedField = 'description';
const otherExpectedField = 'instructions';
const unexpectedField = 'does-not-exist';
let file = { data: {} };
beforeEach(() => {
file = { data: {} };
});
it('should take return a function', () => {
const plugin = textToData(['a-section-id']);
expect(typeof plugin).toEqual('function');
});
it('throws when no argument or the incorrect argument is supplied', () => {
expect.assertions(5);
const expectedError =
"textToData must have an array of section id's supplied";
expect(() => {
textToData();
}).toThrow(expectedError);
expect(() => {
textToData('');
}).toThrow(expectedError);
expect(() => {
textToData({});
}).toThrow(expectedError);
expect(() => {
textToData(1);
}).toThrow(expectedError);
expect(() => {
textToData([]);
}).toThrow(expectedError);
});
it("should only add a value for 'found' section id's", () => {
const plugin = textToData([expectedField, unexpectedField]);
plugin(mockAST, file);
expect(expectedField in file.data && !(unexpectedField in file.data)).toBe(
true
);
});
it('should add a string relating to the section id to `file.data`', () => {
const plugin = textToData([expectedField]);
plugin(mockAST, file);
const expectedText = 'Welcome to freeCodeCamp';
expect(file.data[expectedField].includes(expectedText)).toBe(true);
});
// eslint-disable-next-line max-len
it('should add an empty string relating to the section id without data to `file.data`', () => {
const plugin = textToData([otherExpectedField]);
plugin(mockAST, file);
expect(file.data[otherExpectedField]).toEqual('');
});
it('should preserve nested html', () => {
const plugin = textToData([expectedField]);
plugin(mockAST, file);
const expectedText = `<blockquote>
<p>Some text in a blockquote</p>
<p>Some text in a blockquote, with <code>code</code></p>
</blockquote>`;
expect(file.data[expectedField].includes(expectedText)).toBe(true);
});
// eslint-disable-next-line max-len
it('should not add paragraphs when html elements are separated by whitespace', () => {
const plugin = textToData([expectedField]);
plugin(adjacentTagsAST, file);
const expectedText1 = `<code>code</code> <tag>with more after a space</tag>`;
const expectedText2 = `another pair of <strong>elements</strong> <em>with a space</em>`;
expect(file.data[expectedField].includes(expectedText1)).toBe(true);
expect(file.data[expectedField].includes(expectedText2)).toBe(true);
});
it('should have an output to match the snapshot', () => {
const plugin = textToData([expectedField, otherExpectedField]);
plugin(mockAST, file);
expect(file.data).toMatchSnapshot();
});
});

View File

@ -1,6 +0,0 @@
exports.sectionFilter = (
{ type, tagName, properties: { id = '' } },
sectionId
) => {
return type === 'element' && tagName === 'section' && id === sectionId;
};