@vetta-org/plugin-vite 0.0.4 → 0.1.0

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.
Files changed (45) hide show
  1. package/dist/build-warning-filter.d.ts +8 -0
  2. package/dist/build-warning-filter.d.ts.map +1 -0
  3. package/dist/build-warning-filter.js +26 -0
  4. package/dist/build-warning-filter.js.map +1 -0
  5. package/dist/cli.d.ts +3 -0
  6. package/dist/cli.d.ts.map +1 -0
  7. package/dist/cli.js +83 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/dev-events.d.ts +23 -0
  10. package/dist/dev-events.d.ts.map +1 -0
  11. package/dist/dev-events.js +9 -0
  12. package/dist/dev-events.js.map +1 -0
  13. package/dist/dev-server.d.ts +9 -0
  14. package/dist/dev-server.d.ts.map +1 -0
  15. package/dist/dev-server.js +239 -0
  16. package/dist/dev-server.js.map +1 -0
  17. package/dist/dev-vite-plugins.d.ts +5 -0
  18. package/dist/dev-vite-plugins.d.ts.map +1 -0
  19. package/dist/dev-vite-plugins.js +144 -0
  20. package/dist/dev-vite-plugins.js.map +1 -0
  21. package/dist/host-theme.d.ts +5 -0
  22. package/dist/host-theme.d.ts.map +1 -0
  23. package/dist/host-theme.js +42 -0
  24. package/dist/host-theme.js.map +1 -0
  25. package/dist/index.d.ts +2 -0
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +97 -4
  28. package/dist/index.js.map +1 -1
  29. package/dist/pack.d.ts +4 -0
  30. package/dist/pack.d.ts.map +1 -1
  31. package/dist/pack.js +68 -87
  32. package/dist/pack.js.map +1 -1
  33. package/dist/permission-contract.d.ts +13 -0
  34. package/dist/permission-contract.d.ts.map +1 -0
  35. package/dist/permission-contract.js +94 -0
  36. package/dist/permission-contract.js.map +1 -0
  37. package/dist/request-query.d.ts +8 -0
  38. package/dist/request-query.d.ts.map +1 -0
  39. package/dist/request-query.js +19 -0
  40. package/dist/request-query.js.map +1 -0
  41. package/dist/style-scope.d.ts +8 -0
  42. package/dist/style-scope.d.ts.map +1 -1
  43. package/dist/style-scope.js +102 -3
  44. package/dist/style-scope.js.map +1 -1
  45. package/package.json +13 -3
@@ -2,9 +2,32 @@ import { readFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import postcss from "postcss";
4
4
  import selectorParser from "postcss-selector-parser";
5
+ import { hasOpaqueResourceQuery } from "./request-query.js";
5
6
  const PLUGIN_ROOT_ATTRIBUTE = "data-vetta-plugin-root";
6
7
  const PLUGIN_ID_PATTERN = /^[a-z0-9][a-z0-9._-]{0,63}$/;
7
8
  const KEYFRAMES_PATTERN = /(?:^|-)keyframes$/i;
9
+ const ICONIFY_CLASS_PATTERN = /^icon-\[[a-z0-9]+(?:-[a-z0-9]+)*--[a-z0-9]+(?:-[a-z0-9]+)*\]$/u;
10
+ const ICONIFY_DECLARATION_VALUES = {
11
+ width: "1em",
12
+ height: "1em",
13
+ "-webkit-mask-image": "var(--svg)",
14
+ "mask-image": "var(--svg)",
15
+ "background-color": "currentColor",
16
+ display: "inline-block",
17
+ "-webkit-mask-size": "100% 100%",
18
+ "mask-size": "100% 100%",
19
+ "-webkit-mask-repeat": "no-repeat",
20
+ "mask-repeat": "no-repeat",
21
+ };
22
+ const ICONIFY_SVG_VALUE_PATTERN = /^url\((?:"|')?data:image\/svg\+xml,/u;
23
+ /**
24
+ * 全局化的 Iconify 规则要放进一个嵌套 layer:插件样式表在宿主之后加载,
25
+ * 而 `icon-[…]{width:1em;height:1em}` 与宿主的 `.w-4/.h-4` 同特异性,
26
+ * 直接全局化会让宿主里任何同名图标退化成 1em(字号),把相邻文字挤偏。
27
+ * 同一 layer 内「未嵌套的规则」优先于其子 layer,因此包一层即可让显式尺寸工具类稳定胜出,
28
+ * 同时保留插件自身不写尺寸时的 1em 默认值。
29
+ */
30
+ const ICONIFY_LAYER_NAME = "vetta-plugin-icons";
8
31
  function createPluginRootAttribute(pluginId) {
9
32
  return selectorParser.attribute({
10
33
  attribute: PLUGIN_ROOT_ATTRIBUTE,
@@ -44,18 +67,71 @@ function replacePluginRootSelectors(selector) {
44
67
  function isKeyframesAtRule(node) {
45
68
  return node.type === "atrule" && KEYFRAMES_PATTERN.test(node.name);
46
69
  }
70
+ function hasOnlyIconifySelectors(rule) {
71
+ let selectorCount = 0;
72
+ let valid = true;
73
+ selectorParser((selectors) => {
74
+ selectors.each((selector) => {
75
+ selectorCount += 1;
76
+ const nodes = selector.nodes.filter((node) => node.type !== "comment");
77
+ const candidate = nodes[0];
78
+ if (nodes.length !== 1 ||
79
+ candidate?.type !== "class" ||
80
+ !ICONIFY_CLASS_PATTERN.test(candidate.value)) {
81
+ valid = false;
82
+ }
83
+ });
84
+ }).processSync(rule.selector);
85
+ return valid && selectorCount > 0;
86
+ }
87
+ function hasOnlyIconifyDeclarations(rule) {
88
+ let hasSvg = false;
89
+ let hasMask = false;
90
+ for (const node of rule.nodes) {
91
+ if (node.type !== "decl")
92
+ return false;
93
+ if (node.prop === "--svg") {
94
+ if (!ICONIFY_SVG_VALUE_PATTERN.test(node.value))
95
+ return false;
96
+ hasSvg = true;
97
+ continue;
98
+ }
99
+ if (ICONIFY_DECLARATION_VALUES[node.prop] !== node.value)
100
+ return false;
101
+ if (node.prop === "mask-image" || node.prop === "-webkit-mask-image")
102
+ hasMask = true;
103
+ }
104
+ return hasSvg && hasMask;
105
+ }
106
+ function isSafeGlobalIconifyRule(rule) {
107
+ return hasOnlyIconifySelectors(rule) && hasOnlyIconifyDeclarations(rule);
108
+ }
47
109
  function createScopeRule(pluginId) {
48
110
  return postcss.atRule({
49
111
  name: "scope",
50
112
  params: `(${createPluginRootAttribute(pluginId).toString()})`,
51
113
  });
52
114
  }
115
+ function createIconifyLayerRule() {
116
+ return postcss.atRule({ name: "layer", params: ICONIFY_LAYER_NAME });
117
+ }
53
118
  function scopeRulesInContainer(container, pluginId) {
54
119
  if (!container.nodes)
55
120
  return;
56
121
  let currentScope;
122
+ let currentIconifyLayer;
57
123
  for (const node of [...container.nodes]) {
58
124
  if (node.type === "rule") {
125
+ if (isSafeGlobalIconifyRule(node)) {
126
+ currentScope = undefined;
127
+ if (!currentIconifyLayer) {
128
+ currentIconifyLayer = createIconifyLayerRule();
129
+ node.before(currentIconifyLayer);
130
+ }
131
+ currentIconifyLayer.append(node);
132
+ continue;
133
+ }
134
+ currentIconifyLayer = undefined;
59
135
  if (!currentScope) {
60
136
  currentScope = createScopeRule(pluginId);
61
137
  node.before(currentScope);
@@ -64,6 +140,7 @@ function scopeRulesInContainer(container, pluginId) {
64
140
  continue;
65
141
  }
66
142
  currentScope = undefined;
143
+ currentIconifyLayer = undefined;
67
144
  if (node.type === "atrule" && !isKeyframesAtRule(node)) {
68
145
  const atRule = node;
69
146
  if (atRule.nodes)
@@ -71,7 +148,7 @@ function scopeRulesInContainer(container, pluginId) {
71
148
  }
72
149
  }
73
150
  }
74
- function scopePluginCss(css, pluginId) {
151
+ export function scopePluginCss(css, pluginId) {
75
152
  const root = postcss.parse(css);
76
153
  root.walkRules((rule) => {
77
154
  if (isInsideKeyframes(rule))
@@ -81,6 +158,19 @@ function scopePluginCss(css, pluginId) {
81
158
  scopeRulesInContainer(root, pluginId);
82
159
  return root.toString();
83
160
  }
161
+ /**
162
+ * Vite can import a CSS file as a JavaScript resource module via queries such
163
+ * as `?raw`. Those requests keep the `.css` pathname, but their transform
164
+ * input is JavaScript and must not be parsed by PostCSS. Other queries such as
165
+ * `?direct` and HMR timestamps still represent stylesheet requests.
166
+ */
167
+ export function isPluginStylesheetRequest(id) {
168
+ const queryIndex = id.indexOf("?");
169
+ const pathname = queryIndex === -1 ? id : id.slice(0, queryIndex);
170
+ if (!pathname.endsWith(".css"))
171
+ return false;
172
+ return !hasOpaqueResourceQuery(id);
173
+ }
84
174
  function readPluginId(rootDir) {
85
175
  const manifestPath = join(rootDir, "plugin.json");
86
176
  const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
@@ -91,12 +181,21 @@ function readPluginId(rootDir) {
91
181
  }
92
182
  export function createPluginStyleScopePlugin() {
93
183
  let pluginId = "";
184
+ let command = "build";
94
185
  return {
95
186
  name: "vetta-plugin-style-scope",
96
- apply: "build",
97
- enforce: "post",
187
+ enforce: "pre",
98
188
  configResolved(config) {
99
189
  pluginId = readPluginId(config.root);
190
+ command = config.command;
191
+ },
192
+ transform(code, id) {
193
+ if (command !== "serve" || !isPluginStylesheetRequest(id))
194
+ return;
195
+ return {
196
+ code: scopePluginCss(code, pluginId),
197
+ map: null,
198
+ };
100
199
  },
101
200
  generateBundle(_options, bundle) {
102
201
  for (const output of Object.values(bundle)) {
@@ -1 +1 @@
1
- {"version":3,"file":"style-scope.js","sourceRoot":"","sources":["../src/style-scope.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,OAA8D,MAAM,SAAS,CAAC;AACrF,OAAO,cAAc,MAAM,yBAAyB,CAAC;AAGrD,MAAM,qBAAqB,GAAG,wBAAwB,CAAC;AACvD,MAAM,iBAAiB,GAAG,6BAA6B,CAAC;AACxD,MAAM,iBAAiB,GAAG,oBAAoB,CAAC;AAE/C,SAAS,yBAAyB,CAAC,QAAgB,EAAE;IACpD,OAAO,cAAc,CAAC,SAAS,CAAC;QAC/B,SAAS,EAAE,qBAAqB;QAChC,QAAQ,EAAE,GAAG;QACb,SAAS,EAAE,GAAG;QACd,IAAI,EAAE,EAAE;QACR,KAAK,EAAE,QAAQ;KACf,CAAC,CAAC;AAAA,CACH;AAED,SAAS,iBAAiB,CAAC,IAAU,EAAW;IAC/C,IAAI,MAAM,GAAqB,IAAI,CAAC,MAAM,CAAC;IAC3C,OAAO,MAAM,EAAE,CAAC;QACf,IACC,MAAM,CAAC,IAAI,KAAK,QAAQ;YACxB,MAAM,IAAI,MAAM;YAChB,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ;YAC/B,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAClC,CAAC;YACF,OAAO,IAAI,CAAC;QACb,CAAC;QACD,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IACxB,CAAC;IACD,OAAO,KAAK,CAAC;AAAA,CACb;AAED,SAAS,0BAA0B,CAAC,QAAgB,EAAU;IAC7D,OAAO,cAAc,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC;QACpC,SAAS,CAAC,WAAW,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;YACjC,IAAI,MAAM,CAAC,KAAK,KAAK,OAAO,EAAE,CAAC;gBAC9B,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;gBAC/D,OAAO;YACR,CAAC;YACD,IAAI,MAAM,CAAC,KAAK,KAAK,OAAO,EAAE,CAAC;gBAC9B,MAAM,iBAAiB,GACtB,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpF,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,GAAG,iBAAiB,CAAC,CAAC;YACtF,CAAC;QAAA,CACD,CAAC,CAAC;IAAA,CACH,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;AAAA,CACzB;AAED,SAAS,iBAAiB,CAAC,IAAU,EAAW;IAC/C,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,iBAAiB,CAAC,IAAI,CAAE,IAAe,CAAC,IAAI,CAAC,CAAC;AAAA,CAC/E;AAED,SAAS,eAAe,CAAC,QAAgB,EAAU;IAClD,OAAO,OAAO,CAAC,MAAM,CAAC;QACrB,IAAI,EAAE,OAAO;QACb,MAAM,EAAE,IAAI,yBAAyB,CAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE,GAAG;KAC7D,CAAC,CAAC;AAAA,CACH;AAED,SAAS,qBAAqB,CAAC,SAAoB,EAAE,QAAgB,EAAQ;IAC5E,IAAI,CAAC,SAAS,CAAC,KAAK;QAAE,OAAO;IAC7B,IAAI,YAAgC,CAAC;IACrC,KAAK,MAAM,IAAI,IAAI,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;QACzC,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC1B,IAAI,CAAC,YAAY,EAAE,CAAC;gBACnB,YAAY,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;gBACzC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;YAC3B,CAAC;YACD,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC1B,SAAS;QACV,CAAC;QAED,YAAY,GAAG,SAAS,CAAC;QACzB,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC;YACxD,MAAM,MAAM,GAAG,IAAc,CAAC;YAC9B,IAAI,MAAM,CAAC,KAAK;gBAAE,qBAAqB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC3D,CAAC;IACF,CAAC;AAAA,CACD;AAED,SAAS,cAAc,CAAC,GAAW,EAAE,QAAgB,EAAU;IAC9D,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAChC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QACxB,IAAI,iBAAiB,CAAC,IAAI,CAAC;YAAE,OAAO;QACpC,IAAI,CAAC,QAAQ,GAAG,0BAA0B,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAAA,CAC1D,CAAC,CAAC;IACH,qBAAqB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACtC,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;AAAA,CACvB;AAED,SAAS,YAAY,CAAC,OAAe,EAAU;IAC9C,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAqB,CAAC;IACpF,IAAI,OAAO,QAAQ,CAAC,EAAE,KAAK,QAAQ,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;QAC7E,MAAM,IAAI,KAAK,CAAC,wBAAwB,YAAY,EAAE,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,QAAQ,CAAC,EAAE,CAAC;AAAA,CACnB;AAED,MAAM,UAAU,4BAA4B,GAAW;IACtD,IAAI,QAAQ,GAAG,EAAE,CAAC;IAClB,OAAO;QACN,IAAI,EAAE,0BAA0B;QAChC,KAAK,EAAE,OAAO;QACd,OAAO,EAAE,MAAM;QACf,cAAc,CAAC,MAAM,EAAE;YACtB,QAAQ,GAAG,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAAA,CACrC;QACD,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE;YAChC,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC5C,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC;oBAAE,SAAS;gBAC3E,MAAM,GAAG,GAAG,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;gBAC5G,MAAM,CAAC,MAAM,GAAG,cAAc,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;YAC/C,CAAC;QAAA,CACD;KACD,CAAC;AAAA,CACF","sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport postcss, { type AtRule, type Container, type Node, type Rule } from \"postcss\";\nimport selectorParser from \"postcss-selector-parser\";\nimport type { Plugin } from \"vite\";\n\nconst PLUGIN_ROOT_ATTRIBUTE = \"data-vetta-plugin-root\";\nconst PLUGIN_ID_PATTERN = /^[a-z0-9][a-z0-9._-]{0,63}$/;\nconst KEYFRAMES_PATTERN = /(?:^|-)keyframes$/i;\n\nfunction createPluginRootAttribute(pluginId: string) {\n\treturn selectorParser.attribute({\n\t\tattribute: PLUGIN_ROOT_ATTRIBUTE,\n\t\toperator: \"=\",\n\t\tquoteMark: '\"',\n\t\traws: {},\n\t\tvalue: pluginId,\n\t});\n}\n\nfunction isInsideKeyframes(rule: Rule): boolean {\n\tlet parent: Node | undefined = rule.parent;\n\twhile (parent) {\n\t\tif (\n\t\t\tparent.type === \"atrule\" &&\n\t\t\t\"name\" in parent &&\n\t\t\ttypeof parent.name === \"string\" &&\n\t\t\tKEYFRAMES_PATTERN.test(parent.name)\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\t\tparent = parent.parent;\n\t}\n\treturn false;\n}\n\nfunction replacePluginRootSelectors(selector: string): string {\n\treturn selectorParser((selectors) => {\n\t\tselectors.walkPseudos((pseudo) => {\n\t\t\tif (pseudo.value === \":root\") {\n\t\t\t\tpseudo.replaceWith(selectorParser.pseudo({ value: \":scope\" }));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (pseudo.value === \":host\") {\n\t\t\t\tconst hostArgumentNodes =\n\t\t\t\t\tpseudo.nodes.length === 1 ? pseudo.nodes[0].nodes.map((node) => node.clone()) : [];\n\t\t\t\tpseudo.replaceWith(selectorParser.pseudo({ value: \":scope\" }), ...hostArgumentNodes);\n\t\t\t}\n\t\t});\n\t}).processSync(selector);\n}\n\nfunction isKeyframesAtRule(node: Node): boolean {\n\treturn node.type === \"atrule\" && KEYFRAMES_PATTERN.test((node as AtRule).name);\n}\n\nfunction createScopeRule(pluginId: string): AtRule {\n\treturn postcss.atRule({\n\t\tname: \"scope\",\n\t\tparams: `(${createPluginRootAttribute(pluginId).toString()})`,\n\t});\n}\n\nfunction scopeRulesInContainer(container: Container, pluginId: string): void {\n\tif (!container.nodes) return;\n\tlet currentScope: AtRule | undefined;\n\tfor (const node of [...container.nodes]) {\n\t\tif (node.type === \"rule\") {\n\t\t\tif (!currentScope) {\n\t\t\t\tcurrentScope = createScopeRule(pluginId);\n\t\t\t\tnode.before(currentScope);\n\t\t\t}\n\t\t\tcurrentScope.append(node);\n\t\t\tcontinue;\n\t\t}\n\n\t\tcurrentScope = undefined;\n\t\tif (node.type === \"atrule\" && !isKeyframesAtRule(node)) {\n\t\t\tconst atRule = node as AtRule;\n\t\t\tif (atRule.nodes) scopeRulesInContainer(atRule, pluginId);\n\t\t}\n\t}\n}\n\nfunction scopePluginCss(css: string, pluginId: string): string {\n\tconst root = postcss.parse(css);\n\troot.walkRules((rule) => {\n\t\tif (isInsideKeyframes(rule)) return;\n\t\trule.selector = replacePluginRootSelectors(rule.selector);\n\t});\n\tscopeRulesInContainer(root, pluginId);\n\treturn root.toString();\n}\n\nfunction readPluginId(rootDir: string): string {\n\tconst manifestPath = join(rootDir, \"plugin.json\");\n\tconst manifest = JSON.parse(readFileSync(manifestPath, \"utf8\")) as { id?: unknown };\n\tif (typeof manifest.id !== \"string\" || !PLUGIN_ID_PATTERN.test(manifest.id)) {\n\t\tthrow new Error(`Invalid plugin id in ${manifestPath}`);\n\t}\n\treturn manifest.id;\n}\n\nexport function createPluginStyleScopePlugin(): Plugin {\n\tlet pluginId = \"\";\n\treturn {\n\t\tname: \"vetta-plugin-style-scope\",\n\t\tapply: \"build\",\n\t\tenforce: \"post\",\n\t\tconfigResolved(config) {\n\t\t\tpluginId = readPluginId(config.root);\n\t\t},\n\t\tgenerateBundle(_options, bundle) {\n\t\t\tfor (const output of Object.values(bundle)) {\n\t\t\t\tif (output.type !== \"asset\" || !output.fileName.endsWith(\".css\")) continue;\n\t\t\t\tconst css = typeof output.source === \"string\" ? output.source : Buffer.from(output.source).toString(\"utf8\");\n\t\t\t\toutput.source = scopePluginCss(css, pluginId);\n\t\t\t}\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"style-scope.js","sourceRoot":"","sources":["../src/style-scope.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport postcss, { type AtRule, type Container, type Node, type Rule } from \"postcss\";\nimport selectorParser from \"postcss-selector-parser\";\nimport type { Plugin } from \"vite\";\nimport { hasOpaqueResourceQuery } from \"./request-query.js\";\n\nconst PLUGIN_ROOT_ATTRIBUTE = \"data-vetta-plugin-root\";\nconst PLUGIN_ID_PATTERN = /^[a-z0-9][a-z0-9._-]{0,63}$/;\nconst KEYFRAMES_PATTERN = /(?:^|-)keyframes$/i;\nconst ICONIFY_CLASS_PATTERN = /^icon-\\[[a-z0-9]+(?:-[a-z0-9]+)*--[a-z0-9]+(?:-[a-z0-9]+)*\\]$/u;\nconst ICONIFY_DECLARATION_VALUES: Readonly<Record<string, string>> = {\n\twidth: \"1em\",\n\theight: \"1em\",\n\t\"-webkit-mask-image\": \"var(--svg)\",\n\t\"mask-image\": \"var(--svg)\",\n\t\"background-color\": \"currentColor\",\n\tdisplay: \"inline-block\",\n\t\"-webkit-mask-size\": \"100% 100%\",\n\t\"mask-size\": \"100% 100%\",\n\t\"-webkit-mask-repeat\": \"no-repeat\",\n\t\"mask-repeat\": \"no-repeat\",\n};\nconst ICONIFY_SVG_VALUE_PATTERN = /^url\\((?:\"|')?data:image\\/svg\\+xml,/u;\n/**\n * 全局化的 Iconify 规则要放进一个嵌套 layer:插件样式表在宿主之后加载,\n * 而 `icon-[…]{width:1em;height:1em}` 与宿主的 `.w-4/.h-4` 同特异性,\n * 直接全局化会让宿主里任何同名图标退化成 1em(字号),把相邻文字挤偏。\n * 同一 layer 内「未嵌套的规则」优先于其子 layer,因此包一层即可让显式尺寸工具类稳定胜出,\n * 同时保留插件自身不写尺寸时的 1em 默认值。\n */\nconst ICONIFY_LAYER_NAME = \"vetta-plugin-icons\";\n\nfunction createPluginRootAttribute(pluginId: string) {\n\treturn selectorParser.attribute({\n\t\tattribute: PLUGIN_ROOT_ATTRIBUTE,\n\t\toperator: \"=\",\n\t\tquoteMark: '\"',\n\t\traws: {},\n\t\tvalue: pluginId,\n\t});\n}\n\nfunction isInsideKeyframes(rule: Rule): boolean {\n\tlet parent: Node | undefined = rule.parent;\n\twhile (parent) {\n\t\tif (\n\t\t\tparent.type === \"atrule\" &&\n\t\t\t\"name\" in parent &&\n\t\t\ttypeof parent.name === \"string\" &&\n\t\t\tKEYFRAMES_PATTERN.test(parent.name)\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\t\tparent = parent.parent;\n\t}\n\treturn false;\n}\n\nfunction replacePluginRootSelectors(selector: string): string {\n\treturn selectorParser((selectors) => {\n\t\tselectors.walkPseudos((pseudo) => {\n\t\t\tif (pseudo.value === \":root\") {\n\t\t\t\tpseudo.replaceWith(selectorParser.pseudo({ value: \":scope\" }));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (pseudo.value === \":host\") {\n\t\t\t\tconst hostArgumentNodes =\n\t\t\t\t\tpseudo.nodes.length === 1 ? pseudo.nodes[0].nodes.map((node) => node.clone()) : [];\n\t\t\t\tpseudo.replaceWith(selectorParser.pseudo({ value: \":scope\" }), ...hostArgumentNodes);\n\t\t\t}\n\t\t});\n\t}).processSync(selector);\n}\n\nfunction isKeyframesAtRule(node: Node): boolean {\n\treturn node.type === \"atrule\" && KEYFRAMES_PATTERN.test((node as AtRule).name);\n}\n\nfunction hasOnlyIconifySelectors(rule: Rule): boolean {\n\tlet selectorCount = 0;\n\tlet valid = true;\n\tselectorParser((selectors) => {\n\t\tselectors.each((selector) => {\n\t\t\tselectorCount += 1;\n\t\t\tconst nodes = selector.nodes.filter((node) => node.type !== \"comment\");\n\t\t\tconst candidate = nodes[0];\n\t\t\tif (\n\t\t\t\tnodes.length !== 1 ||\n\t\t\t\tcandidate?.type !== \"class\" ||\n\t\t\t\t!ICONIFY_CLASS_PATTERN.test(candidate.value)\n\t\t\t) {\n\t\t\t\tvalid = false;\n\t\t\t}\n\t\t});\n\t}).processSync(rule.selector);\n\treturn valid && selectorCount > 0;\n}\n\nfunction hasOnlyIconifyDeclarations(rule: Rule): boolean {\n\tlet hasSvg = false;\n\tlet hasMask = false;\n\tfor (const node of rule.nodes) {\n\t\tif (node.type !== \"decl\") return false;\n\t\tif (node.prop === \"--svg\") {\n\t\t\tif (!ICONIFY_SVG_VALUE_PATTERN.test(node.value)) return false;\n\t\t\thasSvg = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (ICONIFY_DECLARATION_VALUES[node.prop] !== node.value) return false;\n\t\tif (node.prop === \"mask-image\" || node.prop === \"-webkit-mask-image\") hasMask = true;\n\t}\n\treturn hasSvg && hasMask;\n}\n\nfunction isSafeGlobalIconifyRule(rule: Rule): boolean {\n\treturn hasOnlyIconifySelectors(rule) && hasOnlyIconifyDeclarations(rule);\n}\n\nfunction createScopeRule(pluginId: string): AtRule {\n\treturn postcss.atRule({\n\t\tname: \"scope\",\n\t\tparams: `(${createPluginRootAttribute(pluginId).toString()})`,\n\t});\n}\n\nfunction createIconifyLayerRule(): AtRule {\n\treturn postcss.atRule({ name: \"layer\", params: ICONIFY_LAYER_NAME });\n}\n\nfunction scopeRulesInContainer(container: Container, pluginId: string): void {\n\tif (!container.nodes) return;\n\tlet currentScope: AtRule | undefined;\n\tlet currentIconifyLayer: AtRule | undefined;\n\tfor (const node of [...container.nodes]) {\n\t\tif (node.type === \"rule\") {\n\t\t\tif (isSafeGlobalIconifyRule(node)) {\n\t\t\t\tcurrentScope = undefined;\n\t\t\t\tif (!currentIconifyLayer) {\n\t\t\t\t\tcurrentIconifyLayer = createIconifyLayerRule();\n\t\t\t\t\tnode.before(currentIconifyLayer);\n\t\t\t\t}\n\t\t\t\tcurrentIconifyLayer.append(node);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tcurrentIconifyLayer = undefined;\n\t\t\tif (!currentScope) {\n\t\t\t\tcurrentScope = createScopeRule(pluginId);\n\t\t\t\tnode.before(currentScope);\n\t\t\t}\n\t\t\tcurrentScope.append(node);\n\t\t\tcontinue;\n\t\t}\n\n\t\tcurrentScope = undefined;\n\t\tcurrentIconifyLayer = undefined;\n\t\tif (node.type === \"atrule\" && !isKeyframesAtRule(node)) {\n\t\t\tconst atRule = node as AtRule;\n\t\t\tif (atRule.nodes) scopeRulesInContainer(atRule, pluginId);\n\t\t}\n\t}\n}\n\nexport function scopePluginCss(css: string, pluginId: string): string {\n\tconst root = postcss.parse(css);\n\troot.walkRules((rule) => {\n\t\tif (isInsideKeyframes(rule)) return;\n\t\trule.selector = replacePluginRootSelectors(rule.selector);\n\t});\n\tscopeRulesInContainer(root, pluginId);\n\treturn root.toString();\n}\n\n/**\n * Vite can import a CSS file as a JavaScript resource module via queries such\n * as `?raw`. Those requests keep the `.css` pathname, but their transform\n * input is JavaScript and must not be parsed by PostCSS. Other queries such as\n * `?direct` and HMR timestamps still represent stylesheet requests.\n */\nexport function isPluginStylesheetRequest(id: string): boolean {\n\tconst queryIndex = id.indexOf(\"?\");\n\tconst pathname = queryIndex === -1 ? id : id.slice(0, queryIndex);\n\tif (!pathname.endsWith(\".css\")) return false;\n\treturn !hasOpaqueResourceQuery(id);\n}\n\nfunction readPluginId(rootDir: string): string {\n\tconst manifestPath = join(rootDir, \"plugin.json\");\n\tconst manifest = JSON.parse(readFileSync(manifestPath, \"utf8\")) as { id?: unknown };\n\tif (typeof manifest.id !== \"string\" || !PLUGIN_ID_PATTERN.test(manifest.id)) {\n\t\tthrow new Error(`Invalid plugin id in ${manifestPath}`);\n\t}\n\treturn manifest.id;\n}\n\nexport function createPluginStyleScopePlugin(): Plugin {\n\tlet pluginId = \"\";\n\tlet command: \"build\" | \"serve\" = \"build\";\n\treturn {\n\t\tname: \"vetta-plugin-style-scope\",\n\t\tenforce: \"pre\",\n\t\tconfigResolved(config) {\n\t\t\tpluginId = readPluginId(config.root);\n\t\t\tcommand = config.command;\n\t\t},\n\t\ttransform(code, id) {\n\t\t\tif (command !== \"serve\" || !isPluginStylesheetRequest(id)) return;\n\t\t\treturn {\n\t\t\t\tcode: scopePluginCss(code, pluginId),\n\t\t\t\tmap: null,\n\t\t\t};\n\t\t},\n\t\tgenerateBundle(_options, bundle) {\n\t\t\tfor (const output of Object.values(bundle)) {\n\t\t\t\tif (output.type !== \"asset\" || !output.fileName.endsWith(\".css\")) continue;\n\t\t\t\tconst css = typeof output.source === \"string\" ? output.source : Buffer.from(output.source).toString(\"utf8\");\n\t\t\t\toutput.source = scopePluginCss(css, pluginId);\n\t\t\t}\n\t\t},\n\t};\n}\n"]}
package/package.json CHANGED
@@ -1,14 +1,18 @@
1
1
  {
2
2
  "name": "@vetta-org/plugin-vite",
3
- "version": "0.0.4",
3
+ "version": "0.1.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
7
+ "bin": {
8
+ "vetta-plugin": "./dist/cli.js"
9
+ },
7
10
  "exports": {
8
11
  ".": {
9
12
  "types": "./dist/index.d.ts",
10
13
  "import": "./dist/index.js"
11
14
  },
15
+ "./cli": "./dist/cli.js",
12
16
  "./pack": {
13
17
  "types": "./dist/pack.d.ts",
14
18
  "import": "./dist/pack.js"
@@ -19,19 +23,25 @@
19
23
  ],
20
24
  "scripts": {
21
25
  "clean": "rm -rf dist",
22
- "build": "tsgo -p tsconfig.build.json"
26
+ "build": "tsgo -p tsconfig.build.json",
27
+ "test": "bun ../../../scripts/quality/run-vitest.mjs --run"
23
28
  },
24
29
  "dependencies": {
25
30
  "@module-federation/vite": "^1.16.6",
31
+ "@vitejs/plugin-react": "^5.0.4",
32
+ "chokidar": "^4.0.3",
26
33
  "postcss": "^8.5.15",
27
34
  "postcss-selector-parser": "^7.1.4"
28
35
  },
29
36
  "peerDependencies": {
37
+ "@vetta-org/plugin-sdk": ">=0.2.0 <0.3.0",
30
38
  "vite": "^7.0.0"
31
39
  },
32
40
  "devDependencies": {
41
+ "@vetta-org/plugin-sdk": "workspace:*",
33
42
  "typescript": "^5.9.2",
34
- "vite": "^7.1.7"
43
+ "vite": "^7.1.7",
44
+ "vitest": "^3.2.4"
35
45
  },
36
46
  "publishConfig": {
37
47
  "access": "public",