Skip to content

Commit

Permalink
Support handlebars (#3534)
Browse files Browse the repository at this point in the history
* feat(glimmer): initial HTML/Handlebars/Glimmer support

* feat(glimmer): support un-escaped mustache expressions

* fix(glimmer): add 'as |foo|' syntax

* fix(glimmer): support {{foo bar}} syntax

* feat(glimmer): implement all AST types

* feat(glimmer): implement if/else if/else

* test(glimmer): ignore leading/trailing whitespace from AST_COMPARE

* fix(glimmer): do not use trailing slash for void self-closing elements

* chore(build): disable html tests until we can sort out the glimmer dependency

* feat(html): complete rebase on parse5 addition

* Prettier Support For Glimmer VM/Handlebars

Polished Support for Sub Expressions
Added test cases for glimmer primitives
Added support for concat statements
Attempted to make element nodes work
Attempted block statements
Element Nodes are OK
Added support for block elements that are not else-if related
Added support for Else/If
Cleaning up
Rebase
Switch node 4 syntax
Update build

* Removed dead code/partials

* Added new lines to end of test files.

* Rebase after plugin change

* Added ignores to code coverage
  • Loading branch information
robert-j-webb authored and vjeux committed Dec 29, 2017
1 parent 6a75f66 commit 833666a
Show file tree
Hide file tree
Showing 35 changed files with 1,346 additions and 6 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
},
"dependencies": {
"@babel/code-frame": "7.0.0-beta.35",
"@glimmer/syntax": "0.30.3",
"babylon": "7.0.0-beta.34",
"camelcase": "4.1.0",
"chalk": "2.1.0",
Expand Down
5 changes: 5 additions & 0 deletions scripts/build/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ for (const parser of parsers) {
shell.exec(
`rollup -c scripts/build/rollup.parser.config.js --environment parser:${parser}`
);
if (parser.endsWith("glimmer")) {
shell.exec(
`node_modules/babel-cli/bin/babel.js dist/parser-glimmer.js --out-file dist/parser-glimmer.js --presets=es2015`
);
}
}

shell.echo("\nsrc/language-css/parser-postcss.js → dist/parser-postcss.js");
Expand Down
1 change: 1 addition & 0 deletions scripts/build/parsers.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module.exports = [
"language-js/parser-flow",
"language-js/parser-typescript",
"language-graphql/parser-graphql",
"language-handlebars/parser-glimmer",
"language-css/parser-postcss",
"language-html/parser-parse5",
"language-markdown/parser-markdown",
Expand Down
19 changes: 18 additions & 1 deletion scripts/build/rollup.parser.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,24 @@ export default Object.assign(baseConfig, {
: {},
json(),
resolve({ preferBuiltins: true }),
commonjs(),
commonjs(
parser.endsWith("glimmer")
? {
namedExports: {
"node_modules/handlebars/lib/index.js": ["parse"],
"node_modules/simple-html-tokenizer/dist/simple-html-tokenizer.js": [
"EntityParser",
"HTML5NamedCharRefs",
"EventedTokenizer"
],
"node_modules/@glimmer/syntax/dist/modules/index.js": "default",
"node_modules/@glimmer/syntax/dist/modules/es2017/index.js":
"default"
},
ignore: ["source-map"]
}
: {}
),
{
transformBundle(code) {
const result = uglify.minify(code, {});
Expand Down
1 change: 1 addition & 0 deletions src/cli/constant.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ const detailedOptions = normalizeDetailedOptions({
"less",
"scss",
"json",
// "glimmer",
"graphql",
"markdown",
"vue"
Expand Down
8 changes: 8 additions & 0 deletions src/common/clean-ast.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,14 @@ function massageAST(ast, parent) {
newObj.value = newObj.value.replace(/ /g, "");
}

// (Glimmer/HTML) ignore TextNode whitespace
if (ast.type === "TextNode") {
if (ast.chars.replace(/\s+/, "") === "") {
return undefined;
}
newObj.chars = ast.chars.replace(/^\s+/, "").replace(/\s+$/, "");
}

if (
(ast.type === "value-word" && ast.isColor && ast.isHex) ||
ast.type === "media-feature" ||
Expand Down
1 change: 1 addition & 0 deletions src/common/load-plugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ function loadPlugins(options) {
const internalPlugins = [
require("../language-js"),
require("../language-css"),
require("../language-handlebars"),
require("../language-graphql"),
require("../language-markdown"),
require("../language-html"),
Expand Down
37 changes: 37 additions & 0 deletions src/language-handlebars/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"use strict";

const printer = require("./printer-glimmer");

// Based on:
// https://github.com/github/linguist/blob/master/lib/linguist/languages.yml

const languages = [
{
type: "markup",
group: "HTML",
aliases: ["hbs", "htmlbars"],
extensions: [".handlebars", ".hbs"],
tm_scope: "text.html.handlebars",
ace_mode: "handlebars",
language_id: 155
}
];

const parsers = {
glimmer: {
get parse() {
return eval("require")("./parser-glimmer");
},
astFormat: "glimmer"
}
};

const printers = {
glimmer: printer
};

module.exports = {
languages,
parsers,
printers
};
45 changes: 45 additions & 0 deletions src/language-handlebars/parser-glimmer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"use strict";

const createError = require("../common/parser-create-error");
function removeEmptyNodes(node) {
return (
node.type !== "TextNode" ||
(node.type === "TextNode" &&
node.chars.replace(/^\s+/, "").replace(/\s+$/, "") !== "")
);
}
function removeWhiteSpace() {
return {
visitor: {
Program(node) {
node.body = node.body.filter(removeEmptyNodes);
},
ElementNode(node) {
node.children = node.children.filter(removeEmptyNodes);
}
}
};
}

function parse(text) {
try {
const glimmer = require("@glimmer/syntax").preprocess;
return glimmer(text, {
plugins: {
ast: [removeWhiteSpace]
}
});
/* istanbul ignore next */
} catch (error) {
const matches = error.message.match(/on line (\d+)/);
if (matches) {
throw createError(error.message, {
start: { line: +matches[1], column: 0 },
end: { line: +matches[1], column: 80 }
});
} else {
throw error;
}
}
}
module.exports = parse;

0 comments on commit 833666a

Please sign in to comment.