@plumeria/vite-plugin 2.4.1 → 3.0.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 (2) hide show
  1. package/dist/index.js +175 -90
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { createFilter } from 'vite';
2
2
  import { parseSync } from '@swc/core';
3
3
  import path from 'path';
4
- import { transpile } from 'zss-engine';
5
- import { createCSS, createTheme, collectLocalConsts, objectExpressionToObject, scanForCreateStatic, scanForCreateTheme, scanForKeyframes, scanForViewTransition, t, tables, traverse, } from '@plumeria/utils';
4
+ import { genBase36Hash } from 'zss-engine';
5
+ import { tables, traverse, getStyleRecords, collectLocalConsts, objectExpressionToObject, scanForCreateStatic, scanForCreateTheme, scanForKeyframes, scanForViewTransition, t, extractOndemandStyles, } from '@plumeria/utils';
6
6
  const TARGET_EXTENSIONS = ['ts', 'tsx', 'js', 'jsx', 'vue', 'svelte'];
7
7
  const EXTENSION_PATTERN = /\.(ts|tsx|js|jsx|vue|svelte)$/;
8
8
  export function plumeria(options = {}) {
@@ -17,19 +17,6 @@ export function plumeria(options = {}) {
17
17
  return {
18
18
  name: '@plumeria/vite-plugin',
19
19
  enforce: 'pre',
20
- config: ({ build = {} }) => ({
21
- build: {
22
- ...build,
23
- rollupOptions: {
24
- ...build.rollupOptions,
25
- external: [
26
- ...(build.rollupOptions?.external || []),
27
- 'fs',
28
- 'util',
29
- ],
30
- },
31
- },
32
- }),
33
20
  configResolved(resolvedConfig) {
34
21
  isDev = resolvedConfig.command === 'serve';
35
22
  config = resolvedConfig;
@@ -67,8 +54,6 @@ export function plumeria(options = {}) {
67
54
  .concat(ctx.modules);
68
55
  },
69
56
  transform(source, url) {
70
- if (!isDev)
71
- return;
72
57
  const [id] = url.split('?', 1);
73
58
  if (id.includes('node_modules')) {
74
59
  return null;
@@ -76,7 +61,7 @@ export function plumeria(options = {}) {
76
61
  if (url.includes('?')) {
77
62
  return null;
78
63
  }
79
- const ext = path.extname(id).slice(1);
64
+ const ext = id.split('.').pop() || '';
80
65
  if (!TARGET_EXTENSIONS.includes(ext)) {
81
66
  return null;
82
67
  }
@@ -98,13 +83,13 @@ export function plumeria(options = {}) {
98
83
  const { themeTableLocal, createThemeObjectTableLocal } = scanForCreateTheme(addDependency);
99
84
  tables.themeTable = themeTableLocal;
100
85
  tables.createThemeObjectTable = createThemeObjectTableLocal;
101
- const extractedObjects = [];
86
+ const extractedSheets = [];
102
87
  let ast;
103
88
  const scriptContents = getScriptContents(source, id);
89
+ const replacements = [];
104
90
  for (const content of scriptContents) {
105
- if (!content.trim()) {
91
+ if (!content.trim())
106
92
  continue;
107
- }
108
93
  try {
109
94
  ast = parseSync(content, {
110
95
  syntax: 'typescript',
@@ -118,89 +103,191 @@ export function plumeria(options = {}) {
118
103
  }
119
104
  const localConsts = collectLocalConsts(ast);
120
105
  Object.assign(tables.staticTable, localConsts);
106
+ const localCreateStyles = {};
121
107
  traverse(ast, {
108
+ VariableDeclarator({ node }) {
109
+ if (node.id.type === 'Identifier' &&
110
+ node.init &&
111
+ t.isCallExpression(node.init) &&
112
+ t.isMemberExpression(node.init.callee) &&
113
+ t.isIdentifier(node.init.callee.object, { name: 'css' }) &&
114
+ t.isIdentifier(node.init.callee.property, { name: 'create' }) &&
115
+ node.init.arguments.length === 1 &&
116
+ t.isObjectExpression(node.init.arguments[0].expression)) {
117
+ const obj = objectExpressionToObject(node.init.arguments[0].expression, tables.staticTable, tables.keyframesHashTable, tables.viewTransitionHashTable, tables.themeTable);
118
+ if (obj) {
119
+ localCreateStyles[node.id.value] = obj;
120
+ const hashMap = {};
121
+ Object.entries(obj).forEach(([key, style]) => {
122
+ const records = getStyleRecords(key, style, 1);
123
+ const propMap = {};
124
+ extractOndemandStyles(style, extractedSheets);
125
+ records.forEach((r) => {
126
+ propMap[r.key] = r.hash;
127
+ extractedSheets.push(r.sheet);
128
+ });
129
+ hashMap[key] = records.map((r) => r.hash).join(' ');
130
+ });
131
+ replacements.push({
132
+ start: node.init.span.start - ast.span.start,
133
+ end: node.init.span.end - ast.span.start,
134
+ content: JSON.stringify(hashMap),
135
+ });
136
+ }
137
+ }
138
+ },
122
139
  CallExpression({ node }) {
123
140
  const callee = node.callee;
124
141
  if (t.isMemberExpression(callee) &&
125
142
  t.isIdentifier(callee.object, { name: 'css' }) &&
126
143
  t.isIdentifier(callee.property)) {
127
144
  const args = node.arguments;
128
- if (callee.property.value === 'create' &&
129
- args.length === 1 &&
145
+ if (callee.property.value === 'props') {
146
+ const merged = {};
147
+ let allStatic = true;
148
+ args.forEach((arg) => {
149
+ const expr = arg.expression;
150
+ if (t.isObjectExpression(expr)) {
151
+ const obj = objectExpressionToObject(expr, tables.staticTable, tables.keyframesHashTable, tables.viewTransitionHashTable, tables.themeTable);
152
+ if (obj) {
153
+ Object.assign(merged, obj);
154
+ }
155
+ else {
156
+ allStatic = false;
157
+ }
158
+ }
159
+ else if (t.isMemberExpression(expr)) {
160
+ if (t.isIdentifier(expr.object) &&
161
+ t.isIdentifier(expr.property)) {
162
+ const varName = expr.object.value;
163
+ const propName = expr.property.value;
164
+ const styleSet = localCreateStyles[varName];
165
+ if (styleSet && styleSet[propName]) {
166
+ Object.assign(merged, styleSet[propName]);
167
+ }
168
+ else {
169
+ allStatic = false;
170
+ }
171
+ }
172
+ else {
173
+ allStatic = false;
174
+ }
175
+ }
176
+ else if (t.isIdentifier(expr)) {
177
+ const obj = localCreateStyles[expr.value];
178
+ if (obj) {
179
+ Object.assign(merged, obj);
180
+ }
181
+ else {
182
+ allStatic = false;
183
+ }
184
+ }
185
+ else {
186
+ allStatic = false;
187
+ }
188
+ });
189
+ if (allStatic && Object.keys(merged).length > 0) {
190
+ extractOndemandStyles(merged, extractedSheets);
191
+ const hash = genBase36Hash(merged, 1, 8);
192
+ const records = getStyleRecords(hash, merged);
193
+ records.forEach((r) => extractedSheets.push(r.sheet));
194
+ replacements.push({
195
+ start: node.span.start - ast.span.start,
196
+ end: node.span.end - ast.span.start,
197
+ content: JSON.stringify(records.map((r) => r.hash).join(' ')),
198
+ });
199
+ }
200
+ }
201
+ else if (callee.property.value === 'keyframes' &&
202
+ args.length > 0 &&
130
203
  t.isObjectExpression(args[0].expression)) {
131
204
  const obj = objectExpressionToObject(args[0].expression, tables.staticTable, tables.keyframesHashTable, tables.viewTransitionHashTable, tables.themeTable);
132
- if (obj) {
133
- extractedObjects.push(obj);
134
- }
205
+ const hash = genBase36Hash(obj, 1, 8);
206
+ tables.keyframesObjectTable[hash] = obj;
207
+ replacements.push({
208
+ start: node.span.start - ast.span.start,
209
+ end: node.span.end - ast.span.start,
210
+ content: JSON.stringify(`kf-${hash}`),
211
+ });
212
+ }
213
+ else if (callee.property.value === 'viewTransition' &&
214
+ args.length > 0 &&
215
+ t.isObjectExpression(args[0].expression)) {
216
+ const obj = objectExpressionToObject(args[0].expression, tables.staticTable, tables.keyframesHashTable, tables.viewTransitionHashTable, tables.themeTable);
217
+ const hash = genBase36Hash(obj, 1, 8);
218
+ tables.viewTransitionObjectTable[hash] = obj;
219
+ replacements.push({
220
+ start: node.span.start - ast.span.start,
221
+ end: node.span.end - ast.span.start,
222
+ content: JSON.stringify(`vt-${hash}`),
223
+ });
224
+ }
225
+ else if (callee.property.value === 'createTheme' &&
226
+ args.length > 0 &&
227
+ t.isObjectExpression(args[0].expression)) {
228
+ const obj = objectExpressionToObject(args[0].expression, tables.staticTable, tables.keyframesHashTable, tables.viewTransitionHashTable, tables.themeTable);
229
+ const hash = genBase36Hash(obj, 1, 8);
230
+ tables.createThemeObjectTable[hash] = obj;
231
+ replacements.push({
232
+ start: node.span.start - ast.span.start,
233
+ end: node.span.end - ast.span.start,
234
+ content: JSON.stringify(''),
235
+ });
236
+ }
237
+ else if (callee.property.value === 'createStatic' &&
238
+ args.length > 0 &&
239
+ t.isStringLiteral(args[0].expression)) {
240
+ replacements.push({
241
+ start: node.span.start - ast.span.start,
242
+ end: node.span.end - ast.span.start,
243
+ content: JSON.stringify(''),
244
+ });
135
245
  }
136
246
  }
137
247
  },
138
248
  });
139
249
  }
140
- const fileStyles = {};
141
- if (extractedObjects.length > 0) {
142
- const combinedStyles = extractedObjects.reduce((acc, obj) => Object.assign(acc, obj), {});
143
- const base = createCSS(combinedStyles);
144
- if (base)
145
- fileStyles.baseStyles = base;
146
- }
147
- if (Object.keys(tables.keyframesObjectTable).length > 0) {
148
- fileStyles.keyframeStyles = Object.entries(tables.keyframesObjectTable)
149
- .map(([hash, obj]) => transpile({ [`@keyframes kf-${hash}`]: obj }, undefined, '--global').styleSheet)
150
- .join('\n');
151
- }
152
- if (Object.keys(tables.viewTransitionObjectTable).length > 0) {
153
- fileStyles.viewTransitionStyles = Object.entries(tables.viewTransitionObjectTable)
154
- .map(([hash, obj]) => transpile({
155
- [`::view-transition-group(vt-${hash})`]: obj.group,
156
- [`::view-transition-image-pair(vt-${hash})`]: obj.imagePair,
157
- [`::view-transition-old(vt-${hash})`]: obj.old,
158
- [`::view-transition-new(vt-${hash})`]: obj.new,
159
- }, undefined, '--global').styleSheet)
160
- .join('\n');
161
- }
162
- if (Object.keys(tables.createThemeObjectTable).length > 0) {
163
- fileStyles.themeStyles = Object.values(tables.createThemeObjectTable)
164
- .map((obj) => transpile(createTheme(obj), undefined, '--global')
165
- .styleSheet)
166
- .join('\n');
167
- }
168
- const sections = [];
169
- if (fileStyles.keyframeStyles?.trim())
170
- sections.push(fileStyles.keyframeStyles);
171
- if (fileStyles.viewTransitionStyles?.trim())
172
- sections.push(fileStyles.viewTransitionStyles);
173
- if (fileStyles.themeStyles?.trim())
174
- sections.push(fileStyles.themeStyles);
175
- if (fileStyles.baseStyles?.trim())
176
- sections.push(fileStyles.baseStyles);
177
- const generatedCSS = sections.join('\n');
178
- if (!generatedCSS) {
179
- return null;
180
- }
181
- const baseId = id.replace(EXTENSION_PATTERN, '');
182
- const cssFilename = `${baseId}.zero.css`;
183
- const cssRelativePath = path
184
- .relative(config.root, cssFilename)
185
- .replace(/\\/g, '/');
186
- const cssId = `/${cssRelativePath}`;
187
- cssLookup.set(cssFilename, generatedCSS);
188
- cssFileLookup.set(cssId, cssFilename);
189
- const targetIndex = targets.findIndex((t) => t.id === id);
190
- if (targetIndex !== -1) {
191
- targets[targetIndex].dependencies = dependencies;
192
- }
193
- else {
194
- targets.push({ id, dependencies });
195
- }
196
- if (devServer?.moduleGraph) {
197
- const cssModule = devServer.moduleGraph.getModuleById(cssFilename);
198
- if (cssModule) {
199
- devServer.reloadModule(cssModule);
250
+ const buffer = Buffer.from(source);
251
+ let offset = 0;
252
+ const parts = [];
253
+ replacements
254
+ .sort((a, b) => a.start - b.start)
255
+ .forEach((r) => {
256
+ parts.push(buffer.subarray(offset, r.start));
257
+ parts.push(Buffer.from(r.content));
258
+ offset = r.end;
259
+ });
260
+ parts.push(buffer.subarray(offset));
261
+ const transformedCode = Buffer.concat(parts).toString();
262
+ if (extractedSheets.length > 0) {
263
+ const generatedCSS = extractedSheets.join('');
264
+ const baseId = id.replace(EXTENSION_PATTERN, '');
265
+ const cssFilename = `${baseId}.zero.css`;
266
+ const cssRelativePath = path
267
+ .relative(config.root, cssFilename)
268
+ .replace(/\\/g, '/');
269
+ const cssId = `/${cssRelativePath}`;
270
+ cssLookup.set(cssFilename, generatedCSS);
271
+ cssFileLookup.set(cssId, cssFilename);
272
+ const targetIndex = targets.findIndex((t) => t.id === id);
273
+ if (targetIndex !== -1) {
274
+ targets[targetIndex].dependencies = dependencies;
275
+ }
276
+ else {
277
+ targets.push({ id, dependencies });
278
+ }
279
+ if (devServer?.moduleGraph) {
280
+ const cssModule = devServer.moduleGraph.getModuleById(cssFilename);
281
+ if (cssModule)
282
+ devServer.reloadModule(cssModule);
200
283
  }
284
+ return {
285
+ code: injectImport(transformedCode, id, cssFilename),
286
+ map: null,
287
+ };
201
288
  }
202
289
  return {
203
- code: injectImport(source, id, cssFilename),
290
+ code: transformedCode,
204
291
  map: null,
205
292
  };
206
293
  },
@@ -216,9 +303,7 @@ function getScriptContents(code, id) {
216
303
  function injectImport(code, id, importPath) {
217
304
  const importStmt = `\nimport ${JSON.stringify(importPath)};`;
218
305
  if (id.endsWith('.vue') || id.endsWith('.svelte')) {
219
- return code.replace(/(<script[^>]*>)([\s\S]*?)(<\/script>)/, (_match, open, content, close) => {
220
- return `${open}${content}${importStmt}\n${close}`;
221
- });
306
+ return code.replace(/(<script[^>]*>)([\s\S]*?)(<\/script>)/, (_match, open, content, close) => `${open}${content}${importStmt}\n${close}`);
222
307
  }
223
308
  return `${code}${importStmt}`;
224
309
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plumeria/vite-plugin",
3
- "version": "2.4.1",
3
+ "version": "3.0.0",
4
4
  "type": "module",
5
5
  "description": "Plumeria Vite plugin",
6
6
  "author": "Refirst 11",
@@ -22,12 +22,12 @@
22
22
  "dist/"
23
23
  ],
24
24
  "dependencies": {
25
- "@plumeria/utils": "^2.4.1"
25
+ "@plumeria/utils": "^3.0.0"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@swc/core": "1.15.2",
29
29
  "vite": "^7.1.1",
30
- "zss-engine": "2.1.0"
30
+ "zss-engine": "2.1.2"
31
31
  },
32
32
  "publishConfig": {
33
33
  "access": "public",