Add Front Matter support to Handlebars (#17781)
Co-authored-by: fisker Cheung <lionkay@gmail.com>
This commit is contained in:
1 parent
17cf07e68a
commit
e51ff9ad41
25 files changed
+554
-3
No files matched your search
@@ -0,0 +1,20 @@
|
||||
#### Added Front Matter support to Handlebars (#17781 by @Codezilluh)
|
||||
|
||||
Front matter can now be used in Handlebars.
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```hbs
|
||||
---
|
||||
title: My page title
|
||||
keywords:
|
||||
- word
|
||||
- other word
|
||||
---
|
||||
|
||||
<h1>{{title}}</h1>
|
||||
<ul>
|
||||
{{#each keywords}}
|
||||
<li>{{this}}</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
```
|
||||
@@ -1,6 +1,9 @@
|
||||
import { cleanFrontMatter } from "../utils/front-matter/index.js";
|
||||
import htmlWhitespaceUtils from "../utils/html-whitespace-utils.js";
|
||||
|
||||
function clean(original, cloned, parent) {
|
||||
cleanFrontMatter(original, cloned);
|
||||
|
||||
// (Glimmer/HTML) ignore TextNode
|
||||
if (original.type === "TextNode") {
|
||||
const trimmed = original.chars.trim();
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
import {
|
||||
isEmbedFrontMatter,
|
||||
printEmbedFrontMatter,
|
||||
} from "../utils/front-matter/embed.js";
|
||||
|
||||
function embed(path /* , options*/) {
|
||||
const { node } = path;
|
||||
|
||||
if (isEmbedFrontMatter(path)) {
|
||||
return printEmbedFrontMatter;
|
||||
}
|
||||
|
||||
if (node.type !== "TextNode") {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { preprocess as parseGlimmer } from "@glimmer/syntax";
|
||||
import createError from "../common/parser-create-error.js";
|
||||
import parseFrontMatter from "../utils/front-matter/parse.js";
|
||||
import { locEnd, locStart } from "./loc.js";
|
||||
|
||||
/* from the following template: `non-escaped mustache \\{{helper}}`
|
||||
@@ -57,10 +58,12 @@ const glimmerParseOptions = {
|
||||
plugins: { ast: [glimmerPrettierParsePlugin] },
|
||||
};
|
||||
|
||||
function parse(text /* , options */) {
|
||||
function parse(text) {
|
||||
const { frontMatter, content } = parseFrontMatter(text);
|
||||
|
||||
let ast;
|
||||
try {
|
||||
ast = parseGlimmer(text, glimmerParseOptions);
|
||||
ast = parseGlimmer(content, glimmerParseOptions);
|
||||
} catch (error) {
|
||||
const location = getErrorLocation(error);
|
||||
|
||||
@@ -74,6 +77,25 @@ function parse(text /* , options */) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
if (frontMatter) {
|
||||
const frontMatterNode = {
|
||||
...frontMatter,
|
||||
loc: {
|
||||
start: {
|
||||
...frontMatter.start,
|
||||
offset: frontMatter.start.index,
|
||||
},
|
||||
end: {
|
||||
...frontMatter.end,
|
||||
offset: frontMatter.end.index,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// @ts-expect-error
|
||||
ast.body.unshift(frontMatterNode);
|
||||
}
|
||||
|
||||
return ast;
|
||||
}
|
||||
|
||||
|
||||
@@ -395,6 +395,9 @@ function print(path, options, print) {
|
||||
case "CommentStatement":
|
||||
return ["<!--", node.value, "-->"];
|
||||
|
||||
case "front-matter":
|
||||
return node.raw;
|
||||
|
||||
case "StringLiteral":
|
||||
return printStringLiteral(path, options);
|
||||
|
||||
|
||||
@@ -1 +1,7 @@
|
||||
export { visitorKeys as default } from "@glimmer/syntax";
|
||||
import { visitorKeys } from "@glimmer/syntax";
|
||||
|
||||
// add front-matter to the glimmer visitor keys
|
||||
export default {
|
||||
...visitorKeys,
|
||||
"front-matter": [],
|
||||
};
|
||||
@@ -0,0 +1,277 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`close.hbs format 1`] = `
|
||||
====================================options=====================================
|
||||
parsers: ["glimmer"]
|
||||
printWidth: 80
|
||||
| printWidth
|
||||
=====================================input======================================
|
||||
---
|
||||
title: An ancient philosophy...
|
||||
keywords:
|
||||
- ancient
|
||||
- philosophy
|
||||
---
|
||||
<h1>{{title}}</h1>
|
||||
<p>
|
||||
Keywords: {{#each keywords}}{{this}}{{#unless @last}}, {{/unless}}{{/each}}
|
||||
</p>
|
||||
|
||||
=====================================output=====================================
|
||||
---
|
||||
title: An ancient philosophy...
|
||||
keywords:
|
||||
- ancient
|
||||
- philosophy
|
||||
---
|
||||
|
||||
<h1>{{title}}</h1>
|
||||
<p>
|
||||
Keywords:
|
||||
{{#each keywords}}{{this}}{{#unless @last}}, {{/unless}}{{/each}}
|
||||
</p>
|
||||
================================================================================
|
||||
`;
|
||||
|
||||
exports[`empty.hbs format 1`] = `
|
||||
====================================options=====================================
|
||||
parsers: ["glimmer"]
|
||||
printWidth: 80
|
||||
| printWidth
|
||||
=====================================input======================================
|
||||
---
|
||||
---
|
||||
|
||||
<h1>Uh oh!</h1>
|
||||
|
||||
=====================================output=====================================
|
||||
---
|
||||
---
|
||||
|
||||
<h1>Uh oh!</h1>
|
||||
================================================================================
|
||||
`;
|
||||
|
||||
exports[`empty-no-newline.hbs format 1`] = `
|
||||
====================================options=====================================
|
||||
parsers: ["glimmer"]
|
||||
printWidth: 80
|
||||
| printWidth
|
||||
=====================================input======================================
|
||||
--- ---
|
||||
|
||||
=====================================output=====================================
|
||||
--- ---
|
||||
================================================================================
|
||||
`;
|
||||
|
||||
exports[`explicit-language.hbs format 1`] = `
|
||||
====================================options=====================================
|
||||
parsers: ["glimmer"]
|
||||
printWidth: 80
|
||||
| printWidth
|
||||
=====================================input======================================
|
||||
---yaml
|
||||
foo: bar
|
||||
"additional information ":
|
||||
- Yes
|
||||
- No
|
||||
data: {x:1,
|
||||
y:100000000}
|
||||
---
|
||||
|
||||
{{! Some handlebars code can go here.}}
|
||||
|
||||
=====================================output=====================================
|
||||
---yaml
|
||||
foo: bar
|
||||
"additional information ":
|
||||
- Yes
|
||||
- No
|
||||
data: { x:1, y:100000000 }
|
||||
---
|
||||
|
||||
{{! Some handlebars code can go here.}}
|
||||
================================================================================
|
||||
`;
|
||||
|
||||
exports[`invalid-yaml.hbs format 1`] = `
|
||||
====================================options=====================================
|
||||
parsers: ["glimmer"]
|
||||
printWidth: 80
|
||||
| printWidth
|
||||
=====================================input======================================
|
||||
---
|
||||
first: Thing
|
||||
second Thing
|
||||
---
|
||||
|
||||
<div class=" class-a"></div>
|
||||
|
||||
=====================================output=====================================
|
||||
---
|
||||
first: Thing
|
||||
second Thing
|
||||
---
|
||||
|
||||
<div class="class-a"></div>
|
||||
================================================================================
|
||||
`;
|
||||
|
||||
exports[`spaced.hbs format 1`] = `
|
||||
====================================options=====================================
|
||||
parsers: ["glimmer"]
|
||||
printWidth: 80
|
||||
| printWidth
|
||||
=====================================input======================================
|
||||
---
|
||||
title: An ancient philosophy...
|
||||
keywords:
|
||||
- ancient
|
||||
- philosophy
|
||||
---
|
||||
|
||||
<h1>{{title}}</h1>
|
||||
<p>
|
||||
Keywords: {{#each keywords}}{{this}}{{#unless @last}}, {{/unless}}{{/each}}
|
||||
</p>
|
||||
|
||||
=====================================output=====================================
|
||||
---
|
||||
title: An ancient philosophy...
|
||||
keywords:
|
||||
- ancient
|
||||
- philosophy
|
||||
---
|
||||
|
||||
<h1>{{title}}</h1>
|
||||
<p>
|
||||
Keywords:
|
||||
{{#each keywords}}{{this}}{{#unless @last}}, {{/unless}}{{/each}}
|
||||
</p>
|
||||
================================================================================
|
||||
`;
|
||||
|
||||
exports[`touching.hbs format 1`] = `
|
||||
====================================options=====================================
|
||||
parsers: ["glimmer"]
|
||||
printWidth: 80
|
||||
| printWidth
|
||||
=====================================input======================================
|
||||
---
|
||||
name: Smith
|
||||
--- <head>
|
||||
<title>{{name}}</title>
|
||||
</head>
|
||||
|
||||
=====================================output=====================================
|
||||
---
|
||||
name: Smith
|
||||
---
|
||||
|
||||
<head>
|
||||
<title>{{name}}</title>
|
||||
</head>
|
||||
================================================================================
|
||||
`;
|
||||
|
||||
exports[`very-ugly-yaml.hbs format 1`] = `
|
||||
====================================options=====================================
|
||||
parsers: ["glimmer"]
|
||||
printWidth: 80
|
||||
| printWidth
|
||||
=====================================input======================================
|
||||
---
|
||||
foo: bar
|
||||
test: " word"
|
||||
|
||||
|
||||
nest :
|
||||
|
||||
x: 100
|
||||
y: false
|
||||
"more stuff":
|
||||
- do
|
||||
- do
|
||||
long_text: >
|
||||
lots of text
|
||||
content
|
||||
to put here and other
|
||||
places?
|
||||
|
||||
---
|
||||
|
||||
=====================================output=====================================
|
||||
---
|
||||
foo: bar
|
||||
test: " word"
|
||||
|
||||
nest:
|
||||
x: 100
|
||||
y: false
|
||||
"more stuff":
|
||||
- do
|
||||
- do
|
||||
long_text: >
|
||||
lots of text
|
||||
content
|
||||
to put here and other
|
||||
places?
|
||||
---
|
||||
================================================================================
|
||||
`;
|
||||
|
||||
exports[`yaml-format.hbs format 1`] = `
|
||||
====================================options=====================================
|
||||
parsers: ["glimmer"]
|
||||
printWidth: 80
|
||||
| printWidth
|
||||
=====================================input======================================
|
||||
---
|
||||
title: "Example Document"
|
||||
date: 1993-02-01
|
||||
author:
|
||||
name: Arthur Mitchell
|
||||
tags:
|
||||
- tutorial
|
||||
- example
|
||||
summary: >
|
||||
A very long example document written for a person other than me, I don't know
|
||||
why this is so long. Very good example... Yes!
|
||||
---
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>{{title}}</title>
|
||||
</head>
|
||||
<body>
|
||||
{{! comment --- }}
|
||||
{{summary}}
|
||||
</body>
|
||||
</html>
|
||||
|
||||
=====================================output=====================================
|
||||
---
|
||||
title: "Example Document"
|
||||
date: 1993-02-01
|
||||
author:
|
||||
name: Arthur Mitchell
|
||||
tags:
|
||||
- tutorial
|
||||
- example
|
||||
summary: >
|
||||
A very long example document written for a person other than me, I don't know
|
||||
why this is so long. Very good example... Yes!
|
||||
---
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>{{title}}</title>
|
||||
</head>
|
||||
<body>
|
||||
{{! comment --- }}
|
||||
{{summary}}
|
||||
</body>
|
||||
</html>
|
||||
================================================================================
|
||||
`;
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
title: An ancient philosophy...
|
||||
keywords:
|
||||
- ancient
|
||||
- philosophy
|
||||
---
|
||||
<h1>{{title}}</h1>
|
||||
<p>
|
||||
Keywords: {{#each keywords}}{{this}}{{#unless @last}}, {{/unless}}{{/each}}
|
||||
</p>
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`format-embed-off.hbs - {"embeddedLanguageFormatting":"off"} format 1`] = `
|
||||
====================================options=====================================
|
||||
embeddedLanguageFormatting: "off"
|
||||
parsers: ["glimmer"]
|
||||
printWidth: 80
|
||||
| printWidth
|
||||
=====================================input======================================
|
||||
---
|
||||
title: A very interesting subject
|
||||
keywords:
|
||||
- some
|
||||
- keywords
|
||||
- for testing
|
||||
data: {x:1,
|
||||
y:100000000}
|
||||
---
|
||||
<h1>{{title}}</h1>
|
||||
<p>
|
||||
Keywords: {{#each keywords}}
|
||||
{{this}}{{#unless @last}}, {{/unless}}
|
||||
{{/each}}
|
||||
</p>
|
||||
|
||||
=====================================output=====================================
|
||||
---
|
||||
title: A very interesting subject
|
||||
keywords:
|
||||
- some
|
||||
- keywords
|
||||
- for testing
|
||||
data: {x:1,
|
||||
y:100000000}
|
||||
---
|
||||
|
||||
<h1>{{title}}</h1>
|
||||
<p>
|
||||
Keywords:
|
||||
{{#each keywords}}
|
||||
{{this}}{{#unless @last}}, {{/unless}}
|
||||
{{/each}}
|
||||
</p>
|
||||
================================================================================
|
||||
`;
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
---
|
||||
title: A very interesting subject
|
||||
keywords:
|
||||
- some
|
||||
- keywords
|
||||
- for testing
|
||||
data: {x:1,
|
||||
y:100000000}
|
||||
---
|
||||
<h1>{{title}}</h1>
|
||||
<p>
|
||||
Keywords: {{#each keywords}}
|
||||
{{this}}{{#unless @last}}, {{/unless}}
|
||||
{{/each}}
|
||||
</p>
|
||||
@@ -0,0 +1 @@
|
||||
runFormatTest(import.meta, ["glimmer"], { embeddedLanguageFormatting: "off" });
|
||||
@@ -0,0 +1 @@
|
||||
--- ---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
---
|
||||
|
||||
<h1>Uh oh!</h1>
|
||||
@@ -0,0 +1,10 @@
|
||||
---yaml
|
||||
foo: bar
|
||||
"additional information ":
|
||||
- Yes
|
||||
- No
|
||||
data: {x:1,
|
||||
y:100000000}
|
||||
---
|
||||
|
||||
{{! Some handlebars code can go here.}}
|
||||
@@ -0,0 +1 @@
|
||||
runFormatTest(import.meta, ["glimmer"]);
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
first: Thing
|
||||
second Thing
|
||||
---
|
||||
|
||||
<div class=" class-a"></div>
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
title: An ancient philosophy...
|
||||
keywords:
|
||||
- ancient
|
||||
- philosophy
|
||||
---
|
||||
|
||||
<h1>{{title}}</h1>
|
||||
<p>
|
||||
Keywords: {{#each keywords}}{{this}}{{#unless @last}}, {{/unless}}{{/each}}
|
||||
</p>
|
||||
@@ -0,0 +1,46 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`toml.hbs format 1`] = `
|
||||
====================================options=====================================
|
||||
parsers: ["glimmer"]
|
||||
printWidth: 80
|
||||
| printWidth
|
||||
=====================================input======================================
|
||||
---toml
|
||||
test = "Toml test"
|
||||
---
|
||||
<h1>{{test}}</h1>
|
||||
|
||||
=====================================output=====================================
|
||||
---toml
|
||||
!!! Formatted by with 'dummy-toml-plugin-parser-name' parser
|
||||
test = "Toml test"
|
||||
---
|
||||
|
||||
<h1>{{test}}</h1>
|
||||
================================================================================
|
||||
`;
|
||||
|
||||
exports[`toml2.hbs format 1`] = `
|
||||
====================================options=====================================
|
||||
parsers: ["glimmer"]
|
||||
printWidth: 80
|
||||
| printWidth
|
||||
=====================================input======================================
|
||||
+++
|
||||
Test TOML data
|
||||
+++
|
||||
|
||||
<Foo as
|
||||
|bar baz qux|></Foo>{{#Foo as
|
||||
|bar baz qux|}}{{/Foo}}
|
||||
|
||||
=====================================output=====================================
|
||||
+++
|
||||
!!! Formatted by with 'dummy-toml-plugin-parser-name' parser
|
||||
Test TOML data
|
||||
+++
|
||||
|
||||
<Foo as |bar baz qux| />{{#Foo as |bar baz qux|}}{{/Foo}}
|
||||
================================================================================
|
||||
`;
|
||||
@@ -0,0 +1,3 @@
|
||||
import prettierPluginDummyToml from "../../../../config/prettier-plugins/prettier-plugin-dummy-toml/index.js";
|
||||
|
||||
runFormatTest(import.meta, ["glimmer"], { plugins: [prettierPluginDummyToml] });
|
||||
@@ -0,0 +1,4 @@
|
||||
---toml
|
||||
test = "Toml test"
|
||||
---
|
||||
<h1>{{test}}</h1>
|
||||
@@ -0,0 +1,7 @@
|
||||
+++
|
||||
Test TOML data
|
||||
+++
|
||||
|
||||
<Foo as
|
||||
|bar baz qux|></Foo>{{#Foo as
|
||||
|bar baz qux|}}{{/Foo}}
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
name: Smith
|
||||
--- <head>
|
||||
<title>{{name}}</title>
|
||||
</head>
|
||||
@@ -0,0 +1,19 @@
|
||||
---
|
||||
foo: bar
|
||||
test: " word"
|
||||
|
||||
|
||||
nest :
|
||||
|
||||
x: 100
|
||||
y: false
|
||||
"more stuff":
|
||||
- do
|
||||
- do
|
||||
long_text: >
|
||||
lots of text
|
||||
content
|
||||
to put here and other
|
||||
places?
|
||||
|
||||
---
|
||||
@@ -0,0 +1,22 @@
|
||||
---
|
||||
title: "Example Document"
|
||||
date: 1993-02-01
|
||||
author:
|
||||
name: Arthur Mitchell
|
||||
tags:
|
||||
- tutorial
|
||||
- example
|
||||
summary: >
|
||||
A very long example document written for a person other than me, I don't know
|
||||
why this is so long. Very good example... Yes!
|
||||
---
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>{{title}}</title>
|
||||
</head>
|
||||
<body>
|
||||
{{! comment --- }}
|
||||
{{summary}}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1251,6 +1251,7 @@ exports[`visitor keys glimmer 1`] = `
|
||||
],
|
||||
"TextNode": [],
|
||||
"UndefinedLiteral": [],
|
||||
"front-matter": [],
|
||||
}
|
||||
`;
|
||||
|
||||
|
||||
Reference in new issue
Block a user