diff --git a/.eslintrc.json b/.eslintrc.json index d132ee3..26d041a 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -10,5 +10,18 @@ "ecmaVersion": "latest", "sourceType": "module" }, - "rules": {} + "rules": { + "n/no-unpublished-import": [ + "error", + { + "allowModules": ["diff"] + } + ], + "n/no-extraneous-import": [ + "error", + { + "allowModules": ["colors"] + } + ] + } } diff --git a/.gitignore b/.gitignore index 40b878d..9cf6fff 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -node_modules/ \ No newline at end of file +node_modules/ +.idea diff --git a/.nmvrc b/.nmvrc new file mode 100644 index 0000000..6f7f377 --- /dev/null +++ b/.nmvrc @@ -0,0 +1 @@ +v16 diff --git a/package-lock.json b/package-lock.json index 46d9bcd..a6d7206 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "css-tree": "^2.3.1" }, "devDependencies": { + "diff": "^5.1.0", "eslint": "^8.50.0", "eslint-plugin-import": "^2.28.1", "eslint-plugin-n": "^16.0.1", @@ -20,7 +21,7 @@ "prettier-plugin-packagejson": "^2.4.5" }, "engines": { - "node": "^14.13.0 || >=15.0.0" + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -540,12 +541,6 @@ "node": ">=10" } }, - "node_modules/builtins/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/bundle-name": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", @@ -792,6 +787,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/diff": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", + "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -1151,12 +1155,6 @@ "node": ">=10" } }, - "node_modules/eslint-plugin-n/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/eslint-plugin-unicorn": { "version": "48.0.1", "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-48.0.1.tgz", @@ -1228,12 +1226,6 @@ "node": ">=10" } }, - "node_modules/eslint-plugin-unicorn/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/eslint-scope": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", @@ -3759,6 +3751,12 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -4141,12 +4139,6 @@ "requires": { "lru-cache": "^6.0.0" } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true } } }, @@ -4319,6 +4311,12 @@ "integrity": "sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==", "dev": true }, + "diff": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", + "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", + "dev": true + }, "dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -4678,12 +4676,6 @@ "requires": { "lru-cache": "^6.0.0" } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true } } }, @@ -4733,12 +4725,6 @@ "requires": { "lru-cache": "^6.0.0" } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true } } }, @@ -6457,6 +6443,12 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index 4660bb3..87f71ab 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "type": "module", "main": "index.js", "scripts": { + "add-syntax": "node testing/add-syntax.js", "eslint": "eslint --fix .", "prettier-check": "prettier --check .", "prettier-format": "prettier --write .", @@ -15,6 +16,7 @@ "css-tree": "^2.3.1" }, "devDependencies": { + "diff": "^5.1.0", "eslint": "^8.50.0", "eslint-plugin-import": "^2.28.1", "eslint-plugin-n": "^16.0.1", @@ -23,6 +25,6 @@ "prettier-plugin-packagejson": "^2.4.5" }, "engines": { - "node": "^14.13.0 || >=15.0.0" + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" } } diff --git a/query-syntax.js b/query-syntax.js index 97e87e6..ccff22d 100644 --- a/query-syntax.js +++ b/query-syntax.js @@ -67,8 +67,18 @@ function addToConstructMap(map, list) { } } +function appendPropertyNewValues(list) { + for (const item of list) { + const property = properties.get(item.name); + if (property && item.newValues) { + property.value += ` | ${item.newValues}`; + } + } +} + function extractDataFromSpec(spec) { addToConstructMap(properties, spec.properties); + appendPropertyNewValues(spec.properties); addToConstructMap(atrules, spec.atrules); addToConstructMap(selectors, spec.selectors); @@ -111,9 +121,6 @@ function getTypesForSyntaxes(syntaxes, typesToOmit, constituents) { if (node.type === "Type" && !constituents.includes(node.name)) { constituents.push(node.name); } - /* if (node.type === "Function" && !constituents.includes(node.name)) { - constituents.push(node.name); - } */ } for (const syntax of syntaxes) { @@ -121,13 +128,16 @@ function getTypesForSyntaxes(syntaxes, typesToOmit, constituents) { const ast = definitionSyntax.parse(syntax); definitionSyntax.walk(ast, processNode); } catch (e) { - console.log("error parsing syntax: ", syntax); + console.log("error parsing syntax: ", syntax, e); } } } function getValue(name) { - return functions.get(`${name}()`) || types.get(name) || values.get(name); + if (name.includes("()")) { + return functions.get(name); + } + return types.get(name) || values.get(name); } /** @@ -174,7 +184,9 @@ export function getConstituentSyntaxes(itemSyntax, typesToOmit) { if (constituentSyntaxEntry && constituentSyntaxEntry.value) { constituentSyntaxes.push(constituentSyntaxEntry.value); } else if (constituentSyntaxEntry && constituentSyntaxEntry.values) { - constituentSyntaxes.push(constituentSyntaxes.values); + constituentSyntaxes.push( + ...constituentSyntaxEntry.values.map((v) => v.value) + ); } } } @@ -189,7 +201,8 @@ export function getConstituentSyntaxes(itemSyntax, typesToOmit) { syntaxes.push({ type: constituent, syntax: - valueEntry.value || valueEntry.values.map((v) => v.name).join(" | "), + valueEntry.value || + valueEntry.values.map((v) => `<${v.name}>`).join(" | "), }); } } @@ -210,7 +223,7 @@ export function getSyntax(name, type, typesToOmit) { switch (type) { case "property": - syntax = properties.get(name)?.value; + syntax = properties.has(name) ? properties.get(name).value : undefined; break; case "type": if (name.endsWith(">")) { diff --git a/testing/add-syntax.js b/testing/add-syntax.js new file mode 100644 index 0000000..ad746a1 --- /dev/null +++ b/testing/add-syntax.js @@ -0,0 +1,41 @@ +/* + This script updates syntax for given CSS feature and type in test data. +*/ + +/* eslint-disable-next-line n/no-unsupported-features/node-builtins */ +import fs from "node:fs/promises"; +import * as Utils from "./utils.js"; + +const helpMessage = + "Usage:\n\t" + + "npm run add-syntax '[feature-name]' '[feature-type]'\n\t" + + "node testing/add-syntax '[feature-name]' '[feature-type]'\n"; + +if (process.argv.length < 3) { + console.error(helpMessage); + /* eslint-disable-next-line no-process-exit, n/no-process-exit */ + process.exit(1); +} else if (process.argv[2] === "--help" || process.argv[2] === "-h") { + console.info(helpMessage); + /* eslint-disable-next-line no-process-exit, n/no-process-exit */ + process.exit(0); +} + +const name = process.argv[2]; +const type = process.argv[3]; +let syntax = Utils.getSyntaxForType(name, type); + +if (syntax) { + syntax = { + name: name, + type: type, + ...syntax, + }; + + await fs.writeFile( + `testing/data/${type}__${name}.json`, + JSON.stringify(syntax, undefined, " ") + ); +} + +console.log(`Added ${type}__${name}`); diff --git a/testing/check-syntaxes.js b/testing/check-syntaxes.js index cb1ef79..bbf9a90 100644 --- a/testing/check-syntaxes.js +++ b/testing/check-syntaxes.js @@ -1,5 +1,30 @@ +/* + This script tests all the syntaxes in test data against syntaxes returend by the current code. +*/ + +/* eslint-disable-next-line n/no-unsupported-features/node-builtins */ import fs from "node:fs/promises"; import * as Utils from "./utils.js"; +import * as Diff from "diff"; +/* eslint-disable-next-line no-unused-vars */ + +function logDiff(oldString, newString) { + const diff = Diff.diffLines(oldString, newString); + + for (const part of diff) { + let prefix = ""; + if (part.added) { + prefix = "+"; + } else if (part.removed) { + prefix = "-"; + } + let value = prefix + part.value.replaceAll("\n", "\n" + prefix); + value = value.replace(/[+-]$/gm, ""); + process.stdout.write(value); + } + + console.log("\n----"); +} const errors = []; let total = 0; @@ -20,6 +45,8 @@ for await (const filePath of Utils.walkSync("testing/data")) { ); if (oldSyntax !== newSyntax) { + console.warn(`${data.name} ${data.type}`); + logDiff(oldSyntax, newSyntax); errors.push(`${data.name} ${data.type}`); } } catch (e) { diff --git a/testing/data/@counter-style.json b/testing/data/@counter-style.json deleted file mode 100644 index 718c4e0..0000000 --- a/testing/data/@counter-style.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "@counter-style", - "type": "at-rule", - "syntax": "@counter-style { }", - "constituents": [] -} \ No newline at end of file diff --git a/testing/data/@counter-style__fallback.json b/testing/data/@counter-style__fallback.json deleted file mode 100644 index 5d0f649..0000000 --- a/testing/data/@counter-style__fallback.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "fallback", - "type": "at-rule-descriptor", - "syntax": "", - "constituents": [] -} \ No newline at end of file diff --git a/testing/data/@counter-style__speak-as.json b/testing/data/@counter-style__speak-as.json deleted file mode 100644 index 57aa11a..0000000 --- a/testing/data/@counter-style__speak-as.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "speak-as", - "type": "at-rule-descriptor", - "syntax": "auto | bullets | numbers | words | spell-out | ", - "constituents": [] -} \ No newline at end of file diff --git a/testing/data/@counter-style__system.json b/testing/data/@counter-style__system.json deleted file mode 100644 index 220b288..0000000 --- a/testing/data/@counter-style__system.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "system", - "type": "at-rule-descriptor", - "syntax": "cyclic | numeric | alphabetic | symbolic | additive | [fixed ?] | [ extends ]", - "constituents": [] -} \ No newline at end of file diff --git a/testing/data/@font-feature-values__font-display.json b/testing/data/@font-feature-values__font-display.json deleted file mode 100644 index a5e21d4..0000000 --- a/testing/data/@font-feature-values__font-display.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "font-display", - "type": "at-rule-descriptor", - "syntax": "auto | block | swap | fallback | optional", - "constituents": [] -} \ No newline at end of file diff --git a/testing/data/@font-palette-values__font-family.json b/testing/data/@font-palette-values__font-family.json deleted file mode 100644 index c8200a8..0000000 --- a/testing/data/@font-palette-values__font-family.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "font-family", - "type": "at-rule-descriptor", - "syntax": "", - "constituents": [] -} \ No newline at end of file diff --git a/testing/data/angle-percentage.json b/testing/data/angle-percentage.json deleted file mode 100644 index 7a61ac3..0000000 --- a/testing/data/angle-percentage.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "angle-percentage", - "type": "type", - "syntax": "[ | ]", - "constituents": [] -} \ No newline at end of file diff --git a/testing/data/animation-delay.json b/testing/data/animation-delay.json deleted file mode 100644 index c52b42f..0000000 --- a/testing/data/animation-delay.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "animation-delay", - "type": "property", - "syntax": "