chore: remove old parser

This commit is contained in:
Oliver Eyton-Williams
2021-02-01 19:31:39 +01:00
committed by Mrugesh Mohapatra
parent e3511f2930
commit a3a678b7af
139 changed files with 4 additions and 4 deletions

View File

@ -0,0 +1,10 @@
{
"type": "leafDirective",
"name": "id",
"attributes": { "id": "html-key" },
"children": [],
"position": {
"start": { "line": 29, "column": 1, "offset": 200 },
"end": { "line": 29, "column": 16, "offset": 215 }
}
}

View File

@ -0,0 +1,21 @@
{
"type": "paragraph",
"children": [
{
"type": "image",
"title": null,
"url": "https://www.image.com",
"alt": "html-key",
"position": {
"start": { "line": 65, "column": 1, "offset": 481 },
"end": { "line": 65, "column": 35, "offset": 515 },
"indent": []
}
}
],
"position": {
"start": { "line": 65, "column": 1, "offset": 481 },
"end": { "line": 65, "column": 35, "offset": 515 },
"indent": []
}
}

View File

@ -0,0 +1,119 @@
{
"type": "paragraph",
"children": [
{
"type": "html",
"value": "<code>",
"position": {
"start": { "line": 3, "column": 1, "offset": 19 },
"end": { "line": 3, "column": 7, "offset": 25 },
"indent": []
}
},
{
"type": "text",
"value": " code in ",
"position": {
"start": { "line": 3, "column": 7, "offset": 25 },
"end": { "line": 3, "column": 16, "offset": 34 },
"indent": []
}
},
{
"type": "html",
"value": "</code>",
"position": {
"start": { "line": 3, "column": 16, "offset": 34 },
"end": { "line": 3, "column": 23, "offset": 41 },
"indent": []
}
},
{
"type": "text",
"value": " code tags ",
"position": {
"start": { "line": 3, "column": 23, "offset": 41 },
"end": { "line": 3, "column": 34, "offset": 52 },
"indent": []
}
},
{
"type": "emphasis",
"children": [
{
"type": "text",
"value": "emphasis",
"position": {
"start": { "line": 3, "column": 35, "offset": 53 },
"end": { "line": 3, "column": 43, "offset": 61 },
"indent": []
}
}
],
"position": {
"start": { "line": 3, "column": 34, "offset": 52 },
"end": { "line": 3, "column": 44, "offset": 62 },
"indent": []
}
},
{
"type": "text",
"value": " followed by ",
"position": {
"start": { "line": 3, "column": 44, "offset": 62 },
"end": { "line": 3, "column": 57, "offset": 75 },
"indent": []
}
},
{
"type": "html",
"value": "<div>",
"position": {
"start": { "line": 3, "column": 57, "offset": 75 },
"end": { "line": 3, "column": 62, "offset": 80 },
"indent": []
}
},
{
"type": "html",
"value": "<span>",
"position": {
"start": { "line": 3, "column": 62, "offset": 80 },
"end": { "line": 3, "column": 68, "offset": 86 },
"indent": []
}
},
{
"type": "text",
"value": "some nested html ",
"position": {
"start": { "line": 3, "column": 68, "offset": 86 },
"end": { "line": 3, "column": 85, "offset": 103 },
"indent": []
}
},
{
"type": "html",
"value": "</span>",
"position": {
"start": { "line": 3, "column": 85, "offset": 103 },
"end": { "line": 3, "column": 92, "offset": 110 },
"indent": []
}
},
{
"type": "html",
"value": "</div>",
"position": {
"start": { "line": 3, "column": 92, "offset": 110 },
"end": { "line": 3, "column": 98, "offset": 116 },
"indent": []
}
}
],
"position": {
"start": { "line": 3, "column": 1, "offset": 19 },
"end": { "line": 3, "column": 98, "offset": 116 },
"indent": []
}
}

View File

@ -0,0 +1,113 @@
[
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "Paragraph 1",
"position": {
"start": { "line": 3, "column": 1, "offset": 19 },
"end": { "line": 3, "column": 12, "offset": 30 },
"indent": []
}
}
],
"position": {
"start": { "line": 3, "column": 1, "offset": 19 },
"end": { "line": 3, "column": 12, "offset": 30 },
"indent": []
}
},
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "Third ",
"position": {
"start": { "line": 5, "column": 1, "offset": 32 },
"end": { "line": 5, "column": 7, "offset": 38 },
"indent": []
}
},
{
"type": "emphasis",
"children": [
{
"type": "text",
"value": "hint",
"position": {
"start": { "line": 5, "column": 8, "offset": 39 },
"end": { "line": 5, "column": 12, "offset": 43 },
"indent": []
}
}
],
"position": {
"start": { "line": 5, "column": 7, "offset": 38 },
"end": { "line": 5, "column": 13, "offset": 44 },
"indent": []
}
},
{
"type": "text",
"value": " with ",
"position": {
"start": { "line": 5, "column": 13, "offset": 44 },
"end": { "line": 5, "column": 19, "offset": 50 },
"indent": []
}
},
{
"type": "html",
"value": "<code>",
"position": {
"start": { "line": 5, "column": 19, "offset": 50 },
"end": { "line": 5, "column": 25, "offset": 56 },
"indent": []
}
},
{
"type": "text",
"value": "code",
"position": {
"start": { "line": 5, "column": 25, "offset": 56 },
"end": { "line": 5, "column": 29, "offset": 60 },
"indent": []
}
},
{
"type": "html",
"value": "</code>",
"position": {
"start": { "line": 5, "column": 29, "offset": 60 },
"end": { "line": 5, "column": 36, "offset": 67 },
"indent": []
}
},
{
"type": "text",
"value": " and ",
"position": {
"start": { "line": 5, "column": 36, "offset": 67 },
"end": { "line": 5, "column": 41, "offset": 72 },
"indent": []
}
},
{
"type": "inlineCode",
"value": "inline code",
"position": {
"start": { "line": 5, "column": 41, "offset": 72 },
"end": { "line": 5, "column": 54, "offset": 85 },
"indent": []
}
}
],
"position": {
"start": { "line": 5, "column": 1, "offset": 32 },
"end": { "line": 5, "column": 54, "offset": 85 },
"indent": []
}
}
]

View File

@ -0,0 +1,66 @@
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "Just some ",
"position": {
"start": { "line": 11, "column": 1, "offset": 120 },
"end": { "line": 11, "column": 11, "offset": 130 },
"indent": []
}
},
{
"type": "emphasis",
"children": [
{
"type": "text",
"value": "emphasis",
"position": {
"start": { "line": 11, "column": 12, "offset": 131 },
"end": { "line": 11, "column": 20, "offset": 139 },
"indent": []
}
}
],
"position": {
"start": { "line": 11, "column": 11, "offset": 130 },
"end": { "line": 11, "column": 21, "offset": 140 },
"indent": []
}
},
{
"type": "text",
"value": " and a bit of ",
"position": {
"start": { "line": 11, "column": 21, "offset": 140 },
"end": { "line": 11, "column": 35, "offset": 154 },
"indent": []
}
},
{
"type": "strong",
"children": [
{
"type": "text",
"value": "bold",
"position": {
"start": { "line": 11, "column": 37, "offset": 156 },
"end": { "line": 11, "column": 41, "offset": 160 },
"indent": []
}
}
],
"position": {
"start": { "line": 11, "column": 35, "offset": 154 },
"end": { "line": 11, "column": 43, "offset": 162 },
"indent": []
}
}
],
"position": {
"start": { "line": 11, "column": 1, "offset": 120 },
"end": { "line": 11, "column": 43, "offset": 162 },
"indent": []
}
}

View File

@ -0,0 +1,31 @@
{
"type": "paragraph",
"children": [
{
"type": "imageReference",
"identifier": "html-key",
"label": "html-key",
"referenceType": "shortcut",
"alt": "html-key",
"position": {
"start": { "line": 65, "column": 1, "offset": 481 },
"end": { "line": 65, "column": 12, "offset": 492 },
"indent": []
}
},
{
"type": "text",
"value": "\nMore stuff in the paragraph",
"position": {
"start": { "line": 65, "column": 12, "offset": 492 },
"end": { "line": 66, "column": 28, "offset": 520 },
"indent": [1]
}
}
],
"position": {
"start": { "line": 65, "column": 1, "offset": 481 },
"end": { "line": 66, "column": 28, "offset": 520 },
"indent": [1]
}
}

View File

@ -0,0 +1,19 @@
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "--description--",
"position": {
"start": { "line": 65, "column": 1, "offset": 481 },
"end": { "line": 65, "column": 12, "offset": 492 },
"indent": []
}
}
],
"position": {
"start": { "line": 65, "column": 1, "offset": 481 },
"end": { "line": 65, "column": 12, "offset": 492 },
"indent": []
}
}

View File

@ -0,0 +1,395 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`between-headings should match the hints snapshot 1`] = `
Array [
Object {
"children": Array [
Object {
"position": Object {
"end": Object {
"column": 11,
"line": 19,
"offset": 142,
},
"start": Object {
"column": 1,
"line": 19,
"offset": 132,
},
},
"type": "text",
"value": "First hint",
},
],
"position": Object {
"end": Object {
"column": 11,
"line": 19,
"offset": 142,
},
"start": Object {
"column": 1,
"line": 19,
"offset": 132,
},
},
"type": "paragraph",
},
Object {
"lang": "js",
"meta": null,
"position": Object {
"end": Object {
"column": 4,
"line": 23,
"offset": 166,
},
"start": Object {
"column": 1,
"line": 21,
"offset": 144,
},
},
"type": "code",
"value": "// test code",
},
Object {
"children": Array [
Object {
"position": Object {
"end": Object {
"column": 18,
"line": 25,
"offset": 185,
},
"start": Object {
"column": 1,
"line": 25,
"offset": 168,
},
},
"type": "text",
"value": "Second hint with ",
},
Object {
"position": Object {
"end": Object {
"column": 24,
"line": 25,
"offset": 191,
},
"start": Object {
"column": 18,
"line": 25,
"offset": 185,
},
},
"type": "html",
"value": "<code>",
},
Object {
"position": Object {
"end": Object {
"column": 28,
"line": 25,
"offset": 195,
},
"start": Object {
"column": 24,
"line": 25,
"offset": 191,
},
},
"type": "text",
"value": "code",
},
Object {
"position": Object {
"end": Object {
"column": 35,
"line": 25,
"offset": 202,
},
"start": Object {
"column": 28,
"line": 25,
"offset": 195,
},
},
"type": "html",
"value": "</code>",
},
],
"position": Object {
"end": Object {
"column": 35,
"line": 25,
"offset": 202,
},
"start": Object {
"column": 1,
"line": 25,
"offset": 168,
},
},
"type": "paragraph",
},
Object {
"lang": "js",
"meta": null,
"position": Object {
"end": Object {
"column": 4,
"line": 29,
"offset": 231,
},
"start": Object {
"column": 1,
"line": 27,
"offset": 204,
},
},
"type": "code",
"value": "// more test code",
},
Object {
"children": Array [
Object {
"position": Object {
"end": Object {
"column": 7,
"line": 31,
"offset": 239,
},
"start": Object {
"column": 1,
"line": 31,
"offset": 233,
},
},
"type": "text",
"value": "Third ",
},
Object {
"children": Array [
Object {
"position": Object {
"end": Object {
"column": 12,
"line": 31,
"offset": 244,
},
"start": Object {
"column": 8,
"line": 31,
"offset": 240,
},
},
"type": "text",
"value": "hint",
},
],
"position": Object {
"end": Object {
"column": 13,
"line": 31,
"offset": 245,
},
"start": Object {
"column": 7,
"line": 31,
"offset": 239,
},
},
"type": "emphasis",
},
Object {
"position": Object {
"end": Object {
"column": 19,
"line": 31,
"offset": 251,
},
"start": Object {
"column": 13,
"line": 31,
"offset": 245,
},
},
"type": "text",
"value": " with ",
},
Object {
"position": Object {
"end": Object {
"column": 25,
"line": 31,
"offset": 257,
},
"start": Object {
"column": 19,
"line": 31,
"offset": 251,
},
},
"type": "html",
"value": "<code>",
},
Object {
"position": Object {
"end": Object {
"column": 29,
"line": 31,
"offset": 261,
},
"start": Object {
"column": 25,
"line": 31,
"offset": 257,
},
},
"type": "text",
"value": "code",
},
Object {
"position": Object {
"end": Object {
"column": 36,
"line": 31,
"offset": 268,
},
"start": Object {
"column": 29,
"line": 31,
"offset": 261,
},
},
"type": "html",
"value": "</code>",
},
Object {
"position": Object {
"end": Object {
"column": 41,
"line": 31,
"offset": 273,
},
"start": Object {
"column": 36,
"line": 31,
"offset": 268,
},
},
"type": "text",
"value": " and ",
},
Object {
"position": Object {
"end": Object {
"column": 54,
"line": 31,
"offset": 286,
},
"start": Object {
"column": 41,
"line": 31,
"offset": 273,
},
},
"type": "inlineCode",
"value": "inline code",
},
],
"position": Object {
"end": Object {
"column": 54,
"line": 31,
"offset": 286,
},
"start": Object {
"column": 1,
"line": 31,
"offset": 233,
},
},
"type": "paragraph",
},
Object {
"lang": "js",
"meta": null,
"position": Object {
"end": Object {
"column": 4,
"line": 38,
"offset": 353,
},
"start": Object {
"column": 1,
"line": 33,
"offset": 288,
},
},
"type": "code",
"value": "// more test code
if(let x of xs) {
console.log(x);
}",
},
]
`;
exports[`between-headings should match the instructions snapshot 1`] = `
Array [
Object {
"children": Array [
Object {
"position": Object {
"end": Object {
"column": 12,
"line": 11,
"offset": 89,
},
"start": Object {
"column": 1,
"line": 11,
"offset": 78,
},
},
"type": "text",
"value": "Paragraph 0",
},
],
"position": Object {
"end": Object {
"column": 12,
"line": 11,
"offset": 89,
},
"start": Object {
"column": 1,
"line": 11,
"offset": 78,
},
},
"type": "paragraph",
},
Object {
"lang": "html",
"meta": null,
"position": Object {
"end": Object {
"column": 4,
"line": 15,
"offset": 117,
},
"start": Object {
"column": 1,
"line": 13,
"offset": 91,
},
},
"type": "code",
"value": "code example 0",
},
]
`;

View File

@ -0,0 +1,46 @@
const between = require('unist-util-find-all-between');
const find = require('unist-util-find');
const findAfter = require('unist-util-find-after');
const findAllAfter = require('unist-util-find-all-after');
function getAllBetween(tree, marker) {
const start = find(tree, {
type: 'heading',
children: [
{
type: 'text',
value: marker
}
]
});
if (!start) return [];
const isEnd = node => {
return (
node.type === 'heading' && node.depth <= start.depth && isMarker(node)
);
};
const isMarker = node => {
if (node.children && node.children[0]) {
const child = node.children[0];
return (
child.type === 'text' &&
child.value.startsWith('--') &&
child.value.endsWith('--')
);
} else {
return false;
}
};
const end = findAfter(tree, start, isEnd);
const targetNodes = end
? between(tree, start, end)
: findAllAfter(tree, start);
return targetNodes;
}
module.exports = getAllBetween;

View File

@ -0,0 +1,51 @@
/* global expect*/
const isArray = require('lodash/isArray');
const find = require('unist-util-find');
const { root } = require('mdast-builder');
const getAllBetween = require('./between-headings');
const simpleAst = require('../../__fixtures__/ast-simple.json');
const extraHeadingAst = require('../../__fixtures__/ast-extra-heading.json');
describe('between-headings', () => {
it('should return an array', () => {
expect.assertions(1);
const actual = getAllBetween(simpleAst, '--hints--');
expect(isArray(actual)).toBe(true);
});
it('should return an empty array if the marker is not present', () => {
expect.assertions(2);
const actual = getAllBetween(simpleAst, '--not-a-marker--');
expect(isArray(actual)).toBe(true);
expect(actual.length).toBe(0);
});
it('should include any headings without markers', () => {
expect.assertions(1);
const actual = getAllBetween(extraHeadingAst, '--description--');
expect(
find(root(actual), {
value: 'this should still be inside --description--'
})
).not.toBeUndefined();
});
it('should include the rest of the AST if there is no end marker', () => {
expect.assertions(2);
const actual = getAllBetween(extraHeadingAst, '--solutions--');
expect(actual.length > 0).toBe(true);
expect(
find(root(actual), { value: 'body {\n background: white;\n}' })
).not.toBeUndefined();
});
it('should match the hints snapshot', () => {
const actual = getAllBetween(simpleAst, '--hints--');
expect(actual).toMatchSnapshot();
});
it('should match the instructions snapshot', () => {
const actual = getAllBetween(simpleAst, '--instructions--');
expect(actual).toMatchSnapshot();
});
});

View File

@ -0,0 +1,84 @@
const is = require('unist-util-is');
const position = require('unist-util-position');
const { isEmpty } = require('lodash');
const getId = require('./get-id');
const keyToSection = {
head: 'before-user-code',
tail: 'after-user-code'
};
const supportedLanguages = ['js', 'css', 'html', 'jsx', 'py'];
function defaultFile(lang, id) {
return {
key: `index${lang}`,
ext: lang,
name: 'index',
contents: '',
head: '',
tail: '',
id
};
}
function getFileVisitor(seeds, seedKey, validate) {
return (node, index, parent) => {
if (is(node, 'root')) return;
if (is(node, 'code')) {
codeToData(node, seeds, seedKey, validate);
return;
}
idToData(node, index, parent, seeds);
};
}
function codeToData(node, seeds, seedKey, validate) {
if (validate) validate(node);
const lang = node.lang;
if (!supportedLanguages.includes(lang))
throw Error(`On line ${
position.start(node).line
} '${lang}' is not a supported language.
Please use one of js, css, html, jsx or py
`);
const key = `index${lang}`;
const id = seeds[key] ? seeds[key].id : '';
// the contents will be missing if there is an id preceding this code
// block.
if (!seeds[key]) {
seeds[key] = defaultFile(lang, id);
}
if (isEmpty(node.value) && seedKey !== 'contents') {
const section = keyToSection[seedKey];
throw Error(`Empty code block in --${section}-- section`);
}
seeds[key][seedKey] = isEmpty(seeds[key][seedKey])
? node.value
: seeds[key][seedKey] + '\n' + node.value;
}
function idToData(node, index, parent, seeds) {
const id = getId(node);
// If this is reached, the node type is neither root nor code. If it is not
// an id, there must be a syntax error.
if (!id) {
throw Error(
'Unexpected syntax in seed/solution. Must be ::id{#id} or a code ' +
'block (```) \n'
);
}
const codeNode = parent.children[index + 1];
if (codeNode && is(codeNode, 'code')) {
const key = `index${codeNode.lang}`;
if (seeds[key]) throw Error('::id{#id}s must come before code blocks');
seeds[key] = defaultFile(codeNode.lang, id);
} else {
throw Error('::id{#id}s must come before code blocks');
}
}
module.exports.getFileVisitor = getFileVisitor;

View File

@ -0,0 +1,33 @@
describe('get-file-visitor', () => {
it('should join code with newlines', () => {
/* i.e. if you've got two js code blocks it should do this
```js
one
```
```js
two
```
become
```js
one
two
```
not
```js
onetwo
```
or
```js
one
two
```
*/
});
});

View File

@ -0,0 +1,8 @@
// getId expects the image reference node to be the sole node in a paragraph
function getId(node) {
const { type, name, attributes } = node;
if (type !== 'leafDirective' || name !== 'id' || !attributes) return null;
return attributes.id;
}
module.exports = getId;

View File

@ -0,0 +1,45 @@
/* global expect*/
const getId = require('./get-id');
const idNode = require('./__fixtures__/id-node.json');
const imageNode = require('./__fixtures__/image-node.json');
const multipleChildrenNode = require('./__fixtures__/multiple-children.json');
const nonIdNode = require('./__fixtures__/non-id-node.json');
describe('get-id', () => {
it('should return a string', () => {
expect.assertions(1);
const actual = getId(idNode);
expect(typeof actual).toBe('string');
});
it('should get the expected identifier', () => {
expect.assertions(1);
const actual = getId(idNode);
expect(actual).toBe('html-key');
});
it('should return null if the node does contain an id', () => {
expect.assertions(1);
const actual = getId(nonIdNode);
expect(actual).toBeNull();
});
// TODO: bin this (and the json!) after development (it'll be a silly test
// once we're using directives)
it('should ignore image nodes', () => {
expect.assertions(1);
const actual = getId(imageNode);
expect(actual).toBeNull();
});
// TODO: bin this (and the json!) after development (it'll be a silly test
// once we're using directives)
// TODO: do we want to fail silently? Might it be better to output warnings
// or perhaps even stop the parser? Probably warnings if anything.
it('should ignore paragraphs that contain more than the id element', () => {
expect.assertions(1);
const actual = getId(multipleChildrenNode);
expect(actual).toBeNull();
});
});

View File

@ -0,0 +1,15 @@
const hastToHTML = require('hast-util-to-html');
const mdastToHast = require('mdast-util-to-hast');
const { root } = require('mdast-builder');
function mdastToHTML(nodes) {
if (!Array.isArray(nodes))
throw Error('mdastToHTML expects an array argument');
// - the 'nodes' are children, so first need embedding in a parent
return hastToHTML(mdastToHast(root(nodes), { allowDangerousHtml: true }), {
allowDangerousHtml: true
});
}
module.exports = mdastToHTML;

View File

@ -0,0 +1,42 @@
/* global expect*/
const mdastToHTML = require('./mdast-to-html');
const mdastMixedNodes = require('./__fixtures__/mdast-mixed-nodes.json');
const mdastWithEmNode = require('./__fixtures__/mdast-with-em.json');
const singleNode = require('./__fixtures__/non-id-node.json');
const leadingInlineHTMLNode = require('./__fixtures__/leading-html-node.json');
describe('mdast-to-html', () => {
it('should return a string', () => {
expect.assertions(1);
const actual = mdastToHTML(mdastMixedNodes);
expect(typeof actual).toBe('string');
});
it('throws if it is not passed an array', () => {
expect.assertions(1);
expect(() => mdastToHTML(singleNode)).toThrow(
'mdastToHTML expects an array argument'
);
});
it('should convert markdown nodes into html', () => {
const actual = mdastToHTML([mdastWithEmNode]);
expect(actual).toBe(
'<p>Just some <em>emphasis</em> and a bit of <strong>bold</strong></p>'
);
});
it('should not escape html', () => {
const actual = mdastToHTML(mdastMixedNodes);
expect(actual).toBe(`<p>Paragraph 1</p>
<p>Third <em>hint</em> with <code>code</code> and <code>inline code</code></p>`);
});
it('should put inline html inside the enclosing paragraph', () => {
const actual = mdastToHTML([leadingInlineHTMLNode]);
expect(actual).toBe(
'<p><code> code in </code> code tags <em>emphasis</em> followed' +
' by <div><span>some nested html </span></div></p>'
);
});
});

View File

@ -0,0 +1,20 @@
const is = require('unist-util-is');
// TODO: specific tests for this would be nice, even though it is somewhat
// covered by the plugins that use it.
function splitOnThematicBreak(nodes) {
return nodes.reduce(
(prev, curr) => {
if (is(curr, 'thematicBreak')) {
return [...prev, []];
} else {
const first = prev.slice(0, -1);
const last = prev.slice(-1)[0];
return [...first, [...last, curr]];
}
},
[[]]
);
}
exports.splitOnThematicBreak = splitOnThematicBreak;