feat: format yaml front matter (#4773)

* refactor: front-matter

* feat: format yaml front matter
master
Ika 2018-07-03 09:54:40 +08:00 committed by GitHub
parent 6a6e8cada0
commit 99c4e41fa1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 180 additions and 39 deletions

View File

@ -3,11 +3,21 @@
const htmlTagNames = require("html-tag-names");
function clean(ast, newObj, parent) {
["raws", "sourceIndex", "source", "before", "after", "trailingComma"].forEach(
name => {
delete newObj[name];
}
);
[
"raw", // front-matter
"raws",
"sourceIndex",
"source",
"before",
"after",
"trailingComma"
].forEach(name => {
delete newObj[name];
});
if (ast.type === "yaml") {
delete newObj.value;
}
// --insert-pragma
if (
@ -16,7 +26,8 @@ function clean(ast, newObj, parent) {
parent.nodes.length !== 0 &&
// first non-front-matter comment
(parent.nodes[0] === ast ||
(parent.nodes[0].type === "front-matter" && parent.nodes[1] === ast))
((parent.nodes[0].type === "yaml" || parent.nodes[0].type === "toml") &&
parent.nodes[1] === ast))
) {
/**
* something

44
src/language-css/embed.js Normal file
View File

@ -0,0 +1,44 @@
"use strict";
const {
builders: { hardline, literalline, concat, markAsRoot },
utils: { mapDoc }
} = require("../doc");
function embed(path, print, textToDoc /*, options */) {
const node = path.getValue();
if (node.type === "yaml") {
return markAsRoot(
concat([
"---",
hardline,
node.value.trim()
? replaceNewlinesWithLiterallines(
textToDoc(node.value, { parser: "yaml" })
)
: "",
"---",
hardline
])
);
}
return null;
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
);
}
}
module.exports = embed;

View File

@ -497,10 +497,7 @@ function parseWithParser(parser, text) {
result = parseNestedCSS(addTypePrefix(result, "css-"));
if (frontMatter) {
result.nodes.unshift({
type: "front-matter",
value: frontMatter
});
result.nodes.unshift(frontMatter);
}
return result;

View File

@ -10,7 +10,8 @@ function hasPragma(text) {
function insertPragma(text) {
const { frontMatter, content } = parseFrontMatter(text);
return (
(frontMatter ? frontMatter + "\n\n" : "") + jsPragma.insertPragma(content)
(frontMatter ? frontMatter.raw + "\n\n" : "") +
jsPragma.insertPragma(content)
);
}

View File

@ -1,6 +1,7 @@
"use strict";
const clean = require("./clean");
const embed = require("./embed");
const { insertPragma } = require("./pragma");
const {
printNumber,
@ -93,8 +94,9 @@ function genericPrint(path, options, print) {
}
switch (node.type) {
case "front-matter":
return concat([node.value, hardline]);
case "yaml":
case "toml":
return concat([node.raw, hardline]);
case "css-root": {
const nodes = printNodeSequence(path, options, print);
@ -834,7 +836,8 @@ function printNodeSequence(path, options, print) {
options.locStart(node.nodes[i + 1]),
{ backwards: true }
) &&
node.nodes[i].type !== "front-matter") ||
node.nodes[i].type !== "yaml" &&
node.nodes[i].type !== "toml") ||
(node.nodes[i + 1].type === "css-atrule" &&
node.nodes[i + 1].name === "else" &&
node.nodes[i].type !== "css-comment")
@ -848,7 +851,8 @@ function printNodeSequence(path, options, print) {
pathChild.getValue(),
options
) &&
node.nodes[i].type !== "front-matter"
node.nodes[i].type !== "yaml" &&
node.nodes[i].type !== "toml"
) {
parts.push(hardline);
}
@ -906,6 +910,7 @@ function printCssNumber(rawNumber) {
module.exports = {
print: genericPrint,
embed,
insertPragma,
hasPrettierIgnore: hasIgnoreComment,
massageAstNode: clean

View File

@ -33,6 +33,21 @@ function embed(path, print, textToDoc, options) {
}
}
if (node.type === "yaml") {
return markAsRoot(
concat([
"---",
hardline,
node.value.trim()
? replaceNewlinesWithLiterallines(
textToDoc(node.value, { parser: "yaml" })
)
: "",
"---"
])
);
}
return null;
function getParserName(lang) {

View File

@ -138,10 +138,7 @@ function frontMatter() {
const parsed = parseFrontMatter(value);
if (parsed.frontMatter) {
return eat(parsed.frontMatter)({
type: "front-matter",
value: parsed.frontMatter
});
return eat(parsed.frontMatter.raw)(parsed.frontMatter);
}
}
tokenizer.onlyAtStart = true;

View File

@ -24,7 +24,7 @@ module.exports = {
const extracted = parseFrontMatter(text);
const pragma = `<!-- @${pragmas[0]} -->`;
return extracted.frontMatter
? `${extracted.frontMatter}\n\n${pragma}\n\n${extracted.content}`
? `${extracted.frontMatter.raw}\n\n${pragma}\n\n${extracted.content}`
: `${pragma}\n\n${extracted.content}`;
}
};

View File

@ -226,8 +226,12 @@ function genericPrint(path, options, print) {
style
]);
}
case "front-matter":
return node.value;
case "yaml":
case "toml":
return options.originalText.slice(
node.position.start.offset,
node.position.end.offset
);
case "html": {
const parentNode = path.getParentNode();
const value =
@ -840,9 +844,10 @@ function clamp(value, min, max) {
function clean(ast, newObj, parent) {
delete newObj.position;
delete newObj.raw; // front-matter
// for codeblock
if (ast.type === "code") {
if (ast.type === "code" || ast.type === "yaml") {
delete newObj.value;
}
// for whitespace: "\n" and " " are considered the same
@ -855,7 +860,8 @@ function clean(ast, newObj, parent) {
parent.type === "root" &&
parent.children.length > 0 &&
(parent.children[0] === ast ||
(parent.children[0].type === "front-matter" &&
((parent.children[0].type === "yaml" ||
parent.children[0].type === "toml") &&
parent.children[1] === ast)) &&
ast.type === "html" &&
pragma.startWithPragma(ast.value)

View File

@ -1,25 +1,32 @@
"use strict";
const escape = require("escape-string-regexp");
const DELIMITER_MAP = {
"---": "yaml",
"+++": "toml"
};
function parse(text) {
let delimiter;
const delimiterRegex = Object.keys(DELIMITER_MAP)
.map(escape)
.join("|");
if (text.indexOf("---") === 0) {
delimiter = "---";
} else if (text.indexOf("+++") === 0) {
delimiter = "+++";
}
const match = text.match(
new RegExp(`^(${delimiterRegex})\\n(?:([\\s\\S]*?)\\n)?\\1(\\n|$)`)
);
let end = -1;
if (!delimiter || (end = text.indexOf(`\n${delimiter}`, 3)) === -1) {
if (match === null) {
return { frontMatter: null, content: text };
}
end = end + 4;
const raw = match[0].trimRight();
const delimiter = match[1];
const value = match[2];
return {
frontMatter: text.slice(0, end),
content: text.slice(end)
frontMatter: { type: DELIMITER_MAP[delimiter], value, raw },
content: text.slice(raw.length)
};
}

View File

@ -20,6 +20,32 @@ description: Description
`;
exports[`dirty.css 1`] = `
---
hello: world
a:
- 123
- 666
---
.class {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
---
hello: world
a:
- 123
- 666
---
.class {
}
`;
exports[`empty.css 1`] = `
---
---
@ -51,9 +77,6 @@ a {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
---
---
a {

12
tests/css_yaml/dirty.css Normal file
View File

@ -0,0 +1,12 @@
---
hello: world
a:
- 123
- 666
---
.class {
}

View File

@ -1,5 +1,22 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`complex.md 1`] = `
---
- hello: world
- 123
---
# something
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
---
- hello: world
- 123
---
# something
`;
exports[`empty.md 1`] = `
---
---

View File

@ -0,0 +1,6 @@
---
- hello: world
- 123
---
# something