diff --git a/changelog_unreleased/handlebars/pr-7275.md b/changelog_unreleased/handlebars/pr-7275.md
new file mode 100644
index 000000000..3a2a6a7d8
--- /dev/null
+++ b/changelog_unreleased/handlebars/pr-7275.md
@@ -0,0 +1,49 @@
+#### Glimmer: Add prettier-ignore ([#7275](https://github.com/prettier/prettier/pull/7275) by [@chadian](https://github.com/chadian))
+
+
+```hbs
+{{! Input}}
+{{! prettier-ignore }}
+
+ "hello! my parent was ignored"
+ {{#my-crazy-component "shall" be="preserved"}}
+
+ {{/my-crazy-component}}
+
+
+{{#a-normal-component isRestoredTo = "order" }}
+
+{{/a-normal-component}}
+
+{{! Prettier stable}}
+{{! prettier-ignore }}
+
+ "hello! my parent was ignored"
+ {{#my-crazy-component "shall" be="preserved"}}
+
+ {{/my-crazy-component}}
+
+
+{{#a-normal-component isRestoredTo="order"}}
+
+{{/a-normal-component}}
+
+{{! Prettier master}}
+{{! prettier-ignore }}
+
+ "hello! my parent was ignored"
+ {{#my-crazy-component "shall" be="preserved"}}
+
+ {{/my-crazy-component}}
+
+
+{{#a-normal-component isRestoredTo='order'}}
+
+{{/a-normal-component}}
+```
diff --git a/docs/ignore.md b/docs/ignore.md
index d4b3a7db0..fe4a54f8e 100644
--- a/docs/ignore.md
+++ b/docs/ignore.md
@@ -117,3 +117,18 @@ This type of ignore is only allowed to be used in top-level and aimed to disable
}
}
```
+
+## Handlebars
+
+
+```hbs
+{{! prettier-ignore }}
+
+ "hello! my parent was ignored"
+ {{#my-crazy-component "shall" be="preserved"}}
+
+ {{/my-crazy-component}}
+
+```
diff --git a/src/language-handlebars/parser-glimmer.js b/src/language-handlebars/parser-glimmer.js
index 3c4568b2f..fe47501de 100644
--- a/src/language-handlebars/parser-glimmer.js
+++ b/src/language-handlebars/parser-glimmer.js
@@ -29,6 +29,10 @@ module.exports = {
glimmer: {
parse,
astFormat: "glimmer",
+ // TODO: `locStart` and `locEnd` should return a number offset
+ // https://prettier.io/docs/en/plugins.html#parsers
+ // but we need access to the original text to use
+ // `loc.start` and `loc.end` objects to calculate the offset
locStart(node) {
return node.loc && node.loc.start;
},
diff --git a/src/language-handlebars/printer-glimmer.js b/src/language-handlebars/printer-glimmer.js
index 1c7e382cc..8888ede19 100644
--- a/src/language-handlebars/printer-glimmer.js
+++ b/src/language-handlebars/printer-glimmer.js
@@ -40,6 +40,22 @@ function print(path, options, print) {
return "";
}
+ if (hasPrettierIgnore(path)) {
+ const startOffset = locationToOffset(
+ options.originalText,
+ n.loc.start.line - 1,
+ n.loc.start.column
+ );
+ const endOffset = locationToOffset(
+ options.originalText,
+ n.loc.end.line - 1,
+ n.loc.end.column
+ );
+
+ const ignoredText = options.originalText.slice(startOffset, endOffset);
+ return ignoredText;
+ }
+
switch (n.type) {
case "Block":
case "Program":
@@ -474,15 +490,15 @@ function isParentOfType(path, nodeType) {
return p && p.type === nodeType;
}
-function getPreviousNode(path) {
+function getPreviousNode(path, lookBack = 1) {
const node = path.getValue();
const parentNode = path.getParentNode(0);
- const children = parentNode.children || parentNode.body;
+ const children = parentNode && (parentNode.children || parentNode.body);
if (children) {
const nodeIndex = children.indexOf(node);
if (nodeIndex > 0) {
- const previousNode = children[nodeIndex - 1];
+ const previousNode = children[nodeIndex - lookBack];
return previousNode;
}
}
@@ -553,6 +569,58 @@ function generateHardlines(number = 0, max = 0) {
return new Array(Math.min(number, max)).fill(hardline);
}
+function hasPrettierIgnore(path) {
+ const n = path.getValue();
+ const previousPreviousNode = getPreviousNode(path, 2);
+ const isIgnoreNode = isPrettierIgnoreNode(n);
+ const isCoveredByIgnoreNode = isPrettierIgnoreNode(previousPreviousNode);
+
+ return isIgnoreNode || isCoveredByIgnoreNode;
+}
+
+/* istanbul ignore next
+ https://github.com/glimmerjs/glimmer-vm/blob/master/packages/%40glimmer/compiler/lib/location.ts#L5-L29
+*/
+function locationToOffset(source, line, column) {
+ let seenLines = 0;
+ let seenChars = 0;
+
+ // eslint-disable-next-line no-constant-condition
+ while (true) {
+ if (seenChars === source.length) {
+ return null;
+ }
+
+ let nextLine = source.indexOf("\n", seenChars);
+ if (nextLine === -1) {
+ nextLine = source.length;
+ }
+
+ if (seenLines === line) {
+ if (seenChars + column > nextLine) {
+ return null;
+ }
+ return seenChars + column;
+ } else if (nextLine === -1) {
+ return null;
+ }
+ seenLines += 1;
+ seenChars = nextLine + 1;
+ }
+}
+
+function isPrettierIgnoreNode(node) {
+ if (!node) {
+ return false;
+ }
+
+ const isMustacheComment = node.type === "MustacheCommentStatement";
+ const containsPrettierIgnore =
+ typeof node.value === "string" && node.value.trim() === "prettier-ignore";
+
+ return isMustacheComment && containsPrettierIgnore;
+}
+
module.exports = {
print,
massageAstNode: clean
diff --git a/tests/handlebars-prettier-ignore/__snapshots__/jsfmt.spec.js.snap b/tests/handlebars-prettier-ignore/__snapshots__/jsfmt.spec.js.snap
new file mode 100644
index 000000000..f7e122adf
--- /dev/null
+++ b/tests/handlebars-prettier-ignore/__snapshots__/jsfmt.spec.js.snap
@@ -0,0 +1,154 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`prettier-ignore.hbs 1`] = `
+====================================options=====================================
+parsers: ["glimmer"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+{{! prettier-ignore }}
+
+ "hello! my parent was ignored"
+ {{#my-crazy-component "shall" be="preserved"}}
+
+ {{/my-crazy-component}}
+
+
+{{#a-normal-component isRestoredTo = "order" }}
+
+{{/a-normal-component}}
+
+
+
+ {{! prettier-ignore }}
+
+
+
+
+
+
+ {{#another-sibling as |isFixed|}}
+
+
{{ isFixed }}
+
+ All of this should be fixed
+
+
+
+ {{/another-sibling}}
+
+=====================================output=====================================
+{{! prettier-ignore }}
+
+ "hello! my parent was ignored"
+ {{#my-crazy-component "shall" be="preserved"}}
+
+ {{/my-crazy-component}}
+
+
+{{#a-normal-component isRestoredTo="order"}}
+
+{{/a-normal-component}}
+
+
+
+ {{! prettier-ignore }}
+
+
+
+
+
+
+ {{#another-sibling as |isFixed|}}
+
+ {{isFixed}}
+
+ All of this should be fixed
+
+ {{/another-sibling}}
+
+================================================================================
+`;
+
+exports[`prettier-ignore.hbs 2`] = `
+====================================options=====================================
+parsers: ["glimmer"]
+printWidth: 80
+singleQuote: true
+ | printWidth
+=====================================input======================================
+{{! prettier-ignore }}
+
+ "hello! my parent was ignored"
+ {{#my-crazy-component "shall" be="preserved"}}
+
+ {{/my-crazy-component}}
+
+
+{{#a-normal-component isRestoredTo = "order" }}
+
+{{/a-normal-component}}
+
+
+
+ {{! prettier-ignore }}
+
+
+
+
+
+
+ {{#another-sibling as |isFixed|}}
+
+
{{ isFixed }}
+
+ All of this should be fixed
+
+
+
+ {{/another-sibling}}
+
+=====================================output=====================================
+{{! prettier-ignore }}
+
+ "hello! my parent was ignored"
+ {{#my-crazy-component "shall" be="preserved"}}
+
+ {{/my-crazy-component}}
+
+
+{{#a-normal-component isRestoredTo='order'}}
+
+{{/a-normal-component}}
+
+
+
+ {{! prettier-ignore }}
+
+
+
+
+
+
+ {{#another-sibling as |isFixed|}}
+
+ {{isFixed}}
+
+ All of this should be fixed
+
+ {{/another-sibling}}
+
+================================================================================
+`;
diff --git a/tests/handlebars-prettier-ignore/jsfmt.spec.js b/tests/handlebars-prettier-ignore/jsfmt.spec.js
new file mode 100644
index 000000000..4abf117d9
--- /dev/null
+++ b/tests/handlebars-prettier-ignore/jsfmt.spec.js
@@ -0,0 +1,2 @@
+run_spec(__dirname, ["glimmer"]);
+run_spec(__dirname, ["glimmer"], { singleQuote: true });
diff --git a/tests/handlebars-prettier-ignore/prettier-ignore.hbs b/tests/handlebars-prettier-ignore/prettier-ignore.hbs
new file mode 100644
index 000000000..cfe3574a1
--- /dev/null
+++ b/tests/handlebars-prettier-ignore/prettier-ignore.hbs
@@ -0,0 +1,34 @@
+{{! prettier-ignore }}
+
+ "hello! my parent was ignored"
+ {{#my-crazy-component "shall" be="preserved"}}
+
+ {{/my-crazy-component}}
+
+
+{{#a-normal-component isRestoredTo = "order" }}
+
+{{/a-normal-component}}
+
+
+
+ {{! prettier-ignore }}
+
+
+
+
+
+
+ {{#another-sibling as |isFixed|}}
+
+
{{ isFixed }}
+
+ All of this should be fixed
+
+
+
+ {{/another-sibling}}
+
\ No newline at end of file