@empjs/plugin-lightningcss 1.0.5 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,6 +1 @@
1
- import empLightningcssPlugin from './plugin.js';
2
- import postcss from './postcss-config.js';
3
- import { composeVisitors } from 'lightningcss';
4
- //
5
- export default empLightningcssPlugin;
6
- export { postcss, composeVisitors };
1
+ var k=Object.defineProperty;var w=(r,e)=>()=>(r&&(e=r(r=0)),e);var P=(r,e)=>{for(var t in e)k(r,t,{get:e[t],enumerable:!0})};var d={};P(d,{LightningCSSMinifyPlugin:()=>c,default:()=>O});import{transform as A}from"lightningcss";import{Buffer as _}from"node:buffer";var p,T,c,O,g=w(()=>{"use strict";p="lightningcss-minify-plugin",T=/\.css(?:\?.*)?$/i,c=class{options;transform;constructor(e={}){let{implementation:t}=e;if(t&&typeof t.transform!="function")throw new TypeError(`[${p}]: implementation.transform must be an 'lightningcss' transform function. Received ${typeof t.transform}`);this.transform=t?.transform??A,this.options=e}apply(e){e.hooks.compilation.tap(p,t=>{t.hooks.processAssets.tapPromise({name:p,stage:t?.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE},async()=>await this.transformAssets(t)),t.hooks.statsPrinter.tap(p,s=>{s.hooks.print.for("asset.info.minimized").tap(p,(n,{green:o,formatFlag:i})=>n&&o&&i?o(i("minimized")):"")})})}async transformAssets(e){let{options:{devtool:t},webpack:{sources:{SourceMapSource:s,RawSource:n}}}=e.compiler,o=this.options.sourceMap===void 0?t&&t.includes("source-map"):this.options.sourceMap,{targets:i,...m}=this.options,l=e.getAssets().filter(a=>!a.info.minimized&&T.test(a.name));await Promise.all(l.map(async a=>{let{source:u,map:S}=a.source.sourceAndMap(),V=u.toString(),C=typeof u=="string"?_.from(u):u,y=this.transform({filename:a.name,code:C,minify:!0,sourceMap:o,...m}),v=y.code.toString();e.updateAsset(a.name,o?new s(v,a.name,JSON.parse(y.map.toString()),V,S,!0):new n(v),{...a.info,minimized:!0})}))}},O=c});import{browserslistToTargets as E}from"lightningcss";import M from"browserslist";var L=async(r,e)=>{if(e?.transform===!1)return;let{importResolve:t,chain:s}=r,n=["sass","less","css"],o=e?.transform||{},m={targets:E(M(">= 0.25%")),...o};for(let l of n){let a=s.module.rule(l),u=a.use("lightningcss").loader(t("./loader.cjs",import.meta.url)).options(m);u.before("postcss"),["sass","less"].includes(l)?u.before(`${l}Loader`):u.before("postcss"),a.uses.delete("postcss")}},z=async(r,e)=>{if(e?.minify===!1)return;let{chain:t}=r,s=e?.minify||{},{LightningCSSMinifyPlugin:n}=await Promise.resolve().then(()=>(g(),d));t.optimization.minimizer("minCss").use(n,[s])},j=r=>({name:"@empjs/plugin-lightningcss",async rsConfig(e){await Promise.all([L(e,r),z(e,r)])}}),h=j;var G={designWidth:320,minPixelValue:1,excludeSelectors:[]};function x(r){return t=>{if(!t.name)return!1;for(let s of r)if(t.type===s.type&&(typeof s.name=="string"&&s.name===t.name||typeof s.name=="object"&&s.name.test(t.name)))return!0;return!1}}function b(r={}){let e=Object.assign(G,r),t=x(e.excludeSelectors),s=!1;return{Selector(n){s=!1;for(let o of n)t(o)&&(s=!0)},Length(n){if(n.unit==="px"&&!s&&n.value>e.minPixelValue)return{unit:"vw",value:n.value/e.designWidth*100}}}}function R(r={}){let e=Object.assign({rootValue:16,excludeSelectors:[],minPixelValue:1},r),t=x(e.excludeSelectors),s=!1;return{Selector(n){s=!1;for(let o of n)t(o)&&(s=!0)},Length(n){if(n.unit==="px"&&!s&&n.value>e.minPixelValue)return{unit:"rem",value:n.value/e.rootValue}}}}import{composeVisitors as q}from"lightningcss";var f=class{px_to_rem(e){return R(e)}px_to_viewport(e){return q([b(e)])}apply(e){return e=e||new Map,{Rule:{style(t){for(let s of t.value.selectors)if(s.length===1&&s[0].type==="type"&&s[0].name.startsWith("--"))return e.set(s[0].name,t.value.declarations),{type:"ignored",value:null};return t.value.rules=t.value.rules.filter(s=>{if(s.type==="unknown"&&s.value.name==="apply"){for(let n of s.value.prelude)if(n.type==="dashed-ident"&&e.has(n.value)){let o=e.get(n.value),i=t.value.declarations;i.declarations.push(...o.declarations),i.importantDeclarations.push(...o.importantDeclarations)}return!1}return!0}),t}}}}selector_prefix(){return{Selector(e){return[{type:"class",name:"prefix"},{type:"combinator",value:"descendant"},...e]}}}static_vars(e){return e=e||new Map,{Rule:{unknown(t){return e.set(t.name,t.prelude),[]}},Token:{"at-keyword"(t){if(e.has(t.value))return e.get(t.value)}}}}url(e){return{Url(t){return t.url=e+t.url,t}}}specific_environment_variables(e){let t={};for(let s in e)t[s]=()=>e[s];return{EnvironmentVariable:t}}env_function(e){return{EnvironmentVariable(t){if(t.name.type==="custom")return e[t.name.ident]}}}design_tokens(e){return{Function:{"design-token"(t){if(t.arguments.length===1&&t.arguments[0].type==="token"&&t.arguments[0].value.type==="string")return e[t.arguments[0].value.value]}}}}custom_units(){return{Token:{dimension(e){if(e.unit.startsWith("--"))return{type:"function",value:{name:"calc",arguments:[{type:"token",value:{type:"number",value:e.value}},{type:"token",value:{type:"delim",value:"*"}},{type:"var",value:{name:{ident:e.unit}}}]}}}}}}property_lookup(){return{Rule:{style(e){let t=new Map;for(let s of e.value.declarations.declarations){let n=s.property;s.property==="unparsed"&&(n=s.value.propertyId.property),t.set(n,s)}return e.value.declarations.declarations=e.value.declarations.declarations.map(s=>{if(s.property==="unparsed"&&s.value.value.length===1){let n=s.value.value[0];if(n.type==="token"&&n.value.type==="at-keyword"&&t.has(n.value.value)){let o=t.get(n.value.value);return{property:s.value.propertyId.property,value:o.value}}}return s}),e}}}}focus_visible(){return{Rule:{style(e){let t=null;for(let s of e.value.selectors)for(let[n,o]of s.entries())o.type==="pseudo-class"&&o.kind==="focus-visible"&&(t==null&&(t=[...e.value.selectors.map(i=>[...i])]),s[n]={type:"class",name:"focus-visible"});if(t)return[e,{type:"style",value:{...e.value,selectors:t}}]}}}}dark_theme_class(){return{Rule:{media(e){let t=e.value.query.mediaQueries[0];if(t.condition?.type==="feature"&&t.condition.value.type==="plain"&&t.condition.value.name==="prefers-color-scheme"&&t.condition.value.value.value==="dark"){let s=[e];for(let n of e.value.rules)if(n.type==="style"){let o=[];for(let i of n.value.selectors)o.push([{type:"type",name:"html"},{type:"attribute",name:"theme",operation:{operator:"equal",value:"dark"}},{type:"combinator",value:"descendant"},...i]),i.unshift({type:"type",name:"html"},{type:"pseudo-class",kind:"not",selectors:[[{type:"attribute",name:"theme",operation:{operator:"equal",value:"light"}}]]},{type:"combinator",value:"descendant"});s.push({type:"style",value:{...n.value,selectors:o}})}return s}}}}}fix_100vh(){return{Rule:{style(e){let t;for(let s of e.value.declarations.declarations)s.property==="height"&&s.value.type==="length-percentage"&&s.value.value.type==="dimension"&&s.value.value.value.unit==="vh"&&s.value.value.value.value===100&&(t||(t=structuredClone(e),t.value.declarations.declarations=[]),t.value.declarations.declarations.push({...s,value:{type:"stretch",vendorPrefix:["webkit"]}}));if(t)return[e,{type:"supports",value:{condition:{type:"declaration",propertyId:{property:"-webkit-touch-callout"},value:"none"},loc:e.value.loc,rules:[t]}}]}}}}logical_transforms(){return{Rule:{style(e){let t;for(let s of e.value.declarations.declarations)if(s.property==="transform"){let n=s.value.map(o=>{if(o.type!=="translateX")return o;t||(t=structuredClone(e),t.value.declarations.declarations=[]);let i;switch(o.value.type){case"dimension":i={type:"dimension",value:{unit:o.value.value.unit,value:-o.value.value.value}};break;case"percentage":i={type:"percentage",value:-o.value.value};break;case"calc":i={type:"calc",value:{type:"product",value:[-1,o.value.value]}};break}return{type:"translateX",value:i}});t&&(t.value.selectors.at(-1).push({type:"pseudo-class",kind:"dir",direction:"rtl"}),t.value.declarations.declarations.push({...s,value:n}))}if(t)return[e,t]}}}}hover_media_query(){return{Rule:{media(e){let t=e.value.query.mediaQueries;if(t.length===1&&t[0].condition&&t[0].condition.type==="feature"&&t[0].condition.value.type==="boolean"&&t[0].condition.value.name==="hover"){for(let s of e.value.rules)if(s.type==="style")for(let n of s.value.selectors)n.unshift({type:"class",name:"hoverable"},{type:"combinator",value:"descendant"});return e.value.rules}}}}}momentum_scrolling(e){return{Declaration:{overflow:e,"overflow-x":e,"overflow-y":e}}}size(){return{Declaration:{custom:{size(e){if(e.value[0].type==="length"){let t={type:"length-percentage",value:{type:"dimension",value:e.value[0].value}};return[{property:"width",value:t},{property:"height",value:t}]}}}}}}},W=new f;import{composeVisitors as ee}from"lightningcss";var te=h;export{ee as composeVisitors,te as default,W as postcss};
package/dist/loader.cjs CHANGED
@@ -1,57 +1 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/loader.ts
21
- var loader_exports = {};
22
- __export(loader_exports, {
23
- default: () => loader_default
24
- });
25
- module.exports = __toCommonJS(loader_exports);
26
- var import_lightningcss = require("lightningcss");
27
- var import_node_buffer = require("node:buffer");
28
- var LOADER_NAME = "lightningcss-loader";
29
- async function LightningCSSLoader(source, prevMap) {
30
- const done = this.async();
31
- const options = this.getOptions();
32
- const { implementation, targets, ...opts } = options;
33
- if (implementation && typeof implementation.transform !== "function") {
34
- done(
35
- new TypeError(
36
- `[${LOADER_NAME}]: options.implementation.transform must be an 'lightningcss' transform function. Received ${typeof implementation.transform}`
37
- )
38
- );
39
- return;
40
- }
41
- const transform = implementation?.transform ?? import_lightningcss.transform;
42
- try {
43
- const { code, map } = transform({
44
- filename: this.resourcePath,
45
- code: import_node_buffer.Buffer.from(source),
46
- sourceMap: this.sourceMap,
47
- targets,
48
- inputSourceMap: this.sourceMap && prevMap ? JSON.stringify(prevMap) : void 0,
49
- ...opts
50
- });
51
- const codeAsString = code.toString();
52
- done(null, codeAsString, map && JSON.parse(map.toString()));
53
- } catch (error) {
54
- done(error);
55
- }
56
- }
57
- var loader_default = LightningCSSLoader;
1
+ "use strict";var m=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var S=Object.getOwnPropertyNames;var y=Object.prototype.hasOwnProperty;var l=(n,t)=>{for(var r in t)m(n,r,{get:t[r],enumerable:!0})},h=(n,t,r,e)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of S(t))!y.call(n,o)&&o!==r&&m(n,o,{get:()=>t[o],enumerable:!(e=d(t,o))||e.enumerable});return n};var L=n=>h(m({},"__esModule",{value:!0}),n);var v={};l(v,{default:()=>R});module.exports=L(v);var s=require("lightningcss"),c=require("node:buffer"),O="lightningcss-loader";async function C(n,t){let r=this.async(),e=this.getOptions(),{implementation:o,targets:f,...i}=e;if(o&&typeof o.transform!="function"){r(new TypeError(`[${O}]: options.implementation.transform must be an 'lightningcss' transform function. Received ${typeof o.transform}`));return}let u=o?.transform??s.transform;i.visitor&&(i.visitor=(0,s.composeVisitors)([i.visitor]));try{let{code:a,map:p}=u({filename:this.resourcePath,code:c.Buffer.from(n),sourceMap:this.sourceMap,targets:f,inputSourceMap:this.sourceMap&&t?JSON.stringify(t):void 0,errorRecovery:!0,nonStandard:{deepSelectorCombinator:!0},...i}),g=a.toString();r(null,g,p&&JSON.parse(p.toString()))}catch(a){r(a)}}var R=C;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@empjs/plugin-lightningcss",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "emp v3 lightningcss",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
package/dist/loader.js DELETED
@@ -1,31 +0,0 @@
1
- import { transform as _transform } from 'lightningcss';
2
- import { Buffer } from 'node:buffer';
3
- const LOADER_NAME = 'lightningcss-loader';
4
- async function LightningCSSLoader(source, prevMap) {
5
- const done = this.async();
6
- const options = this.getOptions();
7
- // console.log('options', options)
8
- const { implementation, targets, ...opts } = options;
9
- if (implementation && typeof implementation.transform !== 'function') {
10
- done(new TypeError(`[${LOADER_NAME}]: options.implementation.transform must be an 'lightningcss' transform function. Received ${typeof implementation.transform}`));
11
- return;
12
- }
13
- const transform = implementation?.transform ?? _transform;
14
- // console.log(this.resourcePath, source)
15
- try {
16
- const { code, map } = transform({
17
- filename: this.resourcePath,
18
- code: Buffer.from(source),
19
- sourceMap: this.sourceMap,
20
- targets,
21
- inputSourceMap: this.sourceMap && prevMap ? JSON.stringify(prevMap) : undefined,
22
- ...opts,
23
- });
24
- const codeAsString = code.toString();
25
- done(null, codeAsString, map && JSON.parse(map.toString()));
26
- }
27
- catch (error) {
28
- done(error);
29
- }
30
- }
31
- export default LightningCSSLoader;
package/dist/minimizer.js DELETED
@@ -1,62 +0,0 @@
1
- import { transform as _transform } from 'lightningcss';
2
- import { Buffer } from 'node:buffer';
3
- const PLUGIN_NAME = 'lightningcss-minify-plugin';
4
- //
5
- const CSS_REGEX = /\.css(?:\?.*)?$/i;
6
- export class LightningCSSMinifyPlugin {
7
- options;
8
- transform;
9
- constructor(opts = {}) {
10
- const { implementation } = opts;
11
- if (implementation && typeof implementation.transform !== 'function') {
12
- throw new TypeError(`[${PLUGIN_NAME}]: implementation.transform must be an 'lightningcss' transform function. Received ${typeof implementation.transform}`);
13
- }
14
- this.transform = implementation?.transform ?? _transform;
15
- this.options = opts;
16
- }
17
- apply(compiler) {
18
- compiler.hooks.compilation.tap(PLUGIN_NAME, compilation => {
19
- compilation.hooks.processAssets.tapPromise({
20
- name: PLUGIN_NAME,
21
- stage: compilation?.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE,
22
- }, async () => await this.transformAssets(compilation));
23
- compilation.hooks.statsPrinter.tap(PLUGIN_NAME, statsPrinter => {
24
- statsPrinter.hooks.print
25
- .for('asset.info.minimized')
26
- .tap(PLUGIN_NAME, (minimized, { green, formatFlag }) => minimized && green && formatFlag ? green(formatFlag('minimized')) : '');
27
- });
28
- });
29
- }
30
- async transformAssets(compilation) {
31
- const { options: { devtool }, webpack: { sources: { SourceMapSource, RawSource }, }, } = compilation.compiler;
32
- const sourcemap = this.options.sourceMap === undefined
33
- ? (devtool && devtool.includes('source-map'))
34
- : this.options.sourceMap;
35
- const { targets: userTargets, ...transformOptions } = this.options;
36
- const assets = compilation.getAssets().filter(asset =>
37
- // Filter out already minimized
38
- !asset.info.minimized &&
39
- // Filter out by file type
40
- CSS_REGEX.test(asset.name));
41
- await Promise.all(assets.map(async (asset) => {
42
- const { source, map } = asset.source.sourceAndMap();
43
- const sourceAsString = source.toString();
44
- const code = typeof source === 'string' ? Buffer.from(source) : source;
45
- const result = this.transform({
46
- filename: asset.name,
47
- code,
48
- minify: true,
49
- sourceMap: sourcemap,
50
- ...transformOptions,
51
- });
52
- const codeString = result.code.toString();
53
- compilation.updateAsset(asset.name, sourcemap
54
- ? new SourceMapSource(codeString, asset.name, JSON.parse(result.map.toString()), sourceAsString, map, true)
55
- : new RawSource(codeString), {
56
- ...asset.info,
57
- minimized: true,
58
- });
59
- }));
60
- }
61
- }
62
- export default LightningCSSMinifyPlugin;
package/dist/plugin.js DELETED
@@ -1,47 +0,0 @@
1
- import { browserslistToTargets } from 'lightningcss';
2
- import browserslist from 'browserslist';
3
- const uselightningcssLoader = async (store, o) => {
4
- if (o?.transform === false)
5
- return;
6
- const { importResolve, chain } = store;
7
- const ruleMap = ['sass', 'less', 'css'];
8
- //
9
- const transform = o?.transform || {};
10
- const targets = browserslistToTargets(browserslist('>= 0.25%'));
11
- //
12
- const loaderOptions = { targets, ...transform };
13
- for (const ruleName of ruleMap) {
14
- const rule = chain.module.rule(ruleName);
15
- const useLightningcss = rule
16
- .use('lightningcss')
17
- .loader(importResolve('./loader.cjs', import.meta.url))
18
- .options(loaderOptions);
19
- useLightningcss.before('postcss');
20
- if (!['sass', 'less'].includes(ruleName)) {
21
- useLightningcss.before('postcss');
22
- }
23
- else {
24
- useLightningcss.before(`${ruleName}Loader`);
25
- }
26
- // 删除后引起重排
27
- rule.uses.delete('postcss');
28
- }
29
- };
30
- const uselightningcssMinify = async (store, o) => {
31
- if (o?.minify === false)
32
- return;
33
- const { chain } = store;
34
- const minify = o?.minify || {};
35
- const { LightningCSSMinifyPlugin } = await import('./minimizer.js');
36
- chain.optimization.minimizer('minCss').use(LightningCSSMinifyPlugin, [minify]);
37
- };
38
- //
39
- const empLightningcssPlugin = (o) => {
40
- return {
41
- name: '@empjs/plugin-lightningcss',
42
- async rsConfig(store) {
43
- await Promise.all([uselightningcssLoader(store, o), uselightningcssMinify(store, o)]);
44
- },
45
- };
46
- };
47
- export default empLightningcssPlugin;
@@ -1,441 +0,0 @@
1
- import { createPxToVwVisitor, createPxToRemVisitor } from './px-to-base.js';
2
- import { composeVisitors } from 'lightningcss';
3
- /**
4
- * // 插件编写 https://github.com/parcel-bundler/lightningcss/blob/master/node/test/visitor.test.mjs
5
- */
6
- class PostcssConfig {
7
- /**
8
- * https://github.com/cuth/postcss-pxtorem
9
- */
10
- px_to_rem(op) {
11
- return createPxToRemVisitor(op);
12
- }
13
- /**
14
- * https://github.com/evrone/postcss-px-to-viewport
15
- */
16
- px_to_viewport(op) {
17
- return composeVisitors([createPxToVwVisitor(op)]);
18
- }
19
- /**
20
- * https://www.npmjs.com/package/postcss-apply
21
- */
22
- apply(defined) {
23
- defined = defined ? defined : new Map();
24
- return {
25
- Rule: {
26
- style(rule) {
27
- for (const selector of rule.value.selectors) {
28
- if (selector.length === 1 && selector[0].type === 'type' && selector[0].name.startsWith('--')) {
29
- defined.set(selector[0].name, rule.value.declarations);
30
- return { type: 'ignored', value: null };
31
- }
32
- }
33
- rule.value.rules = rule.value.rules.filter(child => {
34
- if (child.type === 'unknown' && child.value.name === 'apply') {
35
- for (const token of child.value.prelude) {
36
- if (token.type === 'dashed-ident' && defined.has(token.value)) {
37
- const r = defined.get(token.value);
38
- const decls = rule.value.declarations;
39
- decls.declarations.push(...r.declarations);
40
- decls.importantDeclarations.push(...r.importantDeclarations);
41
- }
42
- }
43
- return false;
44
- }
45
- return true;
46
- });
47
- return rule;
48
- },
49
- },
50
- };
51
- }
52
- /**
53
- * https://www.npmjs.com/package/postcss-prefix-selector
54
- */
55
- selector_prefix() {
56
- return {
57
- Selector(selector) {
58
- return [{ type: 'class', name: 'prefix' }, { type: 'combinator', value: 'descendant' }, ...selector];
59
- },
60
- };
61
- }
62
- /**
63
- * https://www.npmjs.com/package/postcss-simple-vars
64
- */
65
- static_vars(declared) {
66
- declared = declared ? declared : new Map();
67
- return {
68
- Rule: {
69
- unknown(rule) {
70
- declared.set(rule.name, rule.prelude);
71
- return [];
72
- },
73
- },
74
- Token: {
75
- 'at-keyword'(token) {
76
- if (declared.has(token.value)) {
77
- return declared.get(token.value);
78
- }
79
- },
80
- },
81
- };
82
- }
83
- /**
84
- * https://www.npmjs.com/package/postcss-url
85
- */
86
- url(hostUrl) {
87
- return {
88
- Url(url) {
89
- url.url = hostUrl + url.url;
90
- return url;
91
- },
92
- };
93
- }
94
- /**
95
- * https://www.npmjs.com/package/postcss-env-function
96
- */
97
- specific_environment_variables(tokens) {
98
- const ev = {};
99
- for (const key in tokens) {
100
- ev[key] = () => tokens[key];
101
- }
102
- return {
103
- EnvironmentVariable: ev,
104
- };
105
- }
106
- /**
107
- * https://www.npmjs.com/package/postcss-env-function
108
- */
109
- env_function(tokens) {
110
- return {
111
- EnvironmentVariable(env) {
112
- if (env.name.type === 'custom') {
113
- return tokens[env.name.ident];
114
- }
115
- },
116
- };
117
- }
118
- /**
119
- * https://www.npmjs.com/package/@csstools/postcss-design-tokens
120
- */
121
- design_tokens(tokens) {
122
- return {
123
- Function: {
124
- 'design-token'(fn) {
125
- if (fn.arguments.length === 1 &&
126
- fn.arguments[0].type === 'token' &&
127
- fn.arguments[0].value.type === 'string') {
128
- return tokens[fn.arguments[0].value.value];
129
- }
130
- },
131
- },
132
- };
133
- }
134
- /**
135
- * https://github.com/csstools/custom-units
136
- */
137
- custom_units() {
138
- return {
139
- Token: {
140
- dimension(token) {
141
- if (token.unit.startsWith('--')) {
142
- return {
143
- type: 'function',
144
- value: {
145
- name: 'calc',
146
- arguments: [
147
- {
148
- type: 'token',
149
- value: {
150
- type: 'number',
151
- value: token.value,
152
- },
153
- },
154
- {
155
- type: 'token',
156
- value: {
157
- type: 'delim',
158
- value: '*',
159
- },
160
- },
161
- {
162
- type: 'var',
163
- value: {
164
- name: {
165
- ident: token.unit,
166
- },
167
- },
168
- },
169
- ],
170
- },
171
- };
172
- }
173
- },
174
- },
175
- };
176
- }
177
- /**
178
- * https://www.npmjs.com/package/postcss-property-lookup
179
- */
180
- property_lookup() {
181
- return {
182
- Rule: {
183
- style(rule) {
184
- const valuesByProperty = new Map();
185
- for (const decl of rule.value.declarations.declarations) {
186
- let name = decl.property;
187
- if (decl.property === 'unparsed') {
188
- name = decl.value.propertyId.property;
189
- }
190
- valuesByProperty.set(name, decl);
191
- }
192
- rule.value.declarations.declarations = rule.value.declarations.declarations.map((decl) => {
193
- // Only single value supported. Would need a way to convert parsed values to unparsed tokens otherwise.
194
- if (decl.property === 'unparsed' && decl.value.value.length === 1) {
195
- const token = decl.value.value[0];
196
- if (token.type === 'token' &&
197
- token.value.type === 'at-keyword' &&
198
- valuesByProperty.has(token.value.value)) {
199
- const v = valuesByProperty.get(token.value.value);
200
- return {
201
- /** @type any */
202
- property: decl.value.propertyId.property,
203
- value: v.value,
204
- };
205
- }
206
- }
207
- return decl;
208
- });
209
- return rule;
210
- },
211
- },
212
- };
213
- }
214
- /**
215
- * https://www.npmjs.com/package/postcss-focus-visible
216
- */
217
- focus_visible() {
218
- return {
219
- Rule: {
220
- style(rule) {
221
- let clone = null;
222
- for (const selector of rule.value.selectors) {
223
- for (const [i, component] of selector.entries()) {
224
- if (component.type === 'pseudo-class' && component.kind === 'focus-visible') {
225
- if (clone == null) {
226
- clone = [...rule.value.selectors.map(s => [...s])];
227
- }
228
- selector[i] = { type: 'class', name: 'focus-visible' };
229
- }
230
- }
231
- }
232
- if (clone) {
233
- return [rule, { type: 'style', value: { ...rule.value, selectors: clone } }];
234
- }
235
- },
236
- },
237
- };
238
- }
239
- /**
240
- * https://github.com/postcss/postcss-dark-theme-class
241
- */
242
- dark_theme_class() {
243
- return {
244
- Rule: {
245
- media(rule) {
246
- const q = rule.value.query.mediaQueries[0];
247
- if (q.condition?.type === 'feature' &&
248
- q.condition.value.type === 'plain' &&
249
- q.condition.value.name === 'prefers-color-scheme' &&
250
- q.condition.value.value.value === 'dark') {
251
- const clonedRules = [rule];
252
- for (const r of rule.value.rules) {
253
- if (r.type === 'style') {
254
- const clonedSelectors = [];
255
- for (const selector of r.value.selectors) {
256
- clonedSelectors.push([
257
- { type: 'type', name: 'html' },
258
- { type: 'attribute', name: 'theme', operation: { operator: 'equal', value: 'dark' } },
259
- { type: 'combinator', value: 'descendant' },
260
- ...selector,
261
- ]);
262
- selector.unshift({ type: 'type', name: 'html' }, {
263
- type: 'pseudo-class',
264
- kind: 'not',
265
- selectors: [[{ type: 'attribute', name: 'theme', operation: { operator: 'equal', value: 'light' } }]],
266
- }, { type: 'combinator', value: 'descendant' });
267
- }
268
- clonedRules.push({ type: 'style', value: { ...r.value, selectors: clonedSelectors } });
269
- }
270
- }
271
- return clonedRules;
272
- }
273
- },
274
- },
275
- };
276
- }
277
- /**
278
- * https://github.com/postcss/postcss-100vh-fix
279
- */
280
- fix_100vh() {
281
- return {
282
- Rule: {
283
- style(style) {
284
- let cloned;
285
- for (const property of style.value.declarations.declarations) {
286
- if (property.property === 'height' &&
287
- property.value.type === 'length-percentage' &&
288
- property.value.value.type === 'dimension' &&
289
- property.value.value.value.unit === 'vh' &&
290
- property.value.value.value.value === 100) {
291
- if (!cloned) {
292
- cloned = structuredClone(style);
293
- cloned.value.declarations.declarations = [];
294
- }
295
- cloned.value.declarations.declarations.push({
296
- ...property,
297
- value: {
298
- type: 'stretch',
299
- vendorPrefix: ['webkit'],
300
- },
301
- });
302
- }
303
- }
304
- if (cloned) {
305
- return [
306
- style,
307
- {
308
- type: 'supports',
309
- value: {
310
- condition: {
311
- type: 'declaration',
312
- propertyId: {
313
- property: '-webkit-touch-callout',
314
- },
315
- value: 'none',
316
- },
317
- loc: style.value.loc,
318
- rules: [cloned],
319
- },
320
- },
321
- ];
322
- }
323
- },
324
- },
325
- };
326
- }
327
- /**
328
- * https://github.com/MohammadYounes/rtlcss
329
- */
330
- logical_transforms() {
331
- return {
332
- Rule: {
333
- style(style) {
334
- let cloned;
335
- for (const property of style.value.declarations.declarations) {
336
- if (property.property === 'transform') {
337
- const clonedTransforms = property.value.map(transform => {
338
- if (transform.type !== 'translateX') {
339
- return transform;
340
- }
341
- if (!cloned) {
342
- cloned = structuredClone(style);
343
- cloned.value.declarations.declarations = [];
344
- }
345
- let value;
346
- switch (transform.value.type) {
347
- case 'dimension':
348
- value = {
349
- type: 'dimension',
350
- value: { unit: transform.value.value.unit, value: -transform.value.value.value },
351
- };
352
- break;
353
- case 'percentage':
354
- value = { type: 'percentage', value: -transform.value.value };
355
- break;
356
- case 'calc':
357
- value = { type: 'calc', value: { type: 'product', value: [-1, transform.value.value] } };
358
- break;
359
- }
360
- return {
361
- type: 'translateX',
362
- value,
363
- };
364
- });
365
- if (cloned) {
366
- cloned.value.selectors.at(-1).push({ type: 'pseudo-class', kind: 'dir', direction: 'rtl' });
367
- cloned.value.declarations.declarations.push({
368
- ...property,
369
- value: clonedTransforms,
370
- });
371
- }
372
- }
373
- }
374
- if (cloned) {
375
- return [style, cloned];
376
- }
377
- },
378
- },
379
- };
380
- }
381
- /**
382
- * https://github.com/twbs/mq4-hover-shim
383
- */
384
- hover_media_query() {
385
- return {
386
- Rule: {
387
- media(media) {
388
- const mediaQueries = media.value.query.mediaQueries;
389
- if (mediaQueries.length === 1 &&
390
- mediaQueries[0].condition &&
391
- mediaQueries[0].condition.type === 'feature' &&
392
- mediaQueries[0].condition.value.type === 'boolean' &&
393
- mediaQueries[0].condition.value.name === 'hover') {
394
- for (const rule of media.value.rules) {
395
- if (rule.type === 'style') {
396
- for (const selector of rule.value.selectors) {
397
- selector.unshift({ type: 'class', name: 'hoverable' }, { type: 'combinator', value: 'descendant' });
398
- }
399
- }
400
- }
401
- return media.value.rules;
402
- }
403
- },
404
- },
405
- };
406
- }
407
- /**
408
- * https://github.com/yunusga/postcss-momentum-scrolling
409
- */
410
- momentum_scrolling(visitOverflow) {
411
- return {
412
- Declaration: {
413
- overflow: visitOverflow,
414
- 'overflow-x': visitOverflow,
415
- 'overflow-y': visitOverflow,
416
- },
417
- };
418
- }
419
- /**
420
- * https://github.com/postcss/postcss-size
421
- */
422
- size() {
423
- return {
424
- Declaration: {
425
- custom: {
426
- size(property) {
427
- if (property.value[0].type === 'length') {
428
- /** @type {import('../ast').Size} */
429
- const value = { type: 'length-percentage', value: { type: 'dimension', value: property.value[0].value } };
430
- return [
431
- { property: 'width', value },
432
- { property: 'height', value },
433
- ];
434
- }
435
- },
436
- },
437
- },
438
- };
439
- }
440
- }
441
- export default new PostcssConfig();
@@ -1,74 +0,0 @@
1
- const baseOptions = {
2
- designWidth: 320,
3
- minPixelValue: 1,
4
- excludeSelectors: [],
5
- };
6
- export function createExcludeFilter(excludes) {
7
- const isExclude = (testItem) => {
8
- if (!testItem.name) {
9
- return false;
10
- }
11
- for (const rule of excludes) {
12
- if (testItem.type === rule.type) {
13
- if (typeof rule.name === 'string' && rule.name === testItem.name) {
14
- return true;
15
- }
16
- if (typeof rule.name === 'object' && rule.name.test(testItem.name)) {
17
- return true;
18
- }
19
- }
20
- }
21
- return false;
22
- };
23
- return isExclude;
24
- }
25
- export function createPxToVwVisitor(userOptions = {}) {
26
- const options = Object.assign(baseOptions, userOptions);
27
- const isExclude = createExcludeFilter(options.excludeSelectors);
28
- let skipCurrentSelector = false;
29
- return {
30
- Selector(selectors) {
31
- skipCurrentSelector = false;
32
- for (const selector of selectors) {
33
- if (isExclude(selector)) {
34
- skipCurrentSelector = true;
35
- }
36
- }
37
- },
38
- Length(length) {
39
- if (length.unit === 'px' && !skipCurrentSelector) {
40
- if (length.value > options.minPixelValue) {
41
- return {
42
- unit: 'vw',
43
- value: (length.value / options.designWidth) * 100,
44
- };
45
- }
46
- }
47
- },
48
- };
49
- }
50
- export function createPxToRemVisitor(options = {}) {
51
- const op = Object.assign({ rootValue: 16, excludeSelectors: [], minPixelValue: 1 }, options);
52
- const isExclude = createExcludeFilter(op.excludeSelectors);
53
- let skipCurrentSelector = false;
54
- return {
55
- Selector(selectors) {
56
- skipCurrentSelector = false;
57
- for (const selector of selectors) {
58
- if (isExclude(selector)) {
59
- skipCurrentSelector = true;
60
- }
61
- }
62
- },
63
- Length(length) {
64
- if (length.unit === 'px' && !skipCurrentSelector) {
65
- if (length.value > op.minPixelValue) {
66
- return {
67
- unit: 'rem',
68
- value: length.value / op.rootValue,
69
- };
70
- }
71
- }
72
- },
73
- };
74
- }