From cd28c22dbec5ac549a3a13ed68b909013f00ac48 Mon Sep 17 00:00:00 2001 From: Ika Date: Wed, 5 Dec 2018 11:15:09 +0800 Subject: [PATCH] feat(html): smart quote for attributes (#5590) --- src/language-html/printer-html.js | 39 ++++++++++++------- src/language-html/utils.js | 18 ++++++++- .../__snapshots__/jsfmt.spec.js.snap | 24 +++++++++++- tests/html_attributes/smart-quotes.html | 5 +++ 4 files changed, 71 insertions(+), 15 deletions(-) create mode 100644 tests/html_attributes/smart-quotes.html diff --git a/src/language-html/printer-html.js b/src/language-html/printer-html.js index d0ba2f0b..1cab5dea 100644 --- a/src/language-html/printer-html.js +++ b/src/language-html/printer-html.js @@ -20,6 +20,7 @@ const { softline } = builders; const { + countChars, countParents, dedentString, forceBreakChildren, @@ -36,7 +37,8 @@ const { replaceDocNewlines, replaceNewlines, shouldNotPrintClosingTag, - shouldPreserveContent + shouldPreserveContent, + unescapeQuoteEntities } = require("./utils"); const preprocess = require("./preprocess"); const assert = require("assert"); @@ -325,19 +327,31 @@ function genericPrint(path, options, print) { printClosingTagSuffix(node, options) ]); } - case "attribute": + case "attribute": { + if (node.value === null) { + return node.rawName; + } + const value = unescapeQuoteEntities(node.value); + const singleQuoteCount = countChars(value, "'"); + const doubleQuoteCount = countChars(value, '"'); + const quote = singleQuoteCount < doubleQuoteCount ? "'" : '"'; return concat([ node.rawName, - node.value === null - ? "" - : concat([ - '="', - concat( - replaceNewlines(node.value.replace(/"/g, """), literalline) - ), - '"' - ]) + concat([ + "=", + quote, + concat( + replaceNewlines( + quote === '"' + ? value.replace(/"/g, """) + : value.replace(/'/g, "'"), + literalline + ) + ), + quote + ]) ]); + } case "yaml": case "toml": return node.raw; @@ -892,8 +906,7 @@ function getTextValueParts(node, value = node.value) { function printEmbeddedAttributeValue(node, originalTextToDoc, options) { const isKeyMatched = patterns => new RegExp(patterns.join("|")).test(node.fullName); - const getValue = () => - node.value.replace(/"/g, '"').replace(/'/g, "'"); + const getValue = () => unescapeQuoteEntities(node.value); let shouldHug = false; diff --git a/src/language-html/utils.js b/src/language-html/utils.js index 8435940d..1c9940e7 100644 --- a/src/language-html/utils.js +++ b/src/language-html/utils.js @@ -602,10 +602,25 @@ function shouldNotPrintClosingTag(node, options) { ); } +function countChars(text, char) { + let counter = 0; + for (let i = 0; i < text.length; i++) { + if (text[i] === char) { + counter++; + } + } + return counter; +} + +function unescapeQuoteEntities(text) { + return text.replace(/'/g, "'").replace(/"/g, '"'); +} + module.exports = { HTML_ELEMENT_ATTRIBUTES, HTML_TAGS, canHaveInterpolation, + countChars, countParents, dedentString, forceBreakChildren, @@ -633,5 +648,6 @@ module.exports = { replaceDocNewlines, replaceNewlines, shouldNotPrintClosingTag, - shouldPreserveContent + shouldPreserveContent, + unescapeQuoteEntities }; diff --git a/tests/html_attributes/__snapshots__/jsfmt.spec.js.snap b/tests/html_attributes/__snapshots__/jsfmt.spec.js.snap index 33f99bd5..1a114d12 100644 --- a/tests/html_attributes/__snapshots__/jsfmt.spec.js.snap +++ b/tests/html_attributes/__snapshots__/jsfmt.spec.js.snap @@ -277,7 +277,29 @@ printWidth: 80 John "ShotGun" Nelson =====================================output===================================== -John "ShotGun" Nelson +John "ShotGun" Nelson + +================================================================================ +`; + +exports[`smart-quotes.html 1`] = ` +====================================options===================================== +parsers: ["html"] +printWidth: 80 + | printWidth +=====================================input====================================== +
+ +=====================================output===================================== +
================================================================================ `; diff --git a/tests/html_attributes/smart-quotes.html b/tests/html_attributes/smart-quotes.html new file mode 100644 index 00000000..290541a6 --- /dev/null +++ b/tests/html_attributes/smart-quotes.html @@ -0,0 +1,5 @@ +