diff --git a/package-lock.json b/package-lock.json
index 5032679..d1c184c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,6 +11,7 @@
"devDependencies": {
"@prettier/plugin-php": "^0.19.2",
"@prettier/plugin-pug": "^2.3.0",
+ "@shopify/prettier-plugin-liquid": "^0.4.0",
"@shufo/prettier-plugin-blade": "^1.8.0",
"@tailwindcss/line-clamp": "^0.3.0",
"@trivago/prettier-plugin-sort-imports": "^3.3.0",
@@ -1778,6 +1779,20 @@
"prettier": "^2.3.0"
}
},
+ "node_modules/@shopify/prettier-plugin-liquid": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@shopify/prettier-plugin-liquid/-/prettier-plugin-liquid-0.4.0.tgz",
+ "integrity": "sha512-pJDTud9alhtCF0ZNDKpREmjvrWSVL60ZJsd1BE1kZ+QWBuuj6MYiVth9edYsupFp3Xa29VqrZ0QaEzgIouOeSg==",
+ "dev": true,
+ "dependencies": {
+ "html-styles": "^1.0.0",
+ "line-column": "^1.0.2",
+ "ohm-js": "^16.3.0"
+ },
+ "peerDependencies": {
+ "prettier": "^2.0.0"
+ }
+ },
"node_modules/@shufo/prettier-plugin-blade": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/@shufo/prettier-plugin-blade/-/prettier-plugin-blade-1.8.0.tgz",
@@ -5490,6 +5505,12 @@
"integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
"dev": true
},
+ "node_modules/html-styles": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/html-styles/-/html-styles-1.0.0.tgz",
+ "integrity": "sha512-cDl5dcj73oI4Hy0DSUNh54CAwslNLJRCCoO+RNkVo+sBrjA/0+7E/xzvj3zH/GxbbBLGJhE0hBe1eg+0FINC6w==",
+ "dev": true
+ },
"node_modules/http-proxy-agent": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
@@ -9538,6 +9559,15 @@
"node": ">=0.10.0"
}
},
+ "node_modules/ohm-js": {
+ "version": "16.4.0",
+ "resolved": "https://registry.npmjs.org/ohm-js/-/ohm-js-16.4.0.tgz",
+ "integrity": "sha512-u1QI5h2w29I4838+/m32rzqfNNH1Qej9L6O1MTZZMx7bVOu09orc/TO0HRVeYh5jStieZ3INszM7oqbCdx2x7A==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.1"
+ }
+ },
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -13880,6 +13910,17 @@
"pug-lexer": "^5.0.0"
}
},
+ "@shopify/prettier-plugin-liquid": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@shopify/prettier-plugin-liquid/-/prettier-plugin-liquid-0.4.0.tgz",
+ "integrity": "sha512-pJDTud9alhtCF0ZNDKpREmjvrWSVL60ZJsd1BE1kZ+QWBuuj6MYiVth9edYsupFp3Xa29VqrZ0QaEzgIouOeSg==",
+ "dev": true,
+ "requires": {
+ "html-styles": "^1.0.0",
+ "line-column": "^1.0.2",
+ "ohm-js": "^16.3.0"
+ }
+ },
"@shufo/prettier-plugin-blade": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/@shufo/prettier-plugin-blade/-/prettier-plugin-blade-1.8.0.tgz",
@@ -16716,6 +16757,12 @@
"integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
"dev": true
},
+ "html-styles": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/html-styles/-/html-styles-1.0.0.tgz",
+ "integrity": "sha512-cDl5dcj73oI4Hy0DSUNh54CAwslNLJRCCoO+RNkVo+sBrjA/0+7E/xzvj3zH/GxbbBLGJhE0hBe1eg+0FINC6w==",
+ "dev": true
+ },
"http-proxy-agent": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
@@ -19688,6 +19735,12 @@
}
}
},
+ "ohm-js": {
+ "version": "16.4.0",
+ "resolved": "https://registry.npmjs.org/ohm-js/-/ohm-js-16.4.0.tgz",
+ "integrity": "sha512-u1QI5h2w29I4838+/m32rzqfNNH1Qej9L6O1MTZZMx7bVOu09orc/TO0HRVeYh5jStieZ3INszM7oqbCdx2x7A==",
+ "dev": true
+ },
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
diff --git a/package.json b/package.json
index 59bdf40..bf33a7b 100644
--- a/package.json
+++ b/package.json
@@ -28,6 +28,7 @@
"devDependencies": {
"@prettier/plugin-php": "^0.19.2",
"@prettier/plugin-pug": "^2.3.0",
+ "@shopify/prettier-plugin-liquid": "^0.4.0",
"@shufo/prettier-plugin-blade": "^1.8.0",
"@tailwindcss/line-clamp": "^0.3.0",
"@trivago/prettier-plugin-sort-imports": "^3.3.0",
diff --git a/src/index.js b/src/index.js
index 7ffd975..81e0b49 100644
--- a/src/index.js
+++ b/src/index.js
@@ -345,6 +345,63 @@ function transformGlimmer(ast, { env }) {
})
}
+function transformLiquid(ast, { env }) {
+ visit(ast, {
+ HtmlElement(node) {
+ node.source = ''
+ console.log({node})
+ },
+
+ AttrSingleQuoted(node, _parent, _key, _index, meta) {
+ if (node.name !== "class") {
+ return;
+ }
+
+ meta.sortTextNodes = true;
+ meta.sourceNode = node;
+ },
+
+ AttrDoubleQuoted(node, _parent, _key, _index, meta) {
+ if (node.name !== "class") {
+ return;
+ }
+
+ meta.sortTextNodes = true;
+
+ // With Liquid Script it uses the "source" of certain nodes as the "source of truth"
+ // We must modify that node's source to get the desired output
+ // Even if we modify the AST it will be ignored
+ meta.sourceNode = node;
+ },
+
+ TextNode(node, _parent, _key, _index, meta) {
+ if (!meta.sortTextNodes) {
+ return;
+ }
+
+ node.value = sortClasses(node.value, { env });
+
+ // This feels hacky but it's necessary
+ node.source = node.source.slice(0, node.position.start) + node.value + node.source.slice(node.position.end);
+ meta.sourceNode.source = node.source;
+ },
+
+ String(node, _parent, _key, _index, meta) {
+ if (!meta.sortTextNodes) {
+ return;
+ }
+
+ node.value = sortClasses(node.value, { env });
+
+ // This feels hacky but it's necessary
+ // String position includes the quotes even if the value doesn't
+ // Hence the +1 and -1 when slicing
+ node.source = node.source.slice(0, node.position.start+1) + node.value + node.source.slice(node.position.end-1);
+ meta.sourceNode.source = node.source;
+ },
+ });
+}
+
function sortStringLiteral(node, { env }) {
let result = sortClasses(node.value, { env })
let didChange = result !== node.value
@@ -500,6 +557,9 @@ export const parsers = {
...base.parsers.php ? { php: createParser('php', transformPHP) } : {},
...base.parsers.melody ? { melody: createParser('melody', transformMelody) } : {},
...base.parsers.pug ? { pug: createParser('pug', transformPug) } : {},
+ ...(base.parsers['liquid-html']
+ ? { 'liquid-html': createParser("liquid-html", transformLiquid) }
+ : {}),
// ...base.parsers.blade ? { blade: createParser('blade', transformBlade) } : {},
}
@@ -733,6 +793,7 @@ function getBasePlugins() {
let php = loadIfExists('@prettier/plugin-php')
let melody = loadIfExists('prettier-plugin-twig-melody')
let pug = loadIfExists('@prettier/plugin-pug')
+ let liquid = loadIfExists('@shopify/prettier-plugin-liquid')
// let blade = loadIfExists('@shufo/prettier-plugin-blade')
return {
@@ -759,6 +820,7 @@ function getBasePlugins() {
...(php?.parsers ?? {}),
...(melody?.parsers ?? {}),
...(pug?.parsers ?? {}),
+ ...(liquid?.parsers ?? {}),
// ...(blade?.parsers ?? {}),
},
printers: {
@@ -782,6 +844,7 @@ function getCompatibleParser(parserFormat, options) {
'prettier-plugin-organize-imports',
'@prettier/plugin-php',
'@prettier/plugin-pug',
+ '@shopify/prettier-plugin-liquid',
'@shufo/prettier-plugin-blade',
'prettier-plugin-css-order',
'prettier-plugin-import-sort',
diff --git a/tests/plugins.test.js b/tests/plugins.test.js
index 48dcc56..576b26b 100644
--- a/tests/plugins.test.js
+++ b/tests/plugins.test.js
@@ -208,6 +208,23 @@ let tests = [
],
}
},
+ {
+ plugins: [
+ '@shopify/prettier-plugin-liquid',
+ ],
+ tests: {
+ 'liquid-html': [
+ [
+ `Example`,
+ `Example`,
+ ],
+ [
+ `{% if state == true %}\n Example\n{% endif %}`,
+ `{% if state == true -%}\n Example\n{%- endif %}`,
+ ],
+ ],
+ }
+ },
]
for (const group of tests) {