diff --git a/package-lock.json b/package-lock.json index 513d1b7d0..46495fcf4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3385,6 +3385,57 @@ "node": ">=6.0.0" } }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", + "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.1" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -3411,6 +3462,17 @@ "once": "^1.4.0" } }, + "node_modules/entities": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", + "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -4254,6 +4316,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/htmlparser2": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz", + "integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "entities": "^4.3.0" + } + }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -5329,6 +5409,25 @@ "resolved": "plugins/postcss-gap-properties", "link": true }, + "node_modules/postcss-html": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/postcss-html/-/postcss-html-1.5.0.tgz", + "integrity": "sha512-kCMRWJRHKicpA166kc2lAVUGxDZL324bkj/pVOb6RhjB0Z5Krl7mN0AsVkBhVIRZZirY0lyQXG38HCVaoKVNoA==", + "dependencies": { + "htmlparser2": "^8.0.0", + "js-tokens": "^8.0.0", + "postcss": "^8.4.0", + "postcss-safe-parser": "^6.0.0" + }, + "engines": { + "node": "^12 || >=14" + } + }, + "node_modules/postcss-html/node_modules/js-tokens": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-8.0.0.tgz", + "integrity": "sha512-PC7MzqInq9OqKyTXfIvQNcjMkODJYC8A17kAaQgeW79yfhqTWSOfjHYQ2mDDcwJ96Iibtwkfh0C7R/OvqPlgVA==" + }, "node_modules/postcss-image-set-function": { "resolved": "plugins/postcss-image-set-function", "link": true @@ -5431,6 +5530,21 @@ "postcss": "^8.0.3" } }, + "node_modules/postcss-safe-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz", + "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==", + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.3.3" + } + }, "node_modules/postcss-selector-not": { "resolved": "plugins/postcss-selector-not", "link": true @@ -6754,7 +6868,8 @@ "license": "CC0-1.0", "dependencies": { "postcss": "~8.4", - "postcss-8.4": "npm:postcss@~8.4" + "postcss-8.4": "npm:postcss@~8.4", + "postcss-html": "^1.5.0" }, "engines": { "node": "^14 || ^16 || >=18" @@ -8938,7 +9053,8 @@ "version": "file:packages/postcss-tape", "requires": { "postcss": "~8.4", - "postcss-8.4": "npm:postcss@~8.4" + "postcss-8.4": "npm:postcss@~8.4", + "postcss-html": "^1.5.0" } }, "@csstools/postcss-text-decoration-shorthand": { @@ -10032,6 +10148,39 @@ "esutils": "^2.0.2" } }, + "dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "requires": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + } + }, + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" + }, + "domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "requires": { + "domelementtype": "^2.3.0" + } + }, + "domutils": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", + "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", + "requires": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.1" + } + }, "eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -10058,6 +10207,11 @@ "once": "^1.4.0" } }, + "entities": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", + "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==" + }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -10676,6 +10830,17 @@ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "dev": true }, + "htmlparser2": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz", + "integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==", + "requires": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "entities": "^4.3.0" + } + }, "https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -11472,6 +11637,24 @@ "version": "file:plugins/postcss-gap-properties", "requires": {} }, + "postcss-html": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/postcss-html/-/postcss-html-1.5.0.tgz", + "integrity": "sha512-kCMRWJRHKicpA166kc2lAVUGxDZL324bkj/pVOb6RhjB0Z5Krl7mN0AsVkBhVIRZZirY0lyQXG38HCVaoKVNoA==", + "requires": { + "htmlparser2": "^8.0.0", + "js-tokens": "^8.0.0", + "postcss": "^8.4.0", + "postcss-safe-parser": "^6.0.0" + }, + "dependencies": { + "js-tokens": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-8.0.0.tgz", + "integrity": "sha512-PC7MzqInq9OqKyTXfIvQNcjMkODJYC8A17kAaQgeW79yfhqTWSOfjHYQ2mDDcwJ96Iibtwkfh0C7R/OvqPlgVA==" + } + } + }, "postcss-image-set-function": { "version": "file:plugins/postcss-image-set-function", "requires": { @@ -11609,6 +11792,12 @@ "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", "requires": {} }, + "postcss-safe-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz", + "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==", + "requires": {} + }, "postcss-selector-not": { "version": "file:plugins/postcss-selector-not", "requires": { diff --git a/packages/postcss-tape/package.json b/packages/postcss-tape/package.json index 85321f6eb..11cf10920 100644 --- a/packages/postcss-tape/package.json +++ b/packages/postcss-tape/package.json @@ -27,7 +27,8 @@ ], "dependencies": { "postcss": "~8.4", - "postcss-8.4": "npm:postcss@~8.4" + "postcss-8.4": "npm:postcss@~8.4", + "postcss-html": "^1.5.0" }, "scripts": { "build": "rollup -c ../../rollup/default.js", diff --git a/packages/postcss-tape/src/index.ts b/packages/postcss-tape/src/index.ts index 81ef3aa0b..e101ed20f 100644 --- a/packages/postcss-tape/src/index.ts +++ b/packages/postcss-tape/src/index.ts @@ -1,12 +1,14 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ - -import postcss from 'postcss'; -import postcssOldestSupported, { AcceptedPlugin } from 'postcss-8.4'; import path from 'path'; import fs, { promises as fsp } from 'fs'; import { strict as assert } from 'assert'; +import postcss from 'postcss'; import type { PluginCreator, Plugin, Result } from 'postcss'; + +import postcssOldestSupported, { AcceptedPlugin } from 'postcss-8.4'; + +import syntaxHTML from 'postcss-html'; + import { formatGitHubActionAnnotation } from './github-annotations'; import { dashesSeparator, formatCSSAssertError, formatWarningsAssertError } from './format-asserts'; import noopPlugin from './noop-plugin'; @@ -34,7 +36,18 @@ type TestCaseOptions = { // Do something before the test is run. before?: () => void, // Do something after the test is run. - after?: () => void|Promise, + after?: () => void | Promise, + + // Process the test cases with "postcss-html" as the syntax + postcssSyntaxHTML?: boolean, +} + +function postcssSyntax(options: TestCaseOptions) { + if (options.postcssSyntaxHTML) { + return syntaxHTML(); + } + + return null; } export default function runner(currentPlugin: PluginCreator) { @@ -145,9 +158,14 @@ export default function runner(currentPlugin: PluginCreator) { const testSourceFilePathWithoutExtension = path.join('.', 'test', testCaseLabel.split(':')[0]); const testFilePathWithoutExtension = path.join('.', 'test', testCaseLabel.replace(/:/g, '.')); - const testFilePath = `${testSourceFilePathWithoutExtension}.css`; - let expectFilePath = `${testFilePathWithoutExtension}.expect.css`; - let resultFilePath = `${testFilePathWithoutExtension}.result.css`; + let extension = 'css'; + if (testCaseOptions.postcssSyntaxHTML) { + extension = 'html'; + } + + const testFilePath = `${testSourceFilePathWithoutExtension}.${extension}`; + let expectFilePath = `${testFilePathWithoutExtension}.expect.${extension}`; + let resultFilePath = `${testFilePathWithoutExtension}.result.${extension}`; if (testCaseOptions.expect) { expectFilePath = path.join('.', 'test', testCaseOptions.expect); @@ -191,6 +209,7 @@ export default function runner(currentPlugin: PluginCreator) { inline: false, annotation: false, }, + syntax: postcssSyntax(testCaseOptions), }); } catch (err) { sawException = true; @@ -260,7 +279,10 @@ export default function runner(currentPlugin: PluginCreator) { // Assert result sourcemaps with recent PostCSS. { try { - if (result.map.toJSON().sources.includes('')) { + if ( + !testCaseOptions.postcssSyntaxHTML && + result.map.toJSON().sources.includes('') + ) { throw new Error('Sourcemap is broken'); } } catch (err) { @@ -296,6 +318,7 @@ export default function runner(currentPlugin: PluginCreator) { inline: false, annotation: false, }, + syntax: postcssSyntax(testCaseOptions), }); if (secondPassResult.warnings().length) { diff --git a/packages/postcss-tape/test-self/document.expect.code b/packages/postcss-tape/test-self/document.expect.code new file mode 100644 index 000000000..573541ac9 --- /dev/null +++ b/packages/postcss-tape/test-self/document.expect.code @@ -0,0 +1 @@ +0 diff --git a/packages/postcss-tape/test-self/document.expect.log b/packages/postcss-tape/test-self/document.expect.log new file mode 100644 index 000000000..1ce3d6ee0 --- /dev/null +++ b/packages/postcss-tape/test-self/document.expect.log @@ -0,0 +1 @@ +pass b-plugin diff --git a/packages/postcss-tape/test-self/test.sh b/packages/postcss-tape/test-self/test.sh index 15de75524..6020840d8 100644 --- a/packages/postcss-tape/test-self/test.sh +++ b/packages/postcss-tape/test-self/test.sh @@ -91,3 +91,16 @@ set -e git --no-pager diff --no-index --word-diff ./test-self/basic.break-css.expect.log ./test-self/basic.break-css.result.log git --no-pager diff --no-index --word-diff ./test-self/basic.break-css.expect.code ./test-self/basic.break-css.result.code # endregion:Basic with broken result CSS + +# region:Document +set +e + +echo "" > ./test-self/document.result.log + +node ./test/document.mjs > ./test-self/document.result.log 2>&1 +echo "$?" > ./test-self/document.result.code + +set -e +git --no-pager diff --no-index --word-diff ./test-self/document.expect.log ./test-self/document.result.log +git --no-pager diff --no-index --word-diff ./test-self/document.expect.code ./test-self/document.result.code +# endregion:Document diff --git a/packages/postcss-tape/test/_a-plugin.mjs b/packages/postcss-tape/test/_a-plugin.mjs index ac19ee8bd..f6d0ab997 100644 --- a/packages/postcss-tape/test/_a-plugin.mjs +++ b/packages/postcss-tape/test/_a-plugin.mjs @@ -4,25 +4,12 @@ const aPlugin = (options) => { replacement: '.baz', warn: false, break_sourcemap: false, - postcss8_3_api_call: false, ...options, }; return { postcssPlugin: 'a-plugin', Declaration(decl) { - if (options.postcss8_3_api_call && decl.value === '1') { - // This test might need updates in the future if we update PostCSS versions. - // Check the release logs of PostCSS and pick something else that is new to use. - // Disabling this test is also fine. - try { - decl.assign({ prop: 'order-b', value: '2' }); - } catch (error) { - // strip stacktrace to ensure the stderr output is the same across multiple machines - console.error('[TAPE DEBUG] ' + error.message); - } - } - if (options.break_sourcemap && decl.value === '1') { decl.replaceWith('order: 2'); } diff --git a/packages/postcss-tape/test/_b-plugin.mjs b/packages/postcss-tape/test/_b-plugin.mjs new file mode 100644 index 000000000..1d8d42a49 --- /dev/null +++ b/packages/postcss-tape/test/_b-plugin.mjs @@ -0,0 +1,21 @@ +const aPlugin = (options) => { + options = { + property: 'order', + replacement: 2, + ...options, + }; + + return { + postcssPlugin: 'b-plugin', + Declaration(decl) { + if (decl.prop === options.property && decl.value !== options.replacement) { + decl.value = options.replacement; + } + }, + }; +}; + +aPlugin.postcss = true; +aPlugin.postcssTapeSelfTest = true; + +export default aPlugin; diff --git a/packages/postcss-tape/test/document.expect.html b/packages/postcss-tape/test/document.expect.html new file mode 100644 index 000000000..322d0105d --- /dev/null +++ b/packages/postcss-tape/test/document.expect.html @@ -0,0 +1,17 @@ + + + + + + + Document + + + +
+ + diff --git a/packages/postcss-tape/test/document.html b/packages/postcss-tape/test/document.html new file mode 100644 index 000000000..1916455d4 --- /dev/null +++ b/packages/postcss-tape/test/document.html @@ -0,0 +1,17 @@ + + + + + + + Document + + + +
+ + diff --git a/packages/postcss-tape/test/document.mjs b/packages/postcss-tape/test/document.mjs new file mode 100644 index 000000000..7b1807a54 --- /dev/null +++ b/packages/postcss-tape/test/document.mjs @@ -0,0 +1,9 @@ +import postcssTape from '../dist/index.mjs'; +import plugin from './_b-plugin.mjs'; + +postcssTape(plugin)({ + 'document': { + postcssSyntaxHTML: true, + message: 'supports basic usage', + }, +}); diff --git a/packages/postcss-tape/test/document.result.html b/packages/postcss-tape/test/document.result.html new file mode 100644 index 000000000..322d0105d --- /dev/null +++ b/packages/postcss-tape/test/document.result.html @@ -0,0 +1,17 @@ + + + + + + + Document + + + +
+ + diff --git a/plugins/postcss-base-plugin/.tape.mjs b/plugins/postcss-base-plugin/.tape.mjs index a6514757d..c9f55d0d8 100644 --- a/plugins/postcss-base-plugin/.tape.mjs +++ b/plugins/postcss-base-plugin/.tape.mjs @@ -11,6 +11,10 @@ postcssTape(plugin)({ color: 'purple' } }, + document: { + postcssSyntaxHTML: true, + message: "supports document usage", + }, 'examples/example': { message: 'minimal example', }, diff --git a/plugins/postcss-base-plugin/test/document.expect.html b/plugins/postcss-base-plugin/test/document.expect.html new file mode 100644 index 000000000..65a369d89 --- /dev/null +++ b/plugins/postcss-base-plugin/test/document.expect.html @@ -0,0 +1,21 @@ + + + + + + + Document + + + +
+ + diff --git a/plugins/postcss-base-plugin/test/document.html b/plugins/postcss-base-plugin/test/document.html new file mode 100644 index 000000000..87d683cc9 --- /dev/null +++ b/plugins/postcss-base-plugin/test/document.html @@ -0,0 +1,21 @@ + + + + + + + Document + + + +
+ + diff --git a/plugins/postcss-base-plugin/test/document.result.html b/plugins/postcss-base-plugin/test/document.result.html new file mode 100644 index 000000000..65a369d89 --- /dev/null +++ b/plugins/postcss-base-plugin/test/document.result.html @@ -0,0 +1,21 @@ + + + + + + + Document + + + +
+ + diff --git a/rollup/configs/externals.js b/rollup/configs/externals.js index 6095a97f5..cb4aab798 100644 --- a/rollup/configs/externals.js +++ b/rollup/configs/externals.js @@ -67,6 +67,7 @@ export const externalsForPlugin = [ 'postcss', /^postcss-\d\.\d$/, /^postcss\/lib\/*/, + 'postcss-html', '@csstools/postcss-cascade-layers', '@csstools/postcss-color-function',