Skip to content

Reduce the amount of generated fallback css (batch 1) #835

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion experimental/css-has-pseudo/.tape.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import postcssTape from '../../packages/postcss-tape/dist/index.mjs';
import { postcssTape } from '../../packages/postcss-tape/dist/index.mjs';
import plugin from '@csstools/css-has-pseudo-experimental';

postcssTape(plugin)({
Expand Down
2 changes: 1 addition & 1 deletion experimental/postcss-nesting/.tape.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import postcssTape from '../../packages/postcss-tape/dist/index.mjs';
import { postcssTape } from '../../packages/postcss-tape/dist/index.mjs';
import plugin from '@csstools/postcss-nesting-experimental';

const mixinPluginRule = () => {
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions packages/postcss-tape/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ _Internal package_
See [.tape.mjs](https://github.com/csstools/postcss-plugins/blob/main/plugins/postcss-base-plugin/.tape.mjs) in the base plugin for a minimal example.

```js
import postcssTape from '../../packages/postcss-tape/dist/index.mjs';
import { postcssTape } from '../../packages/postcss-tape/dist/index.mjs';
import plugin from '@csstools/postcss-base-plugin';

postcssTape(plugin)({
Expand All @@ -30,7 +30,7 @@ Browse the source code and tests here or see tests in plugins for more usage det

## After node 20 is released do a find/replace to migrate fully to workspaces :

- `import postcssTape from '../../packages/postcss-tape/dist/index.mjs';`
- `import postcssTape from '@csstools/postcss-tape';`
- `import { postcssTape } from '../../packages/postcss-tape/dist/index.mjs';`
- `import { postcssTape } from '@csstools/postcss-tape';`

Then add `@csstools/postcss-tape` the each `package.json` as a dev dependency.
2 changes: 1 addition & 1 deletion packages/postcss-tape/dist/index.cjs
Original file line number Diff line number Diff line change
@@ -1 +1 @@
"use strict";var n=require("path"),e=require("fs"),o=require("assert"),s=require("postcss"),t=require("postcss-8.4"),r=require("postcss-html");function formatGitHubActionAnnotation(e,o="error",s={}){let t="::"+o;const r=Object.keys(s).map((e=>{let o=String(s[e]);return"file"===e&&process.env.GITHUB_WORKSPACE&&(o=n.relative(process.env.GITHUB_WORKSPACE,n.resolve(o))),`${e}=${t=o,t.replace(/\r/g,"%0D").replace(/\n/g,"%0A").replace(/]/g,"%5D").replace(/;/g,"%3B")}`;var t})).join(",");return r&&(t+=` ${r}`),`${t}::${i=e||"",i.replace(/\r/g,"%0D").replace(/\n/g,"%0A")}`;var i}const i="----------------------------------------";function formatCSSAssertError(n,e,o,s=!1){let t="";if(t+=`\n${n}\n\n`,e.message&&(t+=`message :\n ${e.message}\n\n`),e.options)try{t+=`options :\n${JSON.stringify(e.options,null,2)}\n\n`}catch(n){}return t+=`output changed :\n${prettyDiff(o.message)}\n`,s||(t+="\n"+i),t}function formatWarningsAssertError(n,e,o,s,t=!1){let r="";if(r+=`\n${n}\n\n`,e.message&&(r+=`message :\n ${e.message}\n\n`),e.options)try{r+=`options :\n${JSON.stringify(e.options,null,2)}\n\n`}catch(n){}return r+=`unexpected or missing warnings :\n+ actual ${o.length}\n- expected ${s}\n`,t||(o.forEach((n=>{r+=`\n[${n.plugin}]: ${n.text}`})),o.length&&(r+="\n"),r+="\n"+i),r}function prettyDiff(n){return n.replace(/[^\\](\\n)/gm,((n,e)=>n.replace(e," "))).replace(/(\\t)/gm,((n,e)=>n.replace(e," "))).replace(/\+$/gm,"").replace(/^Expected values to be strictly equal:\n/,"")}const noopPlugin=()=>({postcssPlugin:"noop-plugin",Rule(){}});function reduceInformationInCssSyntaxError(n){"CssSyntaxError"!==n.name||process.env.DEBUG||(delete n.source,n.input&&delete n.input.source,delete n.postcssNode)}noopPlugin.postcss=!0;const c=process.env.GITHUB_ACTIONS&&"true"===process.env.ENABLE_ANNOTATIONS_FOR_NODE&&"true"===process.env.ENABLE_ANNOTATIONS_FOR_OS;function postcssSyntax(n){return n.postcssSyntaxHTML?r():null}module.exports=function runner(r){let a=!1;{!0!==r.postcss&&(a=!0,c?console.log(formatGitHubActionAnnotation('postcss flag not set to "true" on exported plugin object',"error",{file:"./package.json",line:1,col:1})):console.error(`\npostcss flag not set to "true"\n\n${i}`));const n=r();n.postcssPlugin&&"string"==typeof n.postcssPlugin||(a=!0,c?console.log(formatGitHubActionAnnotation('plugin name not set via "postcssPlugin"',"error",{file:"./package.json",line:1,col:1})):console.error(`\nplugin name not set via "postcssPlugin"\n\n${i}`));const o=JSON.parse(e.readFileSync("./package.json").toString());o.keywords&&o.keywords.includes("postcss-plugin")||(a=!0,c?console.log(formatGitHubActionAnnotation('package.json does not include "postcss-plugin" keyword',"error",{file:"./package.json",line:1,col:1})):console.error(`\npackage.json does not include "postcss-plugin" keyword\n\n${i}`));const s=["css-has-pseudo","css-blank-pseudo","css-prefers-color-scheme","@csstools/css-has-pseudo-experimental"].includes(o.name);o.name.startsWith("postcss-")||o.name.startsWith("@csstools/postcss-")||s||(a=!0,c?console.log(formatGitHubActionAnnotation('plugin name in package.json does not start with "postcss-"',"error",{file:"./package.json",line:1,col:1})):console.error(`\nplugin name in package.json does not start with "postcss-"\n\n${i}`)),Object.keys(Object(o.dependencies)).includes("postcss")&&!("postcssTapeSelfTest"in r)&&(a=!0,c?console.log(formatGitHubActionAnnotation("postcss should only be a peer and/or dev dependency","error",{file:"./package.json",line:1,col:1})):console.error(`\npostcss should only be a peer and/or dev dependency\n\n${i}`))}return async l=>{const p=new Set;for(const u in l){const g=l[u];g.before&&await g.before();const f=n.join(".","test",u.split(":")[0]),d=n.join(".","test",u.replace(/:/g,"."));let m="css";g.postcssSyntaxHTML&&(m="html");const S=`${f}.${m}`;let A=`${d}.expect.${m}`,$=`${d}.result.${m}`;g.expect&&(A=n.join(".","test",g.expect)),g.result&&($=n.join(".","test",g.result));const y=g.plugins??[r(g.options)],w=await e.promises.readFile(S,"utf8");let h,b="";try{b=await e.promises.readFile(A,"utf8")}catch(e){a=!0,b=!1,c?console.log(formatGitHubActionAnnotation(`${u}\n\nmissing or broken "expect" file: "${n.parse(A).base}"`,"error",{file:S,line:1,col:1})):(p.add(u),console.error(`\n${u}\n\nmissing or broken "expect" file: "${n.parse(A).base}"\n\n${i}`))}let x=!1;try{h=await s(y).process(w,{from:S,to:$,map:{inline:!1,annotation:!1},syntax:postcssSyntax(g)})}catch(n){if(reduceInformationInCssSyntaxError(n),x=!0,g.exception&&g.exception.test(n.message))continue;throw n}!x&&g.exception&&(a=!0,c?console.log(formatGitHubActionAnnotation(`${u}\n\nexpected an exception but got none`,"error",{file:S,line:1,col:1})):(p.add(u),console.error(`\n${u}\n\nexpected an exception but got none\n\n${i}`)));const E=h.css.toString();if(await e.promises.writeFile($,E,"utf8"),process.env.REWRITE_EXPECTS&&e.promises.writeFile(A,E,"utf8"),!1!==b){try{o.strict.strictEqual(E,b)}catch(n){a=!0,c?console.log(formatGitHubActionAnnotation(formatCSSAssertError(u,g,n,!0),"error",{file:A,line:1,col:1})):(p.add(u),console.error(formatCSSAssertError(u,g,n)))}try{if(!g.postcssSyntaxHTML&&h.map.toJSON().sources.includes("<no source>"))throw new Error("Sourcemap is broken")}catch(n){a=!0;const e='\nThis is most likely a newly created PostCSS AST Node without a value for "source".\nsee :\n- https://github.com/postcss/postcss/blob/main/docs/guidelines/plugin.md#24-set-nodesource-for-new-nodes\n- https://postcss.org/api/#node-source';c?console.log(formatGitHubActionAnnotation(`${u}\n\nbroken source map: ${JSON.stringify(h.map.toJSON().sources)}\n${e}`,"error",{file:S,line:1,col:1})):(p.add(u),console.error(`\n${u}\n\nbroken source map: ${JSON.stringify(h.map.toJSON().sources)}\n${e}\n\n${i}`))}g.after&&await g.after();try{const n=await e.promises.readFile($,"utf8");if((await s([noopPlugin()]).process(n,{from:$,to:$,map:{inline:!1,annotation:!1},syntax:postcssSyntax(g)})).warnings().length)throw new Error("Unexpected warnings on second pass")}catch(n){a=!0,c?console.log(formatGitHubActionAnnotation(`${u}\n\nresult was not parsable with PostCSS.`,"error",{file:A,line:1,col:1})):(p.add(u),console.error(`\n${u}\n\nresult was not parsable with PostCSS.\n\n${i}`))}if(s([noopPlugin()]).version!==t([noopPlugin()]).version){const n=await t(y).process(w,{from:S,to:$,map:{inline:!1,annotation:!1}});try{o.strict.strictEqual(n.css.toString(),E)}catch(n){reduceInformationInCssSyntaxError(n),a=!0,c?console.log(formatGitHubActionAnnotation("testing older PostCSS:\n"+formatCSSAssertError(u,g,n,!0),"error",{file:A,line:1,col:1})):(p.add(u),console.error("testing older PostCSS:\n"+formatCSSAssertError(u,g,n)))}}try{(h.warnings().length||g.warnings)&&o.strict.strictEqual(h.warnings().length,g.warnings)}catch(n){a=!0,c?console.log(formatGitHubActionAnnotation(formatWarningsAssertError(u,g,h.warnings(),g.warnings,!0),"error",{file:A,line:1,col:1})):(p.add(u),console.error(formatWarningsAssertError(u,g,h.warnings(),g.warnings)))}}}if(p.size){console.error("\nunexpected failures:");for(const n of p.values())console.error(" - "+n)}a&&process.exit(1),console.warn("pass "+r().postcssPlugin)}};
"use strict";var e=require("path"),n=require("fs"),o=require("assert"),s=require("postcss"),t=require("postcss-8.4"),r=require("postcss-html");function formatGitHubActionAnnotation(n,o="error",s={}){let t="::"+o;const r=Object.keys(s).map((n=>{let o=String(s[n]);return"file"===n&&process.env.GITHUB_WORKSPACE&&(o=e.relative(process.env.GITHUB_WORKSPACE,e.resolve(o))),`${n}=${t=o,t.replace(/\r/g,"%0D").replace(/\n/g,"%0A").replace(/]/g,"%5D").replace(/;/g,"%3B")}`;var t})).join(",");return r&&(t+=` ${r}`),`${t}::${c=n||"",c.replace(/\r/g,"%0D").replace(/\n/g,"%0A")}`;var c}const c="----------------------------------------";function formatCSSAssertError(e,n,o,s=!1){let t="";if(t+=`\n${e}\n\n`,n.message&&(t+=`message :\n ${n.message}\n\n`),n.options)try{t+=`options :\n${JSON.stringify(n.options,null,2)}\n\n`}catch(e){}return t+=`output changed :\n${prettyDiff(o.message)}\n`,s||(t+="\n"+c),t}function formatWarningsAssertError(e,n,o,s,t=!1){let r="";if(r+=`\n${e}\n\n`,n.message&&(r+=`message :\n ${n.message}\n\n`),n.options)try{r+=`options :\n${JSON.stringify(n.options,null,2)}\n\n`}catch(e){}return r+=`unexpected or missing warnings :\n+ actual ${o.length}\n- expected ${s}\n`,t||(o.forEach((e=>{r+=`\n[${e.plugin}]: ${e.text}`})),o.length&&(r+="\n"),r+="\n"+c),r}function prettyDiff(e){return e.replace(/[^\\](\\n)/gm,((e,n)=>e.replace(n," "))).replace(/(\\t)/gm,((e,n)=>e.replace(n," "))).replace(/\+$/gm,"").replace(/^Expected values to be strictly equal:\n/,"")}const noopPlugin=()=>({postcssPlugin:"noop-plugin",Rule(){}});function reduceInformationInCssSyntaxError(e){"CssSyntaxError"!==e.name||process.env.DEBUG||(delete e.source,e.input&&delete e.input.source,delete e.postcssNode)}noopPlugin.postcss=!0;const i=process.env.GITHUB_ACTIONS&&"true"===process.env.ENABLE_ANNOTATIONS_FOR_NODE&&"true"===process.env.ENABLE_ANNOTATIONS_FOR_OS;function postcssSyntax(e){return e.postcssSyntaxHTML?r():null}const a={postcssPlugin:"declaration-cloner",Declaration(e){"to-clone"===e.prop&&e.cloneBefore({prop:"cloned"})}},l={postcssPlugin:"rule-cloner",prepare(){const e=new WeakSet;return{Rule(n){e.has(n)||"to-clone"===n.selector&&(e.add(n),n.cloneBefore({selector:"cloned"}))}}}};exports.declarationClonerPlugin=a,exports.postcssTape=function postcssTape(r){let a=!1;{!0!==r.postcss&&(a=!0,i?console.log(formatGitHubActionAnnotation('postcss flag not set to "true" on exported plugin object',"error",{file:"./package.json",line:1,col:1})):console.error(`\npostcss flag not set to "true"\n\n${c}`));const e=r();e.postcssPlugin&&"string"==typeof e.postcssPlugin||(a=!0,i?console.log(formatGitHubActionAnnotation('plugin name not set via "postcssPlugin"',"error",{file:"./package.json",line:1,col:1})):console.error(`\nplugin name not set via "postcssPlugin"\n\n${c}`));const o=JSON.parse(n.readFileSync("./package.json").toString());o.keywords&&o.keywords.includes("postcss-plugin")||(a=!0,i?console.log(formatGitHubActionAnnotation('package.json does not include "postcss-plugin" keyword',"error",{file:"./package.json",line:1,col:1})):console.error(`\npackage.json does not include "postcss-plugin" keyword\n\n${c}`));const s=["css-has-pseudo","css-blank-pseudo","css-prefers-color-scheme","@csstools/css-has-pseudo-experimental"].includes(o.name);o.name.startsWith("postcss-")||o.name.startsWith("@csstools/postcss-")||s||(a=!0,i?console.log(formatGitHubActionAnnotation('plugin name in package.json does not start with "postcss-"',"error",{file:"./package.json",line:1,col:1})):console.error(`\nplugin name in package.json does not start with "postcss-"\n\n${c}`)),Object.keys(Object(o.dependencies)).includes("postcss")&&!("postcssTapeSelfTest"in r)&&(a=!0,i?console.log(formatGitHubActionAnnotation("postcss should only be a peer and/or dev dependency","error",{file:"./package.json",line:1,col:1})):console.error(`\npostcss should only be a peer and/or dev dependency\n\n${c}`))}return async l=>{const p=new Set;for(const u in l){const g=l[u];g.before&&await g.before();const f=e.join(".","test",u.split(":")[0]),d=e.join(".","test",u.replace(/:/g,"."));let m="css";g.postcssSyntaxHTML&&(m="html");const S=`${f}.${m}`;let A=`${d}.expect.${m}`,$=`${d}.result.${m}`;g.expect&&(A=e.join(".","test",g.expect)),g.result&&($=e.join(".","test",g.result));const w=g.plugins??[r(g.options)],y=await n.promises.readFile(S,"utf8");let h,b="";try{b=await n.promises.readFile(A,"utf8")}catch(n){a=!0,b=!1,i?console.log(formatGitHubActionAnnotation(`${u}\n\nmissing or broken "expect" file: "${e.parse(A).base}"`,"error",{file:S,line:1,col:1})):(p.add(u),console.error(`\n${u}\n\nmissing or broken "expect" file: "${e.parse(A).base}"\n\n${c}`))}let x=!1;try{h=await s(w).process(y,{from:S,to:$,map:{inline:!1,annotation:!1},syntax:postcssSyntax(g)})}catch(e){if(reduceInformationInCssSyntaxError(e),x=!0,g.exception&&g.exception.test(e.message))continue;throw e}!x&&g.exception&&(a=!0,i?console.log(formatGitHubActionAnnotation(`${u}\n\nexpected an exception but got none`,"error",{file:S,line:1,col:1})):(p.add(u),console.error(`\n${u}\n\nexpected an exception but got none\n\n${c}`)));const E=h.css.toString();if(await n.promises.writeFile($,E,"utf8"),process.env.REWRITE_EXPECTS&&n.promises.writeFile(A,E,"utf8"),!1!==b){try{o.strict.strictEqual(E,b)}catch(e){a=!0,i?console.log(formatGitHubActionAnnotation(formatCSSAssertError(u,g,e,!0),"error",{file:A,line:1,col:1})):(p.add(u),console.error(formatCSSAssertError(u,g,e)))}try{if(!g.postcssSyntaxHTML&&h.map.toJSON().sources.includes("<no source>"))throw new Error("Sourcemap is broken")}catch(e){a=!0;const n='\nThis is most likely a newly created PostCSS AST Node without a value for "source".\nsee :\n- https://github.com/postcss/postcss/blob/main/docs/guidelines/plugin.md#24-set-nodesource-for-new-nodes\n- https://postcss.org/api/#node-source';i?console.log(formatGitHubActionAnnotation(`${u}\n\nbroken source map: ${JSON.stringify(h.map.toJSON().sources)}\n${n}`,"error",{file:S,line:1,col:1})):(p.add(u),console.error(`\n${u}\n\nbroken source map: ${JSON.stringify(h.map.toJSON().sources)}\n${n}\n\n${c}`))}g.after&&await g.after();try{const e=await n.promises.readFile($,"utf8");if((await s([noopPlugin()]).process(e,{from:$,to:$,map:{inline:!1,annotation:!1},syntax:postcssSyntax(g)})).warnings().length)throw new Error("Unexpected warnings on second pass")}catch(e){a=!0,i?console.log(formatGitHubActionAnnotation(`${u}\n\nresult was not parsable with PostCSS.`,"error",{file:A,line:1,col:1})):(p.add(u),console.error(`\n${u}\n\nresult was not parsable with PostCSS.\n\n${c}`))}if(s([noopPlugin()]).version!==t([noopPlugin()]).version){const e=await t(w).process(y,{from:S,to:$,map:{inline:!1,annotation:!1}});try{o.strict.strictEqual(e.css.toString(),E)}catch(e){reduceInformationInCssSyntaxError(e),a=!0,i?console.log(formatGitHubActionAnnotation("testing older PostCSS:\n"+formatCSSAssertError(u,g,e,!0),"error",{file:A,line:1,col:1})):(p.add(u),console.error("testing older PostCSS:\n"+formatCSSAssertError(u,g,e)))}}try{(h.warnings().length||g.warnings)&&o.strict.strictEqual(h.warnings().length,g.warnings)}catch(e){a=!0,i?console.log(formatGitHubActionAnnotation(formatWarningsAssertError(u,g,h.warnings(),g.warnings,!0),"error",{file:A,line:1,col:1})):(p.add(u),console.error(formatWarningsAssertError(u,g,h.warnings(),g.warnings)))}}}if(p.size){console.error("\nunexpected failures:");for(const e of p.values())console.error(" - "+e)}a&&process.exit(1),console.warn("pass "+r().postcssPlugin)}},exports.ruleClonerPlugin=l;
12 changes: 11 additions & 1 deletion packages/postcss-tape/dist/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,15 @@ type TestCaseOptions = {
after?: () => void | Promise<void>;
postcssSyntaxHTML?: boolean;
};
export default function runner(currentPlugin: PluginCreator<unknown>): (options: Record<string, TestCaseOptions>) => Promise<void>;
export declare function postcssTape(currentPlugin: PluginCreator<unknown>): (options: Record<string, TestCaseOptions>) => Promise<void>;
export declare const declarationClonerPlugin: {
postcssPlugin: string;
Declaration(decl: any): void;
};
export declare const ruleClonerPlugin: {
postcssPlugin: string;
prepare(): {
Rule(rule: any): void;
};
};
export {};
Loading