@plumeria/vite-plugin 0.29.0 → 1.0.1

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.d.ts CHANGED
@@ -1,2 +1,6 @@
1
- import type { PluginOption } from 'vite';
2
- export default function plumeria(): PluginOption;
1
+ import type { Plugin, FilterPattern } from 'vite';
2
+ export interface PluginOptions {
3
+ include?: FilterPattern;
4
+ exclude?: FilterPattern;
5
+ }
6
+ export declare function plumeria(options?: PluginOptions): Plugin;
package/dist/index.js CHANGED
@@ -1,6 +1,22 @@
1
- export default function plumeria() {
1
+ import { createFilter } from 'vite';
2
+ import { parseSync } from '@swc/core';
3
+ import path from 'path';
4
+ import { transpile } from 'zss-engine';
5
+ import { createCSS, createTokens, collectLocalConsts, objectExpressionToObject, scanForDefineConsts, scanForDefineTokens, scanForKeyframes, scanForViewTransition, t, tables, traverse, } from '@plumeria/utils';
6
+ const TARGET_EXTENSIONS = ['ts', 'tsx', 'js', 'jsx', 'vue', 'svelte'];
7
+ const EXTENSION_PATTERN = /\.(ts|tsx|js|jsx|vue|svelte)$/;
8
+ export function plumeria(options = {}) {
9
+ const { include, exclude } = options;
10
+ const filter = createFilter(include, exclude);
11
+ const cssLookup = new Map();
12
+ const cssFileLookup = new Map();
13
+ const targets = [];
14
+ let config;
15
+ let devServer;
2
16
  return {
3
17
  name: '@plumeria/vite-plugin',
18
+ apply: 'serve',
19
+ enforce: 'pre',
4
20
  config: ({ build = {} }) => ({
5
21
  build: {
6
22
  ...build,
@@ -13,5 +29,184 @@ export default function plumeria() {
13
29
  },
14
30
  },
15
31
  }),
32
+ configResolved(resolvedConfig) {
33
+ config = resolvedConfig;
34
+ },
35
+ configureServer(_server) {
36
+ devServer = _server;
37
+ },
38
+ resolveId(importeeUrl) {
39
+ const [id] = importeeUrl.split('?', 1);
40
+ if (cssLookup.has(id)) {
41
+ return id;
42
+ }
43
+ return cssFileLookup.get(id);
44
+ },
45
+ load(url) {
46
+ const [id] = url.split('?', 1);
47
+ return cssLookup.get(id);
48
+ },
49
+ handleHotUpdate(ctx) {
50
+ if (ctx.modules.length) {
51
+ return ctx.modules;
52
+ }
53
+ const affected = targets.filter((target) => target.dependencies.some((dep) => dep === ctx.file));
54
+ return affected
55
+ .map((target) => devServer.moduleGraph.getModuleById(target.id))
56
+ .filter((m) => !!m)
57
+ .concat(ctx.modules);
58
+ },
59
+ transform(source, url) {
60
+ const [id] = url.split('?', 1);
61
+ if (id.includes('node_modules')) {
62
+ return null;
63
+ }
64
+ if (url.includes('?')) {
65
+ return null;
66
+ }
67
+ const ext = path.extname(id).slice(1);
68
+ if (!TARGET_EXTENSIONS.includes(ext)) {
69
+ return null;
70
+ }
71
+ if (!filter(id)) {
72
+ return null;
73
+ }
74
+ const dependencies = [];
75
+ const addDependency = (depPath) => {
76
+ dependencies.push(depPath);
77
+ this.addWatchFile(depPath);
78
+ };
79
+ tables.constTable = scanForDefineConsts(addDependency);
80
+ const { keyframesHashTableLocal, keyframesObjectTableLocal } = scanForKeyframes(addDependency);
81
+ tables.keyframesHashTable = keyframesHashTableLocal;
82
+ tables.keyframesObjectTable = keyframesObjectTableLocal;
83
+ const { viewTransitionHashTableLocal, viewTransitionObjectTableLocal } = scanForViewTransition(addDependency);
84
+ tables.viewTransitionHashTable = viewTransitionHashTableLocal;
85
+ tables.viewTransitionObjectTable = viewTransitionObjectTableLocal;
86
+ const { tokensTableLocal, defineTokensObjectTableLocal } = scanForDefineTokens(addDependency);
87
+ tables.tokensTable = tokensTableLocal;
88
+ tables.defineTokensObjectTable = defineTokensObjectTableLocal;
89
+ const extractedObjects = [];
90
+ let ast;
91
+ const scriptContents = getScriptContents(source, id);
92
+ for (const content of scriptContents) {
93
+ if (!content.trim()) {
94
+ continue;
95
+ }
96
+ try {
97
+ ast = parseSync(content, {
98
+ syntax: 'typescript',
99
+ tsx: true,
100
+ target: 'es2022',
101
+ });
102
+ }
103
+ catch (err) {
104
+ console.warn(`Zero Styled: Parse error in ${id}`, err);
105
+ continue;
106
+ }
107
+ const localConsts = collectLocalConsts(ast);
108
+ Object.assign(tables.constTable, localConsts);
109
+ traverse(ast, {
110
+ CallExpression({ node }) {
111
+ const callee = node.callee;
112
+ if (t.isMemberExpression(callee) &&
113
+ t.isIdentifier(callee.object, { name: 'css' }) &&
114
+ t.isIdentifier(callee.property)) {
115
+ const args = node.arguments;
116
+ if (callee.property.value === 'create' &&
117
+ args.length === 1 &&
118
+ t.isObjectExpression(args[0].expression)) {
119
+ const obj = objectExpressionToObject(args[0].expression, tables.constTable, tables.keyframesHashTable, tables.viewTransitionHashTable, tables.tokensTable);
120
+ if (obj) {
121
+ extractedObjects.push(obj);
122
+ }
123
+ }
124
+ }
125
+ },
126
+ });
127
+ }
128
+ const fileStyles = {};
129
+ if (extractedObjects.length > 0) {
130
+ const combinedStyles = extractedObjects.reduce((acc, obj) => Object.assign(acc, obj), {});
131
+ const base = createCSS(combinedStyles);
132
+ if (base)
133
+ fileStyles.baseStyles = base;
134
+ }
135
+ if (Object.keys(tables.keyframesObjectTable).length > 0) {
136
+ fileStyles.keyframeStyles = Object.entries(tables.keyframesObjectTable)
137
+ .map(([hash, obj]) => transpile({ [`@keyframes kf-${hash}`]: obj }, undefined, '--global').styleSheet)
138
+ .join('\n');
139
+ }
140
+ if (Object.keys(tables.viewTransitionObjectTable).length > 0) {
141
+ fileStyles.viewTransitionStyles = Object.entries(tables.viewTransitionObjectTable)
142
+ .map(([hash, obj]) => transpile({
143
+ [`::view-transition-group(vt-${hash})`]: obj.group,
144
+ [`::view-transition-image-pair(vt-${hash})`]: obj.imagePair,
145
+ [`::view-transition-old(vt-${hash})`]: obj.old,
146
+ [`::view-transition-new(vt-${hash})`]: obj.new,
147
+ }, undefined, '--global').styleSheet)
148
+ .join('\n');
149
+ }
150
+ if (Object.keys(tables.defineTokensObjectTable).length > 0) {
151
+ fileStyles.tokenStyles = Object.values(tables.defineTokensObjectTable)
152
+ .map((obj) => transpile(createTokens(obj), undefined, '--global').styleSheet)
153
+ .join('\n');
154
+ }
155
+ const sections = [];
156
+ if (fileStyles.keyframeStyles?.trim())
157
+ sections.push(fileStyles.keyframeStyles);
158
+ if (fileStyles.viewTransitionStyles?.trim())
159
+ sections.push(fileStyles.viewTransitionStyles);
160
+ if (fileStyles.tokenStyles?.trim())
161
+ sections.push(fileStyles.tokenStyles);
162
+ if (fileStyles.baseStyles?.trim())
163
+ sections.push(fileStyles.baseStyles);
164
+ const generatedCSS = sections.join('\n');
165
+ if (!generatedCSS) {
166
+ return null;
167
+ }
168
+ const cssFilename = path
169
+ .normalize(`${id.replace(EXTENSION_PATTERN, '')}.zero.css`)
170
+ .replace(/\\/g, path.posix.sep);
171
+ const cssRelativePath = path
172
+ .relative(config.root, cssFilename)
173
+ .replace(/\\/g, path.posix.sep);
174
+ const cssId = `/${cssRelativePath}`;
175
+ cssLookup.set(cssFilename, generatedCSS);
176
+ cssFileLookup.set(cssId, cssFilename);
177
+ const targetIndex = targets.findIndex((t) => t.id === id);
178
+ if (targetIndex !== -1) {
179
+ targets[targetIndex].dependencies = dependencies;
180
+ }
181
+ else {
182
+ targets.push({ id, dependencies });
183
+ }
184
+ if (devServer?.moduleGraph) {
185
+ const cssModule = devServer.moduleGraph.getModuleById(cssFilename);
186
+ if (cssModule) {
187
+ devServer.reloadModule(cssModule);
188
+ }
189
+ }
190
+ return {
191
+ code: injectImport(source, id, cssFilename),
192
+ map: null,
193
+ };
194
+ },
16
195
  };
17
196
  }
197
+ function getScriptContents(code, id) {
198
+ if (id.endsWith('.vue') || id.endsWith('.svelte')) {
199
+ const matches = code.matchAll(/<script[^>]*>([\s\S]*?)<\/script>/g);
200
+ return Array.from(matches).map((match) => match[1]);
201
+ }
202
+ return [code];
203
+ }
204
+ function injectImport(code, id, importPath) {
205
+ const importStmt = `\nimport ${JSON.stringify(importPath)};`;
206
+ if (id.endsWith('.vue') || id.endsWith('.svelte')) {
207
+ return code.replace(/(<script[^>]*>)([\s\S]*?)(<\/script>)/, (_match, open, content, close) => {
208
+ return `${open}${content}${importStmt}\n${close}`;
209
+ });
210
+ }
211
+ return `${code}${importStmt}`;
212
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plumeria/vite-plugin",
3
- "version": "0.29.0",
3
+ "version": "1.0.1",
4
4
  "type": "module",
5
5
  "description": "Plumeria Vite plugin",
6
6
  "repository": {
@@ -14,8 +14,13 @@
14
14
  "files": [
15
15
  "dist/"
16
16
  ],
17
+ "dependencies": {
18
+ "@plumeria/utils": "^1.0.1"
19
+ },
17
20
  "devDependencies": {
18
- "vite": "^7.1.1"
21
+ "@swc/core": "1.15.2",
22
+ "vite": "^7.1.1",
23
+ "zss-engine": "1.0.0"
19
24
  },
20
25
  "publishConfig": {
21
26
  "access": "public",