feat(html): support front matter (#5110)

- format yaml front matter
- preserve toml front matter
master
Ika 2018-09-19 22:10:41 +08:00 committed by GitHub
parent 02fcea06fd
commit 8ddff0787a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 120 additions and 6 deletions

View File

@ -6,4 +6,9 @@ module.exports = function(ast, newNode) {
if (ast.type === "text") {
return null;
}
// may be formatted by multiparser
if (ast.type === "yaml") {
return null;
}
};

View File

@ -2,8 +2,8 @@
const { hasNewlineInRange } = require("../common/util");
const {
builders: { hardline, concat },
utils: { stripTrailingHardline, removeLines }
builders: { hardline, concat, markAsRoot, literalline },
utils: { stripTrailingHardline, removeLines, mapDoc }
} = require("../doc");
function embed(path, print, textToDoc, options) {
@ -71,10 +71,41 @@ function embed(path, print, textToDoc, options) {
'"'
]);
}
break;
}
case "yaml":
return markAsRoot(
concat([
"---",
hardline,
node.value.trim()
? replaceNewlinesWithLiterallines(
textToDoc(node.value, { parser: "yaml" })
)
: "",
"---",
hardline
])
);
}
}
function replaceNewlinesWithLiterallines(doc) {
return mapDoc(
doc,
currentDoc =>
typeof currentDoc === "string" && currentDoc.includes("\n")
? concat(
currentDoc
.split(/(\n)/g)
.map((v, i) => (i % 2 === 0 ? v : literalline))
)
: currentDoc
);
}
function parseJavaScriptExpression(text, parsers) {
// Force parsing as an expression
const ast = parsers.babylon(`(${text})`);

View File

@ -1,6 +1,8 @@
"use strict";
const htmlTagNames = require("html-tag-names");
const parseFrontMatter = require("../utils/front-matter");
const nonFragmentRegex = /^\s*(<!--[\s\S]*?-->\s*)*<(!doctype|html|head|body)[\s>]/i;
function parse(text /*, parsers, opts*/) {
@ -8,13 +10,21 @@ function parse(text /*, parsers, opts*/) {
const parse5 = require("parse5");
const htmlparser2TreeAdapter = require("parse5-htmlparser2-tree-adapter");
const isFragment = !nonFragmentRegex.test(text);
const ast = (isFragment ? parse5.parseFragment : parse5.parse)(text, {
const { frontMatter, content } = parseFrontMatter(text);
const isFragment = !nonFragmentRegex.test(content);
const ast = (isFragment ? parse5.parseFragment : parse5.parse)(content, {
treeAdapter: htmlparser2TreeAdapter,
sourceCodeLocationInfo: true
});
return normalize(ast, text);
const normalizedAst = normalize(ast, text);
if (frontMatter) {
normalizedAst.children.unshift(frontMatter);
}
return normalizedAst;
}
function normalize(node, text) {

View File

@ -193,7 +193,10 @@ function genericPrint(path, options, print) {
return concat([n.key, '="', n.value.replace(/"/g, "&quot;"), '"']);
}
// front matter
case "yaml":
case "toml":
return concat([n.raw, hardline]);
default:
/* istanbul ignore next */
throw new Error("unknown htmlparser2 type: " + n.type);

View File

@ -0,0 +1,46 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`invalid.html - parse5-verify 1`] = `
---
invalid:
invalid:
---
<html><head></head><body></body></html>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
---
invalid:
invalid:
---
<html>
<head></head>
<body></body>
</html>
`;
exports[`yaml.html - parse5-verify 1`] = `
---
hello: world
---
<html><head></head><body></body></html>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
---
hello: world
---
<html>
<head></head>
<body></body>
</html>
`;

View File

@ -0,0 +1,8 @@
---
invalid:
invalid:
---
<html><head></head><body></body></html>

View File

@ -0,0 +1 @@
run_spec(__dirname, ["parse5"]);

10
tests/html_yaml/yaml.html Normal file
View File

@ -0,0 +1,10 @@
---
hello: world
---
<html><head></head><body></body></html>