From 88bcec10ccda8339b281d6425d8ea50e5e4a3867 Mon Sep 17 00:00:00 2001 From: Ika Date: Thu, 11 Oct 2018 16:02:35 +0800 Subject: [PATCH 001/177] feat: support pragma --- src/language-html/parser-html.js | 2 ++ src/language-html/pragma.js | 14 ++++++++++++ src/language-html/printer-htmlparser2.js | 2 ++ .../insert/__snapshots__/jsfmt.spec.js.snap | 21 ++++++++++++++++++ tests/html_pragma/insert/jsfmt.spec.js | 1 + tests/html_pragma/insert/with-pragma.html | 3 +++ tests/html_pragma/insert/without-pragma.html | 1 + .../require/__snapshots__/jsfmt.spec.js.snap | 22 +++++++++++++++++++ tests/html_pragma/require/jsfmt.spec.js | 1 + tests/html_pragma/require/with-pragma.html | 4 ++++ tests/html_pragma/require/without-pragma.html | 2 ++ 11 files changed, 73 insertions(+) create mode 100644 src/language-html/pragma.js create mode 100644 tests/html_pragma/insert/__snapshots__/jsfmt.spec.js.snap create mode 100644 tests/html_pragma/insert/jsfmt.spec.js create mode 100644 tests/html_pragma/insert/with-pragma.html create mode 100644 tests/html_pragma/insert/without-pragma.html create mode 100644 tests/html_pragma/require/__snapshots__/jsfmt.spec.js.snap create mode 100644 tests/html_pragma/require/jsfmt.spec.js create mode 100644 tests/html_pragma/require/with-pragma.html create mode 100644 tests/html_pragma/require/without-pragma.html diff --git a/src/language-html/parser-html.js b/src/language-html/parser-html.js index 1e3469644242..82d8105e8a94 100644 --- a/src/language-html/parser-html.js +++ b/src/language-html/parser-html.js @@ -2,6 +2,7 @@ const parseFrontMatter = require("../utils/front-matter"); const { HTML_ELEMENT_ATTRIBUTES, HTML_TAGS, mapNode } = require("./utils"); +const { hasPragma } = require("./pragma"); function parse(text, parsers, options, { shouldParseFrontMatter = true } = {}) { const { frontMatter, content } = shouldParseFrontMatter @@ -217,6 +218,7 @@ module.exports = { parsers: { html: { parse, + hasPragma, astFormat: "htmlparser2", locStart, locEnd diff --git a/src/language-html/pragma.js b/src/language-html/pragma.js new file mode 100644 index 000000000000..650328d4f3ef --- /dev/null +++ b/src/language-html/pragma.js @@ -0,0 +1,14 @@ +"use strict"; + +function hasPragma(text) { + return /^\s*/.test(text); +} + +function insertPragma(text) { + return "\n\n" + text.replace(/^\s*\n/, ""); +} + +module.exports = { + hasPragma, + insertPragma +}; diff --git a/src/language-html/printer-htmlparser2.js b/src/language-html/printer-htmlparser2.js index 279431e5ef46..f987f6f91879 100644 --- a/src/language-html/printer-htmlparser2.js +++ b/src/language-html/printer-htmlparser2.js @@ -34,6 +34,7 @@ const { } = require("./utils"); const preprocess = require("./preprocess"); const assert = require("assert"); +const { insertPragma } = require("./pragma"); function concat(parts) { const newParts = normalizeParts(parts); @@ -578,6 +579,7 @@ function printClosingTagEndMarker(node) { module.exports = { preprocess, print: genericPrint, + insertPragma, massageAstNode: clean, embed, hasPrettierIgnore diff --git a/tests/html_pragma/insert/__snapshots__/jsfmt.spec.js.snap b/tests/html_pragma/insert/__snapshots__/jsfmt.spec.js.snap new file mode 100644 index 000000000000..ed4f00c2b849 --- /dev/null +++ b/tests/html_pragma/insert/__snapshots__/jsfmt.spec.js.snap @@ -0,0 +1,21 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`with-pragma.html - html-verify 1`] = ` + + +Hello World +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +Hello World + +`; + +exports[`without-pragma.html - html-verify 1`] = ` +Hello World +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +Hello World + +`; diff --git a/tests/html_pragma/insert/jsfmt.spec.js b/tests/html_pragma/insert/jsfmt.spec.js new file mode 100644 index 000000000000..d7461ff2d287 --- /dev/null +++ b/tests/html_pragma/insert/jsfmt.spec.js @@ -0,0 +1 @@ +run_spec(__dirname, ["html"], { insertPragma: true }); diff --git a/tests/html_pragma/insert/with-pragma.html b/tests/html_pragma/insert/with-pragma.html new file mode 100644 index 000000000000..352d2124e5e5 --- /dev/null +++ b/tests/html_pragma/insert/with-pragma.html @@ -0,0 +1,3 @@ + + +Hello World diff --git a/tests/html_pragma/insert/without-pragma.html b/tests/html_pragma/insert/without-pragma.html new file mode 100644 index 000000000000..e0a4a305cdb9 --- /dev/null +++ b/tests/html_pragma/insert/without-pragma.html @@ -0,0 +1 @@ +Hello World diff --git a/tests/html_pragma/require/__snapshots__/jsfmt.spec.js.snap b/tests/html_pragma/require/__snapshots__/jsfmt.spec.js.snap new file mode 100644 index 000000000000..c5166dceff9e --- /dev/null +++ b/tests/html_pragma/require/__snapshots__/jsfmt.spec.js.snap @@ -0,0 +1,22 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`with-pragma.html - html-verify 1`] = ` + + +
666
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +
666
+ +`; + +exports[`without-pragma.html - html-verify 1`] = ` +
666
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +
666
+ +`; diff --git a/tests/html_pragma/require/jsfmt.spec.js b/tests/html_pragma/require/jsfmt.spec.js new file mode 100644 index 000000000000..356f6e9167f4 --- /dev/null +++ b/tests/html_pragma/require/jsfmt.spec.js @@ -0,0 +1 @@ +run_spec(__dirname, ["html"], { requirePragma: true }); diff --git a/tests/html_pragma/require/with-pragma.html b/tests/html_pragma/require/with-pragma.html new file mode 100644 index 000000000000..2dcc4229c8a6 --- /dev/null +++ b/tests/html_pragma/require/with-pragma.html @@ -0,0 +1,4 @@ + + +
666
diff --git a/tests/html_pragma/require/without-pragma.html b/tests/html_pragma/require/without-pragma.html new file mode 100644 index 000000000000..4b46c5df9d10 --- /dev/null +++ b/tests/html_pragma/require/without-pragma.html @@ -0,0 +1,2 @@ +
666
From a31faad645ba496013ce5eea5573664e6b8b7772 Mon Sep 17 00:00:00 2001 From: Ika Date: Thu, 11 Oct 2018 16:17:12 +0800 Subject: [PATCH 002/177] feat: update inferScriptParser - merge logic from language-vue --- src/language-html/utils.js | 39 ++++++++++++------- .../html_css/__snapshots__/jsfmt.spec.js.snap | 2 +- .../html_js/__snapshots__/jsfmt.spec.js.snap | 31 ++++++++------- 3 files changed, 43 insertions(+), 29 deletions(-) diff --git a/src/language-html/utils.js b/src/language-html/utils.js index 1b8eed5f390e..b09ee0cb64b5 100644 --- a/src/language-html/utils.js +++ b/src/language-html/utils.js @@ -261,26 +261,37 @@ function hasNonTextChild(node) { } function inferScriptParser(node) { - if ( - node.name === "script" && - ((!node.attribs.lang && !node.attribs.type) || + if (node.name === "script" && !node.attribs.src) { + if ( + (!node.attribs.lang && !node.attribs.type) || node.attribs.type === "text/javascript" || node.attribs.type === "text/babel" || - node.attribs.type === "application/javascript") - ) { - return "babylon"; - } + node.attribs.type === "application/javascript" + ) { + return "babylon"; + } - if ( - node.name === "script" && - (node.attribs.type === "application/x-typescript" || - node.attribs.lang === "ts") - ) { - return "typescript"; + if ( + node.attribs.type === "application/x-typescript" || + node.attribs.lang === "ts" || + node.attribs.lang === "tsx" + ) { + return "typescript"; + } } if (node.name === "style") { - return "css"; + if (!node.attribs.lang || node.attribs.lang === "postcss") { + return "css"; + } + + if (node.attribs.lang === "scss") { + return "scss"; + } + + if (node.attribs.lang === "less") { + return "less"; + } } return null; diff --git a/tests/html_css/__snapshots__/jsfmt.spec.js.snap b/tests/html_css/__snapshots__/jsfmt.spec.js.snap index c3d18195d04e..da15a1497d29 100644 --- a/tests/html_css/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_css/__snapshots__/jsfmt.spec.js.snap @@ -36,7 +36,7 @@ exports[`less.html - html-verify 1`] = ` + `; @@ -46,7 +45,6 @@ const x = 1; - + `; diff --git a/tests/multiparser_vue/__snapshots__/jsfmt.spec.js.snap b/tests/multiparser_vue/__snapshots__/jsfmt.spec.js.snap index 684d5402a9a8..1c3670d05b99 100644 --- a/tests/multiparser_vue/__snapshots__/jsfmt.spec.js.snap +++ b/tests/multiparser_vue/__snapshots__/jsfmt.spec.js.snap @@ -63,10 +63,10 @@ exports[`template-bind.vue - vue-verify 1`] = ` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ `; @@ -85,11 +85,12 @@ exports[`template-class.vue - vue-verify 1`] = ` `; @@ -118,10 +119,12 @@ p { font-size : 2em ; text-align : center ; } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - + - + - + `; diff --git a/tests/range_vue/__snapshots__/jsfmt.spec.js.snap b/tests/range_vue/__snapshots__/jsfmt.spec.js.snap index ab6fa7b00001..3b327792eb0e 100644 --- a/tests/range_vue/__snapshots__/jsfmt.spec.js.snap +++ b/tests/range_vue/__snapshots__/jsfmt.spec.js.snap @@ -15,8 +15,7 @@ let Prettier = format => { your.js('though') } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - `; diff --git a/tests/require-pragma/vue/__snapshots__/jsfmt.spec.js.snap b/tests/require-pragma/vue/__snapshots__/jsfmt.spec.js.snap index b8b93a41c9d2..cb87d7271519 100644 --- a/tests/require-pragma/vue/__snapshots__/jsfmt.spec.js.snap +++ b/tests/require-pragma/vue/__snapshots__/jsfmt.spec.js.snap @@ -17,8 +17,7 @@ const x = 1; - + `; diff --git a/tests/vue_examples/__snapshots__/jsfmt.spec.js.snap b/tests/vue_examples/__snapshots__/jsfmt.spec.js.snap index dfe7afb36a42..f8e26fff16aa 100644 --- a/tests/vue_examples/__snapshots__/jsfmt.spec.js.snap +++ b/tests/vue_examples/__snapshots__/jsfmt.spec.js.snap @@ -133,19 +133,26 @@ export default { @@ -284,19 +291,26 @@ export default { @@ -307,7 +321,9 @@ exports[`script_src.vue - vue-verify 1`] = ` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - + `; @@ -316,7 +332,9 @@ exports[`script_src.vue - vue-verify 2`] = ` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - + `; @@ -400,15 +418,11 @@ exports[`test.vue - vue-verify 1`] = ` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - + `; @@ -425,15 +439,11 @@ exports[`test.vue - vue-verify 2`] = ` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - + `; diff --git a/tests_config/require_standalone.js b/tests_config/require_standalone.js index 8f01fcecabb7..331ba12a1541 100644 --- a/tests_config/require_standalone.js +++ b/tests_config/require_standalone.js @@ -14,7 +14,6 @@ const sources = [ "parser-markdown.js", "parser-postcss.js", "parser-typescript.js", - "parser-vue.js", "parser-yaml.js" ].map(filename => fs.readFileSync(path.join(process.env.PRETTIER_DIR, filename), "utf-8") diff --git a/website/static/service-worker.js b/website/static/service-worker.js index de5af787c43b..5fe9e2f8873d 100644 --- a/website/static/service-worker.js +++ b/website/static/service-worker.js @@ -16,7 +16,6 @@ toolbox.precache([ "lib/parser-markdown.js", "lib/parser-postcss.js", "lib/parser-typescript.js", - "lib/parser-vue.js", "lib/parser-yaml.js", "playground.js", "https://unpkg.com/sw-toolbox@3.6.0/sw-toolbox.js", diff --git a/website/static/worker.js b/website/static/worker.js index cd8cf8d942c0..720a865bd75c 100644 --- a/website/static/worker.js +++ b/website/static/worker.js @@ -74,12 +74,6 @@ var parsers = { return prettierPlugins.markdown.parsers.mdx; }, - // Vue - get vue() { - importScriptOnce("lib/parser-vue.js"); - return prettierPlugins.vue.parsers.vue; - }, - // YAML get yaml() { importScriptOnce("lib/parser-yaml.js"); @@ -96,6 +90,11 @@ var parsers = { get html() { importScriptOnce("lib/parser-html.js"); return prettierPlugins.html.parsers.html; + }, + // Vue + get vue() { + importScriptOnce("lib/parser-html.js"); + return prettierPlugins.html.parsers.vue; } }; From 2174ad887d8943eb14f080ddbdde968112d947c5 Mon Sep 17 00:00:00 2001 From: Ika Date: Thu, 11 Oct 2018 17:57:37 +0800 Subject: [PATCH 006/177] fix: force not to break ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - + `; @@ -332,9 +330,7 @@ exports[`script_src.vue - vue-verify 2`] = ` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - + `; From e8a1200451f7667d459778046eb9e843021af3cf Mon Sep 17 00:00:00 2001 From: Ika Date: Thu, 11 Oct 2018 17:59:36 +0800 Subject: [PATCH 007/177] chore: move pragma tests --- .../html}/__snapshots__/jsfmt.spec.js.snap | 0 tests/{html_pragma/insert => insert-pragma/html}/jsfmt.spec.js | 0 tests/{html_pragma/insert => insert-pragma/html}/with-pragma.html | 0 .../insert => insert-pragma/html}/without-pragma.html | 0 .../html}/__snapshots__/jsfmt.spec.js.snap | 0 tests/{html_pragma/require => require-pragma/html}/jsfmt.spec.js | 0 .../{html_pragma/require => require-pragma/html}/with-pragma.html | 0 .../require => require-pragma/html}/without-pragma.html | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename tests/{html_pragma/insert => insert-pragma/html}/__snapshots__/jsfmt.spec.js.snap (100%) rename tests/{html_pragma/insert => insert-pragma/html}/jsfmt.spec.js (100%) rename tests/{html_pragma/insert => insert-pragma/html}/with-pragma.html (100%) rename tests/{html_pragma/insert => insert-pragma/html}/without-pragma.html (100%) rename tests/{html_pragma/require => require-pragma/html}/__snapshots__/jsfmt.spec.js.snap (100%) rename tests/{html_pragma/require => require-pragma/html}/jsfmt.spec.js (100%) rename tests/{html_pragma/require => require-pragma/html}/with-pragma.html (100%) rename tests/{html_pragma/require => require-pragma/html}/without-pragma.html (100%) diff --git a/tests/html_pragma/insert/__snapshots__/jsfmt.spec.js.snap b/tests/insert-pragma/html/__snapshots__/jsfmt.spec.js.snap similarity index 100% rename from tests/html_pragma/insert/__snapshots__/jsfmt.spec.js.snap rename to tests/insert-pragma/html/__snapshots__/jsfmt.spec.js.snap diff --git a/tests/html_pragma/insert/jsfmt.spec.js b/tests/insert-pragma/html/jsfmt.spec.js similarity index 100% rename from tests/html_pragma/insert/jsfmt.spec.js rename to tests/insert-pragma/html/jsfmt.spec.js diff --git a/tests/html_pragma/insert/with-pragma.html b/tests/insert-pragma/html/with-pragma.html similarity index 100% rename from tests/html_pragma/insert/with-pragma.html rename to tests/insert-pragma/html/with-pragma.html diff --git a/tests/html_pragma/insert/without-pragma.html b/tests/insert-pragma/html/without-pragma.html similarity index 100% rename from tests/html_pragma/insert/without-pragma.html rename to tests/insert-pragma/html/without-pragma.html diff --git a/tests/html_pragma/require/__snapshots__/jsfmt.spec.js.snap b/tests/require-pragma/html/__snapshots__/jsfmt.spec.js.snap similarity index 100% rename from tests/html_pragma/require/__snapshots__/jsfmt.spec.js.snap rename to tests/require-pragma/html/__snapshots__/jsfmt.spec.js.snap diff --git a/tests/html_pragma/require/jsfmt.spec.js b/tests/require-pragma/html/jsfmt.spec.js similarity index 100% rename from tests/html_pragma/require/jsfmt.spec.js rename to tests/require-pragma/html/jsfmt.spec.js diff --git a/tests/html_pragma/require/with-pragma.html b/tests/require-pragma/html/with-pragma.html similarity index 100% rename from tests/html_pragma/require/with-pragma.html rename to tests/require-pragma/html/with-pragma.html diff --git a/tests/html_pragma/require/without-pragma.html b/tests/require-pragma/html/without-pragma.html similarity index 100% rename from tests/html_pragma/require/without-pragma.html rename to tests/require-pragma/html/without-pragma.html From 7f528c812152adf622ef7922ca4c3380b16b9e7c Mon Sep 17 00:00:00 2001 From: Ika Date: Fri, 12 Oct 2018 12:27:25 +0800 Subject: [PATCH 008/177] test: add tests --- tests/html_cdata/__snapshots__/jsfmt.spec.js.snap | 8 ++++++++ tests/html_cdata/example.html | 1 + tests/html_cdata/jsfmt.spec.js | 1 + 3 files changed, 10 insertions(+) create mode 100644 tests/html_cdata/__snapshots__/jsfmt.spec.js.snap create mode 100644 tests/html_cdata/example.html create mode 100644 tests/html_cdata/jsfmt.spec.js diff --git a/tests/html_cdata/__snapshots__/jsfmt.spec.js.snap b/tests/html_cdata/__snapshots__/jsfmt.spec.js.snap new file mode 100644 index 000000000000..ff804cf5041b --- /dev/null +++ b/tests/html_cdata/__snapshots__/jsfmt.spec.js.snap @@ -0,0 +1,8 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`example.html - html-verify 1`] = ` +John Smith]]> +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +`; diff --git a/tests/html_cdata/example.html b/tests/html_cdata/example.html new file mode 100644 index 000000000000..e62ba2a308f4 --- /dev/null +++ b/tests/html_cdata/example.html @@ -0,0 +1 @@ +John Smith]]> diff --git a/tests/html_cdata/jsfmt.spec.js b/tests/html_cdata/jsfmt.spec.js new file mode 100644 index 000000000000..53763df9b20b --- /dev/null +++ b/tests/html_cdata/jsfmt.spec.js @@ -0,0 +1 @@ +run_spec(__dirname, ["html"]); From f7b85b7b3440ebeaf39eef2fee8db6a9d10bd462 Mon Sep 17 00:00:00 2001 From: Ika Date: Fri, 12 Oct 2018 12:32:01 +0800 Subject: [PATCH 009/177] feat: recognize CDATA --- src/language-html/parser-html.js | 3 +- src/language-html/preprocess.js | 51 +++++++++++++++++++ .../__snapshots__/jsfmt.spec.js.snap | 2 +- 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/language-html/parser-html.js b/src/language-html/parser-html.js index ab66c1da61ab..9fc6e599af85 100644 --- a/src/language-html/parser-html.js +++ b/src/language-html/parser-html.js @@ -89,7 +89,8 @@ function htmlparser2(text, recognizeSelfClosing) { new CustomParser(handler, { lowerCaseTags: true, // preserve lowercase tag names to avoid false check in htmlparser2 and apply the lowercasing later lowerCaseAttributeNames: false, - recognizeSelfClosing + recognizeSelfClosing, + recognizeCDATA: true }).end(text); return handler.dom; diff --git a/src/language-html/preprocess.js b/src/language-html/preprocess.js index a5adcf24cda6..f08b2ccf2709 100644 --- a/src/language-html/preprocess.js +++ b/src/language-html/preprocess.js @@ -15,6 +15,7 @@ const LineAndColumn = (m => m.default || m)(require("lines-and-columns")); const PREPROCESS_PIPELINE = [ renameScriptAndStyleWithTag, + mergeCdataIntoText, processDirectives, addIsSelfClosing, extractWhitespaces, @@ -31,6 +32,56 @@ function preprocess(ast, options) { return ast; } +function mergeCdataIntoText(ast, options) { + return mapNode(ast, node => { + if (node.type === "cdata") { + const newNode = Object.assign({}, node, { + // we cannot use child.data here since there's no child for whitespace-only text in cdata + data: options.originalText.slice( + options.locStart(node), + options.locEnd(node) + ) + }); + delete newNode.children; + return newNode; + } + + if (node.children && node.children.some(child => child.type === "cdata")) { + const newChildren = []; + for (const child of node.children) { + if (child.type !== "text" && child.type !== "cdata") { + newChildren.push(child); + continue; + } + + const newChild = + child.type === "text" + ? child + : Object.assign({}, child, { type: "text" }); + + if ( + newChildren.length === 0 || + newChildren[newChildren.length - 1].type !== "text" + ) { + newChildren.push(newChild); + continue; + } + + const lastChild = newChildren.pop(); + newChildren.push( + Object.assign({}, lastChild, { + data: lastChild.data + newChild.data, + endIndex: newChild.endIndex + }) + ); + } + return Object.assign({}, node, { children: newChildren }); + } + + return node; + }); +} + /** add `startLocation` and `endLocation` field */ function addStartAndEndLocation(ast, options) { const locator = new LineAndColumn(options.originalText); diff --git a/tests/html_cdata/__snapshots__/jsfmt.spec.js.snap b/tests/html_cdata/__snapshots__/jsfmt.spec.js.snap index ff804cf5041b..41dd5590442a 100644 --- a/tests/html_cdata/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_cdata/__snapshots__/jsfmt.spec.js.snap @@ -3,6 +3,6 @@ exports[`example.html - html-verify 1`] = ` John Smith]]> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - +John Smith]]> `; From 7ca1eb80bb33578f080ae76a02cae5678d604dae Mon Sep 17 00:00:00 2001 From: Ika Date: Fri, 12 Oct 2018 12:59:00 +0800 Subject: [PATCH 010/177] test: add tests --- tests/multiparser_vue/__snapshots__/jsfmt.spec.js.snap | 6 ++++++ tests/multiparser_vue/template-bind.vue | 3 +++ 2 files changed, 9 insertions(+) diff --git a/tests/multiparser_vue/__snapshots__/jsfmt.spec.js.snap b/tests/multiparser_vue/__snapshots__/jsfmt.spec.js.snap index 1c3670d05b99..f8f63b2cdeac 100644 --- a/tests/multiparser_vue/__snapshots__/jsfmt.spec.js.snap +++ b/tests/multiparser_vue/__snapshots__/jsfmt.spec.js.snap @@ -56,6 +56,9 @@ export default { exports[`template-bind.vue - vue-verify 1`] = `

From ba824a3e53d30dce55d659c179ecc1f166226d0b Mon Sep 17 00:00:00 2001 From: Ika Date: Sun, 21 Oct 2018 21:50:59 +0800 Subject: [PATCH 090/177] test: add tests --- .../html_vue/__snapshots__/jsfmt.spec.js.snap | 110 ++++++++++++++++++ tests/html_vue/pre-child.vue | 28 +++++ 2 files changed, 138 insertions(+) create mode 100644 tests/html_vue/pre-child.vue diff --git a/tests/html_vue/__snapshots__/jsfmt.spec.js.snap b/tests/html_vue/__snapshots__/jsfmt.spec.js.snap index 37ed56a84f11..2ee29a273450 100644 --- a/tests/html_vue/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_vue/__snapshots__/jsfmt.spec.js.snap @@ -670,6 +670,116 @@ export default { `; +exports[`pre-child.vue - vue-verify 1`] = ` + +
+  
+  
+  
+
+
+
+
+
+ + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +
+   
+  
+
+
+
+
+ +
+ + + + +`; + +exports[`pre-child.vue - vue-verify 2`] = ` + +
+  
+  
+  
+
+
+
+
+
+ + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +
+   
+  
+
+
+
+
+ +
+ + + + +`; + exports[`script_src.vue - vue-verify 1`] = ` diff --git a/tests/html_vue/pre-child.vue b/tests/html_vue/pre-child.vue new file mode 100644 index 000000000000..5dc17348ce8c --- /dev/null +++ b/tests/html_vue/pre-child.vue @@ -0,0 +1,28 @@ + +
+  
+  
+  
+
+
+
+
+
+ + + From 9a370900349b342627cc884e5645b0853a311e0d Mon Sep 17 00:00:00 2001 From: Ika Date: Sun, 21 Oct 2018 21:58:50 +0800 Subject: [PATCH 091/177] fix: preserve tags in

---
 src/language-html/utils.js                    | 20 ++++++---
 .../html_vue/__snapshots__/jsfmt.spec.js.snap | 44 ++++++++++++++-----
 2 files changed, 47 insertions(+), 17 deletions(-)

diff --git a/src/language-html/utils.js b/src/language-html/utils.js
index 926082c9ba25..ff212f84f3c5 100644
--- a/src/language-html/utils.js
+++ b/src/language-html/utils.js
@@ -74,6 +74,14 @@ function hasPrettierIgnore(path) {
     return false;
   }
 
+  // TODO: handle non-text children in 
+  if (
+    isPreLikeNode(node) &&
+    node.children.some(child => child.type !== "text")
+  ) {
+    return true;
+  }
+
   const parentNode = path.getParentNode();
   if (!parentNode) {
     return false;
@@ -326,12 +334,14 @@ function isBlockLikeCssDisplay(cssDisplay) {
   return cssDisplay === "block" || cssDisplay.startsWith("table");
 }
 
+function isPreLikeNode(node) {
+  return ["pre", "pre-wrap"].indexOf(getNodeCssStyleWhiteSpace(node)) !== -1;
+}
+
 function getNodeCssStyleDisplay(node, prevNode, options) {
-  switch (getNodeCssStyleWhiteSpace(node)) {
-    case "pre":
-    case "pre-wrap":
-      // textarea-like
-      return "block";
+  if (isPreLikeNode(node)) {
+    // textarea-like
+    return "block";
   }
 
   if (prevNode && prevNode.type === "comment") {
diff --git a/tests/html_vue/__snapshots__/jsfmt.spec.js.snap b/tests/html_vue/__snapshots__/jsfmt.spec.js.snap
index 2ee29a273450..8a4f254ebe63 100644
--- a/tests/html_vue/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/html_vue/__snapshots__/jsfmt.spec.js.snap
@@ -703,14 +703,25 @@ exports[`pre-child.vue - vue-verify 1`] = `
 
-
-   
-  
+
+  
+  
+  
-
@@ -758,14 +768,25 @@ exports[`pre-child.vue - vue-verify 2`] = ` -
-   
-  
+
+  
+  
+  
-
From b80123d7d3e6761d7934301e00f6c30f6fc2431e Mon Sep 17 00:00:00 2001 From: Ika Date: Sun, 21 Oct 2018 22:33:50 +0800 Subject: [PATCH 092/177] fix: do not remove sensitive whitespace --- src/language-html/printer-htmlparser2.js | 5 ++++- tests/html_angular/__snapshots__/jsfmt.spec.js.snap | 2 +- tests/html_tags/__snapshots__/jsfmt.spec.js.snap | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/language-html/printer-htmlparser2.js b/src/language-html/printer-htmlparser2.js index c46af7246439..6dcd458f0a8d 100644 --- a/src/language-html/printer-htmlparser2.js +++ b/src/language-html/printer-htmlparser2.js @@ -168,7 +168,10 @@ function genericPrint(path, options, print) { (node.next ? needsToBorrowPrevClosingTagEndMarker(node.next) : needsToBorrowLastChildClosingTagEndMarker(node.parent)) - ? "" + ? node.lastChild.hasTrailingSpaces && + node.lastChild.isTrailingSpaceSensitive + ? " " + : "" : node.lastChild.hasTrailingSpaces && node.lastChild.isTrailingSpaceSensitive ? line diff --git a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap index 9d004ba2ff49..99850c573a97 100644 --- a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap @@ -1557,7 +1557,7 @@ without NgModel
- {{product.price | currency:"USD":true}} + {{product.price | currency:"USD":true}}
top diff --git a/tests/html_tags/__snapshots__/jsfmt.spec.js.snap b/tests/html_tags/__snapshots__/jsfmt.spec.js.snap index e82a0cec0c52..ede8cdfb6f70 100644 --- a/tests/html_tags/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_tags/__snapshots__/jsfmt.spec.js.snap @@ -249,7 +249,7 @@ exports[`custom-self-closing.html - html-verify 4`] = `
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
`; From 2a26ea561d33d17fc1d70e57e549eaa153acf653 Mon Sep 17 00:00:00 2001 From: Ika Date: Mon, 22 Oct 2018 10:44:32 +0800 Subject: [PATCH 093/177] test: add tests --- .../__snapshots__/jsfmt.spec.js.snap | 489 ++++++++++++++++++ tests/html_comments/jsfmt.spec.js | 2 + 2 files changed, 491 insertions(+) diff --git a/tests/html_comments/__snapshots__/jsfmt.spec.js.snap b/tests/html_comments/__snapshots__/jsfmt.spec.js.snap index 9a256f53707e..f5a8e0af7f77 100644 --- a/tests/html_comments/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_comments/__snapshots__/jsfmt.spec.js.snap @@ -35,6 +35,28 @@ exports[`before-text.html - html-verify 3`] = ` `; +exports[`before-text.html - html-verify 4`] = ` + + +123 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +123 + +`; + +exports[`before-text.html - html-verify 5`] = ` + + +123 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +123 + +`; + exports[`conditional.html - html-verify 1`] = ` @@ -141,6 +163,75 @@ exports[`conditional.html - html-verify 3`] = ` `; +exports[`conditional.html - html-verify 4`] = ` + + + + + + + + + + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + + + + + + + + + +`; + +exports[`conditional.html - html-verify 5`] = ` + + + + + + + + + + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + + + + + + + + + +`; + exports[`for_debugging.html - html-verify 1`] = ` @@ -267,6 +358,90 @@ exports[`for_debugging.html - html-verify 3`] = ` `; +exports[`for_debugging.html - html-verify 4`] = ` + + + + + + + + + + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + + + + + + + + + +`; + +exports[`for_debugging.html - html-verify 5`] = ` + + + + + + + + + + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + + + + + + + + + +`; + exports[`hidden.html - html-verify 1`] = ` @@ -369,6 +544,64 @@ exports[`hidden.html - html-verify 3`] = ` `; +exports[`hidden.html - html-verify 4`] = ` + + + + + + + + +

This is a paragraph.

+ + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + + + + + +

This is a paragraph.

+ + + + +`; + +exports[`hidden.html - html-verify 5`] = ` + + + + + + + + +

This is a paragraph.

+ + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + + + + + +

This is a paragraph.

+ + + + +`; + exports[`surrounding-empty-line.html - html-verify 1`] = `
  • First
  • `; + +exports[`surrounding-empty-line.html - html-verify 4`] = ` +
    • First
    • Second
    • Second
    +ab + +ab + +ab + +123456 + +123456 + + + + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +
    • First
    • Second
    • Second
    +ab + +ab + +ab + +123456 123456 + + + + + + + +`; + +exports[`surrounding-empty-line.html - html-verify 5`] = ` +
    • First
    • Second
    • Second
    +ab + +ab + +ab + +123456 + +123456 + + + + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +
      + +
    • First
    • + +
    • Second
    • + +
    • Second
    • + +
    + + + a + + b + + + + + + a + + b + + + + + + a + + b + + + +123 + +456 123 + +456 + + + + + + + +`; diff --git a/tests/html_comments/jsfmt.spec.js b/tests/html_comments/jsfmt.spec.js index 532e226125c3..22f7911a9823 100644 --- a/tests/html_comments/jsfmt.spec.js +++ b/tests/html_comments/jsfmt.spec.js @@ -1,3 +1,5 @@ run_spec(__dirname, ["html"]); run_spec(__dirname, ["html"], { printWidth: 1 }); run_spec(__dirname, ["html"], { printWidth: 999 }); +run_spec(__dirname, ["html"], { htmlWhitespaceSensitivity: "strict" }); +run_spec(__dirname, ["html"], { htmlWhitespaceSensitivity: "ignore" }); From 2c25b7e4396bfc41946ea8f8df6a3d8be4cb0cb7 Mon Sep 17 00:00:00 2001 From: Ika Date: Mon, 22 Oct 2018 10:45:52 +0800 Subject: [PATCH 094/177] test: add tests --- .../html_tags/__snapshots__/jsfmt.spec.js.snap | 18 ++++++++++++++++++ tests/html_tags/tags.html | 1 + 2 files changed, 19 insertions(+) diff --git a/tests/html_tags/__snapshots__/jsfmt.spec.js.snap b/tests/html_tags/__snapshots__/jsfmt.spec.js.snap index ede8cdfb6f70..1946f6b92fec 100644 --- a/tests/html_tags/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_tags/__snapshots__/jsfmt.spec.js.snap @@ -1543,6 +1543,7 @@ exports[`tags.html - html-verify 1`] = ` >

    "" is the property bound title.

    +
  • 12345678901234567890123456789012345678901234567890123456789012345678901234567890
  • ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    @@ -1688,6 +1689,9 @@ exports[`tags.html - html-verify 1`] = ` >

    "" is the property bound title.

    +
  • 12345678901234567890123456789012345678901234567890123456789012345678901234567890
  • `; @@ -1779,6 +1783,7 @@ exports[`tags.html - html-verify 2`] = ` >

    "" is the property bound title.

    +
  • 12345678901234567890123456789012345678901234567890123456789012345678901234567890
  • ~

    @@ -2086,6 +2091,9 @@ exports[`tags.html - html-verify 2`] = ` > title.

    +
  • 12345678901234567890123456789012345678901234567890123456789012345678901234567890
  • `; @@ -2177,6 +2185,7 @@ exports[`tags.html - html-verify 3`] = ` >

    "" is the property bound title.

    +
  • 12345678901234567890123456789012345678901234567890123456789012345678901234567890
  • ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    @@ -2254,6 +2263,7 @@ exports[`tags.html - html-verify 3`] = `

    "" is the property bound title.

    +
  • 12345678901234567890123456789012345678901234567890123456789012345678901234567890
  • `; @@ -2345,6 +2355,7 @@ exports[`tags.html - html-verify 4`] = ` >

    "" is the property bound title.

    +
  • 12345678901234567890123456789012345678901234567890123456789012345678901234567890
  • ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    @@ -2471,6 +2482,9 @@ exports[`tags.html - html-verify 4`] = ` >

    "" is the property bound title.

    +
  • 12345678901234567890123456789012345678901234567890123456789012345678901234567890
  • `; @@ -2562,6 +2576,7 @@ exports[`tags.html - html-verify 5`] = ` >

    "" is the property bound title.

    +
  • 12345678901234567890123456789012345678901234567890123456789012345678901234567890
  • ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    @@ -2738,6 +2753,9 @@ exports[`tags.html - html-verify 5`] = ` property bound title.

    +
  • + 12345678901234567890123456789012345678901234567890123456789012345678901234567890 +
  • `; diff --git a/tests/html_tags/tags.html b/tests/html_tags/tags.html index 9b0609428a2d..adb9976b5699 100644 --- a/tests/html_tags/tags.html +++ b/tests/html_tags/tags.html @@ -85,3 +85,4 @@ >

    "" is the property bound title.

    +
  • 12345678901234567890123456789012345678901234567890123456789012345678901234567890
  • From afb2792cbd76c7c0e87510543a8ca8c3a5afc0da Mon Sep 17 00:00:00 2001 From: Ika Date: Mon, 22 Oct 2018 10:46:32 +0800 Subject: [PATCH 095/177] fix: treat list-item as block --- src/language-html/utils.js | 6 +- .../__snapshots__/jsfmt.spec.js.snap | 56 +++++++++++-------- .../__snapshots__/jsfmt.spec.js.snap | 44 +++++++++------ 3 files changed, 65 insertions(+), 41 deletions(-) diff --git a/src/language-html/utils.js b/src/language-html/utils.js index ff212f84f3c5..255c745c4af1 100644 --- a/src/language-html/utils.js +++ b/src/language-html/utils.js @@ -331,7 +331,11 @@ function inferScriptParser(node) { * firstChild leadingSpaces, lastChild trailingSpaces, and danglingSpaces are insensitive */ function isBlockLikeCssDisplay(cssDisplay) { - return cssDisplay === "block" || cssDisplay.startsWith("table"); + return ( + cssDisplay === "block" || + cssDisplay === "list-item" || + cssDisplay.startsWith("table") + ); } function isPreLikeNode(node) { diff --git a/tests/html_comments/__snapshots__/jsfmt.spec.js.snap b/tests/html_comments/__snapshots__/jsfmt.spec.js.snap index f5a8e0af7f77..971df3a63ee8 100644 --- a/tests/html_comments/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_comments/__snapshots__/jsfmt.spec.js.snap @@ -661,19 +661,21 @@ See console log: --> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      -
    • First
    • +
    • First
    • +
    • Second
    • +
    • Second
    • +
    • Second
    • +
    • Second
    • +
    • First
    • +
    • + First +
    • +
    • Second
    • +
    • + Second +
    • +
    • Second
    • +
    • + Second +
    • + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        -
      • First
      • +
      • First
      • +
      • Second
      • +
      • Second
      • +
      • Second
      • +
      • Second
      • + ".length); + } else if (node instanceof Text) { + node.value = node.sourceSpan.toString(); } - onopentagname(name) { - super.onopentagname(name); - if (this._cbs.onopentag) { - this._attribs = []; - } - } - } + }; - /** - * modifications: - * - add `isSelfClosing` field - * - correct `endIndex` for whitespaces before closing tag end marker (e.g., ``) - */ - class CustomDomHandler extends DomHandler { - onselfclosingtag() { - this._tagStack[this._tagStack.length - 1].isSelfClosing = true; + const lowerCaseIfFn = (text, fn) => { + const lowerCasedText = text.toLowerCase(); + return fn(lowerCasedText) ? lowerCasedText : text; + }; + const normalizeName = node => { + if (node instanceof Element) { + node.name = lowerCaseIfFn( + node.name, + lowerCasedName => lowerCasedName in HTML_TAGS + ); + const CURRENT_HTML_ELEMENT_ATTRIBUTES = + HTML_ELEMENT_ATTRIBUTES[node.name] || Object.create(null); + node.attrs.forEach(attr => { + attr.name = lowerCaseIfFn( + attr.name, + lowerCasedAttrName => + node.name in HTML_ELEMENT_ATTRIBUTES && + (lowerCasedAttrName in HTML_ELEMENT_ATTRIBUTES["*"] || + lowerCasedAttrName in CURRENT_HTML_ELEMENT_ATTRIBUTES) + ); + }); } - onclosetag() { - const elem = this._tagStack.pop(); - if (this._options.withEndIndices && elem) { - const buffer = this._parser._tokenizer._buffer; - let endIndex = this._parser.endIndex; - while (buffer[endIndex] && buffer[endIndex] !== ">") { - endIndex++; - } - elem.endIndex = buffer[endIndex] ? endIndex : this._parser.endIndex; - } - if (this._elementCB) { - this._elementCB(elem); - } + }; + + const fixSourceSpan = node => { + if (node.sourceSpan && node.endSourceSpan) { + node.sourceSpan = new ParseSourceSpan( + node.sourceSpan.start, + node.endSourceSpan.end + ); } - } + }; - const handler = new CustomDomHandler({ - withStartIndices: true, - withEndIndices: true - }); + const addIsVoid = node => { + if (node instanceof Element) { + node.isVoid = getHtmlTagDefinition(node.name).isVoid; + } + }; - new CustomParser(handler, { - lowerCaseTags: true, // preserve lowercase tag names to avoid false check in htmlparser2 and apply the lowercasing later - lowerCaseAttributeNames: false, - recognizeSelfClosing, - recognizeCDATA: true - }).end(text); + visitAll( + new class extends RecursiveVisitor { + visit(node) { + addType(node); + restoreNameAndValue(node); + normalizeName(node); + addIsVoid(node); + fixSourceSpan(node); + } + }(), + rootNodes + ); - return handler.dom; + return rootNodes; } function _parse( @@ -106,120 +138,102 @@ function _parse( ? parseFrontMatter(text) : { frontMatter: null, content: text }; - const ast = normalize( - { - type: "root", - children: htmlparser2(content, recognizeSelfClosing), - startIndex: 0, - endIndex: text.length - }, - text - ); + const ast = { + type: "root", + sourceSpan: { start: { offset: 0 }, end: { offset: text.length } }, + children: ngHtmlParser(content, recognizeSelfClosing) + }; if (frontMatter) { ast.children.unshift(frontMatter); } - const parseSubHtml = subContent => - _parse(subContent, options, recognizeSelfClosing, false); + const parseSubHtml = (subContent, startSourceSpan) => { + const { offset } = startSourceSpan; + const fakeContent = text.slice(0, offset).replace(/[^\r\n]/g, " "); + const realContent = subContent; + const subAst = _parse( + fakeContent + realContent, + options, + recognizeSelfClosing, + false + ); + const ParseSourceSpan = subAst.children[0].sourceSpan.constructor; + subAst.sourceSpan = new ParseSourceSpan( + startSourceSpan, + subAst.children[subAst.children.length - 1].sourceSpan.end + ); + const firstText = subAst.children[0]; + if (firstText.length === offset) { + subAst.children.shift(); + } else { + firstText.sourceSpan = new ParseSourceSpan( + firstText.sourceSpan.start.moveBy(offset), + firstText.sourceSpan.end + ); + firstText.value = firstText.value.slice(offset); + } + return subAst; + }; return mapNode(ast, node => { - const ieConditionalComment = parseIeConditionalComment(node, parseSubHtml); - return ieConditionalComment ? ieConditionalComment : node; + if (node.children) { + const newChildren = []; + + for (const child of node.children) { + if (child.type === "element" && !child.nameSpan) { + Array.prototype.push.apply(newChildren, child.children); + } else { + newChildren.push(child); + } + } + + return Object.assign({}, node, { children: newChildren }); + } + + if (node.type === "comment") { + const ieConditionalComment = parseIeConditionalComment( + node, + parseSubHtml + ); + if (ieConditionalComment) { + return ieConditionalComment; + } + } + + return node; }); } function parseIeConditionalComment(node, parseHtml) { - if (node.type !== "comment") { + if (!node.value) { return null; } - const match = node.data.match(/^(\[if([^\]]*?)\]>)([\s\S]*?))([\s\S]*?) - Object.assign({}, currentNode, { - startIndex: baseIndex + currentNode.startIndex, - endIndex: baseIndex + currentNode.endIndex - }) - ), - { - type: "ieConditionalComment", - condition: condition.trim().replace(/\s+/g, " ") - } - ); -} - -function normalize(node, text) { - delete node.parent; - delete node.next; - delete node.prev; - - if (node.type === "tag" && !(node.name in HTML_TAGS)) { - node.name = text.slice( - node.startIndex + 1, // < - node.startIndex + 1 + node.name.length - ); - } - - if (node.attribs) { - const CURRENT_HTML_ELEMENT_ATTRIBUTES = - HTML_ELEMENT_ATTRIBUTES[node.name] || Object.create(null); - const attributes = node.attribs.map(([attributeKey, attributeValue]) => { - const lowerCaseAttributeKey = attributeKey.toLowerCase(); - return { - type: "attribute", - key: - lowerCaseAttributeKey in HTML_ELEMENT_ATTRIBUTES["*"] || - lowerCaseAttributeKey in CURRENT_HTML_ELEMENT_ATTRIBUTES - ? lowerCaseAttributeKey - : attributeKey, - value: attributeValue - }; - }); - - const attribs = Object.create(null); - for (const attribute of attributes) { - attribs[attribute.key] = attribute.value; - } + const offset = "`; case "interpolation": return "}}"; - case "tag": + case "element": if (node.isSelfClosing) { return "/>"; } @@ -678,29 +688,29 @@ function printClosingTagEndMarker(node) { } } -function getTextDataParts(node, data = node.data) { +function getTextValueParts(node, value = node.value) { return node.isWhiteSpaceSensitive ? node.isIndentationSensitive - ? replaceNewlines(data.replace(/^\s*?\n|\n\s*?$/g, ""), literalline) + ? replaceNewlines(value.replace(/^\s*?\n|\n\s*?$/g, ""), literalline) : replaceNewlines( - dedentString(data.replace(/^\s*?\n|\n\s*?$/g, "")), + dedentString(value.replace(/^\s*?\n|\n\s*?$/g, "")), hardline ) - : join(line, data.split(/\s+/)).parts; + : join(line, value.split(/\s+/)).parts; } function printEmbeddedAttributeValue(node, textToDoc, options) { const isKeyMatched = patterns => - new RegExp(patterns.join("|")).test(node.key); + new RegExp(patterns.join("|")).test(node.name); const getValue = () => node.value.replace(/"/g, '"').replace(/'/g, "'"); if (options.parser === "vue") { - if (node.key === "v-for") { + if (node.name === "v-for") { return printVueFor(getValue(), textToDoc); } - if (node.key === "slot-scope") { + if (node.name === "slot-scope") { return printVueSlotScope(getValue(), textToDoc); } diff --git a/src/language-html/utils.js b/src/language-html/utils.js index 255c745c4af1..3d429ad44116 100644 --- a/src/language-html/utils.js +++ b/src/language-html/utils.js @@ -18,40 +18,6 @@ const htmlElementAttributes = require("html-element-attributes"); const HTML_TAGS = arrayToMap(htmlTagNames); const HTML_ELEMENT_ATTRIBUTES = mapObject(htmlElementAttributes, arrayToMap); -// NOTE: must be same as the one in htmlparser2 so that the parsing won't be inconsistent -// https://github.com/fb55/htmlparser2/blob/v3.9.2/lib/Parser.js#L59-L91 -const VOID_TAGS = arrayToMap([ - "area", - "base", - "basefont", - "br", - "col", - "command", - "embed", - "frame", - "hr", - "img", - "input", - "isindex", - "keygen", - "link", - "meta", - "param", - "source", - "track", - "wbr", - - "path", - "circle", - "ellipse", - "line", - "rect", - "use", - "stop", - "polyline", - "polygon" -]); - function arrayToMap(array) { const map = Object.create(null); for (const value of array) { @@ -97,11 +63,11 @@ function hasPrettierIgnore(path) { } function isPrettierIgnore(node) { - return node.type === "comment" && node.data.trim() === "prettier-ignore"; + return node.type === "comment" && node.value.trim() === "prettier-ignore"; } -function isTag(node, nameOrNames) { - if (node.type !== "tag") { +function isElement(node, nameOrNames) { + if (node.type !== "element") { return false; } @@ -117,7 +83,7 @@ function isTag(node, nameOrNames) { } function isScriptLikeTag(node) { - return isTag(node, ["script", "style"]); + return isElement(node, ["script", "style"]); } function isFrontMatterNode(node) { @@ -224,7 +190,8 @@ function replaceDocNewlines(doc, replacement) { function forceNextEmptyLine(node) { return ( isFrontMatterNode(node) || - (node.next && node.endLocation.line + 1 < node.next.startLocation.line) + (node.next && + node.sourceSpan.end.line + 1 < node.next.sourceSpan.start.line) ); } @@ -232,7 +199,7 @@ function forceNextEmptyLine(node) { function forceBreakContent(node) { return ( forceBreakChildren(node) || - (isTag(node) && + (isElement(node) && node.children.length !== 0 && (["body", "template"].indexOf(node.name) !== -1 || node.children.some(child => hasNonTextChild(child)))) @@ -242,7 +209,7 @@ function forceBreakContent(node) { /** spaces between children */ function forceBreakChildren(node) { return ( - isTag(node) && + isElement(node) && node.children.length !== 0 && (["html", "head", "ul", "ol", "select", "script", "style"].indexOf( node.name @@ -259,10 +226,7 @@ function preferHardlineAsLeadingSpaces(node) { } function preferHardlineAsTrailingSpaces(node) { - return ( - preferHardlineAsSurroundingSpaces(node) || - (isTag(node) && node.name === "br") - ); + return preferHardlineAsSurroundingSpaces(node) || isElement(node, "br"); } function preferHardlineAsSurroundingSpaces(node) { @@ -271,7 +235,7 @@ function preferHardlineAsSurroundingSpaces(node) { case "comment": case "directive": return true; - case "tag": + case "element": return ["script", "select"].indexOf(node.name) !== -1; } return false; @@ -286,40 +250,45 @@ function hasNonTextChild(node) { } function inferScriptParser(node) { - if (node.name === "script" && !node.attribs.src) { + const attrMap = node.attrs.reduce((reduced, attr) => { + reduced[attr.name] = attr.value; + return reduced; + }, {}); + + if (node.name === "script" && !attrMap.src) { if ( - (!node.attribs.lang && !node.attribs.type) || - node.attribs.type === "module" || - node.attribs.type === "text/javascript" || - node.attribs.type === "text/babel" || - node.attribs.type === "application/javascript" + (!attrMap.lang && !attrMap.type) || + attrMap.type === "module" || + attrMap.type === "text/javascript" || + attrMap.type === "text/babel" || + attrMap.type === "application/javascript" ) { return "babylon"; } if ( - node.attribs.type === "application/x-typescript" || - node.attribs.lang === "ts" || - node.attribs.lang === "tsx" + attrMap.type === "application/x-typescript" || + attrMap.lang === "ts" || + attrMap.lang === "tsx" ) { return "typescript"; } - if (node.attribs.type === "text/markdown") { + if (attrMap.type === "text/markdown") { return "markdown"; } } if (node.name === "style") { - if (!node.attribs.lang || node.attribs.lang === "postcss") { + if (!attrMap.lang || attrMap.lang === "postcss") { return "css"; } - if (node.attribs.lang === "scss") { + if (attrMap.lang === "scss") { return "scss"; } - if (node.attribs.lang === "less") { + if (attrMap.lang === "less") { return "less"; } } @@ -350,7 +319,7 @@ function getNodeCssStyleDisplay(node, prevNode, options) { if (prevNode && prevNode.type === "comment") { // - const match = prevNode.data.match(/^\s*display:\s*([a-z]+)\s*$/); + const match = prevNode.value.match(/^\s*display:\s*([a-z]+)\s*$/); if (match) { return match[1]; } @@ -362,25 +331,26 @@ function getNodeCssStyleDisplay(node, prevNode, options) { case "ignore": return "block"; default: - if (isTag(node, "template")) { + if (isElement(node, "template")) { return "inline"; } return ( - (isTag(node) && CSS_DISPLAY_TAGS[node.name]) || CSS_DISPLAY_DEFAULT + (isElement(node) && CSS_DISPLAY_TAGS[node.name]) || CSS_DISPLAY_DEFAULT ); } } function getNodeCssStyleWhiteSpace(node) { return ( - (isTag(node) && CSS_WHITE_SPACE_TAGS[node.name]) || CSS_WHITE_SPACE_DEFAULT + (isElement(node) && CSS_WHITE_SPACE_TAGS[node.name]) || + CSS_WHITE_SPACE_DEFAULT ); } function getCommentData(node) { - const rightTrimmedData = node.data.trimRight(); + const rightTrimmedValue = node.value.trimRight(); - const hasLeadingEmptyLine = /^[^\S\n]*?\n/.test(node.data); + const hasLeadingEmptyLine = /^[^\S\n]*?\n/.test(node.value); if (hasLeadingEmptyLine) { /** * */ - return dedentString(rightTrimmedData.replace(/^\s*\n/, "")); + return dedentString(rightTrimmedValue.replace(/^\s*\n/, "")); } /** @@ -401,19 +371,19 @@ function getCommentData(node) { * * --> */ - if (!rightTrimmedData.includes("\n")) { - return rightTrimmedData.trimLeft(); + if (!rightTrimmedValue.includes("\n")) { + return rightTrimmedValue.trimLeft(); } - const firstNewlineIndex = rightTrimmedData.indexOf("\n"); - const dataWithoutLeadingLine = rightTrimmedData.slice(firstNewlineIndex + 1); + const firstNewlineIndex = rightTrimmedValue.indexOf("\n"); + const dataWithoutLeadingLine = rightTrimmedValue.slice(firstNewlineIndex + 1); const minIndentationForDataWithoutLeadingLine = getMinIndentation( dataWithoutLeadingLine ); - const leadingSpaces = rightTrimmedData.match(/^[^\n\S]*/)[0].length; + const leadingSpaces = rightTrimmedValue.match(/^[^\n\S]*/)[0].length; const commentDataStartColumn = - node.startLocation.column + " */ return ( - leadingLineData.trim() + + leadingLineValue.trim() + "\n" + dedentString( dataWithoutLeadingLine, @@ -513,7 +484,6 @@ function identity(x) { module.exports = { HTML_ELEMENT_ATTRIBUTES, HTML_TAGS, - VOID_TAGS, dedentString, forceBreakChildren, forceBreakContent, diff --git a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap index 99850c573a97..3d4957828dac 100644 --- a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap @@ -986,10 +986,9 @@ can be found in the LICENSE file at http://angular.io/license

        Statement context

        -

        - Component statement context ( (click)="onSave() ) -

        -

        +

        Component statement context ( (click)="onSave() )

        +
        +

        Template $event statement context

        diff --git a/tests/html_basics/__snapshots__/jsfmt.spec.js.snap b/tests/html_basics/__snapshots__/jsfmt.spec.js.snap index cfbe45c3a0bb..f075a924d472 100644 --- a/tests/html_basics/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_basics/__snapshots__/jsfmt.spec.js.snap @@ -260,17 +260,6 @@ exports[`html-comments.html - html-verify 1`] = ` `; -exports[`html-fragment.html - html-verify 1`] = ` -Link - - - -`; - exports[`html5-boilerplate.html - html-verify 1`] = ` @@ -352,7 +341,9 @@ exports[`html5-boilerplate.html - html-verify 1`] = ` > '); + document.write( + ' diff --git a/tests/html_basics/html-fragment.html b/tests/html_basics/html-fragment.html deleted file mode 100644 index 2c402615223c..000000000000 --- a/tests/html_basics/html-fragment.html +++ /dev/null @@ -1,3 +0,0 @@ -Link - - + +
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        @@ -2766,6 +2768,12 @@ exports[`textarea.html - html-verify 1`] = `
        +
        + +
        + `; exports[`textarea.html - html-verify 2`] = ` @@ -2797,6 +2805,8 @@ exports[`textarea.html - html-verify 2`] = `
+ +
~
@@ -2831,6 +2841,12 @@ exports[`textarea.html - html-verify 2`] = `
+
+ +
+ `; exports[`textarea.html - html-verify 3`] = ` @@ -2862,6 +2878,8 @@ exports[`textarea.html - html-verify 3`] = `
+ +
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -2892,6 +2910,12 @@ exports[`textarea.html - html-verify 3`] = `
+
+ +
+ `; exports[`textarea.html - html-verify 4`] = ` @@ -2923,6 +2947,8 @@ exports[`textarea.html - html-verify 4`] = `
+ +
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -2953,6 +2979,12 @@ exports[`textarea.html - html-verify 4`] = `
+
+ `; exports[`textarea.html - html-verify 5`] = ` @@ -2984,6 +3016,8 @@ exports[`textarea.html - html-verify 5`] = `
+ +
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -3014,6 +3048,12 @@ exports[`textarea.html - html-verify 5`] = `
+
+ +
+ `; exports[`unsupported.html - html-verify 1`] = ` diff --git a/tests/html_tags/textarea.html b/tests/html_tags/textarea.html index 3543920e9fad..11c5e41144da 100644 --- a/tests/html_tags/textarea.html +++ b/tests/html_tags/textarea.html @@ -26,3 +26,5 @@
+ +
From 221aa1cb0eb1ca4606fc82ea95ab6c1ea8739d3d Mon Sep 17 00:00:00 2001 From: Ika Date: Thu, 25 Oct 2018 11:24:48 +0800 Subject: [PATCH 102/177] fix: print pre-like tags correctly --- src/language-html/preprocess.js | 25 +++++++ src/language-html/printer-html.js | 31 +++++++- src/language-html/utils.js | 34 ++++++++- .../__snapshots__/jsfmt.spec.js.snap | 73 +++++-------------- 4 files changed, 103 insertions(+), 60 deletions(-) diff --git a/src/language-html/preprocess.js b/src/language-html/preprocess.js index 140cd365a5b1..8585e14f6e53 100644 --- a/src/language-html/preprocess.js +++ b/src/language-html/preprocess.js @@ -13,6 +13,7 @@ const { } = require("./utils"); const PREPROCESS_PIPELINE = [ + removeIgnorableFirstLf, mergeCdataIntoText, extractInterpolation, addIsSelfClosing, @@ -29,6 +30,30 @@ function preprocess(ast, options) { return ast; } +function removeIgnorableFirstLf(ast /*, options */) { + return mapNode(ast, node => { + if ( + node.type === "element" && + node.tagDefinition.ignoreFirstLf && + node.children.length !== 0 && + node.children[0].type === "text" && + node.children[0].value[0] === "\n" + ) { + const text = node.children[0]; + return Object.assign({}, node, { + children: + text.value.length === 1 + ? node.children.slice(1) + : [].concat( + Object.assign({}, text, { value: text.value.slice(1) }), + node.children.slice(1) + ) + }); + } + return node; + }); +} + function mergeCdataIntoText(ast /*, options */) { return mapNode(ast, node => { if (node.children && node.children.some(child => child.type === "cdata")) { diff --git a/src/language-html/printer-html.js b/src/language-html/printer-html.js index 5e86423f17e2..d18f90b991c0 100644 --- a/src/language-html/printer-html.js +++ b/src/language-html/printer-html.js @@ -19,6 +19,7 @@ const { softline } = builders; const { + countParents, dedentString, forceBreakChildren, forceBreakContent, @@ -28,6 +29,8 @@ const { hasPrettierIgnore, identity, inferScriptParser, + isElement, + isPreLikeNode, isScriptLikeTag, normalizeParts, preferHardlineAsLeadingSpaces, @@ -161,7 +164,9 @@ function genericPrint(path, options, print) { node.firstChild.type === "text" && node.firstChild.isWhitespaceSensitive && node.firstChild.isIndentationSensitive - ? literalline + ? node.firstChild.value.indexOf("\n") === -1 + ? "" + : literalline : node.firstChild.hasLeadingSpaces && node.firstChild.isLeadingSpaceSensitive ? line @@ -179,7 +184,27 @@ function genericPrint(path, options, print) { : node.lastChild.hasTrailingSpaces && node.lastChild.isTrailingSpaceSensitive ? line - : softline + : isElement(node) && + isPreLikeNode(node) && + node.lastChild.type === "text" && + (node.lastChild.value.indexOf("\n") === -1 || + new RegExp( + `\\n\\s{${options.tabWidth * + countParents( + path, + n => n.parent && n.parent.type !== "root" + )}}$` + ).test(node.lastChild.value)) + ? /** + *
+ *
+                           *         something
+                           *       
+ * ~ + *
+ */ + "" + : softline ]) ]) ), @@ -691,7 +716,7 @@ function printClosingTagEndMarker(node) { function getTextValueParts(node, value = node.value) { return node.isWhitespaceSensitive ? node.isIndentationSensitive - ? replaceNewlines(value.replace(/^\s*?\n|\n\s*?$/g, ""), literalline) + ? replaceNewlines(value, literalline) : replaceNewlines( dedentString(value.replace(/^\s*?\n|\n\s*?$/g, "")), hardline diff --git a/src/language-html/utils.js b/src/language-html/utils.js index c72710244abf..2aec387a51d0 100644 --- a/src/language-html/utils.js +++ b/src/language-html/utils.js @@ -115,6 +115,14 @@ function isLeadingSpaceSensitiveNode(node, { prev, parent }) { return false; } + if (!node.prev && isElement(parent) && parent.tagDefinition.ignoreFirstLf) { + return false; + } + + if (isPreLikeNode(parent)) { + return true; + } + if ( !prev && (parent.type === "root" || @@ -140,6 +148,10 @@ function isTrailingSpaceSensitiveNode(node, { next, parent }) { return false; } + if (isPreLikeNode(parent)) { + return true; + } + if ( !next && (parent.type === "root" || @@ -325,12 +337,23 @@ function isPreLikeNode(node) { return getNodeCssStyleWhiteSpace(node).startsWith("pre"); } -function getNodeCssStyleDisplay(node, prevNode, options) { - if (isPreLikeNode(node)) { - // textarea-like - return "block"; +function countParents(path, predicate = () => true) { + let counter = 0; + for (let i = path.stack.length - 1; i >= 0; i--) { + const value = path.stack[i]; + if ( + value && + typeof value === "object" && + !Array.isArray(value) && + predicate(value) + ) { + counter++; + } } + return counter; +} +function getNodeCssStyleDisplay(node, prevNode, options) { if (prevNode && prevNode.type === "comment") { // const match = prevNode.value.match(/^\s*display:\s*([a-z]+)\s*$/); @@ -499,6 +522,7 @@ module.exports = { HTML_ELEMENT_ATTRIBUTES, HTML_TAGS, canHaveInterpolation, + countParents, dedentString, forceBreakChildren, forceBreakContent, @@ -512,9 +536,11 @@ module.exports = { identity, inferScriptParser, isDanglingSpaceSensitiveNode, + isElement, isFrontMatterNode, isIndentationSensitiveNode, isLeadingSpaceSensitiveNode, + isPreLikeNode, isScriptLikeTag, isTrailingSpaceSensitiveNode, isWhitespaceSensitiveNode, diff --git a/tests/html_tags/__snapshots__/jsfmt.spec.js.snap b/tests/html_tags/__snapshots__/jsfmt.spec.js.snap index 3486b0a24d90..bb54a039d3fa 100644 --- a/tests/html_tags/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_tags/__snapshots__/jsfmt.spec.js.snap @@ -638,19 +638,16 @@ ___________________________ both spaces and line breaks +
-
-     Foo     Bar
-
+
     Foo     Bar     
      Foo     Bar
 
 Foo     Bar
 
-
-     Foo     Bar
-
+
     Foo     Bar
 ___________________________
@@ -810,19 +807,16 @@ ___________________________
    both             spaces and
 
    line breaks
+
 
-
-     Foo     Bar
-
+
     Foo     Bar     
      Foo     Bar
 
 Foo     Bar
 
-
-     Foo     Bar
-
+
     Foo     Bar
-
-     Foo     Bar
-
+
     Foo     Bar     
      Foo     Bar
 
 Foo     Bar
 
-
-     Foo     Bar
-
+
     Foo     Bar
 ___________________________
@@ -1164,19 +1155,16 @@ ___________________________
    both             spaces and
 
    line breaks
+
 
-
-     Foo     Bar
-
+
     Foo     Bar     
      Foo     Bar
 
 Foo     Bar
 
-
-     Foo     Bar
-
+
     Foo     Bar
 ___________________________
@@ -1336,19 +1324,16 @@ ___________________________
    both             spaces and
 
    line breaks
+
 
-
-     Foo     Bar
-
+
     Foo     Bar     
      Foo     Bar
 
 Foo     Bar
 
-
-     Foo     Bar
-
+
     Foo     Bar
 ___________________________
@@ -2768,11 +2753,7 @@ exports[`textarea.html - html-verify 1`] = `
 
 
 
-
- -
+
`; @@ -2842,9 +2823,7 @@ exports[`textarea.html - html-verify 2`] = `
- +
`; @@ -2910,11 +2889,7 @@ exports[`textarea.html - html-verify 3`] = ` -
- -
+
`; @@ -2979,11 +2954,7 @@ exports[`textarea.html - html-verify 4`] = ` -
+
`; @@ -3048,11 +3019,7 @@ exports[`textarea.html - html-verify 5`] = ` -
- -
+
`; From ab96b2e6a87752ec81b6f734def205787a88a4e2 Mon Sep 17 00:00:00 2001 From: Ika Date: Thu, 25 Oct 2018 22:06:24 +0800 Subject: [PATCH 103/177] feat(angular): add surrounding spaces for `=` in NGMicrosyntaxLet --- src/language-js/printer-estree.js | 2 +- .../html_angular/__snapshots__/jsfmt.spec.js.snap | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/language-js/printer-estree.js b/src/language-js/printer-estree.js index 8ad1dd43c7a2..82ae349178db 100644 --- a/src/language-js/printer-estree.js +++ b/src/language-js/printer-estree.js @@ -3443,7 +3443,7 @@ function printPathNoParens(path, options, print, args) { return concat([ "let ", path.call(print, "key"), - n.value === null ? "" : concat(["=", path.call(print, "value")]) + n.value === null ? "" : concat([" = ", path.call(print, "value")]) ]); case "NGMicrosyntaxAs": return concat([ diff --git a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap index 3d4957828dac..61bf6e80f4ae 100644 --- a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap @@ -102,16 +102,16 @@ exports[`attributes.component.html - angular-verify 1`] = ` *ngFor="let hero of heroes" *ngFor=" let hero of [1, 2, 3, 666666666666666666666666666666666666]; - let i=index + let i = index " *ngFor="let hero of heroes; trackBy: trackByHeroes" *ngFor="let item of items; index as i; trackBy: trackByFn" - *ngFor="let hero of heroes; let i=index" + *ngFor="let hero of heroes; let i = index" *ngFor="let hero of heroes; value: myValue" *ngIf="condition; then: thenBlock; else: elseBlock" *ngIf="condition as value; else: elseBlock" *directive="let hero" - *directive="let hero=hello" + *directive="let hero = hello" *directive="let hero of heroes" *directive="let hero of heroes" *directive="a" @@ -1402,13 +1402,17 @@ without NgModel

*ngFor with index

with semi-colon separator

-
{{i + 1}} - {{hero.name}}
+
+ {{i + 1}} - {{hero.name}} +

with comma separator

-
{{i + 1}} - {{hero.name}}
+
+ {{i + 1}} - {{hero.name}} +
top From 6e6fc984efa497b65638c1891da4c97f56f4fa1a Mon Sep 17 00:00:00 2001 From: Ika Date: Thu, 25 Oct 2018 22:17:48 +0800 Subject: [PATCH 104/177] test: add tests --- .../__snapshots__/jsfmt.spec.js.snap | 1680 +++++++++++++++++ tests/html_angular/attributes.component.html | 3 + tests/html_angular/jsfmt.spec.js | 1 + 3 files changed, 1684 insertions(+) diff --git a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap index 61bf6e80f4ae..fb08af7db4bf 100644 --- a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap @@ -15,6 +15,9 @@ exports[`attributes.component.html - angular-verify 1`] = ` [target]=" [ 1 ] " [target]=" { 'a' : 1 } " [target]=" { a : 1 } " + [target]=" { + trailingComma : 'notAllowed' + }" [target]=" true " [target]=" undefined " [target]=" null " @@ -75,6 +78,141 @@ exports[`attributes.component.html - angular-verify 1`] = ` [target]="[1]" [target]="{ a: 1 }" [target]="{ a: 1 }" + [target]="{ + trailingComma: 'notAllowed' + }" + [target]="true" + [target]="undefined" + [target]="null" + [target]="1" + [target]="1" + [target]="'hello'" + [target]="a(1, 2)" + [target]="a.b(1, 2)" + [target]="x!" + [target]="!x" + [target]="a" + [target]="a" + [target]="a // hello " + [target]="a.b" + [target]="javascript: 'hello world' " + [target]="a?.b()" + [target]="a?.b" + on-target="(a = 1)" + (target)="(a = 1)" + (target)="(a.b = 1)" + (target)="(a[b] = 1)" + (target)="a // hello " + (target)="a; b" + *ngIf="something ? true : false" + *ngFor="let hero of heroes" + *ngFor=" + let hero of [1, 2, 3, 666666666666666666666666666666666666]; + let i = index + " + *ngFor="let hero of heroes; trackBy: trackByHeroes" + *ngFor="let item of items; index as i; trackBy: trackByFn" + *ngFor="let hero of heroes; let i = index" + *ngFor="let hero of heroes; value: myValue" + *ngIf="condition; then: thenBlock; else: elseBlock" + *ngIf="condition as value; else: elseBlock" + *directive="let hero" + *directive="let hero = hello" + *directive="let hero of heroes" + *directive="let hero of heroes" + *directive="a" + *directive="a as b" + *directive="a; b" + *directive="a; b" + *directive="a; b: c" + *directive="a; b: c" + *directive="a; b: c as d" + *directive="a; b as c" +> + +`; + +exports[`attributes.component.html - angular-verify 2`] = ` +
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +
{{ a | b : c }}
+
{{ 0 - 1 }}
+
{{ - 1 }}
+
{{ a ? 1 : 2 }}
+
{{ a ( 1 ) ( 2 ) }}
+
{{ a [ b ] }}
+
{{ [ 1 ] }}
+
{{ { 'a' : 1 } }}
+
{{ { a : 1 } }}
+
{{ true }}
+
{{ undefined }}
+
{{ null }}
+
{{ ( 1 ) }}
+
{{ 1 }}
+
{{ 'hello' }}
+
{{ a ( 1 , 2 ) }}
+
{{ a . b ( 1 , 2 ) }}
+
{{ x ! }}
+
{{ ! x }}
+
{{ ( ( a ) ) }}
+
{{ a }}
+
{{ a // hello }}
+
{{ a . b }}
+
{{ a ?. b ( ) }}
+
{{ a ?. b }}
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +
{{a | b:c}}
+
{{0 - 1}}
+
{{-1}}
+
{{a ? 1 : 2}}
+
{{a(1)(2)}}
+
{{a[b]}}
+
{{[1]}}
+
{{ { a: 1 } }}
+
{{ { a: 1 } }}
+
{{true}}
+
{{undefined}}
+
{{null}}
+
{{1}}
+
{{1}}
+
{{"hello"}}
+
{{a(1, 2)}}
+
{{a.b(1, 2)}}
+
{{x!}}
+
{{!x}}
+
{{a}}
+
{{a}}
+
{{a // hello }}
+
{{a.b}}
+
{{a?.b()}}
+
{{a?.b}}
+ +`; + exports[`real-world.component.html - angular-verify 1`] = ` @@ -1667,3 +1860,1490 @@ without NgModel
--> `; + +exports[`real-world.component.html - angular-verify 2`] = ` + + + +

Template Syntax

+Interpolation
+Expression context
+Statement context
+Mental Model
+Buttons
+Properties vs. Attributes
+
+Property Binding
+ +
+Event Binding
+Two-way Binding
+
+
Directives
+ +
+Template reference variables
+Inputs and outputs
+Pipes
+Safe navigation operator ?.
+Non-null assertion operator !.
+Enums
+ + +

Interpolation

+ +

My current hero is {{currentHero.name}}

+ +

+ {{title}} + +

+ + +

The sum of 1 + 1 is {{1 + 1}}

+ + +

The sum of 1 + 1 is not {{1 + 1 + getVal()}}

+ +top + +

Expression context

+ +

Component expression context ({{title}}, [hidden]="isUnchanged")

+
+ {{title}} + changed +
+ + +

Template input variable expression context (let hero)

+ + +
{{hero.name}}
+
+ +

Template reference variable expression context (#heroInput)

+
+ Type something: + {{heroInput.value}} +
+ +top + +

Statement context

+ +

Component statement context ( (click)="onSave() ) +

+ +
+ +

Template $event statement context

+
+ +
+ +

Template input variable statement context (let hero)

+ +
+ +
+ +

Template reference variable statement context (#heroForm)

+
+
...
+
+ +top + + +

New Mental Model

+ + + +
Mental Model
+ + +

+ +
+ +
Mental Model
+ + +
+

+ +
+ + +
+

+ +
+ + +
+
+

+ + + +
click me
+{{clicked}} +

+ +
+ Hero Name: + + {{name}} +
+

+ + +

+ +
Special
+

+ + + +top + + +

Property vs. Attribute (img examples)

+ + + +

+ + + + + +top + + +

Buttons

+ + + + +

+ + +

+ + + +top + + +

Property Binding

+ + + +
[ngClass] binding to the classes property
+ + + + +
+ +
+ + +

is the interpolated image.

+

is the property bound image.

+ +

"{{title}}" is the interpolated title.

+

"" is the property bound title.

+ + +

"{{evilTitle}}" is the interpolated evil title.

+

"" is the property bound evil title.

+ +top + + +

Attribute Binding

+ + + + + + + + + +
One-Two
FiveSix
+ +
+ + +

+ + +
+ + + + + + + +
+ +top + + +

Class Binding

+ + +
Bad curly special
+ + +
Bad curly
+ + +
The class binding is special
+ + +
This one is not so special
+ +
This class binding is special too
+ +top + + +

Style Binding

+ + + + + + + +top + + +

Event Binding

+ + + + + +
+ +
click with myClick
+{{clickMessage}} +
+ + + + +
+ + + + +
Click me +
Click me too!
+
+ + +
+ +
+ + +
+ +
+ +top + +

Two-way Binding

+
+ +
Resizable Text
+ +
+
+
+

De-sugared two-way binding

+ +
+ +top + + +

NgModel (two-way) Binding

+ +

Result: {{currentHero.name}}

+ + +without NgModel +
+ +[(ngModel)] +
+ +bindon-ngModel +
+ +(ngModelChange)="...name=$event" +
+ +(ngModelChange)="setUppercaseName($event)" + +top + + +

NgClass Binding

+ +

currentClasses is {{currentClasses | json}}

+
This div is initially saveable, unchanged, and special
+ + +
+ | + | + + +

+
+ This div should be {{ canSave ? "": "not"}} saveable, + {{ isUnchanged ? "unchanged" : "modified" }} and, + {{ isSpecial ? "": "not"}} special after clicking "Refresh".
+

+ +
This div is special
+ +
Bad curly special
+
Curly special
+ +top + + +

NgStyle Binding

+ +
+ This div is x-large or smaller. +
+ +

[ngStyle] binding to currentStyles - CSS property names

+

currentStyles is {{currentStyles | json}}

+
+ This div is initially italic, normal weight, and extra large (24px). +
+ + +
+ | + | + + +

+
+ This div should be {{ canSave ? "italic": "plain"}}, + {{ isUnchanged ? "normal weight" : "bold" }} and, + {{ isSpecial ? "extra large": "normal size"}} after clicking "Refresh".
+ +top + + +

NgIf Binding

+ + + +
Hello, {{currentHero.name}}
+
Hello, {{nullHero.name}}
+ + + +Add {{currentHero.name}} with template + + +
Hero Detail removed from DOM (via template) because isActive is false
+ + + + + +
Show with class
+
Hide with class
+ + + + +
Show with style
+
Hide with style
+ +top + + +

NgFor Binding

+ +
+
{{hero.name}}
+
+
+ +
+ + +
+ +top + +

*ngFor with index

+

with semi-colon separator

+
+
{{i + 1}} - {{hero.name}}
+
+ +

with comma separator

+
+ +
{{i + 1}} - {{hero.name}}
+
+ +top + +

*ngFor trackBy

+ + + + +

without trackBy

+
+
({{hero.id}}) {{hero.name}}
+ +
+ Hero DOM elements change #{{heroesNoTrackByCount}} without trackBy +
+
+ +

with trackBy

+
+
({{hero.id}}) {{hero.name}}
+ +
+ Hero DOM elements change #{{heroesWithTrackByCount}} with trackBy +
+
+ +


+ +

with trackBy and semi-colon separator

+
+
+ ({{hero.id}}) {{hero.name}} +
+
+ +

with trackBy and comma separator

+
+
({{hero.id}}) {{hero.name}}
+
+ +

with trackBy and space separator

+
+
({{hero.id}}) {{hero.name}}
+
+ +

with generic trackById function

+
+
({{hero.id}}) {{hero.name}}
+
+ +top + + +

NgSwitch Binding

+ +

Pick your favorite hero

+
+ +
+ +
+ + + +
Are you as confused as {{currentHero.name}}?
+ +
+ +top + + +

Template reference variables

+ + + + + + + + + + + + + + +

Example Form

+ + +top + + +

Inputs and Outputs

+ + + + + + + +
myClick2
+{{clickMessage2}} + +top + + +

Pipes

+ +
Title through uppercase pipe: {{title | uppercase}}
+ + +
+ Title through a pipe chain: + {{title | uppercase | lowercase}} +
+ + +
Birthdate: {{currentHero?.birthdate | date:'longDate'}}
+ +
{{currentHero | json}}
+ +
Birthdate: {{(currentHero?.birthdate | date:'longDate') | uppercase}}
+ +
+ + {{product.price | currency:'USD':true}} +
+ +top + + +

Safe navigation operator ?.

+ +
+ The title is {{title}} +
+ +
+ The current hero's name is {{currentHero?.name}} +
+ +
+ The current hero's name is {{currentHero.name}} +
+ + + + + +
The null hero's name is {{nullHero.name}}
+ +
+The null hero's name is {{nullHero && nullHero.name}} +
+ +
+ + The null hero's name is {{nullHero?.name}} +
+ + +top + + +

Non-null assertion operator !.

+ +
+ +
+ The hero's name is {{hero!.name}} +
+
+ +top + + +

$any type cast function $any( ).

+ +
+ +
+ The hero's marker is {{$any(hero).marker}} +
+
+ +
+ +
+ Undeclared members is {{$any(this).member}} +
+
+ +top + + + +

Enums in binding

+ +

+ The name of the Color.Red enum is {{Color[Color.Red]}}.
+ The current color is {{Color[color]}} and its number is {{color}}.
+ +

+ +top + + + + +
+
+
+ +
+ +
+
+ {{submitMessage}} +
+
+ + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + +

Template Syntax

+Interpolation
+Expression context
+Statement context
+Mental Model
+Buttons
+Properties vs. Attributes
+
+Property Binding
+ +
+Event Binding
+Two-way Binding
+
+
Directives
+ +
+Template reference variables
+Inputs and outputs
+Pipes
+Safe navigation operator ?.
+Non-null assertion operator !.
+Enums
+ + +
+

Interpolation

+ +

My current hero is {{currentHero.name}}

+ +

{{title}}

+ + +

The sum of 1 + 1 is {{1 + 1}}

+ + +

The sum of 1 + 1 is not {{1 + 1 + getVal()}}

+ +top + +
+

Expression context

+ +

+ Component expression context ({{title}}, + [hidden]="isUnchanged") +

+
{{title}} changed
+ +

Template input variable expression context (let hero)

+ + +
{{hero.name}}
+
+ +

Template reference variable expression context (#heroInput)

+
+ Type something: {{heroInput.value}} +
+ +top + +
+

Statement context

+ +

Component statement context ( (click)="onSave() )

+
+ +

Template $event statement context

+
+ +

Template input variable statement context (let hero)

+ +
+ +
+ +

Template reference variable statement context (#heroForm)

+
+
...
+
+ +top + + +
+

New Mental Model

+ + + +
Mental Model
+

+ +
+ +
Mental Model
+ + +
+

+ +
+ + +
+

+ +
+ + +
+
+

+ + + +
click me
+{{clicked}}

+ +
Hero Name: {{name}}
+

+ +

+ +
Special
+

+ + + +top + + +
+

Property vs. Attribute (img examples)

+ + + +

+ + + + +top + + +
+

Buttons

+ + +

+ + +

+ + + +top + + +
+

Property Binding

+ + + +
[ngClass] binding to the classes property
+ + + + +
+ + +

is the interpolated image.

+

is the property bound image.

+ +

+ "{{title}}" is the interpolated title. +

+

"" is the property bound title.

+ + +

+ "{{evilTitle}}" is the interpolated evil title. +

+

+ "" is the property bound evil + title. +

+ +top + + +
+

Attribute Binding

+ + + + + + + + + + + + + + +
One-Two
FiveSix
+ +
+ + +

+ + +
+ + + + + + + +
+ +top + + +
+

Class Binding

+ + +
Bad curly special
+ + +
Bad curly
+ + +
The class binding is special
+ + +
+ This one is not so special +
+ +
This class binding is special too
+ +top + + +
+

Style Binding

+ + + + + + + +top + + +
+

Event Binding

+ + + + + +
+ +
click with myClick
+ {{clickMessage}} +
+ + + +
+ + + + +
+ Click me +
Click me too!
+
+ + +
+ +
+ + +
+ +
+ +top + +
+

Two-way Binding

+
+ +
Resizable Text
+ +
+
+
+

De-sugared two-way binding

+ +
+ +top + + +
+

NgModel (two-way) Binding

+ +

Result: {{currentHero.name}}

+ + +without NgModel
+ [(ngModel)]
+ bindon-ngModel
+ +(ngModelChange)="...name=$event"
+ +(ngModelChange)="setUppercaseName($event)" + +top + + +
+

NgClass Binding

+ +

currentClasses is {{currentClasses | json}}

+
+ This div is initially saveable, unchanged, and special +
+ + +
+ | + +| + +

+
+ This div should be {{canSave ? "" : "not"}} saveable, + {{isUnchanged ? "unchanged" : "modified"}} and, + {{isSpecial ? "" : "not"}} special after clicking "Refresh". +
+

+ +
This div is special
+ +
Bad curly special
+
Curly special
+ +top + + +
+

NgStyle Binding

+ +
+ This div is x-large or smaller. +
+ +

[ngStyle] binding to currentStyles - CSS property names

+

currentStyles is {{currentStyles | json}}

+
+ This div is initially italic, normal weight, and extra large (24px). +
+ + +
+ | + | + +

+
+ This div should be {{canSave ? "italic" : "plain"}}, + {{isUnchanged ? "normal weight" : "bold"}} and, + {{isSpecial ? "extra large" : "normal size"}} after clicking "Refresh". +
+ +top + + +
+

NgIf Binding

+ + + +
Hello, {{currentHero.name}}
+
Hello, {{nullHero.name}}
+ + + +Add {{currentHero.name}} with template + + +
Hero Detail removed from DOM (via template) because isActive is false
+ + + + + +
Show with class
+
Hide with class
+ + + + +
Show with style
+
Hide with style
+ +top + + +
+

NgFor Binding

+ +
+
{{hero.name}}
+
+
+ +
+ + +
+ +top + +

*ngFor with index

+

with semi-colon separator

+
+
+ {{i + 1}} - {{hero.name}} +
+
+ +

with comma separator

+
+ +
+ {{i + 1}} - {{hero.name}} +
+
+ +top + +

*ngFor trackBy

+ + + + +

without trackBy

+
+
({{hero.id}}) {{hero.name}}
+ +
+ Hero DOM elements change #{{heroesNoTrackByCount}} without trackBy +
+
+ +

with trackBy

+
+
+ ({{hero.id}}) {{hero.name}} +
+ +
+ Hero DOM elements change #{{heroesWithTrackByCount}} with trackBy +
+
+ +


+ +

with trackBy and semi-colon separator

+
+
+ ({{hero.id}}) {{hero.name}} +
+
+ +

with trackBy and comma separator

+
+
+ ({{hero.id}}) {{hero.name}} +
+
+ +

with trackBy and space separator

+
+
+ ({{hero.id}}) {{hero.name}} +
+
+ +

with generic trackById function

+
+
+ ({{hero.id}}) {{hero.name}} +
+
+ +top + + +
+

NgSwitch Binding

+ +

Pick your favorite hero

+
+ +
+ +
+ + + +
+ Are you as confused as {{currentHero.name}}? +
+ +
+ +top + + +
+

Template reference variables

+ + + + + + + + + + + + + + +

Example Form

+ + +top + + +
+

Inputs and Outputs

+ + + + + + +
myClick2
+{{clickMessage2}} + +top + + +
+

Pipes

+ +
Title through uppercase pipe: {{title | uppercase}}
+ + +
Title through a pipe chain: {{title | uppercase | lowercase}}
+ + +
Birthdate: {{currentHero?.birthdate | date:"longDate"}}
+ +
{{currentHero | json}}
+ +
Birthdate: {{currentHero?.birthdate | date:"longDate" | uppercase}}
+ +
+ + {{product.price | currency:"USD":true}} +
+ +top + + +
+

Safe navigation operator ?.

+ +
The title is {{title}}
+ +
The current hero's name is {{currentHero?.name}}
+ +
The current hero's name is {{currentHero.name}}
+ + + + +
The null hero's name is {{nullHero.name}}
+ +
The null hero's name is {{nullHero && nullHero.name}}
+ +
+ + The null hero's name is {{nullHero?.name}} +
+ +top + + +
+

Non-null assertion operator !.

+ +
+ +
The hero's name is {{hero!.name}}
+
+ +top + + +
+

$any type cast function $any( ).

+ +
+ +
The hero's marker is {{$any(hero).marker}}
+
+ +
+ +
Undeclared members is {{$any(this).member}}
+
+ +top + + + +
+

Enums in binding

+ +

+ The name of the Color.Red enum is {{Color[Color.Red]}}.
+ The current color is {{Color[color]}} and its number is {{color}}.
+ +

+ +top + + + +
+
+
+ +
+ +
+
{{submitMessage}}
+
+ + + +`; diff --git a/tests/html_angular/attributes.component.html b/tests/html_angular/attributes.component.html index 7a05b50cccf8..665619c3ebee 100644 --- a/tests/html_angular/attributes.component.html +++ b/tests/html_angular/attributes.component.html @@ -12,6 +12,9 @@ [target]=" [ 1 ] " [target]=" { 'a' : 1 } " [target]=" { a : 1 } " + [target]=" { + trailingComma : 'notAllowed' + }" [target]=" true " [target]=" undefined " [target]=" null " diff --git a/tests/html_angular/jsfmt.spec.js b/tests/html_angular/jsfmt.spec.js index b802ad8670c5..21bd6c0be802 100644 --- a/tests/html_angular/jsfmt.spec.js +++ b/tests/html_angular/jsfmt.spec.js @@ -1 +1,2 @@ run_spec(__dirname, ["angular"]); +run_spec(__dirname, ["angular"], { trailingComma: "es5" }); From 5a0bd751aa8f0fa288ffd85bd0614609ac1170be Mon Sep 17 00:00:00 2001 From: Ika Date: Thu, 25 Oct 2018 22:18:23 +0800 Subject: [PATCH 105/177] fix(angular): trailing comma is not allowed in angular-specifix syntax --- src/language-html/printer-html.js | 27 ++++++++++++------- .../__snapshots__/jsfmt.spec.js.snap | 2 +- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/language-html/printer-html.js b/src/language-html/printer-html.js index d18f90b991c0..43b60fc11500 100644 --- a/src/language-html/printer-html.js +++ b/src/language-html/printer-html.js @@ -76,12 +76,12 @@ function embed(path, print, textToDoc, options) { indent( concat([ softline, - textToDoc(node.value, { - parser: - options.parser === "angular" - ? "__ng_interpolation" - : "__js_expression" - }) + textToDoc( + node.value, + options.parser === "angular" + ? { parser: "__ng_interpolation", trailingComma: "none" } + : { parser: "__js_expression" } + ) ]) ), node.parent.next && @@ -790,11 +790,17 @@ function printEmbeddedAttributeValue(node, textToDoc, options) { const ngExpressionBindingPatterns = ["^\\[.+\\]$", "^bind(on)?-"]; if (isKeyMatched(ngStatementBindingPatterns)) { - return textToDoc(getValue(), { parser: "__ng_action" }); + return textToDoc(getValue(), { + parser: "__ng_action", + trailingComma: "none" + }); } if (isKeyMatched(ngExpressionBindingPatterns)) { - return textToDoc(getValue(), { parser: "__ng_binding" }); + return textToDoc(getValue(), { + parser: "__ng_binding", + trailingComma: "none" + }); } if (isKeyMatched(ngDirectiveBindingPatterns)) { @@ -803,7 +809,10 @@ function printEmbeddedAttributeValue(node, textToDoc, options) { indent( concat([ softline, - textToDoc(getValue(), { parser: "__ng_directive" }) + textToDoc(getValue(), { + parser: "__ng_directive", + trailingComma: "none" + }) ]) ), softline diff --git a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap index fb08af7db4bf..286558da9b81 100644 --- a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap @@ -211,7 +211,7 @@ exports[`attributes.component.html - angular-verify 2`] = ` [target]="{ a: 1 }" [target]="{ a: 1 }" [target]="{ - trailingComma: 'notAllowed', + trailingComma: 'notAllowed' }" [target]="true" [target]="undefined" From fdfcd7b0f89d7145c1e377b763189b0746776e56 Mon Sep 17 00:00:00 2001 From: Ika Date: Thu, 25 Oct 2018 23:02:17 +0800 Subject: [PATCH 106/177] test: add tests --- .../__snapshots__/jsfmt.spec.js.snap | 29 +++++++++++++++++++ tests/angular_interpolation/jsfmt.spec.js | 2 ++ .../angular_interpolation/pipe-expression.ng | 12 ++++++++ 3 files changed, 43 insertions(+) create mode 100644 tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap create mode 100644 tests/angular_interpolation/jsfmt.spec.js create mode 100644 tests/angular_interpolation/pipe-expression.ng diff --git a/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap b/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap new file mode 100644 index 000000000000..132a6a7178d7 --- /dev/null +++ b/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap @@ -0,0 +1,29 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`pipe-expression.ng - __ng_interpolation-verify 1`] = ` +[ + a ? (b | c : d) : (e | f : g), + a | b | c | d, + ((a | b) | c) | d, + a | b:(c | d), + { a: b | c }, + (a + b) | c, + (a | b) + c, + fn(a | b), + a?.b(c | d), + a[b | c] +] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[ + a ? b | c:d : e | f:g, + a | b | c | d, + a | b | c | d, + a | b:c | d, + { a: b | c }, + a + b | c, + a | b + c, + fn(a | b), + a?.b(c | d), + a[b | c] +] +`; diff --git a/tests/angular_interpolation/jsfmt.spec.js b/tests/angular_interpolation/jsfmt.spec.js new file mode 100644 index 000000000000..614637e912fa --- /dev/null +++ b/tests/angular_interpolation/jsfmt.spec.js @@ -0,0 +1,2 @@ +run_spec(__dirname, ["__ng_interpolation"]); + diff --git a/tests/angular_interpolation/pipe-expression.ng b/tests/angular_interpolation/pipe-expression.ng new file mode 100644 index 000000000000..75dd159a8ad0 --- /dev/null +++ b/tests/angular_interpolation/pipe-expression.ng @@ -0,0 +1,12 @@ +[ + a ? (b | c : d) : (e | f : g), + a | b | c | d, + ((a | b) | c) | d, + a | b:(c | d), + { a: b | c }, + (a + b) | c, + (a | b) + c, + fn(a | b), + a?.b(c | d), + a[b | c] +] From 5e0533b2c9221181551d212b7d6b9953f971409e Mon Sep 17 00:00:00 2001 From: Ika Date: Thu, 25 Oct 2018 23:03:20 +0800 Subject: [PATCH 107/177] fix(angular): add missing parens for pipe expression in some cases --- src/language-js/needs-parens.js | 14 ++++++++++++++ .../__snapshots__/jsfmt.spec.js.snap | 6 +++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/language-js/needs-parens.js b/src/language-js/needs-parens.js index 53144ec55b55..7a783381bf9a 100644 --- a/src/language-js/needs-parens.js +++ b/src/language-js/needs-parens.js @@ -613,6 +613,20 @@ function needsParens(path, options) { return true; } return false; + case "NGPipeExpression": + if ( + parent.type === "NGRoot" || + parent.type === "ObjectProperty" || + parent.type === "ArrayExpression" || + parent.type === "CallExpression" || + parent.type === "OptionalCallExpression" || + (parent.type === "NGPipeExpression" && name === "right") || + parent.type === "MemberExpression" || + parent.type === "AssignmentExpression" + ) { + return false; + } + return true; } return false; diff --git a/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap b/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap index 132a6a7178d7..55ab144aa7c4 100644 --- a/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap +++ b/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap @@ -15,13 +15,13 @@ exports[`pipe-expression.ng - __ng_interpolation-verify 1`] = ` ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [ - a ? b | c:d : e | f:g, + a ? (b | c:d) : (e | f:g), a | b | c | d, a | b | c | d, - a | b:c | d, + a | b:(c | d), { a: b | c }, a + b | c, - a | b + c, + (a | b) + c, fn(a | b), a?.b(c | d), a[b | c] From 3195482c00cdde1692b477827caa6c7f88641af1 Mon Sep 17 00:00:00 2001 From: Ika Date: Thu, 25 Oct 2018 23:28:47 +0800 Subject: [PATCH 108/177] style: fix linting --- tests/angular_interpolation/jsfmt.spec.js | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/angular_interpolation/jsfmt.spec.js b/tests/angular_interpolation/jsfmt.spec.js index 614637e912fa..09a639b7b7f2 100644 --- a/tests/angular_interpolation/jsfmt.spec.js +++ b/tests/angular_interpolation/jsfmt.spec.js @@ -1,2 +1 @@ run_spec(__dirname, ["__ng_interpolation"]); - From 3a59ef281d026eede697ae385dd2179c32bbecb3 Mon Sep 17 00:00:00 2001 From: Ika Date: Thu, 25 Oct 2018 23:52:06 +0800 Subject: [PATCH 109/177] test: add tests --- .../angular_interpolation/__snapshots__/jsfmt.spec.js.snap | 6 ++++-- tests/angular_interpolation/pipe-expression.ng | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap b/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap index 55ab144aa7c4..08e04a389948 100644 --- a/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap +++ b/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap @@ -11,7 +11,8 @@ exports[`pipe-expression.ng - __ng_interpolation-verify 1`] = ` (a | b) + c, fn(a | b), a?.b(c | d), - a[b | c] + a[b | c], + ($students | async).items ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [ @@ -24,6 +25,7 @@ exports[`pipe-expression.ng - __ng_interpolation-verify 1`] = ` (a | b) + c, fn(a | b), a?.b(c | d), - a[b | c] + a[b | c], + $students | async.items ] `; diff --git a/tests/angular_interpolation/pipe-expression.ng b/tests/angular_interpolation/pipe-expression.ng index 75dd159a8ad0..893dbe5230a9 100644 --- a/tests/angular_interpolation/pipe-expression.ng +++ b/tests/angular_interpolation/pipe-expression.ng @@ -8,5 +8,6 @@ (a | b) + c, fn(a | b), a?.b(c | d), - a[b | c] + a[b | c], + ($students | async).items ] From ae74fa24530b6c977c27479962157888d94f8e83 Mon Sep 17 00:00:00 2001 From: Ika Date: Thu, 25 Oct 2018 23:54:12 +0800 Subject: [PATCH 110/177] fix(angular): add parens for pipe in memberExpression.object --- src/language-js/needs-parens.js | 2 +- tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/language-js/needs-parens.js b/src/language-js/needs-parens.js index 7a783381bf9a..40f74c496c1c 100644 --- a/src/language-js/needs-parens.js +++ b/src/language-js/needs-parens.js @@ -621,7 +621,7 @@ function needsParens(path, options) { parent.type === "CallExpression" || parent.type === "OptionalCallExpression" || (parent.type === "NGPipeExpression" && name === "right") || - parent.type === "MemberExpression" || + (parent.type === "MemberExpression" && name === "property") || parent.type === "AssignmentExpression" ) { return false; diff --git a/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap b/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap index 08e04a389948..3ee8ade00223 100644 --- a/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap +++ b/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap @@ -26,6 +26,6 @@ exports[`pipe-expression.ng - __ng_interpolation-verify 1`] = ` fn(a | b), a?.b(c | d), a[b | c], - $students | async.items + ($students | async).items ] `; From dd2a16b0653129e9a34ca95d9353f07a60951471 Mon Sep 17 00:00:00 2001 From: Ika Date: Fri, 26 Oct 2018 00:14:59 +0800 Subject: [PATCH 111/177] test: add tests --- .../angular_interpolation/__snapshots__/jsfmt.spec.js.snap | 6 ++++-- tests/angular_interpolation/pipe-expression.ng | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap b/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap index 3ee8ade00223..029b03f62653 100644 --- a/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap +++ b/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap @@ -12,7 +12,8 @@ exports[`pipe-expression.ng - __ng_interpolation-verify 1`] = ` fn(a | b), a?.b(c | d), a[b | c], - ($students | async).items + ($students | async).items, + ($students | async)() ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [ @@ -26,6 +27,7 @@ exports[`pipe-expression.ng - __ng_interpolation-verify 1`] = ` fn(a | b), a?.b(c | d), a[b | c], - ($students | async).items + ($students | async).items, + $students | async() ] `; diff --git a/tests/angular_interpolation/pipe-expression.ng b/tests/angular_interpolation/pipe-expression.ng index 893dbe5230a9..27add64367b2 100644 --- a/tests/angular_interpolation/pipe-expression.ng +++ b/tests/angular_interpolation/pipe-expression.ng @@ -9,5 +9,6 @@ fn(a | b), a?.b(c | d), a[b | c], - ($students | async).items + ($students | async).items, + ($students | async)() ] From f295fc3116720d6e52847c043f56eed7f0cf2870 Mon Sep 17 00:00:00 2001 From: Ika Date: Fri, 26 Oct 2018 00:15:52 +0800 Subject: [PATCH 112/177] fix(angular): add parens for pipe in callExpression.callee --- src/language-js/needs-parens.js | 5 +++-- tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/language-js/needs-parens.js b/src/language-js/needs-parens.js index 40f74c496c1c..e3f18a2ccb14 100644 --- a/src/language-js/needs-parens.js +++ b/src/language-js/needs-parens.js @@ -618,8 +618,9 @@ function needsParens(path, options) { parent.type === "NGRoot" || parent.type === "ObjectProperty" || parent.type === "ArrayExpression" || - parent.type === "CallExpression" || - parent.type === "OptionalCallExpression" || + ((parent.type === "CallExpression" || + parent.type === "OptionalCallExpression") && + parent.arguments[name] === node) || (parent.type === "NGPipeExpression" && name === "right") || (parent.type === "MemberExpression" && name === "property") || parent.type === "AssignmentExpression" diff --git a/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap b/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap index 029b03f62653..52e48549a596 100644 --- a/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap +++ b/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap @@ -28,6 +28,6 @@ exports[`pipe-expression.ng - __ng_interpolation-verify 1`] = ` a?.b(c | d), a[b | c], ($students | async).items, - $students | async() + ($students | async)() ] `; From 2d874abf4eea0deece06d9cbfb766dea2524c69e Mon Sep 17 00:00:00 2001 From: Ika Date: Fri, 26 Oct 2018 21:01:19 +0800 Subject: [PATCH 113/177] test: add tests --- .../__snapshots__/jsfmt.spec.js.snap | 14 ++++++++++++++ tests/angular_interpolation/logical-expression.ng | 3 +++ 2 files changed, 17 insertions(+) create mode 100644 tests/angular_interpolation/logical-expression.ng diff --git a/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap b/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap index 52e48549a596..24d69dff83d7 100644 --- a/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap +++ b/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap @@ -1,5 +1,19 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`logical-expression.ng - __ng_interpolation-verify 1`] = ` +[ + advancedSearchService.patientInformationFieldsRow2 && advancedSearchService.patientInformationFieldsRow2.indexOf(advancedSearchService.formElementData.customFieldList[i].customFieldType) !== -1 +] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[ + advancedSearchService.patientInformationFieldsRow2 && + advancedSearchService.patientInformationFieldsRow2.indexOf( + advancedSearchService.formElementData.customFieldList[i].customFieldType + ) !== + -1 +] +`; + exports[`pipe-expression.ng - __ng_interpolation-verify 1`] = ` [ a ? (b | c : d) : (e | f : g), diff --git a/tests/angular_interpolation/logical-expression.ng b/tests/angular_interpolation/logical-expression.ng new file mode 100644 index 000000000000..fc56a8e99723 --- /dev/null +++ b/tests/angular_interpolation/logical-expression.ng @@ -0,0 +1,3 @@ +[ + advancedSearchService.patientInformationFieldsRow2 && advancedSearchService.patientInformationFieldsRow2.indexOf(advancedSearchService.formElementData.customFieldList[i].customFieldType) !== -1 +] From a7eb4e5f96efa02002672e280957a5f9a4da5102 Mon Sep 17 00:00:00 2001 From: Ika Date: Fri, 26 Oct 2018 21:02:28 +0800 Subject: [PATCH 114/177] fix: update angular-estree-parser to fix unexpected `-1` formatting --- package.json | 2 +- .../__snapshots__/jsfmt.spec.js.snap | 3 +-- yarn.lock | 8 ++++---- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 901bc503d7f5..d75b17f8c26e 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "@babel/parser": "7.1.2", "@glimmer/syntax": "0.30.3", "@iarna/toml": "2.0.0", - "angular-estree-parser": "1.1.0", + "angular-estree-parser": "1.1.1", "angular-html-parser": "1.0.0", "camelcase": "4.1.0", "chalk": "2.1.0", diff --git a/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap b/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap index 24d69dff83d7..3635682e285c 100644 --- a/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap +++ b/tests/angular_interpolation/__snapshots__/jsfmt.spec.js.snap @@ -9,8 +9,7 @@ exports[`logical-expression.ng - __ng_interpolation-verify 1`] = ` advancedSearchService.patientInformationFieldsRow2 && advancedSearchService.patientInformationFieldsRow2.indexOf( advancedSearchService.formElementData.customFieldList[i].customFieldType - ) !== - -1 + ) !== -1 ] `; diff --git a/yarn.lock b/yarn.lock index eff792d48180..dcc339c57354 100644 --- a/yarn.lock +++ b/yarn.lock @@ -760,10 +760,10 @@ amdefine@>=0.0.4: resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= -angular-estree-parser@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/angular-estree-parser/-/angular-estree-parser-1.1.0.tgz#64bb1f8ebced8167ad64bf93c00d65f142a83fa5" - integrity sha512-kLigPNv5DoOU0E+lMh9aAFWakAoOPtM5Xk6HOKHLVZqRWM30Z6MnQrXSGwOShWv7HyXtpqftoe85dYvFPVW8Sg== +angular-estree-parser@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/angular-estree-parser/-/angular-estree-parser-1.1.1.tgz#408a2e0f2ca95a7d8563a4c93d3411c7148d9b67" + integrity sha512-9FoXf5n9seO0SioEabxr+dUHxjiUIN/+Nh20rSlMucWd1NH85C0CQbfBlpjukW2sY3hWROYbz3apl4532eXeqw== dependencies: lines-and-columns "^1.1.6" tslib "^1.9.3" From 35f91e21cd0730e2d0517cad729dad07569766ba Mon Sep 17 00:00:00 2001 From: Ika Date: Fri, 26 Oct 2018 21:43:45 +0800 Subject: [PATCH 115/177] test: add tests --- .../__snapshots__/jsfmt.spec.js.snap | 92 +++++++++++++++++++ .../html_angular/interpolation.component.html | 15 +++ 2 files changed, 107 insertions(+) diff --git a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap index 286558da9b81..694c4da90046 100644 --- a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap @@ -290,6 +290,21 @@ exports[`interpolation.component.html - angular-verify 1`] = `
{{ a . b }}
{{ a ?. b ( ) }}
{{ a ?. b }}
+ + + + + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{{a | b:c}}
{{0 - 1}}
@@ -316,6 +331,37 @@ exports[`interpolation.component.html - angular-verify 1`] = `
{{a.b}}
{{a?.b()}}
{{a?.b}}
+ + + + + `; @@ -345,6 +391,21 @@ exports[`interpolation.component.html - angular-verify 2`] = `
{{ a . b }}
{{ a ?. b ( ) }}
{{ a ?. b }}
+ + + + + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{{a | b:c}}
{{0 - 1}}
@@ -371,6 +432,37 @@ exports[`interpolation.component.html - angular-verify 2`] = `
{{a.b}}
{{a?.b()}}
{{a?.b}}
+ + + + + `; diff --git a/tests/html_angular/interpolation.component.html b/tests/html_angular/interpolation.component.html index 896ece2845b4..357cb8adf900 100644 --- a/tests/html_angular/interpolation.component.html +++ b/tests/html_angular/interpolation.component.html @@ -23,3 +23,18 @@
{{ a . b }}
{{ a ?. b ( ) }}
{{ a ?. b }}
+ + + + + From 5ec06f7e26ac7a54bed099d1d9b38f8af441f8f9 Mon Sep 17 00:00:00 2001 From: Ika Date: Fri, 26 Oct 2018 22:01:38 +0800 Subject: [PATCH 116/177] feat: add a special case for interpolation-only elements --- src/language-html/printer-html.js | 201 ++++++++++-------- .../__snapshots__/jsfmt.spec.js.snap | 30 ++- 2 files changed, 130 insertions(+), 101 deletions(-) diff --git a/src/language-html/printer-html.js b/src/language-html/printer-html.js index 43b60fc11500..a7ce1b413cff 100644 --- a/src/language-html/printer-html.js +++ b/src/language-html/printer-html.js @@ -27,7 +27,6 @@ const { getCommentData, getLastDescendant, hasPrettierIgnore, - identity, inferScriptParser, isElement, isPreLikeNode, @@ -144,72 +143,110 @@ function genericPrint(path, options, print) { hardline ]); case "element": - case "ieConditionalComment": + case "ieConditionalComment": { + /** + * do not break: + * + *
{{ + * ~ + * interpolation + * }}
+ * ~ + * + * exception: break if the opening tag breaks + * + *
{{ + * interpolation + * }}
+ */ + const shouldHugContent = + node.children.length === 1 && + node.firstChild.type === "interpolation" && + (!node.firstChild.isLeadingSpaceSensitive || + !node.firstChild.hasLeadingSpaces) && + (!node.lastChild.isTrailingSpaceSensitive || + !node.lastChild.hasTrailingSpaces); + const attrGroupId = Symbol("element-attr-group-id"); return concat([ group( concat([ - printOpeningTag(path, options, print), + group(printOpeningTag(path, options, print), { id: attrGroupId }), node.children.length === 0 ? node.hasDanglingSpaces && node.isDanglingSpaceSensitive ? line : "" : concat([ forceBreakContent(node) ? breakParent : "", - (isScriptLikeTag(node) && - node.parent.type === "root" && - options.parser === "vue" - ? identity - : indent)( + (childrenDoc => + shouldHugContent + ? ifBreak(indent(childrenDoc), childrenDoc, { + groupId: attrGroupId + }) + : isScriptLikeTag(node) && + node.parent.type === "root" && + options.parser === "vue" + ? childrenDoc + : indent(childrenDoc))( concat([ - node.firstChild.type === "text" && - node.firstChild.isWhitespaceSensitive && - node.firstChild.isIndentationSensitive - ? node.firstChild.value.indexOf("\n") === -1 - ? "" - : literalline - : node.firstChild.hasLeadingSpaces && - node.firstChild.isLeadingSpaceSensitive - ? line - : softline, + shouldHugContent + ? ifBreak(softline, "", { groupId: attrGroupId }) + : node.firstChild.type === "text" && + node.firstChild.isWhitespaceSensitive && + node.firstChild.isIndentationSensitive + ? node.firstChild.value.indexOf("\n") === -1 + ? "" + : literalline + : node.firstChild.hasLeadingSpaces && + node.firstChild.isLeadingSpaceSensitive + ? line + : softline, printChildren(path, options, print) ]) ), - (node.next - ? needsToBorrowPrevClosingTagEndMarker(node.next) - : needsToBorrowLastChildClosingTagEndMarker(node.parent)) - ? node.lastChild.hasTrailingSpaces && - node.lastChild.isTrailingSpaceSensitive - ? " " - : "" - : node.lastChild.hasTrailingSpaces && - node.lastChild.isTrailingSpaceSensitive - ? line - : isElement(node) && - isPreLikeNode(node) && - node.lastChild.type === "text" && - (node.lastChild.value.indexOf("\n") === -1 || - new RegExp( - `\\n\\s{${options.tabWidth * - countParents( - path, - n => n.parent && n.parent.type !== "root" - )}}$` - ).test(node.lastChild.value)) - ? /** - *
- *
-                           *         something
-                           *       
- * ~ - *
- */ - "" - : softline + shouldHugContent + ? ifBreak(softline, "", { groupId: attrGroupId }) + : (node.next + ? needsToBorrowPrevClosingTagEndMarker(node.next) + : needsToBorrowLastChildClosingTagEndMarker(node.parent)) + ? node.lastChild.hasTrailingSpaces && + node.lastChild.isTrailingSpaceSensitive + ? " " + : "" + : node.lastChild.hasTrailingSpaces && + node.lastChild.isTrailingSpaceSensitive + ? line + : isElement(node) && + isPreLikeNode(node) && + node.lastChild.type === "text" && + (node.lastChild.value.indexOf("\n") === -1 || + new RegExp( + `\\n\\s{${options.tabWidth * + countParents( + path, + n => n.parent && n.parent.type !== "root" + )}}$` + ).test(node.lastChild.value)) + ? /** + *
+ *
+                             *         something
+                             *       
+ * ~ + *
+ */ + "" + : softline ]) ]) ), printClosingTag(node) ]); + } case "interpolation": return concat([ printOpeningTagStart(node), @@ -489,40 +526,38 @@ function printOpeningTag(path, options, print) { */ " " : "" - : group( - concat([ - indent( - concat([ - forceNotToBreakAttrContent ? " " : line, - join(line, path.map(print, "attrs")) - ]) - ), - /** - * 123456 - */ - (node.firstChild && - needsToBorrowParentOpeningTagEndMarker(node.firstChild)) || - /** - * 123 - */ - (node.isSelfClosing && - needsToBorrowLastChildClosingTagEndMarker(node.parent)) - ? "" - : node.isSelfClosing - ? forceNotToBreakAttrContent - ? " " - : line - : forceNotToBreakAttrContent - ? "" - : softline - ]) - ), + : concat([ + indent( + concat([ + forceNotToBreakAttrContent ? " " : line, + join(line, path.map(print, "attrs")) + ]) + ), + /** + * 123456 + */ + (node.firstChild && + needsToBorrowParentOpeningTagEndMarker(node.firstChild)) || + /** + * 123 + */ + (node.isSelfClosing && + needsToBorrowLastChildClosingTagEndMarker(node.parent)) + ? "" + : node.isSelfClosing + ? forceNotToBreakAttrContent + ? " " + : line + : forceNotToBreakAttrContent + ? "" + : softline + ]), node.isSelfClosing ? "" : printOpeningTagEnd(node) ]); } diff --git a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap index 694c4da90046..e5330c785788 100644 --- a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap @@ -331,12 +331,9 @@ exports[`interpolation.component.html - angular-verify 1`] = `
{{a.b}}
{{a?.b()}}
{{a?.b}}
- +
top @@ -1357,9 +1357,9 @@ can be found in the LICENSE file at http://angular.io/license

- + top @@ -1908,9 +1908,9 @@ without NgModel

The name of the Color.Red enum is {{Color[Color.Red]}}.
The current color is {{Color[color]}} and its number is {{color}}.
- +

top @@ -2818,7 +2818,7 @@ can be found in the LICENSE file at http://angular.io/license
Special


- + top @@ -2844,9 +2844,9 @@ can be found in the LICENSE file at http://angular.io/license

- + top @@ -3395,9 +3395,9 @@ without NgModel

The name of the Color.Red enum is {{Color[Color.Red]}}.
The current color is {{Color[color]}} and its number is {{color}}.
- +

top diff --git a/tests/html_attributes/__snapshots__/jsfmt.spec.js.snap b/tests/html_attributes/__snapshots__/jsfmt.spec.js.snap index dbdf774ea5ae..cbf575a57847 100644 --- a/tests/html_attributes/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_attributes/__snapshots__/jsfmt.spec.js.snap @@ -175,33 +175,33 @@ exports[`boolean.html - html-verify 1`] = ` - - - - - - - - - + + + + + + + + + diff --git a/tests/html_tags/__snapshots__/jsfmt.spec.js.snap b/tests/html_tags/__snapshots__/jsfmt.spec.js.snap index bb54a039d3fa..99ab59800fbe 100644 --- a/tests/html_tags/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_tags/__snapshots__/jsfmt.spec.js.snap @@ -1602,16 +1602,16 @@ exports[`tags.html - html-verify 1`] = `

- +



- +

"" is the property bound title.

  • @@ -1985,29 +1985,33 @@ exports[`tags.html - html-verify 2`] = `
    + 12345678901234567890 +

    + Disabled + Cancel +

    + 12345678901234567890 +

    + Disabled + Cancel +

    "Click here! Click here! Click here! Click here! Click here! Click here! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - +

    - +
    - - + +
    `; From 0cc6987e96c59b2ad75bf360a981210019ed0750 Mon Sep 17 00:00:00 2001 From: Ika Date: Sat, 27 Oct 2018 17:08:11 +0800 Subject: [PATCH 120/177] test: add tests --- .../html_whitespace/__snapshots__/jsfmt.spec.js.snap | 12 ++++++++++++ tests/html_whitespace/display-inline-block.html | 1 + 2 files changed, 13 insertions(+) diff --git a/tests/html_whitespace/__snapshots__/jsfmt.spec.js.snap b/tests/html_whitespace/__snapshots__/jsfmt.spec.js.snap index f6a55bd97383..c49434ceeaff 100644 --- a/tests/html_whitespace/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_whitespace/__snapshots__/jsfmt.spec.js.snap @@ -25,6 +25,7 @@ Click here! Click here! Click here! Click here! Click here! Click here! + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + `; diff --git a/tests/html_whitespace/display-inline-block.html b/tests/html_whitespace/display-inline-block.html index 263669e85831..dbfd8c45f36d 100644 --- a/tests/html_whitespace/display-inline-block.html +++ b/tests/html_whitespace/display-inline-block.html @@ -9,3 +9,4 @@ + From 73283a3c83acd48dcc2d68557c58a9ded2f4592e Mon Sep 17 00:00:00 2001 From: Ika Date: Sat, 27 Oct 2018 17:23:27 +0800 Subject: [PATCH 121/177] fix: add css display for video, audio, source and track --- src/language-html/constants.evaluate.js | 11 ++++++++++- src/language-html/utils.js | 3 --- tests/html_tags/__snapshots__/jsfmt.spec.js.snap | 10 +++++++--- .../__snapshots__/jsfmt.spec.js.snap | 15 ++++----------- 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/language-html/constants.evaluate.js b/src/language-html/constants.evaluate.js index 7cfec6031c05..2ce6efaf500b 100644 --- a/src/language-html/constants.evaluate.js +++ b/src/language-html/constants.evaluate.js @@ -19,7 +19,16 @@ const getCssStyleTags = property => const CSS_DISPLAY_TAGS = Object.assign({}, getCssStyleTags("display"), { // TODO: send PR to upstream - button: "inline-block" + button: "inline-block", + + // special cases for some css display=none elements + template: "inline", + source: "block", + track: "block", + + // there's no css display for these elements but they behave these ways + video: "inline-block", + audio: "inline-block" }); const CSS_DISPLAY_DEFAULT = "inline"; const CSS_WHITE_SPACE_TAGS = getCssStyleTags("white-space"); diff --git a/src/language-html/utils.js b/src/language-html/utils.js index 1eac3ab4c629..0307612d6589 100644 --- a/src/language-html/utils.js +++ b/src/language-html/utils.js @@ -388,9 +388,6 @@ function getNodeCssStyleDisplay(node, prevNode, options) { case "ignore": return "block"; default: - if (isElement(node, "template")) { - return "inline"; - } return ( (isElement(node) && CSS_DISPLAY_TAGS[node.name]) || CSS_DISPLAY_DEFAULT ); diff --git a/tests/html_tags/__snapshots__/jsfmt.spec.js.snap b/tests/html_tags/__snapshots__/jsfmt.spec.js.snap index 99ab59800fbe..b344f2af6400 100644 --- a/tests/html_tags/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_tags/__snapshots__/jsfmt.spec.js.snap @@ -1539,8 +1539,8 @@ exports[`tags.html - html-verify 1`] = `
    string
    @@ -2141,7 +2141,11 @@ exports[`tags.html - html-verify 3`] = `
    very very very very very very very very very very very very very very very very long string
    string
    very very very very very very very very very very very very very very very very long string
    - +
    string
    string
    diff --git a/tests/html_whitespace/__snapshots__/jsfmt.spec.js.snap b/tests/html_whitespace/__snapshots__/jsfmt.spec.js.snap index c49434ceeaff..379e1e7cf0f3 100644 --- a/tests/html_whitespace/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_whitespace/__snapshots__/jsfmt.spec.js.snap @@ -48,17 +48,10 @@ Click here! Click here! Click here! Click here! Click here! Click here! Click here! Click here! Click here! Click here! Click here! Click here!
    - + `; From ee952e6b690a325909dcdda3b4d1162271a7a7e6 Mon Sep 17 00:00:00 2001 From: Ika Date: Sat, 27 Oct 2018 21:33:45 +0800 Subject: [PATCH 122/177] chore(deps): remove unused dependency --- package.json | 1 - yarn.lock | 12 ------------ 2 files changed, 13 deletions(-) diff --git a/package.json b/package.json index 788adeb5aaa8..c22be2a0fe57 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,6 @@ "minimist": "1.2.0", "n-readlines": "1.0.0", "normalize-path": "3.0.0", - "parse5-htmlparser2-tree-adapter": "5.0.0", "postcss-less": "1.1.5", "postcss-media-query-parser": "0.2.3", "postcss-scss": "1.0.6", diff --git a/yarn.lock b/yarn.lock index d2c35ccd34db..d5e3bc2fb4fc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5106,23 +5106,11 @@ parse-json@^4.0.0: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" -parse5-htmlparser2-tree-adapter@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-5.0.0.tgz#f941eced8061ecb1bc2db744c416a037abfe64d1" - integrity sha512-Rco+Uuas6kYDOJTVlMjtRhSjVOcflt6LNHFJAO5xz+8mMrA23Qzlrc5gGEhl/qKZovZSZCHWtcpZTV4xGexCeg== - dependencies: - parse5 "^5.0.0" - parse5@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608" integrity sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA== -parse5@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.0.0.tgz#4d02710d44f3c3846197a11e205d4ef17842b81a" - integrity sha512-0ywuiUOnpWWeil5grH2rxjyTJoeQVwyBuO2si6QIU9dWtj2npjuyK1HaY1RbLnVfDhEbhyAPNUBKRK0Xj2xE0w== - pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" From 423f165719396e4ed987107869eafbdf2de9609f Mon Sep 17 00:00:00 2001 From: Ika Date: Sun, 28 Oct 2018 16:13:58 +0800 Subject: [PATCH 123/177] test: add tests --- tests/html_angular/__snapshots__/jsfmt.spec.js.snap | 4 ++++ tests/html_angular/interpolation.component.html | 1 + 2 files changed, 5 insertions(+) diff --git a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap index e2f85320720a..8f3ded30ecde 100644 --- a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap @@ -290,6 +290,7 @@ exports[`interpolation.component.html - angular-verify 1`] = `
    {{ a . b }}
    {{ a ?. b ( ) }}
    {{ a ?. b }}
    +
    {{ a // hello }}
    @@ -331,6 +332,7 @@ exports[`interpolation.component.html - angular-verify 1`] = `
    {{a.b}}
    {{a?.b()}}
    {{a?.b}}
    +
    {{a // hello }}
    @@ -388,6 +390,7 @@ exports[`interpolation.component.html - angular-verify 2`] = `
    {{ a . b }}
    {{ a ?. b ( ) }}
    {{ a ?. b }}
    +
    {{ a // hello }}
    @@ -429,6 +432,7 @@ exports[`interpolation.component.html - angular-verify 2`] = `
    {{a.b}}
    {{a?.b()}}
    {{a?.b}}
    +
    {{a // hello }}
    diff --git a/tests/html_angular/interpolation.component.html b/tests/html_angular/interpolation.component.html index 357cb8adf900..85b40efd89a6 100644 --- a/tests/html_angular/interpolation.component.html +++ b/tests/html_angular/interpolation.component.html @@ -23,6 +23,7 @@
    {{ a . b }}
    {{ a ?. b ( ) }}
    {{ a ?. b }}
    +
    {{ a // hello }}
    From e6cfed33e85070bac043363d0e6598a8d52b7762 Mon Sep 17 00:00:00 2001 From: Ika Date: Sun, 28 Oct 2018 16:14:11 +0800 Subject: [PATCH 124/177] feat: add spaces for interpolations Both [Vue] and [Angular] recommend to add spaces there. [vue]: https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/mustache-interpolation-spacing.md [angular]: http://codelyzer.com/rules/angular-whitespace/ --- src/language-html/printer-html.js | 6 +- src/language-js/printer-estree.js | 12 +- .../__snapshots__/jsfmt.spec.js.snap | 332 +++++++++--------- .../html_vue/__snapshots__/jsfmt.spec.js.snap | 26 +- .../__snapshots__/jsfmt.spec.js.snap | 4 +- 5 files changed, 191 insertions(+), 189 deletions(-) diff --git a/src/language-html/printer-html.js b/src/language-html/printer-html.js index a7ce1b413cff..665d768e062e 100644 --- a/src/language-html/printer-html.js +++ b/src/language-html/printer-html.js @@ -74,7 +74,7 @@ function embed(path, print, textToDoc, options) { return concat([ indent( concat([ - softline, + line, textToDoc( node.value, options.parser === "angular" @@ -85,8 +85,8 @@ function embed(path, print, textToDoc, options) { ), node.parent.next && needsToBorrowPrevClosingTagEndMarker(node.parent.next) - ? "" - : softline + ? " " + : line ]); } break; diff --git a/src/language-js/printer-estree.js b/src/language-js/printer-estree.js index 3cb964fa5cde..e01e30196757 100644 --- a/src/language-js/printer-estree.js +++ b/src/language-js/printer-estree.js @@ -3390,23 +3390,15 @@ function printPathNoParens(path, options, print, args) { return concat(parts); - case "NGRoot": { - const shouldPrintSurroundingSpaces = - // avoid invalid syntax `{{{}}}` - options.parser === "__ng_interpolation" && - n.node.type === "ObjectExpression" && - n.node.comments.length === 0; + case "NGRoot": return concat( [].concat( - shouldPrintSurroundingSpaces ? " " : [], path.call(print, "node"), !n.node.comments || n.node.comments.length === 0 ? [] - : concat([" //", n.node.comments[0].value]), - shouldPrintSurroundingSpaces ? " " : [] + : concat([" //", n.node.comments[0].value.trimRight()]) ) ); - } case "NGChainedExpression": return group(join(concat([";", line]), path.map(print, "expressions"))); case "NGEmptyExpression": diff --git a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap index 8f3ded30ecde..c9e65449396d 100644 --- a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap @@ -93,7 +93,7 @@ exports[`attributes.component.html - angular-verify 1`] = ` [target]="!x" [target]="a" [target]="a" - [target]="a // hello " + [target]="a // hello" [target]="a.b" [target]="javascript: 'hello world' " [target]="a?.b()" @@ -102,7 +102,7 @@ exports[`attributes.component.html - angular-verify 1`] = ` (target)="(a = 1)" (target)="(a.b = 1)" (target)="(a[b] = 1)" - (target)="a // hello " + (target)="a // hello" (target)="a; b" *ngIf="something ? true : false" *ngFor="let hero of heroes" @@ -225,7 +225,7 @@ exports[`attributes.component.html - angular-verify 2`] = ` [target]="!x" [target]="a" [target]="a" - [target]="a // hello " + [target]="a // hello" [target]="a.b" [target]="javascript: 'hello world' " [target]="a?.b()" @@ -234,7 +234,7 @@ exports[`attributes.component.html - angular-verify 2`] = ` (target)="(a = 1)" (target)="(a.b = 1)" (target)="(a[b] = 1)" - (target)="a // hello " + (target)="a // hello" (target)="a; b" *ngIf="something ? true : false" *ngFor="let hero of heroes" @@ -307,32 +307,32 @@ exports[`interpolation.component.html - angular-verify 1`] = ` "SearchSelection.transmissionLayoutRadioButton" | localize:localizationSection }} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -
    {{a | b:c}}
    -
    {{0 - 1}}
    -
    {{-1}}
    -
    {{a ? 1 : 2}}
    -
    {{a(1)(2)}}
    -
    {{a[b]}}
    -
    {{[1]}}
    +
    {{ a | b:c }}
    +
    {{ 0 - 1 }}
    +
    {{ -1 }}
    +
    {{ a ? 1 : 2 }}
    +
    {{ a(1)(2) }}
    +
    {{ a[b] }}
    +
    {{ [1] }}
    {{ { a: 1 } }}
    {{ { a: 1 } }}
    -
    {{true}}
    -
    {{undefined}}
    -
    {{null}}
    -
    {{1}}
    -
    {{1}}
    -
    {{"hello"}}
    -
    {{a(1, 2)}}
    -
    {{a.b(1, 2)}}
    -
    {{x!}}
    -
    {{!x}}
    -
    {{a}}
    -
    {{a}}
    -
    {{a // hello }}
    -
    {{a.b}}
    -
    {{a?.b()}}
    -
    {{a?.b}}
    -
    {{a // hello }}
    +
    {{ true }}
    +
    {{ undefined }}
    +
    {{ null }}
    +
    {{ 1 }}
    +
    {{ 1 }}
    +
    {{ "hello" }}
    +
    {{ a(1, 2) }}
    +
    {{ a.b(1, 2) }}
    +
    {{ x! }}
    +
    {{ !x }}
    +
    {{ a }}
    +
    {{ a }}
    +
    {{ a // hello }}
    +
    {{ a.b }}
    +
    {{ a?.b() }}
    +
    {{ a?.b }}
    +
    {{ a // hello }}
    @@ -407,32 +407,32 @@ exports[`interpolation.component.html - angular-verify 2`] = ` "SearchSelection.transmissionLayoutRadioButton" | localize:localizationSection }} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -
    {{a | b:c}}
    -
    {{0 - 1}}
    -
    {{-1}}
    -
    {{a ? 1 : 2}}
    -
    {{a(1)(2)}}
    -
    {{a[b]}}
    -
    {{[1]}}
    +
    {{ a | b:c }}
    +
    {{ 0 - 1 }}
    +
    {{ -1 }}
    +
    {{ a ? 1 : 2 }}
    +
    {{ a(1)(2) }}
    +
    {{ a[b] }}
    +
    {{ [1] }}
    {{ { a: 1 } }}
    {{ { a: 1 } }}
    -
    {{true}}
    -
    {{undefined}}
    -
    {{null}}
    -
    {{1}}
    -
    {{1}}
    -
    {{"hello"}}
    -
    {{a(1, 2)}}
    -
    {{a.b(1, 2)}}
    -
    {{x!}}
    -
    {{!x}}
    -
    {{a}}
    -
    {{a}}
    -
    {{a // hello }}
    -
    {{a.b}}
    -
    {{a?.b()}}
    -
    {{a?.b}}
    -
    {{a // hello }}
    +
    {{ true }}
    +
    {{ undefined }}
    +
    {{ null }}
    +
    {{ 1 }}
    +
    {{ 1 }}
    +
    {{ "hello" }}
    +
    {{ a(1, 2) }}
    +
    {{ a.b(1, 2) }}
    +
    {{ x! }}
    +
    {{ !x }}
    +
    {{ a }}
    +
    {{ a }}
    +
    {{ a // hello }}
    +
    {{ a.b }}
    +
    {{ a?.b() }}
    +
    {{ a?.b }}
    +
    {{ a // hello }}
    @@ -1232,15 +1232,15 @@ can be found in the LICENSE file at http://angular.io/license

    Interpolation

    -

    My current hero is {{currentHero.name}}

    +

    My current hero is {{ currentHero.name }}

    -

    {{title}}

    +

    {{ title }}

    -

    The sum of 1 + 1 is {{1 + 1}}

    +

    The sum of 1 + 1 is {{ 1 + 1 }}

    -

    The sum of 1 + 1 is not {{1 + 1 + getVal()}}

    +

    The sum of 1 + 1 is not {{ 1 + 1 + getVal() }}

    top @@ -1251,17 +1251,19 @@ can be found in the LICENSE file at http://angular.io/license Component expression context ({{title}}, [hidden]="isUnchanged")

    -
    {{title}} changed
    +
    + {{ title }} changed +

    Template input variable expression context (let hero)

    -
    {{hero.name}}
    +
    {{ hero.name }}

    Template reference variable expression context (#heroInput)

    - Type something: {{heroInput.value}} + Type something: {{ heroInput.value }}
    top @@ -1325,9 +1327,9 @@ can be found in the LICENSE file at http://angular.io/license
    click me
    -{{clicked}}

    +{{ clicked }}

    -
    Hero Name: {{name}}
    +
    Hero Name: {{ name }}




    @@ -1389,7 +1391,7 @@ can be found in the LICENSE file at http://angular.io/license

    is the property bound image.

    - "{{title}}" is the interpolated title. + "{{ title }}" is the interpolated title.

    "" is the property bound title.

    @@ -1398,7 +1400,7 @@ can be found in the LICENSE file at http://angular.io/license WARNING: sanitizing HTML stripped some content (see http://g.co/ng/security#xss). -->

    - "{{evilTitle}}" is the interpolated evil title. + "{{ evilTitle }}" is the interpolated evil title.

    "" is the property bound evil @@ -1431,7 +1433,7 @@ can be found in the LICENSE file at http://angular.io/license
    - +

    @@ -1492,7 +1494,7 @@ can be found in the LICENSE file at http://angular.io/license

    click with myClick
    - {{clickMessage}} + {{ clickMessage }}
    @@ -1547,7 +1549,7 @@ can be found in the LICENSE file at http://angular.io/license

    NgModel (two-way) Binding

    -

    Result: {{currentHero.name}}

    +

    Result: {{ currentHero.name }}


    NgClass Binding

    -

    currentClasses is {{currentClasses | json}}

    +

    currentClasses is {{ currentClasses | json }}

    This div is initially saveable, unchanged, and special
    @@ -1592,9 +1594,9 @@ without NgModel


    - This div should be {{canSave ? "" : "not"}} saveable, - {{isUnchanged ? "unchanged" : "modified"}} and, - {{isSpecial ? "" : "not"}} special after clicking "Refresh". + This div should be {{ canSave ? "" : "not" }} saveable, + {{ isUnchanged ? "unchanged" : "modified" }} and, + {{ isSpecial ? "" : "not" }} special after clicking "Refresh".


    @@ -1614,7 +1616,7 @@ without NgModel

    [ngStyle] binding to currentStyles - CSS property names

    -

    currentStyles is {{currentStyles | json}}

    +

    currentStyles is {{ currentStyles | json }}

    This div is initially italic, normal weight, and extra large (24px).
    @@ -1626,9 +1628,9 @@ without NgModel


    - This div should be {{canSave ? "italic" : "plain"}}, - {{isUnchanged ? "normal weight" : "bold"}} and, - {{isSpecial ? "extra large" : "normal size"}} after clicking "Refresh". + This div should be {{ canSave ? "italic" : "plain" }}, + {{ isUnchanged ? "normal weight" : "bold" }} and, + {{ isSpecial ? "extra large" : "normal size" }} after clicking "Refresh".
    top @@ -1639,13 +1641,13 @@ without NgModel
    -
    Hello, {{currentHero.name}}
    -
    Hello, {{nullHero.name}}
    +
    Hello, {{ currentHero.name }}
    +
    Hello, {{ nullHero.name }}
    Add {{currentHero.name}} with templateAdd {{ currentHero.name }} with template @@ -1671,7 +1673,7 @@ without NgModel

    NgFor Binding

    -
    {{hero.name}}
    +
    {{ hero.name }}

    @@ -1686,7 +1688,7 @@ without NgModel

    with semi-colon separator

    - {{i + 1}} - {{hero.name}} + {{ i + 1 }} - {{ hero.name }}
    @@ -1694,7 +1696,7 @@ without NgModel
    - {{i + 1}} - {{hero.name}} + {{ i + 1 }} - {{ hero.name }}
    @@ -1707,21 +1709,23 @@ without NgModel

    without trackBy

    -
    ({{hero.id}}) {{hero.name}}
    +
    + ({{ hero.id }}) {{ hero.name }} +
    - Hero DOM elements change #{{heroesNoTrackByCount}} without trackBy + Hero DOM elements change #{{ heroesNoTrackByCount }} without trackBy

    with trackBy

    - ({{hero.id}}) {{hero.name}} + ({{ hero.id }}) {{ hero.name }}
    - Hero DOM elements change #{{heroesWithTrackByCount}} with trackBy + Hero DOM elements change #{{ heroesWithTrackByCount }} with trackBy
    @@ -1730,28 +1734,28 @@ without NgModel

    with trackBy and semi-colon separator

    - ({{hero.id}}) {{hero.name}} + ({{ hero.id }}) {{ hero.name }}

    with trackBy and comma separator

    - ({{hero.id}}) {{hero.name}} + ({{ hero.id }}) {{ hero.name }}

    with trackBy and space separator

    - ({{hero.id}}) {{hero.name}} + ({{ hero.id }}) {{ hero.name }}

    with generic trackById function

    - ({{hero.id}}) {{hero.name}} + ({{ hero.id }}) {{ hero.name }}
    @@ -1778,7 +1782,7 @@ without NgModel
    [hero]="currentHero" >
    - Are you as confused as {{currentHero.name}}? + Are you as confused as {{ currentHero.name }}?
    @@ -1821,7 +1825,7 @@ without NgModel
    myClick2
    -{{clickMessage2}} +{{ clickMessage2 }} top @@ -1829,21 +1833,21 @@ without NgModel

    Pipes

    -
    Title through uppercase pipe: {{title | uppercase}}
    +
    Title through uppercase pipe: {{ title | uppercase }}
    -
    Title through a pipe chain: {{title | uppercase | lowercase}}
    +
    Title through a pipe chain: {{ title | uppercase | lowercase }}
    -
    Birthdate: {{currentHero?.birthdate | date:"longDate"}}
    +
    Birthdate: {{ currentHero?.birthdate | date:"longDate" }}
    -
    {{currentHero | json}}
    +
    {{ currentHero | json }}
    -
    Birthdate: {{currentHero?.birthdate | date:"longDate" | uppercase}}
    +
    Birthdate: {{ currentHero?.birthdate | date:"longDate" | uppercase }}
    - {{product.price | currency:"USD":true}} + {{ product.price | currency:"USD":true }}
    top @@ -1852,11 +1856,11 @@ without NgModel

    Safe navigation operator ?.

    -
    The title is {{title}}
    +
    The title is {{ title }}
    -
    The current hero's name is {{currentHero?.name}}
    +
    The current hero's name is {{ currentHero?.name }}
    -
    The current hero's name is {{currentHero.name}}
    +
    The current hero's name is {{ currentHero.name }}
    -
    The null hero's name is {{nullHero.name}}
    +
    The null hero's name is {{ nullHero.name }}
    -
    The null hero's name is {{nullHero && nullHero.name}}
    +
    The null hero's name is {{ nullHero && nullHero.name }}
    - The null hero's name is {{nullHero?.name}} + The null hero's name is {{ nullHero?.name }}
    top @@ -1883,7 +1887,7 @@ without NgModel
    -
    The hero's name is {{hero!.name}}
    +
    The hero's name is {{ hero!.name }}
    top @@ -1894,7 +1898,7 @@ without NgModel
    -
    The hero's marker is {{$any(hero).marker}}
    +
    The hero's marker is {{ $any(hero).marker }}
    @@ -1910,8 +1914,8 @@ without NgModel

    Enums in binding

    - The name of the Color.Red enum is {{Color[Color.Red]}}.
    - The current color is {{Color[color]}} and its number is {{color}}.
    + The name of the Color.Red enum is {{ Color[Color.Red] }}.
    + The current color is {{ Color[color] }} and its number is {{ color }}.
    @@ -1940,7 +1944,7 @@ without NgModel

    -
    {{submitMessage}}
    +
    {{ submitMessage }}
    -

    The sum of 1 + 1 is {{1 + 1}}

    +

    The sum of 1 + 1 is {{ 1 + 1 }}

    -

    The sum of 1 + 1 is not {{1 + 1 + getVal()}}

    +

    The sum of 1 + 1 is not {{ 1 + 1 + getVal() }}

    top @@ -2738,17 +2742,19 @@ can be found in the LICENSE file at http://angular.io/license Component expression context ({{title}}, [hidden]="isUnchanged")

    -
    {{title}} changed
    +
    + {{ title }} changed +

    Template input variable expression context (let hero)

    -
    {{hero.name}}
    +
    {{ hero.name }}

    Template reference variable expression context (#heroInput)

    - Type something: {{heroInput.value}} + Type something: {{ heroInput.value }}
    top @@ -2812,9 +2818,9 @@ can be found in the LICENSE file at http://angular.io/license
    click me
    -{{clicked}}

    +{{ clicked }}

    -
    Hero Name: {{name}}
    +
    Hero Name: {{ name }}




    @@ -2876,7 +2882,7 @@ can be found in the LICENSE file at http://angular.io/license

    is the property bound image.

    - "{{title}}" is the interpolated title. + "{{ title }}" is the interpolated title.

    "" is the property bound title.

    @@ -2885,7 +2891,7 @@ can be found in the LICENSE file at http://angular.io/license WARNING: sanitizing HTML stripped some content (see http://g.co/ng/security#xss). -->

    - "{{evilTitle}}" is the interpolated evil title. + "{{ evilTitle }}" is the interpolated evil title.

    "" is the property bound evil @@ -2918,7 +2924,7 @@ can be found in the LICENSE file at http://angular.io/license
    - +

    @@ -2979,7 +2985,7 @@ can be found in the LICENSE file at http://angular.io/license

    click with myClick
    - {{clickMessage}} + {{ clickMessage }}
    @@ -3034,7 +3040,7 @@ can be found in the LICENSE file at http://angular.io/license

    NgModel (two-way) Binding

    -

    Result: {{currentHero.name}}

    +

    Result: {{ currentHero.name }}


    NgClass Binding

    -

    currentClasses is {{currentClasses | json}}

    +

    currentClasses is {{ currentClasses | json }}

    This div is initially saveable, unchanged, and special
    @@ -3079,9 +3085,9 @@ without NgModel


    - This div should be {{canSave ? "" : "not"}} saveable, - {{isUnchanged ? "unchanged" : "modified"}} and, - {{isSpecial ? "" : "not"}} special after clicking "Refresh". + This div should be {{ canSave ? "" : "not" }} saveable, + {{ isUnchanged ? "unchanged" : "modified" }} and, + {{ isSpecial ? "" : "not" }} special after clicking "Refresh".


    @@ -3101,7 +3107,7 @@ without NgModel

    [ngStyle] binding to currentStyles - CSS property names

    -

    currentStyles is {{currentStyles | json}}

    +

    currentStyles is {{ currentStyles | json }}

    This div is initially italic, normal weight, and extra large (24px).
    @@ -3113,9 +3119,9 @@ without NgModel


    - This div should be {{canSave ? "italic" : "plain"}}, - {{isUnchanged ? "normal weight" : "bold"}} and, - {{isSpecial ? "extra large" : "normal size"}} after clicking "Refresh". + This div should be {{ canSave ? "italic" : "plain" }}, + {{ isUnchanged ? "normal weight" : "bold" }} and, + {{ isSpecial ? "extra large" : "normal size" }} after clicking "Refresh".
    top @@ -3126,13 +3132,13 @@ without NgModel
    -
    Hello, {{currentHero.name}}
    -
    Hello, {{nullHero.name}}
    +
    Hello, {{ currentHero.name }}
    +
    Hello, {{ nullHero.name }}
    Add {{currentHero.name}} with templateAdd {{ currentHero.name }} with template @@ -3158,7 +3164,7 @@ without NgModel

    NgFor Binding

    -
    {{hero.name}}
    +
    {{ hero.name }}

    @@ -3173,7 +3179,7 @@ without NgModel

    with semi-colon separator

    - {{i + 1}} - {{hero.name}} + {{ i + 1 }} - {{ hero.name }}
    @@ -3181,7 +3187,7 @@ without NgModel
    - {{i + 1}} - {{hero.name}} + {{ i + 1 }} - {{ hero.name }}
    @@ -3194,21 +3200,23 @@ without NgModel

    without trackBy

    -
    ({{hero.id}}) {{hero.name}}
    +
    + ({{ hero.id }}) {{ hero.name }} +
    - Hero DOM elements change #{{heroesNoTrackByCount}} without trackBy + Hero DOM elements change #{{ heroesNoTrackByCount }} without trackBy

    with trackBy

    - ({{hero.id}}) {{hero.name}} + ({{ hero.id }}) {{ hero.name }}
    - Hero DOM elements change #{{heroesWithTrackByCount}} with trackBy + Hero DOM elements change #{{ heroesWithTrackByCount }} with trackBy
    @@ -3217,28 +3225,28 @@ without NgModel

    with trackBy and semi-colon separator

    - ({{hero.id}}) {{hero.name}} + ({{ hero.id }}) {{ hero.name }}

    with trackBy and comma separator

    - ({{hero.id}}) {{hero.name}} + ({{ hero.id }}) {{ hero.name }}

    with trackBy and space separator

    - ({{hero.id}}) {{hero.name}} + ({{ hero.id }}) {{ hero.name }}

    with generic trackById function

    - ({{hero.id}}) {{hero.name}} + ({{ hero.id }}) {{ hero.name }}
    @@ -3265,7 +3273,7 @@ without NgModel
    [hero]="currentHero" >
    - Are you as confused as {{currentHero.name}}? + Are you as confused as {{ currentHero.name }}?
    @@ -3308,7 +3316,7 @@ without NgModel
    myClick2
    -{{clickMessage2}} +{{ clickMessage2 }} top @@ -3316,21 +3324,21 @@ without NgModel

    Pipes

    -
    Title through uppercase pipe: {{title | uppercase}}
    +
    Title through uppercase pipe: {{ title | uppercase }}
    -
    Title through a pipe chain: {{title | uppercase | lowercase}}
    +
    Title through a pipe chain: {{ title | uppercase | lowercase }}
    -
    Birthdate: {{currentHero?.birthdate | date:"longDate"}}
    +
    Birthdate: {{ currentHero?.birthdate | date:"longDate" }}
    -
    {{currentHero | json}}
    +
    {{ currentHero | json }}
    -
    Birthdate: {{currentHero?.birthdate | date:"longDate" | uppercase}}
    +
    Birthdate: {{ currentHero?.birthdate | date:"longDate" | uppercase }}
    - {{product.price | currency:"USD":true}} + {{ product.price | currency:"USD":true }}
    top @@ -3339,11 +3347,11 @@ without NgModel

    Safe navigation operator ?.

    -
    The title is {{title}}
    +
    The title is {{ title }}
    -
    The current hero's name is {{currentHero?.name}}
    +
    The current hero's name is {{ currentHero?.name }}
    -
    The current hero's name is {{currentHero.name}}
    +
    The current hero's name is {{ currentHero.name }}
    -
    The null hero's name is {{nullHero.name}}
    +
    The null hero's name is {{ nullHero.name }}
    -
    The null hero's name is {{nullHero && nullHero.name}}
    +
    The null hero's name is {{ nullHero && nullHero.name }}
    - The null hero's name is {{nullHero?.name}} + The null hero's name is {{ nullHero?.name }}
    top @@ -3370,7 +3378,7 @@ without NgModel
    -
    The hero's name is {{hero!.name}}
    +
    The hero's name is {{ hero!.name }}
    top @@ -3381,7 +3389,7 @@ without NgModel
    -
    The hero's marker is {{$any(hero).marker}}
    +
    The hero's marker is {{ $any(hero).marker }}
    @@ -3397,8 +3405,8 @@ without NgModel

    Enums in binding

    - The name of the Color.Red enum is {{Color[Color.Red]}}.
    - The current color is {{Color[color]}} and its number is {{color}}.
    + The name of the Color.Red enum is {{ Color[Color.Red] }}.
    + The current color is {{ Color[color] }} and its number is {{ color }}.
    @@ -3427,7 +3435,7 @@ without NgModel

    -
    {{submitMessage}}
    +
    {{ submitMessage }}
    - +

    Template reference variable statement context (#heroForm)

    @@ -2779,9 +2779,9 @@ can be found in the LICENSE file at http://angular.io/license

    Template input variable statement context (let hero)

    - +

    Template reference variable statement context (#heroForm)

    From a3a7f923cdc43a799bf10fde12fcbb5cec8bf295 Mon Sep 17 00:00:00 2001 From: Ika Date: Mon, 29 Oct 2018 14:20:18 +0800 Subject: [PATCH 129/177] test: add tests --- .../__snapshots__/jsfmt.spec.js.snap | 48 +++++++++++++++++++ tests/html_angular/attributes.component.html | 4 ++ .../html_angular/interpolation.component.html | 1 + 3 files changed, 53 insertions(+) diff --git a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap index e9320cb55719..48541bb49318 100644 --- a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap @@ -62,6 +62,10 @@ exports[`attributes.component.html - angular-verify 1`] = ` *directive=" a ; b : c " *directive=" a ; b : c as d " *directive=" a ; b as c " + *ngIf="listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3" + (target)="listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3" + [target]="listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3" + [target]="{ longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong: true }" > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    `; @@ -194,6 +212,10 @@ exports[`attributes.component.html - angular-verify 2`] = ` *directive=" a ; b : c " *directive=" a ; b : c as d " *directive=" a ; b as c " + *ngIf="listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3" + (target)="listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3" + [target]="listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3" + [target]="{ longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong: true }" > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    `; @@ -307,6 +343,7 @@ exports[`interpolation.component.html - angular-verify 1`] = ` "SearchSelection.transmissionLayoutRadioButton" | localize:localizationSection }}
    {{copyTypes[options.copyType]}}
    +{{listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3}} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    {{ a | b:c }}
    {{ 0 - 1 }}
    @@ -365,6 +402,11 @@ exports[`interpolation.component.html - angular-verify 1`] = `
    {{ copyTypes[options.copyType] }}
    +{{ + listRow.NextScheduledSendStatus == 1 || + listRow.NextScheduledSendStatus == 2 || + listRow.NextScheduledSendStatus == 3 +}} `; @@ -411,6 +453,7 @@ exports[`interpolation.component.html - angular-verify 2`] = ` "SearchSelection.transmissionLayoutRadioButton" | localize:localizationSection }}
    {{copyTypes[options.copyType]}}
    +{{listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3}} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    {{ a | b:c }}
    {{ 0 - 1 }}
    @@ -469,6 +512,11 @@ exports[`interpolation.component.html - angular-verify 2`] = `
    {{ copyTypes[options.copyType] }}
    +{{ + listRow.NextScheduledSendStatus == 1 || + listRow.NextScheduledSendStatus == 2 || + listRow.NextScheduledSendStatus == 3 +}} `; diff --git a/tests/html_angular/attributes.component.html b/tests/html_angular/attributes.component.html index 665619c3ebee..f65cf289b273 100644 --- a/tests/html_angular/attributes.component.html +++ b/tests/html_angular/attributes.component.html @@ -59,4 +59,8 @@ *directive=" a ; b : c " *directive=" a ; b : c as d " *directive=" a ; b as c " + *ngIf="listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3" + (target)="listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3" + [target]="listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3" + [target]="{ longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong: true }" > diff --git a/tests/html_angular/interpolation.component.html b/tests/html_angular/interpolation.component.html index 41649f748e31..2056dd136053 100644 --- a/tests/html_angular/interpolation.component.html +++ b/tests/html_angular/interpolation.component.html @@ -40,3 +40,4 @@ "SearchSelection.transmissionLayoutRadioButton" | localize:localizationSection }}
    {{copyTypes[options.copyType]}}
    +{{listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3}} From fa1436a4f169d26e99ccf376d2dc26fc55bcb128 Mon Sep 17 00:00:00 2001 From: Ika Date: Mon, 29 Oct 2018 14:29:04 +0800 Subject: [PATCH 130/177] fix(angular): add missing softlines --- src/language-html/printer-html.js | 30 ++++++++--------- src/language-js/printer-estree.js | 23 ++++++++----- .../__snapshots__/jsfmt.spec.js.snap | 32 ++++++++++++------- 3 files changed, 49 insertions(+), 36 deletions(-) diff --git a/src/language-html/printer-html.js b/src/language-html/printer-html.js index f55b3eb62c5d..305f1dfd1191 100644 --- a/src/language-html/printer-html.js +++ b/src/language-html/printer-html.js @@ -824,35 +824,33 @@ function printEmbeddedAttributeValue(node, textToDoc, options) { */ const ngExpressionBindingPatterns = ["^\\[.+\\]$", "^bind(on)?-"]; + const __ng_root_postprocess = (rootDoc, rootNode) => + rootNode.type === "ObjectExpression" + ? rootDoc + : group(concat([indent(concat([softline, rootDoc])), softline])); + if (isKeyMatched(ngStatementBindingPatterns)) { return textToDoc(getValue(), { parser: "__ng_action", - trailingComma: "none" + trailingComma: "none", + __ng_root_postprocess }); } if (isKeyMatched(ngExpressionBindingPatterns)) { return textToDoc(getValue(), { parser: "__ng_binding", - trailingComma: "none" + trailingComma: "none", + __ng_root_postprocess }); } if (isKeyMatched(ngDirectiveBindingPatterns)) { - return group( - concat([ - indent( - concat([ - softline, - textToDoc(getValue(), { - parser: "__ng_directive", - trailingComma: "none" - }) - ]) - ), - softline - ]) - ); + return textToDoc(getValue(), { + parser: "__ng_directive", + trailingComma: "none", + __ng_root_postprocess + }); } } diff --git a/src/language-js/printer-estree.js b/src/language-js/printer-estree.js index 5294aec7c9b0..3dfd33e2cfd6 100644 --- a/src/language-js/printer-estree.js +++ b/src/language-js/printer-estree.js @@ -3395,15 +3395,22 @@ function printPathNoParens(path, options, print, args) { return concat(parts); - case "NGRoot": - return concat( - [].concat( - path.call(print, "node"), - !n.node.comments || n.node.comments.length === 0 - ? [] - : concat([" //", n.node.comments[0].value.trimRight()]) - ) + case "NGRoot": { + const rootNode = n.node; + const rootDoc = path.call(print, "node"); + const postprocess = options.__ng_root_postprocess || (x => x); + return postprocess( + concat( + [].concat( + rootDoc, + !n.node.comments || n.node.comments.length === 0 + ? [] + : concat([" //", n.node.comments[0].value.trimRight()]) + ) + ), + rootNode ); + } case "NGChainedExpression": return group(join(concat([";", line]), path.map(print, "expressions"))); case "NGEmptyExpression": diff --git a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap index 48541bb49318..f1e4834f8cab 100644 --- a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap @@ -137,12 +137,16 @@ exports[`attributes.component.html - angular-verify 1`] = ` listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3 " - (target)="listRow.NextScheduledSendStatus == 1 || - listRow.NextScheduledSendStatus == 2 || - listRow.NextScheduledSendStatus == 3" - [target]="listRow.NextScheduledSendStatus == 1 || - listRow.NextScheduledSendStatus == 2 || - listRow.NextScheduledSendStatus == 3" + (target)=" + listRow.NextScheduledSendStatus == 1 || + listRow.NextScheduledSendStatus == 2 || + listRow.NextScheduledSendStatus == 3 + " + [target]=" + listRow.NextScheduledSendStatus == 1 || + listRow.NextScheduledSendStatus == 2 || + listRow.NextScheduledSendStatus == 3 + " [target]="{ longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong: true }" @@ -287,12 +291,16 @@ exports[`attributes.component.html - angular-verify 2`] = ` listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3 " - (target)="listRow.NextScheduledSendStatus == 1 || - listRow.NextScheduledSendStatus == 2 || - listRow.NextScheduledSendStatus == 3" - [target]="listRow.NextScheduledSendStatus == 1 || - listRow.NextScheduledSendStatus == 2 || - listRow.NextScheduledSendStatus == 3" + (target)=" + listRow.NextScheduledSendStatus == 1 || + listRow.NextScheduledSendStatus == 2 || + listRow.NextScheduledSendStatus == 3 + " + [target]=" + listRow.NextScheduledSendStatus == 1 || + listRow.NextScheduledSendStatus == 2 || + listRow.NextScheduledSendStatus == 3 + " [target]="{ longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong: true }" From 1fd8844f39353d27bdad38c6ef392901c876ca26 Mon Sep 17 00:00:00 2001 From: Ika Date: Mon, 29 Oct 2018 14:35:57 +0800 Subject: [PATCH 131/177] test: add tests --- .../html_angular/__snapshots__/jsfmt.spec.js.snap | 14 ++++++++++++++ tests/html_angular/attributes.component.html | 1 + 2 files changed, 15 insertions(+) diff --git a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap index f1e4834f8cab..c2672bfe0751 100644 --- a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap @@ -63,6 +63,7 @@ exports[`attributes.component.html - angular-verify 1`] = ` *directive=" a ; b : c as d " *directive=" a ; b as c " *ngIf="listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3" + *ngIf="listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3; else hello" (target)="listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3" [target]="listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3" [target]="{ longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong: true }" @@ -137,6 +138,12 @@ exports[`attributes.component.html - angular-verify 1`] = ` listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3 " + *ngIf=" + listRow.NextScheduledSendStatus == 1 || + listRow.NextScheduledSendStatus == 2 || + listRow.NextScheduledSendStatus == 3; + else: hello + " (target)=" listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || @@ -217,6 +224,7 @@ exports[`attributes.component.html - angular-verify 2`] = ` *directive=" a ; b : c as d " *directive=" a ; b as c " *ngIf="listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3" + *ngIf="listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3; else hello" (target)="listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3" [target]="listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3" [target]="{ longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong: true }" @@ -291,6 +299,12 @@ exports[`attributes.component.html - angular-verify 2`] = ` listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3 " + *ngIf=" + listRow.NextScheduledSendStatus == 1 || + listRow.NextScheduledSendStatus == 2 || + listRow.NextScheduledSendStatus == 3; + else: hello + " (target)=" listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || diff --git a/tests/html_angular/attributes.component.html b/tests/html_angular/attributes.component.html index f65cf289b273..df37a15a653e 100644 --- a/tests/html_angular/attributes.component.html +++ b/tests/html_angular/attributes.component.html @@ -60,6 +60,7 @@ *directive=" a ; b : c as d " *directive=" a ; b as c " *ngIf="listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3" + *ngIf="listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3; else hello" (target)="listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3" [target]="listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3" [target]="{ longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong: true }" From 245a3090832b29129f782038180f2a9eea47f55e Mon Sep 17 00:00:00 2001 From: Ika Date: Mon, 29 Oct 2018 14:36:54 +0800 Subject: [PATCH 132/177] fix(angular): correct indent for root logical expression --- src/language-js/printer-estree.js | 5 +++++ .../__snapshots__/jsfmt.spec.js.snap | 16 ++++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/language-js/printer-estree.js b/src/language-js/printer-estree.js index 3dfd33e2cfd6..334492b1c63c 100644 --- a/src/language-js/printer-estree.js +++ b/src/language-js/printer-estree.js @@ -528,6 +528,11 @@ function printPathNoParens(path, options, print, args) { parent.type === "ReturnStatement" || (parent.type === "JSXExpressionContainer" && parentParent.type === "JSXAttribute") || + (n.type !== "NGPipeExpression" && + ((parent.type === "NGRoot" && options.parser === "__ng_binding") || + (parent.type === "NGMicrosyntaxExpression" && + parentParent.type === "NGMicrosyntax" && + parentParent.body.length === 1))) || (n === parent.body && parent.type === "ArrowFunctionExpression") || (n !== parent.body && parent.type === "ForStatement") || (parent.type === "ConditionalExpression" && diff --git a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap index c2672bfe0751..4f8876304473 100644 --- a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap @@ -135,8 +135,8 @@ exports[`attributes.component.html - angular-verify 1`] = ` *directive="a; b as c" *ngIf=" listRow.NextScheduledSendStatus == 1 || - listRow.NextScheduledSendStatus == 2 || - listRow.NextScheduledSendStatus == 3 + listRow.NextScheduledSendStatus == 2 || + listRow.NextScheduledSendStatus == 3 " *ngIf=" listRow.NextScheduledSendStatus == 1 || @@ -151,8 +151,8 @@ exports[`attributes.component.html - angular-verify 1`] = ` " [target]=" listRow.NextScheduledSendStatus == 1 || - listRow.NextScheduledSendStatus == 2 || - listRow.NextScheduledSendStatus == 3 + listRow.NextScheduledSendStatus == 2 || + listRow.NextScheduledSendStatus == 3 " [target]="{ longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong: true @@ -296,8 +296,8 @@ exports[`attributes.component.html - angular-verify 2`] = ` *directive="a; b as c" *ngIf=" listRow.NextScheduledSendStatus == 1 || - listRow.NextScheduledSendStatus == 2 || - listRow.NextScheduledSendStatus == 3 + listRow.NextScheduledSendStatus == 2 || + listRow.NextScheduledSendStatus == 3 " *ngIf=" listRow.NextScheduledSendStatus == 1 || @@ -312,8 +312,8 @@ exports[`attributes.component.html - angular-verify 2`] = ` " [target]=" listRow.NextScheduledSendStatus == 1 || - listRow.NextScheduledSendStatus == 2 || - listRow.NextScheduledSendStatus == 3 + listRow.NextScheduledSendStatus == 2 || + listRow.NextScheduledSendStatus == 3 " [target]="{ longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong: true From cf6b802d7cadb8f8b32e218a6174bed24a39f400 Mon Sep 17 00:00:00 2001 From: Ika Date: Mon, 29 Oct 2018 14:41:52 +0800 Subject: [PATCH 133/177] fix(angular): put pipe operator on the beginning of the line --- src/language-js/printer-estree.js | 2 +- .../__snapshots__/jsfmt.spec.js.snap | 32 +++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/language-js/printer-estree.js b/src/language-js/printer-estree.js index 334492b1c63c..1ee0e84461f8 100644 --- a/src/language-js/printer-estree.js +++ b/src/language-js/printer-estree.js @@ -5510,7 +5510,7 @@ function printBinaryishExpressions( const shouldInline = shouldInlineLogicalExpression(node); const lineBeforeOperator = - node.operator === "|>" && + (node.operator === "|>" || node.type === "NGPipeExpression") && !hasLeadingOwnLineComment(options.originalText, node.right, options); const operator = node.type === "NGPipeExpression" ? "|" : node.operator; diff --git a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap index 4f8876304473..921e9426d525 100644 --- a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap @@ -399,26 +399,26 @@ exports[`interpolation.component.html - angular-verify 1`] = `
    @@ -509,26 +509,26 @@ exports[`interpolation.component.html - angular-verify 2`] = `
    From f4f2a02f794d92bec13cdbbd8dd5996582d5e2a2 Mon Sep 17 00:00:00 2001 From: Ika Date: Mon, 29 Oct 2018 15:37:38 +0800 Subject: [PATCH 134/177] test: add tests --- tests/html_vue/__snapshots__/jsfmt.spec.js.snap | 16 ++++++++++++++++ tests/html_vue/attributes.vue | 2 ++ 2 files changed, 18 insertions(+) diff --git a/tests/html_vue/__snapshots__/jsfmt.spec.js.snap b/tests/html_vue/__snapshots__/jsfmt.spec.js.snap index d7d629db7cc1..74a5680da117 100644 --- a/tests/html_vue/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_vue/__snapshots__/jsfmt.spec.js.snap @@ -21,6 +21,8 @@ exports[`attributes.vue - vue-verify 1`] = ` @click=" $emit( 'click' ) ;" @click=" $emit( 'click' ) ;if(something){for(let i=j;i<100;i++){}}else{}" slot-scope="{destructuring:{a:{b}}}" + :class="{ longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong: true }" + :class="(() => { return 'hello' })()" >
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    `; @@ -80,6 +88,8 @@ exports[`attributes.vue - vue-verify 2`] = ` @click=" $emit( 'click' ) ;" @click=" $emit( 'click' ) ;if(something){for(let i=j;i<100;i++){}}else{}" slot-scope="{destructuring:{a:{b}}}" + :class="{ longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong: true }" + :class="(() => { return 'hello' })()" >
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    `; diff --git a/tests/html_vue/attributes.vue b/tests/html_vue/attributes.vue index 223b232081ed..55c85a895b7f 100644 --- a/tests/html_vue/attributes.vue +++ b/tests/html_vue/attributes.vue @@ -18,4 +18,6 @@ @click=" $emit( 'click' ) ;" @click=" $emit( 'click' ) ;if(something){for(let i=j;i<100;i++){}}else{}" slot-scope="{destructuring:{a:{b}}}" + :class="{ longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong: true }" + :class="(() => { return 'hello' })()" > From 01f1fb300a88a677b21b86c940b1b91a9c7167d2 Mon Sep 17 00:00:00 2001 From: Ika Date: Mon, 29 Oct 2018 15:40:30 +0800 Subject: [PATCH 135/177] fix(vue): add missing softlines --- src/language-html/printer-html.js | 67 ++++++++++++------- src/language-js/html-binding.js | 4 ++ src/language-js/printer-estree.js | 23 +++---- .../html_vue/__snapshots__/jsfmt.spec.js.snap | 16 +++-- 4 files changed, 64 insertions(+), 46 deletions(-) diff --git a/src/language-html/printer-html.js b/src/language-html/printer-html.js index 305f1dfd1191..402c08288543 100644 --- a/src/language-html/printer-html.js +++ b/src/language-html/printer-html.js @@ -759,12 +759,38 @@ function getTextValueParts(node, value = node.value) { : join(line, value.split(/\s+/)).parts; } -function printEmbeddedAttributeValue(node, textToDoc, options) { +function printEmbeddedAttributeValue(node, originalTextToDoc, options) { const isKeyMatched = patterns => new RegExp(patterns.join("|")).test(node.name); const getValue = () => node.value.replace(/"/g, '"').replace(/'/g, "'"); + let shouldHug = false; + + const __onHtmlBindingRoot = root => { + const rootNode = + root.type === "NGRoot" + ? root.node.type === "NGMicrosyntax" && + root.node.body.length === 1 && + root.node.body[0].type === "NGMicrosyntaxExpression" + ? root.node.body[0].expression + : root.node + : root.type === "JsExpressionRoot" + ? root.node + : root; + if (rootNode && rootNode.type === "ObjectExpression") { + shouldHug = true; + } + }; + + const printMaybeHug = doc => + shouldHug + ? group(doc) + : group(concat([indent(concat([softline, doc])), softline])); + + const textToDoc = (code, opts) => + originalTextToDoc(code, Object.assign({ __onHtmlBindingRoot }, opts)); + if (options.parser === "vue") { if (node.name === "v-for") { return printVueFor(getValue(), textToDoc); @@ -794,19 +820,25 @@ function printEmbeddedAttributeValue(node, textToDoc, options) { const simplePathRE = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['[^']*?']|\["[^"]*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*$/; const value = getValue(); - const doc = + return printMaybeHug( simplePathRE.test(value) || fnExpRE.test(value) ? textToDoc(value, { parser: "__js_expression" }) - : stripTrailingHardline(textToDoc(value, { parser: "babylon" })); - return group(concat([indent(concat([softline, doc])), softline])); + : stripTrailingHardline(textToDoc(value, { parser: "babylon" })) + ); } if (isKeyMatched(vueExpressionBindingPatterns)) { - return textToDoc(getValue(), { parser: "__js_expression" }); + return printMaybeHug( + textToDoc(getValue(), { parser: "__js_expression" }) + ); } } if (options.parser === "angular") { + const ngTextToDoc = (code, opts) => + // angular does not allow trailing comma + textToDoc(code, Object.assign({ trailingComma: "none" }, opts)); + /** * *directive="angularDirective" */ @@ -824,33 +856,18 @@ function printEmbeddedAttributeValue(node, textToDoc, options) { */ const ngExpressionBindingPatterns = ["^\\[.+\\]$", "^bind(on)?-"]; - const __ng_root_postprocess = (rootDoc, rootNode) => - rootNode.type === "ObjectExpression" - ? rootDoc - : group(concat([indent(concat([softline, rootDoc])), softline])); - if (isKeyMatched(ngStatementBindingPatterns)) { - return textToDoc(getValue(), { - parser: "__ng_action", - trailingComma: "none", - __ng_root_postprocess - }); + return printMaybeHug(ngTextToDoc(getValue(), { parser: "__ng_action" })); } if (isKeyMatched(ngExpressionBindingPatterns)) { - return textToDoc(getValue(), { - parser: "__ng_binding", - trailingComma: "none", - __ng_root_postprocess - }); + return printMaybeHug(ngTextToDoc(getValue(), { parser: "__ng_binding" })); } if (isKeyMatched(ngDirectiveBindingPatterns)) { - return textToDoc(getValue(), { - parser: "__ng_directive", - trailingComma: "none", - __ng_root_postprocess - }); + return printMaybeHug( + ngTextToDoc(getValue(), { parser: "__ng_directive" }) + ); } } diff --git a/src/language-js/html-binding.js b/src/language-js/html-binding.js index 5bede6084a8f..411a2e9988ad 100644 --- a/src/language-js/html-binding.js +++ b/src/language-js/html-binding.js @@ -7,6 +7,10 @@ const { function printHtmlBinding(path, options, print) { const node = path.getValue(); + if (options.__onHtmlBindingRoot && path.getName() === null) { + options.__onHtmlBindingRoot(node); + } + if (node.type !== "File") { return; } diff --git a/src/language-js/printer-estree.js b/src/language-js/printer-estree.js index 1ee0e84461f8..c12f9df7ca3b 100644 --- a/src/language-js/printer-estree.js +++ b/src/language-js/printer-estree.js @@ -3400,22 +3400,15 @@ function printPathNoParens(path, options, print, args) { return concat(parts); - case "NGRoot": { - const rootNode = n.node; - const rootDoc = path.call(print, "node"); - const postprocess = options.__ng_root_postprocess || (x => x); - return postprocess( - concat( - [].concat( - rootDoc, - !n.node.comments || n.node.comments.length === 0 - ? [] - : concat([" //", n.node.comments[0].value.trimRight()]) - ) - ), - rootNode + case "NGRoot": + return concat( + [].concat( + path.call(print, "node"), + !n.node.comments || n.node.comments.length === 0 + ? [] + : concat([" //", n.node.comments[0].value.trimRight()]) + ) ); - } case "NGChainedExpression": return group(join(concat([";", line]), path.map(print, "expressions"))); case "NGEmptyExpression": diff --git a/tests/html_vue/__snapshots__/jsfmt.spec.js.snap b/tests/html_vue/__snapshots__/jsfmt.spec.js.snap index 74a5680da117..f824f6e7da96 100644 --- a/tests/html_vue/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_vue/__snapshots__/jsfmt.spec.js.snap @@ -60,9 +60,11 @@ exports[`attributes.vue - vue-verify 1`] = ` :class="{ longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong: true }" - :class="(() => { - return 'hello'; - })()" + :class=" + (() => { + return 'hello'; + })() + " > `; @@ -127,9 +129,11 @@ exports[`attributes.vue - vue-verify 2`] = ` :class="{ longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong: true, }" - :class="(() => { - return 'hello'; - })()" + :class=" + (() => { + return 'hello'; + })() + " > `; From 40db04f871c0db9e9680930e867be9abeb45cb28 Mon Sep 17 00:00:00 2001 From: Ika Date: Tue, 30 Oct 2018 11:07:05 +0800 Subject: [PATCH 136/177] test: add tests --- tests/html_angular/__snapshots__/jsfmt.spec.js.snap | 4 ++++ tests/html_angular/attributes.component.html | 1 + 2 files changed, 5 insertions(+) diff --git a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap index 921e9426d525..c1b7ec03128a 100644 --- a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap @@ -67,6 +67,7 @@ exports[`attributes.component.html - angular-verify 1`] = ` (target)="listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3" [target]="listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3" [target]="{ longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong: true }" + [error]="'We couldn\\\\\\'t find anything with that name.'" > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    `; @@ -228,6 +230,7 @@ exports[`attributes.component.html - angular-verify 2`] = ` (target)="listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3" [target]="listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3" [target]="{ longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong: true }" + [error]="'We couldn\\\\\\'t find anything with that name.'" > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    `; diff --git a/tests/html_angular/attributes.component.html b/tests/html_angular/attributes.component.html index df37a15a653e..fd1f8c245143 100644 --- a/tests/html_angular/attributes.component.html +++ b/tests/html_angular/attributes.component.html @@ -64,4 +64,5 @@ (target)="listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3" [target]="listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || listRow.NextScheduledSendStatus == 3" [target]="{ longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong: true }" + [error]="'We couldn\\\'t find anything with that name.'" > From 4904c1f996f8c155bfd84ca52b5d5bcb23094a99 Mon Sep 17 00:00:00 2001 From: Ika Date: Tue, 30 Oct 2018 11:10:31 +0800 Subject: [PATCH 137/177] fix: always use single quote for expression in attribute --- src/common/util.js | 8 +++++--- src/language-html/printer-html.js | 4 ++-- tests/html_angular/__snapshots__/jsfmt.spec.js.snap | 4 ++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/common/util.js b/src/common/util.js index a04a2d37dfd3..7bea29ca574c 100644 --- a/src/common/util.js +++ b/src/common/util.js @@ -464,9 +464,11 @@ function printString(raw, options, isDirectiveLiteral) { const enclosingQuote = options.parser === "json" ? double.quote - : shouldUseAlternateQuote - ? alternate.quote - : preferred.quote; + : options.__isInHtmlAttribute + ? single.quote + : shouldUseAlternateQuote + ? alternate.quote + : preferred.quote; // Directives are exact code unit sequences, which means that you can't // change the escape sequences they use. diff --git a/src/language-html/printer-html.js b/src/language-html/printer-html.js index 402c08288543..46cb6eb4aa99 100644 --- a/src/language-html/printer-html.js +++ b/src/language-html/printer-html.js @@ -99,8 +99,8 @@ function embed(path, print, textToDoc, options) { const embeddedAttributeValueDoc = printEmbeddedAttributeValue( node, (code, opts) => - // prefer single quote to avoid unnecessary escape - textToDoc(code, Object.assign({ singleQuote: true }, opts)), + // strictly prefer single quote to avoid unnecessary html entity escape + textToDoc(code, Object.assign({ __isInHtmlAttribute: true }, opts)), options ); if (embeddedAttributeValueDoc) { diff --git a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap index c1b7ec03128a..e38c73cdb97b 100644 --- a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap @@ -158,7 +158,7 @@ exports[`attributes.component.html - angular-verify 1`] = ` [target]="{ longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong: true }" - [error]=""We couldn\\\\'t find anything with that name."" + [error]="'We couldn\\\\\\'t find anything with that name.'" > `; @@ -321,7 +321,7 @@ exports[`attributes.component.html - angular-verify 2`] = ` [target]="{ longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong: true }" - [error]=""We couldn\\\\'t find anything with that name."" + [error]="'We couldn\\\\\\'t find anything with that name.'" > `; From 7c9a76adb4f103436694384a45abdef32952b466 Mon Sep 17 00:00:00 2001 From: Ika Date: Tue, 30 Oct 2018 15:45:37 +0800 Subject: [PATCH 138/177] test: add tests --- tests/html_angular/__snapshots__/jsfmt.spec.js.snap | 4 ++++ tests/html_angular/attributes.component.html | 1 + 2 files changed, 5 insertions(+) diff --git a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap index e38c73cdb97b..59c6f83a2673 100644 --- a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap @@ -35,6 +35,7 @@ exports[`attributes.component.html - angular-verify 1`] = ` [target]=" javascript : 'hello world' " [target]=" a ?. b ( ) " [target]=" a ?. b " + [target]=" this . a " on-target=" a = 1 " (target)=" a = 1 " (target)=" a . b = 1 " @@ -104,6 +105,7 @@ exports[`attributes.component.html - angular-verify 1`] = ` [target]="javascript: 'hello world' " [target]="a?.b()" [target]="a?.b" + [target]="a" on-target="(a = 1)" (target)="(a = 1)" (target)="(a.b = 1)" @@ -198,6 +200,7 @@ exports[`attributes.component.html - angular-verify 2`] = ` [target]=" javascript : 'hello world' " [target]=" a ?. b ( ) " [target]=" a ?. b " + [target]=" this . a " on-target=" a = 1 " (target)=" a = 1 " (target)=" a . b = 1 " @@ -267,6 +270,7 @@ exports[`attributes.component.html - angular-verify 2`] = ` [target]="javascript: 'hello world' " [target]="a?.b()" [target]="a?.b" + [target]="a" on-target="(a = 1)" (target)="(a = 1)" (target)="(a.b = 1)" diff --git a/tests/html_angular/attributes.component.html b/tests/html_angular/attributes.component.html index fd1f8c245143..5478f4068b48 100644 --- a/tests/html_angular/attributes.component.html +++ b/tests/html_angular/attributes.component.html @@ -32,6 +32,7 @@ [target]=" javascript : 'hello world' " [target]=" a ?. b ( ) " [target]=" a ?. b " + [target]=" this . a " on-target=" a = 1 " (target)=" a = 1 " (target)=" a . b = 1 " From 3dc4477c2010fc84d1b067f5e33fe3b6fab914de Mon Sep 17 00:00:00 2001 From: Ika Date: Tue, 30 Oct 2018 15:47:13 +0800 Subject: [PATCH 139/177] fix(angular): do not remove `this.` --- package.json | 2 +- tests/html_angular/__snapshots__/jsfmt.spec.js.snap | 4 ++-- yarn.lock | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index b0943560a991..5532531cef98 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "@babel/parser": "7.1.2", "@glimmer/syntax": "0.30.3", "@iarna/toml": "2.0.0", - "angular-estree-parser": "1.1.1", + "angular-estree-parser": "1.1.2", "angular-html-parser": "1.0.0", "camelcase": "4.1.0", "chalk": "2.1.0", diff --git a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap index 59c6f83a2673..2df30c03619f 100644 --- a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap @@ -105,7 +105,7 @@ exports[`attributes.component.html - angular-verify 1`] = ` [target]="javascript: 'hello world' " [target]="a?.b()" [target]="a?.b" - [target]="a" + [target]="this.a" on-target="(a = 1)" (target)="(a = 1)" (target)="(a.b = 1)" @@ -270,7 +270,7 @@ exports[`attributes.component.html - angular-verify 2`] = ` [target]="javascript: 'hello world' " [target]="a?.b()" [target]="a?.b" - [target]="a" + [target]="this.a" on-target="(a = 1)" (target)="(a = 1)" (target)="(a.b = 1)" diff --git a/yarn.lock b/yarn.lock index 7372e4e42715..41d400c9bb9b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -668,9 +668,9 @@ amdefine@>=0.0.4: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" -angular-estree-parser@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/angular-estree-parser/-/angular-estree-parser-1.1.1.tgz#408a2e0f2ca95a7d8563a4c93d3411c7148d9b67" +angular-estree-parser@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/angular-estree-parser/-/angular-estree-parser-1.1.2.tgz#d95f263df5825ea59c643d38b67119576d21c844" dependencies: lines-and-columns "^1.1.6" tslib "^1.9.3" From 875caac392d5eac7d7c7ca079c3c6f95b21db58c Mon Sep 17 00:00:00 2001 From: Ika Date: Tue, 30 Oct 2018 16:24:10 +0800 Subject: [PATCH 140/177] test: add tests --- .../__snapshots__/jsfmt.spec.js.snap | 32 +++++++++++++++++++ tests/html_angular/attributes.component.html | 8 +++++ 2 files changed, 40 insertions(+) diff --git a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap index 2df30c03619f..dadfef4b189a 100644 --- a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap @@ -42,6 +42,14 @@ exports[`attributes.component.html - angular-verify 1`] = ` (target)=" a [ b ] = 1 " (target)=" a // hello " (target)=" a ; b " + (event)=" 0 " + (event)=" a.b " + (event)=" hello " + (event)=" hello() " + (event)=" a && b " + (event)=" a && b() " + (event)=" foo = $event " + (event)=" foo == $event " *ngIf=" something?true:false " *ngFor=" let hero of heroes" *ngFor=" let hero of[1,2,3,666666666666666666666666666666666666]; let i=index" @@ -112,6 +120,14 @@ exports[`attributes.component.html - angular-verify 1`] = ` (target)="(a[b] = 1)" (target)="a // hello" (target)="a; b" + (event)="0" + (event)="a.b" + (event)="hello" + (event)="hello()" + (event)="a && b" + (event)="a && b()" + (event)="(foo = $event)" + (event)="foo == $event" *ngIf="something ? true : false" *ngFor="let hero of heroes" *ngFor=" @@ -207,6 +223,14 @@ exports[`attributes.component.html - angular-verify 2`] = ` (target)=" a [ b ] = 1 " (target)=" a // hello " (target)=" a ; b " + (event)=" 0 " + (event)=" a.b " + (event)=" hello " + (event)=" hello() " + (event)=" a && b " + (event)=" a && b() " + (event)=" foo = $event " + (event)=" foo == $event " *ngIf=" something?true:false " *ngFor=" let hero of heroes" *ngFor=" let hero of[1,2,3,666666666666666666666666666666666666]; let i=index" @@ -277,6 +301,14 @@ exports[`attributes.component.html - angular-verify 2`] = ` (target)="(a[b] = 1)" (target)="a // hello" (target)="a; b" + (event)="0" + (event)="a.b" + (event)="hello" + (event)="hello()" + (event)="a && b" + (event)="a && b()" + (event)="(foo = $event)" + (event)="foo == $event" *ngIf="something ? true : false" *ngFor="let hero of heroes" *ngFor=" diff --git a/tests/html_angular/attributes.component.html b/tests/html_angular/attributes.component.html index 5478f4068b48..c1a30b657fff 100644 --- a/tests/html_angular/attributes.component.html +++ b/tests/html_angular/attributes.component.html @@ -39,6 +39,14 @@ (target)=" a [ b ] = 1 " (target)=" a // hello " (target)=" a ; b " + (event)=" 0 " + (event)=" a.b " + (event)=" hello " + (event)=" hello() " + (event)=" a && b " + (event)=" a && b() " + (event)=" foo = $event " + (event)=" foo == $event " *ngIf=" something?true:false " *ngFor=" let hero of heroes" *ngFor=" let hero of[1,2,3,666666666666666666666666666666666666]; let i=index" From a0711c1c3158e3a1c1dd3dd65617309526607849 Mon Sep 17 00:00:00 2001 From: Ika Date: Tue, 30 Oct 2018 16:44:46 +0800 Subject: [PATCH 141/177] feat(angular): only add parens in action expr if it has no side effect --- src/language-js/needs-parens.js | 2 + src/language-js/parser-angular.js | 14 ++- src/language-js/printer-estree.js | 28 +++++- src/language-js/utils.js | 14 +++ .../__snapshots__/jsfmt.spec.js.snap | 94 +++++++++---------- 5 files changed, 99 insertions(+), 53 deletions(-) diff --git a/src/language-js/needs-parens.js b/src/language-js/needs-parens.js index e3f18a2ccb14..4d65e92987ea 100644 --- a/src/language-js/needs-parens.js +++ b/src/language-js/needs-parens.js @@ -500,6 +500,8 @@ function needsParens(path, options) { return false; } else if (parent.type === "Property" && parent.value === node) { return false; + } else if (parent.type === "NGChainedExpression") { + return false; } return true; } diff --git a/src/language-js/parser-angular.js b/src/language-js/parser-angular.js index a8cc37370f73..1055ab50e96a 100644 --- a/src/language-js/parser-angular.js +++ b/src/language-js/parser-angular.js @@ -3,9 +3,19 @@ const locFns = require("./loc"); function createParser(_parse) { - const parse = (text /*, parsers, opts */) => { + const parse = (text, parsers, options) => { const ngEstreeParser = require("angular-estree-parser"); - return { type: "NGRoot", node: _parse(text, ngEstreeParser) }; + const node = _parse(text, ngEstreeParser); + return { + type: "NGRoot", + node: + options.parser === "__ng_action" && node.type !== "NGChainedExpression" + ? Object.assign({}, node, { + type: "NGChainedExpression", + expressions: [node] + }) + : node + }; }; return Object.assign({ astFormat: "estree", parse }, locFns); } diff --git a/src/language-js/printer-estree.js b/src/language-js/printer-estree.js index c12f9df7ca3b..5119635f96ff 100644 --- a/src/language-js/printer-estree.js +++ b/src/language-js/printer-estree.js @@ -36,6 +36,7 @@ const pathNeedsParens = require("./needs-parens"); const preprocess = require("./preprocess"); const { printHtmlBinding } = require("./html-binding"); const { + hasNode, hasFlowAnnotationComment, hasFlowShorthandAnnotationComment } = require("./utils"); @@ -3410,7 +3411,18 @@ function printPathNoParens(path, options, print, args) { ) ); case "NGChainedExpression": - return group(join(concat([";", line]), path.map(print, "expressions"))); + return group( + join( + concat([";", line]), + path.map( + childPath => + hasNgSideEffect(childPath) + ? print(childPath) + : concat(["(", print(childPath), ")"]), + "expressions" + ) + ) + ); case "NGEmptyExpression": return ""; case "NGQuotedExpression": @@ -3477,6 +3489,20 @@ function isNgForOf(path) { ); } +/** identify if an angular expression seems to have side effects */ +function hasNgSideEffect(path) { + return hasNode(path.getValue(), node => { + switch (node.type) { + case undefined: + return false; + case "CallExpression": + case "OptionalCallExpression": + case "AssignmentExpression": + return true; + } + }); +} + function printStatementSequence(path, options, print) { const printed = []; diff --git a/src/language-js/utils.js b/src/language-js/utils.js index b8a7a946f0a9..5721041bad15 100644 --- a/src/language-js/utils.js +++ b/src/language-js/utils.js @@ -31,7 +31,21 @@ function hasFlowAnnotationComment(comments) { return comments && comments[0].value.match(FLOW_ANNOTATION); } +function hasNode(node, fn) { + if (!node || typeof node !== "object") { + return false; + } + if (Array.isArray(node)) { + return node.some(value => hasNode(value, fn)); + } + const result = fn(node); + return typeof result === "boolean" + ? result + : Object.keys(node).some(key => hasNode(node[key], fn)); +} + module.exports = { + hasNode, hasFlowShorthandAnnotationComment, hasFlowAnnotationComment }; diff --git a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap index dadfef4b189a..27164da3d155 100644 --- a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap @@ -114,20 +114,20 @@ exports[`attributes.component.html - angular-verify 1`] = ` [target]="a?.b()" [target]="a?.b" [target]="this.a" - on-target="(a = 1)" - (target)="(a = 1)" - (target)="(a.b = 1)" - (target)="(a[b] = 1)" - (target)="a // hello" - (target)="a; b" - (event)="0" - (event)="a.b" - (event)="hello" + on-target="a = 1" + (target)="a = 1" + (target)="a.b = 1" + (target)="a[b] = 1" + (target)="(a) // hello" + (target)="(a); (b)" + (event)="(0)" + (event)="(a.b)" + (event)="(hello)" (event)="hello()" - (event)="a && b" + (event)="(a && b)" (event)="a && b()" - (event)="(foo = $event)" - (event)="foo == $event" + (event)="foo = $event" + (event)="(foo == $event)" *ngIf="something ? true : false" *ngFor="let hero of heroes" *ngFor=" @@ -164,9 +164,9 @@ exports[`attributes.component.html - angular-verify 1`] = ` else: hello " (target)=" - listRow.NextScheduledSendStatus == 1 || + (listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || - listRow.NextScheduledSendStatus == 3 + listRow.NextScheduledSendStatus == 3) " [target]=" listRow.NextScheduledSendStatus == 1 || @@ -295,20 +295,20 @@ exports[`attributes.component.html - angular-verify 2`] = ` [target]="a?.b()" [target]="a?.b" [target]="this.a" - on-target="(a = 1)" - (target)="(a = 1)" - (target)="(a.b = 1)" - (target)="(a[b] = 1)" - (target)="a // hello" - (target)="a; b" - (event)="0" - (event)="a.b" - (event)="hello" + on-target="a = 1" + (target)="a = 1" + (target)="a.b = 1" + (target)="a[b] = 1" + (target)="(a) // hello" + (target)="(a); (b)" + (event)="(0)" + (event)="(a.b)" + (event)="(hello)" (event)="hello()" - (event)="a && b" + (event)="(a && b)" (event)="a && b()" - (event)="(foo = $event)" - (event)="foo == $event" + (event)="foo = $event" + (event)="(foo == $event)" *ngIf="something ? true : false" *ngFor="let hero of heroes" *ngFor=" @@ -345,9 +345,9 @@ exports[`attributes.component.html - angular-verify 2`] = ` else: hello " (target)=" - listRow.NextScheduledSendStatus == 1 || + (listRow.NextScheduledSendStatus == 1 || listRow.NextScheduledSendStatus == 2 || - listRow.NextScheduledSendStatus == 3 + listRow.NextScheduledSendStatus == 3) " [target]=" listRow.NextScheduledSendStatus == 1 || @@ -1380,7 +1380,7 @@ can be found in the LICENSE file at http://angular.io/license

    Template reference variable expression context (#heroInput)

    -
    +
    Type something: {{ heroInput.value }}
    @@ -1444,7 +1444,7 @@ can be found in the LICENSE file at http://angular.io/license -
    click me
    +
    click me
    {{ clicked }}

    Hero Name: {{ name }}
    @@ -1611,7 +1611,7 @@ can be found in the LICENSE file at http://angular.io/license
    -
    click with myClick
    +
    click with myClick
    {{ clickMessage }}
    @@ -1652,10 +1652,7 @@ can be found in the LICENSE file at http://angular.io/license

    De-sugared two-way binding

    - +
    top @@ -1671,14 +1668,14 @@ can be found in the LICENSE file at http://angular.io/license without NgModel
    [(ngModel)]
    bindon-ngModel
    (ngModelChange)="...name=$event"
    | @@ -1942,7 +1939,7 @@ without NgModel
    -
    myClick2
    +
    myClick2
    {{ clickMessage2 }} top @@ -2871,7 +2868,7 @@ can be found in the LICENSE file at http://angular.io/license

    Template reference variable expression context (#heroInput)

    -
    +
    Type something: {{ heroInput.value }}
    @@ -2935,7 +2932,7 @@ can be found in the LICENSE file at http://angular.io/license -
    click me
    +
    click me
    {{ clicked }}

    Hero Name: {{ name }}
    @@ -3102,7 +3099,7 @@ can be found in the LICENSE file at http://angular.io/license
    -
    click with myClick
    +
    click with myClick
    {{ clickMessage }}
    @@ -3143,10 +3140,7 @@ can be found in the LICENSE file at http://angular.io/license

    De-sugared two-way binding

    - +
    top @@ -3162,14 +3156,14 @@ can be found in the LICENSE file at http://angular.io/license without NgModel
    [(ngModel)]
    bindon-ngModel
    (ngModelChange)="...name=$event"
    | @@ -3433,7 +3427,7 @@ without NgModel
    -
    myClick2
    +
    myClick2
    {{ clickMessage2 }} top From 2277d5e2d1f814f550796c605db50302968f609d Mon Sep 17 00:00:00 2001 From: Ika Date: Tue, 30 Oct 2018 17:30:08 +0800 Subject: [PATCH 142/177] test: add tests --- .../__snapshots__/jsfmt.spec.js.snap | 120 ++++++++++++++++++ tests/html_tags/tags.html | 13 ++ 2 files changed, 133 insertions(+) diff --git a/tests/html_tags/__snapshots__/jsfmt.spec.js.snap b/tests/html_tags/__snapshots__/jsfmt.spec.js.snap index b344f2af6400..d543ed1c262d 100644 --- a/tests/html_tags/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_tags/__snapshots__/jsfmt.spec.js.snap @@ -1467,6 +1467,19 @@ exports[`tags.html - html-verify 1`] = `

    "" is the property bound title.

  • 12345678901234567890123456789012345678901234567890123456789012345678901234567890
  • +
    + + + + + + + + + + + +
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    @@ -1617,6 +1630,15 @@ exports[`tags.html - html-verify 1`] = `
  • 12345678901234567890123456789012345678901234567890123456789012345678901234567890
  • +
    + + + + + + + +
    `; @@ -1709,6 +1731,19 @@ exports[`tags.html - html-verify 2`] = `

    "" is the property bound title.

  • 12345678901234567890123456789012345678901234567890123456789012345678901234567890
  • +
    + + + + + + + + + + + +
    ~

    @@ -2029,6 +2064,23 @@ exports[`tags.html - html-verify 2`] = `
  • 12345678901234567890123456789012345678901234567890123456789012345678901234567890
  • +
    + + + + + + + + + + + +
    `; @@ -2121,6 +2173,19 @@ exports[`tags.html - html-verify 3`] = `

    "" is the property bound title.

  • 12345678901234567890123456789012345678901234567890123456789012345678901234567890
  • +
    + + + + + + + + + + + +
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    @@ -2205,6 +2270,13 @@ exports[`tags.html - html-verify 3`] = `

    "" is the property bound title.

  • 12345678901234567890123456789012345678901234567890123456789012345678901234567890
  • +
    + + + + + +
    `; @@ -2297,6 +2369,19 @@ exports[`tags.html - html-verify 4`] = `

    "" is the property bound title.

  • 12345678901234567890123456789012345678901234567890123456789012345678901234567890
  • +
    + + + + + + + + + + + +
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    @@ -2426,6 +2511,15 @@ exports[`tags.html - html-verify 4`] = `
  • 12345678901234567890123456789012345678901234567890123456789012345678901234567890
  • +
    + + + + + + + +
    `; @@ -2518,6 +2612,19 @@ exports[`tags.html - html-verify 5`] = `

    "" is the property bound title.

  • 12345678901234567890123456789012345678901234567890123456789012345678901234567890
  • +
    + + + + + + + + + + + +
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    @@ -2697,6 +2804,19 @@ exports[`tags.html - html-verify 5`] = `
  • 12345678901234567890123456789012345678901234567890123456789012345678901234567890
  • +
    + + + + + + + + + + + +
    `; diff --git a/tests/html_tags/tags.html b/tests/html_tags/tags.html index adb9976b5699..df3f23f9c7fb 100644 --- a/tests/html_tags/tags.html +++ b/tests/html_tags/tags.html @@ -86,3 +86,16 @@

    "" is the property bound title.

  • 12345678901234567890123456789012345678901234567890123456789012345678901234567890
  • +
    + + + + + + + + + + + +
    From fffa49d4057187c78425acc316537e96331c36ed Mon Sep 17 00:00:00 2001 From: Ika Date: Tue, 30 Oct 2018 17:33:11 +0800 Subject: [PATCH 143/177] feat: respect linebreak before/after custom elements --- src/language-html/parser-html.js | 22 +++++++---- src/language-html/utils.js | 39 ++++++++++++++++++- .../__snapshots__/jsfmt.spec.js.snap | 32 ++++++++++----- 3 files changed, 75 insertions(+), 18 deletions(-) diff --git a/src/language-html/parser-html.js b/src/language-html/parser-html.js index 701b68469280..596a83885943 100644 --- a/src/language-html/parser-html.js +++ b/src/language-html/parser-html.js @@ -148,8 +148,8 @@ function _parse( ast.children.unshift(frontMatter); } - const parseSubHtml = (subContent, startSourceSpan) => { - const { offset } = startSourceSpan; + const parseSubHtml = (subContent, startSpan) => { + const { offset } = startSpan; const fakeContent = text.slice(0, offset).replace(/[^\r\n]/g, " "); const realContent = subContent; const subAst = _parse( @@ -160,7 +160,7 @@ function _parse( ); const ParseSourceSpan = subAst.children[0].sourceSpan.constructor; subAst.sourceSpan = new ParseSourceSpan( - startSourceSpan, + startSpan, subAst.children[subAst.children.length - 1].sourceSpan.end ); const firstText = subAst.children[0]; @@ -220,11 +220,19 @@ function parseIeConditionalComment(node, parseHtml) { const [, openingTagSuffix, condition, data] = match; const offset = " -
    Birthdate: {{ currentHero?.birthdate | date:"longDate" }}
    +
    Birthdate: {{ currentHero?.birthdate | date: "longDate" }}
    {{ currentHero | json }}
    -
    Birthdate: {{ currentHero?.birthdate | date:"longDate" | uppercase }}
    +
    + Birthdate: {{ currentHero?.birthdate | date: "longDate" | uppercase }} +
    - {{ product.price | currency:"USD":true }} + {{ product.price | currency: "USD":true }}
    top @@ -3442,15 +3446,17 @@ without NgModel
    Title through a pipe chain: {{ title | uppercase | lowercase }}
    -
    Birthdate: {{ currentHero?.birthdate | date:"longDate" }}
    +
    Birthdate: {{ currentHero?.birthdate | date: "longDate" }}
    {{ currentHero | json }}
    -
    Birthdate: {{ currentHero?.birthdate | date:"longDate" | uppercase }}
    +
    + Birthdate: {{ currentHero?.birthdate | date: "longDate" | uppercase }} +
    - {{ product.price | currency:"USD":true }} + {{ product.price | currency: "USD":true }}
    top From 41c3cd222efd37dc6e7fdecce3b3b968da1adc75 Mon Sep 17 00:00:00 2001 From: Ika Date: Thu, 1 Nov 2018 16:24:51 +0800 Subject: [PATCH 148/177] test: add tests --- .../__snapshots__/jsfmt.spec.js.snap | 32 +++++++++++++++++++ tests/html_attributes/srcset.html | 9 ++++++ 2 files changed, 41 insertions(+) create mode 100644 tests/html_attributes/srcset.html diff --git a/tests/html_attributes/__snapshots__/jsfmt.spec.js.snap b/tests/html_attributes/__snapshots__/jsfmt.spec.js.snap index cbf575a57847..e3e88bd15ab4 100644 --- a/tests/html_attributes/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_attributes/__snapshots__/jsfmt.spec.js.snap @@ -237,6 +237,38 @@ exports[`single-quotes.html - html-verify 1`] = ` `; +exports[`srcset.html - html-verify 1`] = ` + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + + +`; + exports[`without-quotes.html - html-verify 1`] = `

    String

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/html_attributes/srcset.html b/tests/html_attributes/srcset.html new file mode 100644 index 000000000000..a320c725d100 --- /dev/null +++ b/tests/html_attributes/srcset.html @@ -0,0 +1,9 @@ + + + From 6ef1328dce9653564b23e7b0db7347575d6b4f2f Mon Sep 17 00:00:00 2001 From: Ika Date: Thu, 1 Nov 2018 17:07:10 +0800 Subject: [PATCH 149/177] feat: support img.srcset --- package.json | 1 + src/language-html/preprocess.js | 9 +++ src/language-html/printer-html.js | 13 ++-- src/language-html/syntax-attribute.js | 64 +++++++++++++++++++ .../__snapshots__/jsfmt.spec.js.snap | 16 ++++- yarn.lock | 4 ++ 6 files changed, 100 insertions(+), 7 deletions(-) create mode 100644 src/language-html/syntax-attribute.js diff --git a/package.json b/package.json index 5532531cef98..5eb3e1a34541 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "minimist": "1.2.0", "n-readlines": "1.0.0", "normalize-path": "3.0.0", + "parse-srcset": "ikatyang/parse-srcset#feat/report-error", "postcss-less": "1.1.5", "postcss-media-query-parser": "0.2.3", "postcss-scss": "1.0.6", diff --git a/src/language-html/preprocess.js b/src/language-html/preprocess.js index 8585e14f6e53..664debd4dbc8 100644 --- a/src/language-html/preprocess.js +++ b/src/language-html/preprocess.js @@ -366,6 +366,15 @@ function addShortcuts(ast /*, options */) { lastChild: { value: lastChild, enumerable: false } }); + if (node.attrs) { + node.attrs.forEach(attribute => + Object.defineProperty(attribute, "parent", { + value: node, + enumerable: false + }) + ); + } + if (node.children) { node.children.forEach((child, childIndex) => _addShortcuts(child, node, childIndex) diff --git a/src/language-html/printer-html.js b/src/language-html/printer-html.js index 46cb6eb4aa99..1ae8ead8e86b 100644 --- a/src/language-html/printer-html.js +++ b/src/language-html/printer-html.js @@ -40,6 +40,7 @@ const preprocess = require("./preprocess"); const assert = require("assert"); const { insertPragma } = require("./pragma"); const { printVueFor, printVueSlotScope } = require("./syntax-vue"); +const { printImgSrcset } = require("./syntax-attribute"); function concat(parts) { const newParts = normalizeParts(parts); @@ -783,14 +784,18 @@ function printEmbeddedAttributeValue(node, originalTextToDoc, options) { } }; - const printMaybeHug = doc => - shouldHug - ? group(doc) - : group(concat([indent(concat([softline, doc])), softline])); + const printHug = doc => group(doc); + const printExpand = doc => + group(concat([indent(concat([softline, doc])), softline])); + const printMaybeHug = doc => (shouldHug ? printHug(doc) : printExpand(doc)); const textToDoc = (code, opts) => originalTextToDoc(code, Object.assign({ __onHtmlBindingRoot }, opts)); + if (node.name === "srcset" && node.parent.name === "img") { + return printExpand(printImgSrcset(getValue())); + } + if (options.parser === "vue") { if (node.name === "v-for") { return printVueFor(getValue(), textToDoc); diff --git a/src/language-html/syntax-attribute.js b/src/language-html/syntax-attribute.js new file mode 100644 index 000000000000..46419cab91b7 --- /dev/null +++ b/src/language-html/syntax-attribute.js @@ -0,0 +1,64 @@ +"use strict"; + +const { + builders: { concat, ifBreak, join, line } +} = require("../doc"); +const parseSrcset = require("parse-srcset"); + +function printImgSrcset(value) { + const srcset = parseSrcset(value, { + logger: { + error(message) { + throw new Error(message); + } + } + }); + + const hasW = srcset.some(src => src.w); + const hasH = srcset.some(src => src.h); + const hasX = srcset.some(src => src.d); + + if (hasW + hasH + hasX !== 1) { + throw new Error(`Mixed descriptor in srcset is not supported`); + } + + const key = hasW ? "w" : hasH ? "h" : "d"; + const unit = hasW ? "w" : hasH ? "h" : "x"; + + const getMax = values => Math.max.apply(Math, values); + + const urls = srcset.map(src => src.url); + const maxUrlLength = getMax(urls.map(url => url.length)); + + const descriptors = srcset + .map(src => src[key]) + .map(descriptor => (descriptor ? descriptor.toString() : "")); + const descriptorLeftLengths = descriptors.map(descriptor => { + const index = descriptor.indexOf("."); + return index === -1 ? descriptor.length : index; + }); + const maxDescriptorLeftLength = getMax(descriptorLeftLengths); + + return join( + concat([",", line]), + urls.map((url, index) => { + const parts = [url]; + + const descriptor = descriptors[index]; + if (descriptor) { + const urlPadding = maxUrlLength - url.length + 1; + const descriptorPadding = + maxDescriptorLeftLength - descriptorLeftLengths[index]; + + const alignment = " ".repeat(urlPadding + descriptorPadding); + parts.push(ifBreak(alignment, " "), descriptor + unit); + } + + return concat(parts); + }) + ); +} + +module.exports = { + printImgSrcset +}; diff --git a/tests/html_attributes/__snapshots__/jsfmt.spec.js.snap b/tests/html_attributes/__snapshots__/jsfmt.spec.js.snap index e3e88bd15ab4..ec16f2fce22d 100644 --- a/tests/html_attributes/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_attributes/__snapshots__/jsfmt.spec.js.snap @@ -250,19 +250,29 @@ sizes="(max-width: 66rem) 100vw, 66rem" alt=""/> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/yarn.lock b/yarn.lock index 41d400c9bb9b..69b07addcb2b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4438,6 +4438,10 @@ parse-json@^4.0.0: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" +parse-srcset@ikatyang/parse-srcset#feat/report-error: + version "1.0.2" + resolved "https://codeload.github.com/ikatyang/parse-srcset/tar.gz/54eb9c1cb21db5c62b4d0e275d7249516df6f0ee" + parse5@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608" From 17d05f917a9747d4fdf5f420aac4d05b9c140c47 Mon Sep 17 00:00:00 2001 From: Ika Date: Thu, 1 Nov 2018 17:31:27 +0800 Subject: [PATCH 150/177] test: add tests --- .../__snapshots__/jsfmt.spec.js.snap | 102 ++++++++++++++++++ .../ignore-attribute.component.html | 23 ++++ 2 files changed, 125 insertions(+) create mode 100644 tests/html_angular/ignore-attribute.component.html diff --git a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap index 595e08e38aab..9e5266cab626 100644 --- a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap @@ -362,6 +362,108 @@ exports[`attributes.component.html - angular-verify 2`] = ` `; +exports[`ignore-attribute.component.html - angular-verify 1`] = ` +
    + +
    + +
    + +
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +
    + +
    + +
    + +
    + +`; + +exports[`ignore-attribute.component.html - angular-verify 2`] = ` +
    + +
    + +
    + +
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +
    + +
    + +
    + +
    + +`; + exports[`interpolation.component.html - angular-verify 1`] = `
    {{ a | b : c }}
    {{ 0 - 1 }}
    diff --git a/tests/html_angular/ignore-attribute.component.html b/tests/html_angular/ignore-attribute.component.html new file mode 100644 index 000000000000..93b1e2acf8db --- /dev/null +++ b/tests/html_angular/ignore-attribute.component.html @@ -0,0 +1,23 @@ +
    + +
    + +
    + +
    From 1a83e6b5385b2b567a62b241f2444451b675b758 Mon Sep 17 00:00:00 2001 From: Ika Date: Thu, 1 Nov 2018 17:39:26 +0800 Subject: [PATCH 151/177] feat: support prettier-ignore-attribute --- src/language-html/printer-html.js | 26 ++++++++++++++++++- src/language-html/utils.js | 15 +++++++++++ .../__snapshots__/jsfmt.spec.js.snap | 24 ++++++++--------- 3 files changed, 52 insertions(+), 13 deletions(-) diff --git a/src/language-html/printer-html.js b/src/language-html/printer-html.js index 1ae8ead8e86b..23c529a6c3e2 100644 --- a/src/language-html/printer-html.js +++ b/src/language-html/printer-html.js @@ -26,6 +26,7 @@ const { forceNextEmptyLine, getCommentData, getLastDescendant, + getPrettierIgnoreAttributeCommentData, hasPrettierIgnore, inferScriptParser, isElement, @@ -531,7 +532,30 @@ function printOpeningTag(path, options, print) { indent( concat([ forceNotToBreakAttrContent ? " " : line, - join(line, path.map(print, "attrs")) + join( + line, + (ignoreAttributeData => { + const hasPrettierIgnoreAttribute = + typeof ignoreAttributeData === "boolean" + ? () => ignoreAttributeData + : Array.isArray(ignoreAttributeData) + ? attr => ignoreAttributeData.indexOf(attr.name) !== -1 + : () => false; + return path.map(attrPath => { + const attr = attrPath.getValue(); + return hasPrettierIgnoreAttribute(attr) + ? options.originalText.slice( + options.locStart(attr), + options.locEnd(attr) + ) + : print(attrPath); + }, "attrs"); + })( + node.prev && + node.prev.type === "comment" && + getPrettierIgnoreAttributeCommentData(node.prev.value) + ) + ) ]) ), /** diff --git a/src/language-html/utils.js b/src/language-html/utils.js index 63ad3da50db3..3bc34d85089a 100644 --- a/src/language-html/utils.js +++ b/src/language-html/utils.js @@ -66,6 +66,20 @@ function isPrettierIgnore(node) { return node.type === "comment" && node.value.trim() === "prettier-ignore"; } +function getPrettierIgnoreAttributeCommentData(value) { + const match = value.trim().match(/^prettier-ignore-attribute(?:\s+([^]+))?$/); + + if (!match) { + return false; + } + + if (!match[1]) { + return true; + } + + return match[1].split(/\s+/); +} + function isElement(node, nameOrNames) { if (node.type !== "element") { return false; @@ -583,6 +597,7 @@ module.exports = { getLastDescendant, getNodeCssStyleDisplay, getNodeCssStyleWhiteSpace, + getPrettierIgnoreAttributeCommentData, getPrevNode, hasPrettierIgnore, identity, diff --git a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap index 9e5266cab626..49ca1540dc40 100644 --- a/tests/html_angular/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_angular/__snapshots__/jsfmt.spec.js.snap @@ -394,21 +394,21 @@ exports[`ignore-attribute.component.html - angular-verify 1`] = ` >
    `; @@ -445,21 +445,21 @@ exports[`ignore-attribute.component.html - angular-verify 2`] = ` >
    `; From 61519c3c5bc340387d5a1a7e080c57c6a2b9e24f Mon Sep 17 00:00:00 2001 From: Ika Date: Thu, 1 Nov 2018 19:09:29 +0800 Subject: [PATCH 152/177] feat: format source.srcset as well --- src/language-html/printer-html.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/language-html/printer-html.js b/src/language-html/printer-html.js index 23c529a6c3e2..e2a26c31348e 100644 --- a/src/language-html/printer-html.js +++ b/src/language-html/printer-html.js @@ -816,7 +816,10 @@ function printEmbeddedAttributeValue(node, originalTextToDoc, options) { const textToDoc = (code, opts) => originalTextToDoc(code, Object.assign({ __onHtmlBindingRoot }, opts)); - if (node.name === "srcset" && node.parent.name === "img") { + if ( + node.name === "srcset" && + (node.parent.name === "img" || node.parent.name === "source") + ) { return printExpand(printImgSrcset(getValue())); } From 4e84e47a67318bcbacd685c10d65a98b955b12e5 Mon Sep 17 00:00:00 2001 From: Ika Date: Thu, 1 Nov 2018 20:48:59 +0800 Subject: [PATCH 153/177] test: add tests --- .../__snapshots__/jsfmt.spec.js.snap | 21 +++++++++++++++++++ tests/html_tags/tags.html | 1 + 2 files changed, 22 insertions(+) diff --git a/tests/html_tags/__snapshots__/jsfmt.spec.js.snap b/tests/html_tags/__snapshots__/jsfmt.spec.js.snap index 6b8d2e12b8bf..cc358f1a88a8 100644 --- a/tests/html_tags/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_tags/__snapshots__/jsfmt.spec.js.snap @@ -1480,6 +1480,7 @@ exports[`tags.html - html-verify 1`] = ` +foreign tag name should not be lower cased ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    @@ -1643,6 +1644,7 @@ exports[`tags.html - html-verify 1`] = ` +foreign tag name should not be lower cased `; @@ -1748,6 +1750,7 @@ exports[`tags.html - html-verify 2`] = ` +foreign tag name should not be lower cased ~

    @@ -2085,6 +2088,18 @@ exports[`tags.html - html-verify 2`] = ` [input]="something" > +foreign + tag + name + should + not + be + lower + cased `; @@ -2190,6 +2205,7 @@ exports[`tags.html - html-verify 3`] = ` +foreign tag name should not be lower cased ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    @@ -2287,6 +2303,7 @@ exports[`tags.html - html-verify 3`] = ` +foreign tag name should not be lower cased `; @@ -2392,6 +2409,7 @@ exports[`tags.html - html-verify 4`] = ` +foreign tag name should not be lower cased ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    @@ -2534,6 +2552,7 @@ exports[`tags.html - html-verify 4`] = ` +foreign tag name should not be lower cased `; @@ -2639,6 +2658,7 @@ exports[`tags.html - html-verify 5`] = ` +foreign tag name should not be lower cased ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    @@ -2831,6 +2851,7 @@ exports[`tags.html - html-verify 5`] = ` +foreign tag name should not be lower cased `; diff --git a/tests/html_tags/tags.html b/tests/html_tags/tags.html index df3f23f9c7fb..5b13eb4cd02d 100644 --- a/tests/html_tags/tags.html +++ b/tests/html_tags/tags.html @@ -99,3 +99,4 @@ +foreign tag name should not be lower cased From 6274f12581c450f4f86dcd13316808f825e5aa58 Mon Sep 17 00:00:00 2001 From: Ika Date: Thu, 1 Nov 2018 21:27:24 +0800 Subject: [PATCH 154/177] fix: disable tag name normalization for foreign tags --- src/language-html/parser-html.js | 61 ++++++++++++++----- src/language-html/preprocess.js | 19 ++++-- src/language-html/printer-html.js | 28 ++++----- src/language-html/utils.js | 46 +++++++------- .../__snapshots__/jsfmt.spec.js.snap | 12 ++-- 5 files changed, 102 insertions(+), 64 deletions(-) diff --git a/src/language-html/parser-html.js b/src/language-html/parser-html.js index 596a83885943..ab5ddf08689c 100644 --- a/src/language-html/parser-html.js +++ b/src/language-html/parser-html.js @@ -50,11 +50,26 @@ function ngHtmlParser(input, canSelfClose) { } }; + const restoreName = node => { + const namespace = node.name.startsWith(":") + ? node.name.slice(1).split(":")[0] + : null; + const rawName = node.nameSpan ? node.nameSpan.toString() : node.name; + const hasExplicitNamespace = rawName.startsWith(`${namespace}:`); + const name = hasExplicitNamespace + ? rawName.slice(namespace.length + 1) + : rawName; + + node.name = name; + node.namespace = namespace; + node.hasExplicitNamespace = hasExplicitNamespace; + }; + const restoreNameAndValue = node => { if (node instanceof Element) { - node.name = node.nameSpan ? node.nameSpan.toString() : node.name; + restoreName(node); node.attrs.forEach(attr => { - attr.name = attr.nameSpan.toString(); + restoreName(attr); if (!attr.valueSpan) { attr.value = null; } else { @@ -79,20 +94,28 @@ function ngHtmlParser(input, canSelfClose) { }; const normalizeName = node => { if (node instanceof Element) { - node.name = lowerCaseIfFn( - node.name, - lowerCasedName => lowerCasedName in HTML_TAGS - ); + if ( + !node.namespace || + node.namespace === node.tagDefinition.implicitNamespacePrefix + ) { + node.name = lowerCaseIfFn( + node.name, + lowerCasedName => lowerCasedName in HTML_TAGS + ); + } + const CURRENT_HTML_ELEMENT_ATTRIBUTES = HTML_ELEMENT_ATTRIBUTES[node.name] || Object.create(null); node.attrs.forEach(attr => { - attr.name = lowerCaseIfFn( - attr.name, - lowerCasedAttrName => - node.name in HTML_ELEMENT_ATTRIBUTES && - (lowerCasedAttrName in HTML_ELEMENT_ATTRIBUTES["*"] || - lowerCasedAttrName in CURRENT_HTML_ELEMENT_ATTRIBUTES) - ); + if (!attr.namespace) { + attr.name = lowerCaseIfFn( + attr.name, + lowerCasedAttrName => + node.name in HTML_ELEMENT_ATTRIBUTES && + (lowerCasedAttrName in HTML_ELEMENT_ATTRIBUTES["*"] || + lowerCasedAttrName in CURRENT_HTML_ELEMENT_ATTRIBUTES) + ); + } }); } }; @@ -108,7 +131,15 @@ function ngHtmlParser(input, canSelfClose) { const addTagDefinition = node => { if (node instanceof Element) { - node.tagDefinition = getHtmlTagDefinition(node.name); + const tagDefinition = getHtmlTagDefinition(node.name); + if ( + !node.namespace || + node.namespace === tagDefinition.implicitNamespacePrefix + ) { + node.tagDefinition = tagDefinition; + } else { + node.tagDefinition = getHtmlTagDefinition(""); // the default one + } } }; @@ -117,8 +148,8 @@ function ngHtmlParser(input, canSelfClose) { visit(node) { addType(node); restoreNameAndValue(node); - normalizeName(node); addTagDefinition(node); + normalizeName(node); fixSourceSpan(node); } }(), diff --git a/src/language-html/preprocess.js b/src/language-html/preprocess.js index 664debd4dbc8..f2f6e1d948ae 100644 --- a/src/language-html/preprocess.js +++ b/src/language-html/preprocess.js @@ -366,11 +366,22 @@ function addShortcuts(ast /*, options */) { lastChild: { value: lastChild, enumerable: false } }); - if (node.attrs) { + if (node.type === "element") { + const rawNameGetter = function() { + return this.hasExplicitNamespace ? this.fullName : this.name; + }; + const fullNameGetter = function() { + return this.namespace ? this.namespace + ":" + this.name : this.name; + }; + Object.defineProperties(node, { + rawName: { get: rawNameGetter, enumerable: false }, + fullName: { get: fullNameGetter, enumerable: false } + }); node.attrs.forEach(attribute => - Object.defineProperty(attribute, "parent", { - value: node, - enumerable: false + Object.defineProperties(attribute, { + parent: { value: node, enumerable: false }, + rawName: { get: rawNameGetter, enumerable: false }, + fullName: { get: fullNameGetter, enumerable: false } }) ); } diff --git a/src/language-html/printer-html.js b/src/language-html/printer-html.js index e2a26c31348e..74d3d7f1a50d 100644 --- a/src/language-html/printer-html.js +++ b/src/language-html/printer-html.js @@ -29,7 +29,6 @@ const { getPrettierIgnoreAttributeCommentData, hasPrettierIgnore, inferScriptParser, - isElement, isPreLikeNode, isScriptLikeTag, normalizeParts, @@ -107,7 +106,7 @@ function embed(path, print, textToDoc, options) { ); if (embeddedAttributeValueDoc) { return concat([ - node.name, + node.rawName, '="', mapDoc( embeddedAttributeValueDoc, @@ -222,7 +221,7 @@ function genericPrint(path, options, print) { : node.lastChild.hasTrailingSpaces && node.lastChild.isTrailingSpaceSensitive ? line - : isElement(node) && + : node.type === "element" && isPreLikeNode(node) && node.lastChild.type === "text" && (node.lastChild.value.indexOf("\n") === -1 || @@ -321,7 +320,7 @@ function genericPrint(path, options, print) { } case "attribute": return concat([ - node.name, + node.rawName, node.value === null ? "" : concat([ @@ -514,9 +513,9 @@ function printOpeningTag(path, options, print) { const node = path.getValue(); const forceNotToBreakAttrContent = node.type === "element" && - node.name === "script" && + node.fullName === "script" && node.attrs.length === 1 && - node.attrs[0].name === "src" && + node.attrs[0].fullName === "src" && node.children.length === 0; return concat([ printOpeningTagStart(node), @@ -539,7 +538,8 @@ function printOpeningTag(path, options, print) { typeof ignoreAttributeData === "boolean" ? () => ignoreAttributeData : Array.isArray(ignoreAttributeData) - ? attr => ignoreAttributeData.indexOf(attr.name) !== -1 + ? attr => + ignoreAttributeData.indexOf(attr.rawName) !== -1 : () => false; return path.map(attrPath => { const attr = attrPath.getValue(); @@ -731,7 +731,7 @@ function printOpeningTagStartMarker(node) { case "docType": return " - new RegExp(patterns.join("|")).test(node.name); + new RegExp(patterns.join("|")).test(node.fullName); const getValue = () => node.value.replace(/"/g, '"').replace(/'/g, "'"); @@ -817,18 +817,18 @@ function printEmbeddedAttributeValue(node, originalTextToDoc, options) { originalTextToDoc(code, Object.assign({ __onHtmlBindingRoot }, opts)); if ( - node.name === "srcset" && - (node.parent.name === "img" || node.parent.name === "source") + node.fullName === "srcset" && + (node.parent.fullName === "img" || node.parent.fullName === "source") ) { return printExpand(printImgSrcset(getValue())); } if (options.parser === "vue") { - if (node.name === "v-for") { + if (node.fullName === "v-for") { return printVueFor(getValue(), textToDoc); } - if (node.name === "slot-scope") { + if (node.fullName === "slot-scope") { return printVueSlotScope(getValue(), textToDoc); } diff --git a/src/language-html/utils.js b/src/language-html/utils.js index 3bc34d85089a..59acd028bf53 100644 --- a/src/language-html/utils.js +++ b/src/language-html/utils.js @@ -80,24 +80,12 @@ function getPrettierIgnoreAttributeCommentData(value) { return match[1].split(/\s+/); } -function isElement(node, nameOrNames) { - if (node.type !== "element") { - return false; - } - - if (!nameOrNames) { - return true; - } - - if (typeof nameOrNames === "string") { - return node.name === nameOrNames; - } - - return nameOrNames.indexOf(node.name) !== -1; -} - function isScriptLikeTag(node) { - return isElement(node, ["script", "style"]); + return ( + node.type === "element" && + !node.namespace && + (node.name === "script" || node.name === "style") + ); } function isFrontMatterNode(node) { @@ -129,7 +117,11 @@ function isLeadingSpaceSensitiveNode(node, { prev, parent }) { return false; } - if (!node.prev && isElement(parent) && parent.tagDefinition.ignoreFirstLf) { + if ( + !node.prev && + parent.type === "element" && + parent.tagDefinition.ignoreFirstLf + ) { return false; } @@ -244,7 +236,7 @@ function forceNextEmptyLine(node) { function forceBreakContent(node) { return ( forceBreakChildren(node) || - (isElement(node) && + (node.type === "element" && node.children.length !== 0 && (["body", "template", "script", "style"].indexOf(node.name) !== -1 || node.children.some(child => hasNonTextChild(child)))) @@ -254,7 +246,7 @@ function forceBreakContent(node) { /** spaces between children */ function forceBreakChildren(node) { return ( - isElement(node) && + node.type === "element" && node.children.length !== 0 && (["html", "head", "ul", "ol", "select"].indexOf(node.name) !== -1 || (node.cssDisplay.startsWith("table") && node.cssDisplay !== "table-cell")) @@ -272,7 +264,7 @@ function preferHardlineAsLeadingSpaces(node) { function preferHardlineAsTrailingSpaces(node) { return ( preferHardlineAsSurroundingSpaces(node) || - isElement(node, "br") || + (node.type === "element" && node.fullName === "br") || isCustomElementWithSurroundingLineBreak(node) ); } @@ -282,7 +274,7 @@ function isCustomElementWithSurroundingLineBreak(node) { } function isCustomElement(node) { - return isElement(node) && node.name.includes("-"); + return node.type === "element" && !node.namespace && node.name.includes("-"); } function hasSurroundingLineBreak(node) { @@ -438,14 +430,19 @@ function getNodeCssStyleDisplay(node, prevNode, options) { return "block"; default: return ( - (isElement(node) && CSS_DISPLAY_TAGS[node.name]) || CSS_DISPLAY_DEFAULT + (node.type === "element" && + !node.namespace && + CSS_DISPLAY_TAGS[node.name]) || + CSS_DISPLAY_DEFAULT ); } } function getNodeCssStyleWhiteSpace(node) { return ( - (isElement(node) && CSS_WHITE_SPACE_TAGS[node.name]) || + (node.type === "element" && + !node.namespace && + CSS_WHITE_SPACE_TAGS[node.name]) || CSS_WHITE_SPACE_DEFAULT ); } @@ -603,7 +600,6 @@ module.exports = { identity, inferScriptParser, isDanglingSpaceSensitiveNode, - isElement, isFrontMatterNode, isIndentationSensitiveNode, isLeadingSpaceSensitiveNode, diff --git a/tests/html_tags/__snapshots__/jsfmt.spec.js.snap b/tests/html_tags/__snapshots__/jsfmt.spec.js.snap index cc358f1a88a8..f0e284a3668a 100644 --- a/tests/html_tags/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_tags/__snapshots__/jsfmt.spec.js.snap @@ -1644,7 +1644,7 @@ exports[`tags.html - html-verify 1`] = ` -foreign tag name should not be lower cased +foreign tag name should not be lower cased `; @@ -2089,7 +2089,7 @@ exports[`tags.html - html-verify 2`] = ` > foreign tag name @@ -2097,7 +2097,7 @@ exports[`tags.html - html-verify 2`] = ` not be lower - cased @@ -2303,7 +2303,7 @@ exports[`tags.html - html-verify 3`] = ` -foreign tag name should not be lower cased +foreign tag name should not be lower cased `; @@ -2552,7 +2552,7 @@ exports[`tags.html - html-verify 4`] = ` -foreign tag name should not be lower cased +foreign tag name should not be lower cased `; @@ -2851,7 +2851,7 @@ exports[`tags.html - html-verify 5`] = ` -foreign tag name should not be lower cased +foreign tag name should not be lower cased `; From 0a00ffc9c7a2f9fd4872e2c00298b3363fdd3449 Mon Sep 17 00:00:00 2001 From: Ika Date: Thu, 1 Nov 2018 21:52:21 +0800 Subject: [PATCH 155/177] test: add tests --- .../html_vue/__snapshots__/jsfmt.spec.js.snap | 100 ++++++++++++++++++ tests/html_vue/filter.vue | 7 ++ 2 files changed, 107 insertions(+) create mode 100644 tests/html_vue/filter.vue diff --git a/tests/html_vue/__snapshots__/jsfmt.spec.js.snap b/tests/html_vue/__snapshots__/jsfmt.spec.js.snap index 9462bc3af6eb..4a91256bae8c 100644 --- a/tests/html_vue/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_vue/__snapshots__/jsfmt.spec.js.snap @@ -466,6 +466,106 @@ export default { `; +exports[`filter.vue - vue-verify 1`] = ` + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + +`; + +exports[`filter.vue - vue-verify 2`] = ` + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + +`; + exports[`interpolations.vue - vue-verify 1`] = `
    Fuga magnam facilis. Voluptatem quaerat porro.{{ diff --git a/tests/html_vue/filter.vue b/tests/html_vue/filter.vue new file mode 100644 index 000000000000..3ab5f8ba7d2a --- /dev/null +++ b/tests/html_vue/filter.vue @@ -0,0 +1,7 @@ + + From c64f50f9d9cf3894ac6afb8034e9186a94d652a9 Mon Sep 17 00:00:00 2001 From: Ika Date: Thu, 1 Nov 2018 21:54:41 +0800 Subject: [PATCH 156/177] fix: `|` in vue expressions are considered vue filters --- src/common/internal-plugins.js | 4 ++ src/language-html/printer-html.js | 19 ++++++-- src/language-js/parser-babylon.js | 4 +- src/language-js/preprocess.js | 6 +-- src/language-js/printer-estree.js | 4 +- src/main/comments.js | 3 +- .../html_vue/__snapshots__/jsfmt.spec.js.snap | 48 +++++++++---------- website/static/worker.js | 4 ++ 8 files changed, 57 insertions(+), 35 deletions(-) diff --git a/src/common/internal-plugins.js b/src/common/internal-plugins.js index 7332a658a5fd..d071a32d79f5 100644 --- a/src/common/internal-plugins.js +++ b/src/common/internal-plugins.js @@ -29,6 +29,10 @@ module.exports = [ return eval("require")("../language-js/parser-babylon").parsers .__js_expression; }, + get __vue_expression() { + return eval("require")("../language-js/parser-babylon").parsers + .__vue_expression; + }, // JS - Flow get flow() { return eval("require")("../language-js/parser-flow").parsers.flow; diff --git a/src/language-html/printer-html.js b/src/language-html/printer-html.js index 74d3d7f1a50d..f0f6d90bd41e 100644 --- a/src/language-html/printer-html.js +++ b/src/language-html/printer-html.js @@ -80,7 +80,9 @@ function embed(path, print, textToDoc, options) { node.value, options.parser === "angular" ? { parser: "__ng_interpolation", trailingComma: "none" } - : { parser: "__js_expression" } + : options.parser === "vue" + ? { parser: "__vue_expression" } + : { parser: "__js_expression" } ) ]) ), @@ -840,11 +842,14 @@ function printEmbeddedAttributeValue(node, originalTextToDoc, options) { */ const vueEventBindingPatterns = ["^@", "^v-on:"]; /** - * :class="jsExpression" - * v-bind:id="jsExpression" + * :class="vueExpression" + * v-bind:id="vueExpression" + */ + const vueExpressionBindingPatterns = ["^:", "^v-bind:"]; + /** * v-if="jsExpression" */ - const vueExpressionBindingPatterns = ["^:", "^v-"]; + const jsExpressionBindingPatterns = ["^v-"]; if (isKeyMatched(vueEventBindingPatterns)) { // copied from https://github.com/vuejs/vue/blob/v2.5.17/src/compiler/codegen/events.js#L3-L4 @@ -860,6 +865,12 @@ function printEmbeddedAttributeValue(node, originalTextToDoc, options) { } if (isKeyMatched(vueExpressionBindingPatterns)) { + return printMaybeHug( + textToDoc(getValue(), { parser: "__vue_expression" }) + ); + } + + if (isKeyMatched(jsExpressionBindingPatterns)) { return printMaybeHug( textToDoc(getValue(), { parser: "__js_expression" }) ); diff --git a/src/language-js/parser-babylon.js b/src/language-js/parser-babylon.js index 01e204d0dd5a..aa26b2783d56 100644 --- a/src/language-js/parser-babylon.js +++ b/src/language-js/parser-babylon.js @@ -181,6 +181,8 @@ module.exports = { locFns ), /** @internal */ - __js_expression: babylon + __js_expression: babylon, + /** for vue filter */ + __vue_expression: babylon } }; diff --git a/src/language-js/preprocess.js b/src/language-js/preprocess.js index a44572ca1533..57489c7b7ae4 100644 --- a/src/language-js/preprocess.js +++ b/src/language-js/preprocess.js @@ -6,11 +6,9 @@ function preprocess(ast, options) { case "json5": case "json-stringify": case "__js_expression": + case "__vue_expression": return Object.assign({}, ast, { - type: - options.parser === "__js_expression" - ? "JsExpressionRoot" - : "JsonRoot", + type: options.parser.startsWith("__") ? "JsExpressionRoot" : "JsonRoot", node: ast, comments: [] }); diff --git a/src/language-js/printer-estree.js b/src/language-js/printer-estree.js index d3db9a49474f..eeae7da53301 100644 --- a/src/language-js/printer-estree.js +++ b/src/language-js/printer-estree.js @@ -5530,7 +5530,9 @@ function printBinaryishExpressions( const shouldInline = shouldInlineLogicalExpression(node); const lineBeforeOperator = - (node.operator === "|>" || node.type === "NGPipeExpression") && + (node.operator === "|>" || + node.type === "NGPipeExpression" || + (node.operator === "|" && options.parser === "__vue_expression")) && !hasLeadingOwnLineComment(options.originalText, node.right, options); const operator = node.type === "NGPipeExpression" ? "|" : node.operator; diff --git a/src/main/comments.js b/src/main/comments.js index 13ae9bab1726..e32146e37ffc 100644 --- a/src/main/comments.js +++ b/src/main/comments.js @@ -183,7 +183,8 @@ function attach(comments, ast, text, options) { if ( options.parser === "json" || options.parser === "json5" || - options.parser === "__js_expression" + options.parser === "__js_expression" || + options.parser === "__vue_expression" ) { if (locStart(comment) - locStart(ast) <= 0) { addLeadingComment(ast, comment); diff --git a/tests/html_vue/__snapshots__/jsfmt.spec.js.snap b/tests/html_vue/__snapshots__/jsfmt.spec.js.snap index 4a91256bae8c..cfb1254a31cb 100644 --- a/tests/html_vue/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_vue/__snapshots__/jsfmt.spec.js.snap @@ -479,28 +479,28 @@ exports[`filter.vue - vue-verify 1`] = `