@plumeria/unplugin 19.1.2 → 19.1.3

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/core.d.ts CHANGED
@@ -1,5 +1,12 @@
1
1
  import type { UnpluginFactory } from 'unplugin';
2
2
  import type { PropertyPolicyOptions } from '@plumeria/utils';
3
+ export type CssImportContext = {
4
+ id: string;
5
+ cssId: string;
6
+ cssFilename: string;
7
+ css: string;
8
+ };
9
+ export type CssImportFormatter = (ctx: CssImportContext) => string | null;
3
10
  export interface PluginOptions extends PropertyPolicyOptions {
4
11
  include?: string | RegExp | Array<string | RegExp>;
5
12
  exclude?: string | RegExp | Array<string | RegExp>;
package/dist/core.js CHANGED
@@ -47,6 +47,7 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
47
47
  const targets = [];
48
48
  const devCssSheets = new Map();
49
49
  let isDev = false;
50
+ let cssImport = null;
50
51
  let viteRoot = process.cwd();
51
52
  return {
52
53
  name: '@plumeria/unplugin',
@@ -63,6 +64,9 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
63
64
  setRoot(root) {
64
65
  viteRoot = root;
65
66
  },
67
+ setCssImport(formatter) {
68
+ cssImport = formatter;
69
+ },
66
70
  },
67
71
  resolveId(id, importer) {
68
72
  const [pathId, query] = id.split('?');
@@ -143,8 +147,16 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
143
147
  else {
144
148
  targets.push({ id, dependencies });
145
149
  }
150
+ const statement = cssImport
151
+ ? cssImport({
152
+ id,
153
+ cssId,
154
+ cssFilename,
155
+ css: cssLookup.get(cssFilename) ?? '',
156
+ })
157
+ : `\nimport ${JSON.stringify(cssId)};`;
146
158
  return {
147
- code: transformedSource + `\nimport ${JSON.stringify(cssId)};`,
159
+ code: statement ? transformedSource + statement : transformedSource,
148
160
  map: null,
149
161
  };
150
162
  }
package/dist/core.mjs CHANGED
@@ -11,6 +11,7 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
11
11
  const targets = [];
12
12
  const devCssSheets = new Map();
13
13
  let isDev = false;
14
+ let cssImport = null;
14
15
  let viteRoot = process.cwd();
15
16
  return {
16
17
  name: '@plumeria/unplugin',
@@ -27,6 +28,9 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
27
28
  setRoot(root) {
28
29
  viteRoot = root;
29
30
  },
31
+ setCssImport(formatter) {
32
+ cssImport = formatter;
33
+ },
30
34
  },
31
35
  resolveId(id, importer) {
32
36
  const [pathId, query] = id.split('?');
@@ -107,8 +111,16 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
107
111
  else {
108
112
  targets.push({ id, dependencies });
109
113
  }
114
+ const statement = cssImport
115
+ ? cssImport({
116
+ id,
117
+ cssId,
118
+ cssFilename,
119
+ css: cssLookup.get(cssFilename) ?? '',
120
+ })
121
+ : `\nimport ${JSON.stringify(cssId)};`;
110
122
  return {
111
- code: transformedSource + `\nimport ${JSON.stringify(cssId)};`,
123
+ code: statement ? transformedSource + statement : transformedSource,
112
124
  map: null,
113
125
  };
114
126
  }
@@ -1,4 +1,6 @@
1
+ import type { CssImportContext } from './core';
1
2
  export declare function resolveVirtualCssPath(): string;
2
3
  export declare function ensureVirtualCssFile(virtualCssPath: string): void;
3
4
  export declare function writeCssBlock(virtualCssPath: string, filePathKey: string, cssContent: string): void;
4
5
  export declare function rewriteImportPath(sourceFilePath: string, virtualCssPath: string): string;
6
+ export declare function createDiskCssImport(getRoot: () => string, virtualCssPath?: string): ({ id, cssFilename, css }: CssImportContext) => string;
package/dist/disk-css.js CHANGED
@@ -37,6 +37,7 @@ exports.resolveVirtualCssPath = resolveVirtualCssPath;
37
37
  exports.ensureVirtualCssFile = ensureVirtualCssFile;
38
38
  exports.writeCssBlock = writeCssBlock;
39
39
  exports.rewriteImportPath = rewriteImportPath;
40
+ exports.createDiskCssImport = createDiskCssImport;
40
41
  const fs = __importStar(require("fs"));
41
42
  const path = __importStar(require("path"));
42
43
  const module_1 = require("module");
@@ -102,3 +103,13 @@ function rewriteImportPath(sourceFilePath, virtualCssPath) {
102
103
  }
103
104
  return relativeImportPath;
104
105
  }
106
+ function createDiskCssImport(getRoot, virtualCssPath = resolveVirtualCssPath()) {
107
+ return ({ id, cssFilename, css }) => {
108
+ ensureVirtualCssFile(virtualCssPath);
109
+ const filePathKey = path
110
+ .relative(getRoot(), cssFilename)
111
+ .replace(/\\/g, '/');
112
+ writeCssBlock(virtualCssPath, filePathKey, css);
113
+ return `\nimport "${rewriteImportPath(id, virtualCssPath)}";`;
114
+ };
115
+ }
package/dist/disk-css.mjs CHANGED
@@ -63,3 +63,13 @@ export function rewriteImportPath(sourceFilePath, virtualCssPath) {
63
63
  }
64
64
  return relativeImportPath;
65
65
  }
66
+ export function createDiskCssImport(getRoot, virtualCssPath = resolveVirtualCssPath()) {
67
+ return ({ id, cssFilename, css }) => {
68
+ ensureVirtualCssFile(virtualCssPath);
69
+ const filePathKey = path
70
+ .relative(getRoot(), cssFilename)
71
+ .replace(/\\/g, '/');
72
+ writeCssBlock(virtualCssPath, filePathKey, css);
73
+ return `\nimport "${rewriteImportPath(id, virtualCssPath)}";`;
74
+ };
75
+ }
package/dist/farm.js CHANGED
@@ -1,70 +1,14 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
2
  Object.defineProperty(exports, "__esModule", { value: true });
36
3
  const unplugin_1 = require("unplugin");
37
4
  const core_1 = require("./core");
38
- const path = __importStar(require("path"));
39
5
  const disk_css_1 = require("./disk-css");
40
6
  function attachFarmHooks(plugin) {
41
- const { targets } = plugin.__plumeriaInternal;
7
+ const { targets, setCssImport } = plugin.__plumeriaInternal;
42
8
  let isDev = false;
43
9
  let farmRoot = process.cwd();
44
- const virtualCssPath = (0, disk_css_1.resolveVirtualCssPath)();
45
- const baseTransform = plugin.transform;
46
- plugin.transform = async function (code, id) {
47
- const result = await baseTransform.call(this, code, id);
48
- if (isDev && result && typeof result === 'object' && result.code) {
49
- const { cssLookup, cssFileLookup } = plugin.__plumeriaInternal;
50
- result.code = result.code.replace(/import\s+["'](\/[^"']+\.zero\.css)["'];/g, (_match, cssPath) => {
51
- const absolutePath = cssFileLookup.get(cssPath);
52
- if (!absolutePath)
53
- return _match;
54
- const cssContent = cssLookup.get(absolutePath);
55
- if (cssContent == null)
56
- return _match;
57
- (0, disk_css_1.ensureVirtualCssFile)(virtualCssPath);
58
- const filePathKey = path
59
- .relative(farmRoot, absolutePath)
60
- .replace(/\\/g, '/');
61
- (0, disk_css_1.writeCssBlock)(virtualCssPath, filePathKey, cssContent);
62
- const importPath = (0, disk_css_1.rewriteImportPath)(id, virtualCssPath);
63
- return `import "${importPath}";`;
64
- });
65
- }
66
- return result;
67
- };
10
+ const diskCssImport = (0, disk_css_1.createDiskCssImport)(() => farmRoot);
11
+ setCssImport((ctx) => isDev ? diskCssImport(ctx) : `\nimport ${JSON.stringify(ctx.cssId)};`);
68
12
  plugin.farm = {
69
13
  config(config) {
70
14
  if (plugin.__plumeriaInternal) {
package/dist/farm.mjs CHANGED
@@ -1,35 +1,12 @@
1
1
  import { createFarmPlugin } from 'unplugin';
2
2
  import { unpluginFactory, EXTENSION_PATTERN } from './core.mjs';
3
- import * as path from 'path';
4
- import { resolveVirtualCssPath, ensureVirtualCssFile, writeCssBlock, rewriteImportPath, } from './disk-css.mjs';
3
+ import { createDiskCssImport } from './disk-css.mjs';
5
4
  function attachFarmHooks(plugin) {
6
- const { targets } = plugin.__plumeriaInternal;
5
+ const { targets, setCssImport } = plugin.__plumeriaInternal;
7
6
  let isDev = false;
8
7
  let farmRoot = process.cwd();
9
- const virtualCssPath = resolveVirtualCssPath();
10
- const baseTransform = plugin.transform;
11
- plugin.transform = async function (code, id) {
12
- const result = await baseTransform.call(this, code, id);
13
- if (isDev && result && typeof result === 'object' && result.code) {
14
- const { cssLookup, cssFileLookup } = plugin.__plumeriaInternal;
15
- result.code = result.code.replace(/import\s+["'](\/[^"']+\.zero\.css)["'];/g, (_match, cssPath) => {
16
- const absolutePath = cssFileLookup.get(cssPath);
17
- if (!absolutePath)
18
- return _match;
19
- const cssContent = cssLookup.get(absolutePath);
20
- if (cssContent == null)
21
- return _match;
22
- ensureVirtualCssFile(virtualCssPath);
23
- const filePathKey = path
24
- .relative(farmRoot, absolutePath)
25
- .replace(/\\/g, '/');
26
- writeCssBlock(virtualCssPath, filePathKey, cssContent);
27
- const importPath = rewriteImportPath(id, virtualCssPath);
28
- return `import "${importPath}";`;
29
- });
30
- }
31
- return result;
32
- };
8
+ const diskCssImport = createDiskCssImport(() => farmRoot);
9
+ setCssImport((ctx) => isDev ? diskCssImport(ctx) : `\nimport ${JSON.stringify(ctx.cssId)};`);
33
10
  plugin.farm = {
34
11
  config(config) {
35
12
  if (plugin.__plumeriaInternal) {
package/dist/vite.js CHANGED
@@ -38,13 +38,30 @@ const core_1 = require("./core");
38
38
  const utils_1 = require("@plumeria/utils");
39
39
  const path = __importStar(require("path"));
40
40
  const disk_css_1 = require("./disk-css");
41
+ function isRscConfig(userConfig) {
42
+ if (userConfig.environments?.rsc)
43
+ return true;
44
+ const plugins = (userConfig.plugins ?? [])
45
+ .flat(Infinity)
46
+ .filter((p) => !!p && typeof p === 'object');
47
+ return plugins.some((p) => p.name === 'rsc' || !!p.name?.startsWith('rsc:'));
48
+ }
41
49
  function attachViteHooks(plugin, options) {
42
50
  let devServer;
43
- const { cssLookup, cssFileLookup, targets, setDev, setRoot } = plugin.__plumeriaInternal;
51
+ const { cssLookup, cssFileLookup, targets, setDev, setRoot, setCssImport } = plugin.__plumeriaInternal;
44
52
  const useDiskEmit = options?.devEmitToDisk ?? false;
45
53
  let isDev = false;
46
54
  let viteRoot = process.cwd();
47
- const virtualCssPath = useDiskEmit ? (0, disk_css_1.resolveVirtualCssPath)() : '';
55
+ const diskCssImport = useDiskEmit
56
+ ? (0, disk_css_1.createDiskCssImport)(() => viteRoot)
57
+ : null;
58
+ setCssImport((ctx) => {
59
+ if (isRsc && isBuild)
60
+ return null;
61
+ if (isDev && diskCssImport)
62
+ return diskCssImport(ctx);
63
+ return `\nimport ${JSON.stringify(ctx.cssId)};`;
64
+ });
48
65
  let propsTableSnapshot = {};
49
66
  const snapshotPropsTable = () => {
50
67
  const snap = {};
@@ -61,43 +78,75 @@ function attachViteHooks(plugin, options) {
61
78
  return snap;
62
79
  };
63
80
  const lastServedCss = new Map();
81
+ let isRsc = false;
82
+ let isBuild = false;
83
+ let sheetRef;
84
+ const clientCssModules = (cssFilename) => {
85
+ const clientEnv = devServer?.environments?.client;
86
+ const graph = clientEnv?.moduleGraph;
87
+ if (!graph)
88
+ return null;
89
+ const mods = new Set(graph.getModulesByFile(cssFilename) ?? []);
90
+ const byId = graph.getModuleById(cssFilename);
91
+ if (byId)
92
+ mods.add(byId);
93
+ return { clientEnv, graph, mods };
94
+ };
95
+ const invalidateClientCss = (cssFilename) => {
96
+ const found = clientCssModules(cssFilename);
97
+ if (!found || found.mods.size === 0)
98
+ return;
99
+ found.mods.forEach((m) => found.graph.invalidateModule(m));
100
+ const cssId = `/${path.relative(viteRoot, cssFilename).replace(/\\/g, '/')}`;
101
+ found.clientEnv.hot.send({
102
+ type: 'update',
103
+ updates: [
104
+ {
105
+ type: 'css-update',
106
+ timestamp: Date.now(),
107
+ path: cssId,
108
+ acceptedPath: cssId,
109
+ },
110
+ ],
111
+ });
112
+ };
113
+ const reloadClientCss = (cssFilename) => {
114
+ const found = clientCssModules(cssFilename);
115
+ if (found && found.mods.size > 0) {
116
+ found.mods.forEach((m) => found.clientEnv.reloadModule(m));
117
+ return true;
118
+ }
119
+ return false;
120
+ };
64
121
  const baseTransform = plugin.transform;
65
122
  plugin.transform = async function (code, id) {
66
123
  const result = await baseTransform.call(this, code, id);
67
- if (isDev &&
68
- useDiskEmit &&
69
- result &&
70
- typeof result === 'object' &&
71
- result.code) {
72
- result.code = result.code.replace(/import\s+["'](\/[^"']+\.zero\.css)["'];/g, (_match, cssPath) => {
73
- const absolutePath = cssFileLookup.get(cssPath);
74
- if (!absolutePath)
75
- return _match;
76
- const cssContent = cssLookup.get(absolutePath);
77
- if (cssContent == null)
78
- return _match;
79
- (0, disk_css_1.ensureVirtualCssFile)(virtualCssPath);
80
- const filePathKey = path
81
- .relative(viteRoot, absolutePath)
82
- .replace(/\\/g, '/');
83
- (0, disk_css_1.writeCssBlock)(virtualCssPath, filePathKey, cssContent);
84
- const importPath = (0, disk_css_1.rewriteImportPath)(id, virtualCssPath);
85
- return `import "${importPath}";`;
86
- });
87
- }
88
- else if (!useDiskEmit &&
124
+ if (!useDiskEmit &&
89
125
  devServer &&
90
126
  result &&
91
127
  typeof result === 'object' &&
92
128
  result.code.includes('.zero.css')) {
93
129
  const baseId = id.replace(core_1.EXTENSION_PATTERN, '');
94
130
  const cssFilename = `${baseId}.zero.css`;
95
- const mod = devServer.moduleGraph.getModuleById(cssFilename);
96
- if (mod) {
97
- const cssContent = cssLookup.get(cssFilename) ?? '';
98
- if (lastServedCss.get(cssFilename) !== cssContent) {
99
- lastServedCss.set(cssFilename, cssContent);
100
- devServer.reloadModule(mod);
131
+ const cssContent = cssLookup.get(cssFilename) ?? '';
132
+ const envName = this.environment?.name;
133
+ const seenKey = `${envName ?? ''}:${cssFilename}`;
134
+ if (envName && envName !== 'client') {
135
+ if (lastServedCss.get(seenKey) !== cssContent) {
136
+ lastServedCss.set(seenKey, cssContent);
137
+ invalidateClientCss(cssFilename);
138
+ }
139
+ }
140
+ else if (lastServedCss.get(seenKey) !== cssContent) {
141
+ if (reloadClientCss(cssFilename)) {
142
+ lastServedCss.set(seenKey, cssContent);
143
+ }
144
+ else {
145
+ const mod = devServer.moduleGraph.getModuleById(cssFilename);
146
+ if (mod) {
147
+ lastServedCss.set(seenKey, cssContent);
148
+ devServer.reloadModule(mod);
149
+ }
101
150
  }
102
151
  }
103
152
  }
@@ -115,14 +164,49 @@ function attachViteHooks(plugin, options) {
115
164
  ],
116
165
  },
117
166
  };
118
- if (command === 'build') {
167
+ isBuild = command === 'build';
168
+ isRsc = isRscConfig(userConfig);
169
+ if (isBuild && !isRsc) {
119
170
  configToReturn.build = {
120
171
  ...(userConfig.build ?? {}),
121
172
  cssCodeSplit: false,
122
173
  };
123
174
  }
175
+ if (isBuild && isRsc) {
176
+ configToReturn.environments = {
177
+ rsc: { build: { cssCodeSplit: false } },
178
+ };
179
+ }
124
180
  return configToReturn;
125
181
  },
182
+ buildStart() {
183
+ sheetRef = undefined;
184
+ },
185
+ async buildEnd() {
186
+ if (!isRsc || !isBuild)
187
+ return;
188
+ if (this.environment?.name !== 'rsc')
189
+ return;
190
+ const source = await (0, utils_1.optimizer)([...cssLookup.keys()]
191
+ .sort()
192
+ .map((key) => cssLookup.get(key))
193
+ .join(''));
194
+ if (!source.trim())
195
+ return;
196
+ sheetRef = this.emitFile({
197
+ type: 'asset',
198
+ name: 'plumeria.css',
199
+ source,
200
+ });
201
+ },
202
+ renderChunk(_code, chunk) {
203
+ if (!sheetRef)
204
+ return null;
205
+ if (this.environment?.name !== 'rsc')
206
+ return null;
207
+ chunk.viteMetadata.importedCss.add(this.getFileName(sheetRef));
208
+ return null;
209
+ },
126
210
  configResolved(config) {
127
211
  viteRoot = config.root;
128
212
  setRoot(config.root);
@@ -174,13 +258,15 @@ function attachViteHooks(plugin, options) {
174
258
  };
175
259
  if (!useDiskEmit) {
176
260
  vitePlugin.resolveId = function (importeeUrl) {
177
- const [id] = importeeUrl.split('?', 1);
261
+ const queryIndex = importeeUrl.indexOf('?');
262
+ const id = queryIndex === -1 ? importeeUrl : importeeUrl.slice(0, queryIndex);
263
+ const query = queryIndex === -1 ? '' : importeeUrl.slice(queryIndex);
178
264
  if (cssLookup.has(id)) {
179
- return id;
265
+ return id + query;
180
266
  }
181
267
  const resolved = cssFileLookup.get(id);
182
268
  if (resolved) {
183
- return resolved;
269
+ return resolved + query;
184
270
  }
185
271
  return null;
186
272
  };
package/dist/vite.mjs CHANGED
@@ -1,15 +1,32 @@
1
1
  import { createVitePlugin } from 'unplugin';
2
2
  import { unpluginFactory, EXTENSION_PATTERN } from './core.mjs';
3
- import { scanAll } from '@plumeria/utils';
3
+ import { scanAll, optimizer } from '@plumeria/utils';
4
4
  import * as path from 'path';
5
- import { resolveVirtualCssPath, ensureVirtualCssFile, writeCssBlock, rewriteImportPath, } from './disk-css.mjs';
5
+ import { createDiskCssImport } from './disk-css.mjs';
6
+ function isRscConfig(userConfig) {
7
+ if (userConfig.environments?.rsc)
8
+ return true;
9
+ const plugins = (userConfig.plugins ?? [])
10
+ .flat(Infinity)
11
+ .filter((p) => !!p && typeof p === 'object');
12
+ return plugins.some((p) => p.name === 'rsc' || !!p.name?.startsWith('rsc:'));
13
+ }
6
14
  function attachViteHooks(plugin, options) {
7
15
  let devServer;
8
- const { cssLookup, cssFileLookup, targets, setDev, setRoot } = plugin.__plumeriaInternal;
16
+ const { cssLookup, cssFileLookup, targets, setDev, setRoot, setCssImport } = plugin.__plumeriaInternal;
9
17
  const useDiskEmit = options?.devEmitToDisk ?? false;
10
18
  let isDev = false;
11
19
  let viteRoot = process.cwd();
12
- const virtualCssPath = useDiskEmit ? resolveVirtualCssPath() : '';
20
+ const diskCssImport = useDiskEmit
21
+ ? createDiskCssImport(() => viteRoot)
22
+ : null;
23
+ setCssImport((ctx) => {
24
+ if (isRsc && isBuild)
25
+ return null;
26
+ if (isDev && diskCssImport)
27
+ return diskCssImport(ctx);
28
+ return `\nimport ${JSON.stringify(ctx.cssId)};`;
29
+ });
13
30
  let propsTableSnapshot = {};
14
31
  const snapshotPropsTable = () => {
15
32
  const snap = {};
@@ -26,43 +43,75 @@ function attachViteHooks(plugin, options) {
26
43
  return snap;
27
44
  };
28
45
  const lastServedCss = new Map();
46
+ let isRsc = false;
47
+ let isBuild = false;
48
+ let sheetRef;
49
+ const clientCssModules = (cssFilename) => {
50
+ const clientEnv = devServer?.environments?.client;
51
+ const graph = clientEnv?.moduleGraph;
52
+ if (!graph)
53
+ return null;
54
+ const mods = new Set(graph.getModulesByFile(cssFilename) ?? []);
55
+ const byId = graph.getModuleById(cssFilename);
56
+ if (byId)
57
+ mods.add(byId);
58
+ return { clientEnv, graph, mods };
59
+ };
60
+ const invalidateClientCss = (cssFilename) => {
61
+ const found = clientCssModules(cssFilename);
62
+ if (!found || found.mods.size === 0)
63
+ return;
64
+ found.mods.forEach((m) => found.graph.invalidateModule(m));
65
+ const cssId = `/${path.relative(viteRoot, cssFilename).replace(/\\/g, '/')}`;
66
+ found.clientEnv.hot.send({
67
+ type: 'update',
68
+ updates: [
69
+ {
70
+ type: 'css-update',
71
+ timestamp: Date.now(),
72
+ path: cssId,
73
+ acceptedPath: cssId,
74
+ },
75
+ ],
76
+ });
77
+ };
78
+ const reloadClientCss = (cssFilename) => {
79
+ const found = clientCssModules(cssFilename);
80
+ if (found && found.mods.size > 0) {
81
+ found.mods.forEach((m) => found.clientEnv.reloadModule(m));
82
+ return true;
83
+ }
84
+ return false;
85
+ };
29
86
  const baseTransform = plugin.transform;
30
87
  plugin.transform = async function (code, id) {
31
88
  const result = await baseTransform.call(this, code, id);
32
- if (isDev &&
33
- useDiskEmit &&
34
- result &&
35
- typeof result === 'object' &&
36
- result.code) {
37
- result.code = result.code.replace(/import\s+["'](\/[^"']+\.zero\.css)["'];/g, (_match, cssPath) => {
38
- const absolutePath = cssFileLookup.get(cssPath);
39
- if (!absolutePath)
40
- return _match;
41
- const cssContent = cssLookup.get(absolutePath);
42
- if (cssContent == null)
43
- return _match;
44
- ensureVirtualCssFile(virtualCssPath);
45
- const filePathKey = path
46
- .relative(viteRoot, absolutePath)
47
- .replace(/\\/g, '/');
48
- writeCssBlock(virtualCssPath, filePathKey, cssContent);
49
- const importPath = rewriteImportPath(id, virtualCssPath);
50
- return `import "${importPath}";`;
51
- });
52
- }
53
- else if (!useDiskEmit &&
89
+ if (!useDiskEmit &&
54
90
  devServer &&
55
91
  result &&
56
92
  typeof result === 'object' &&
57
93
  result.code.includes('.zero.css')) {
58
94
  const baseId = id.replace(EXTENSION_PATTERN, '');
59
95
  const cssFilename = `${baseId}.zero.css`;
60
- const mod = devServer.moduleGraph.getModuleById(cssFilename);
61
- if (mod) {
62
- const cssContent = cssLookup.get(cssFilename) ?? '';
63
- if (lastServedCss.get(cssFilename) !== cssContent) {
64
- lastServedCss.set(cssFilename, cssContent);
65
- devServer.reloadModule(mod);
96
+ const cssContent = cssLookup.get(cssFilename) ?? '';
97
+ const envName = this.environment?.name;
98
+ const seenKey = `${envName ?? ''}:${cssFilename}`;
99
+ if (envName && envName !== 'client') {
100
+ if (lastServedCss.get(seenKey) !== cssContent) {
101
+ lastServedCss.set(seenKey, cssContent);
102
+ invalidateClientCss(cssFilename);
103
+ }
104
+ }
105
+ else if (lastServedCss.get(seenKey) !== cssContent) {
106
+ if (reloadClientCss(cssFilename)) {
107
+ lastServedCss.set(seenKey, cssContent);
108
+ }
109
+ else {
110
+ const mod = devServer.moduleGraph.getModuleById(cssFilename);
111
+ if (mod) {
112
+ lastServedCss.set(seenKey, cssContent);
113
+ devServer.reloadModule(mod);
114
+ }
66
115
  }
67
116
  }
68
117
  }
@@ -80,14 +129,49 @@ function attachViteHooks(plugin, options) {
80
129
  ],
81
130
  },
82
131
  };
83
- if (command === 'build') {
132
+ isBuild = command === 'build';
133
+ isRsc = isRscConfig(userConfig);
134
+ if (isBuild && !isRsc) {
84
135
  configToReturn.build = {
85
136
  ...(userConfig.build ?? {}),
86
137
  cssCodeSplit: false,
87
138
  };
88
139
  }
140
+ if (isBuild && isRsc) {
141
+ configToReturn.environments = {
142
+ rsc: { build: { cssCodeSplit: false } },
143
+ };
144
+ }
89
145
  return configToReturn;
90
146
  },
147
+ buildStart() {
148
+ sheetRef = undefined;
149
+ },
150
+ async buildEnd() {
151
+ if (!isRsc || !isBuild)
152
+ return;
153
+ if (this.environment?.name !== 'rsc')
154
+ return;
155
+ const source = await optimizer([...cssLookup.keys()]
156
+ .sort()
157
+ .map((key) => cssLookup.get(key))
158
+ .join(''));
159
+ if (!source.trim())
160
+ return;
161
+ sheetRef = this.emitFile({
162
+ type: 'asset',
163
+ name: 'plumeria.css',
164
+ source,
165
+ });
166
+ },
167
+ renderChunk(_code, chunk) {
168
+ if (!sheetRef)
169
+ return null;
170
+ if (this.environment?.name !== 'rsc')
171
+ return null;
172
+ chunk.viteMetadata.importedCss.add(this.getFileName(sheetRef));
173
+ return null;
174
+ },
91
175
  configResolved(config) {
92
176
  viteRoot = config.root;
93
177
  setRoot(config.root);
@@ -139,13 +223,15 @@ function attachViteHooks(plugin, options) {
139
223
  };
140
224
  if (!useDiskEmit) {
141
225
  vitePlugin.resolveId = function (importeeUrl) {
142
- const [id] = importeeUrl.split('?', 1);
226
+ const queryIndex = importeeUrl.indexOf('?');
227
+ const id = queryIndex === -1 ? importeeUrl : importeeUrl.slice(0, queryIndex);
228
+ const query = queryIndex === -1 ? '' : importeeUrl.slice(queryIndex);
143
229
  if (cssLookup.has(id)) {
144
- return id;
230
+ return id + query;
145
231
  }
146
232
  const resolved = cssFileLookup.get(id);
147
233
  if (resolved) {
148
- return resolved;
234
+ return resolved + query;
149
235
  }
150
236
  return null;
151
237
  };
package/dist/webpack.js CHANGED
@@ -40,7 +40,13 @@ const path = __importStar(require("path"));
40
40
  const ZERO_CSS_SUFFIX = '(?:$|\\?|%3F)';
41
41
  const VIRTUAL_CSS_PATH = new RegExp(`\\.zero\\.css${ZERO_CSS_SUFFIX}`);
42
42
  function attachWebpackHooks(plugin) {
43
- const { setDev, setRoot } = plugin.__plumeriaInternal;
43
+ const { setDev, setRoot, setCssImport } = plugin.__plumeriaInternal;
44
+ setCssImport(({ id, cssFilename }) => {
45
+ let rel = path.relative(path.dirname(id), cssFilename).replace(/\\/g, '/');
46
+ if (!rel.startsWith('.'))
47
+ rel = `./${rel}`;
48
+ return `\nimport "${rel}?t=${Date.now()}";`;
49
+ });
44
50
  plugin.transformInclude = (id) => {
45
51
  const [pathId] = id.split('?', 1);
46
52
  return (/\.(ts|tsx|js|jsx)$/.test(pathId) &&
@@ -51,25 +57,6 @@ function attachWebpackHooks(plugin) {
51
57
  const [pathId] = id.split('?', 1);
52
58
  return pathId.endsWith('.zero.css');
53
59
  };
54
- const originalTransform = plugin.transform;
55
- plugin.transform = async function (code, id) {
56
- const result = await originalTransform.call(this, code, id);
57
- if (result && typeof result === 'object' && result.code) {
58
- const { cssFileLookup } = plugin.__plumeriaInternal;
59
- result.code = result.code.replace(/import\s+"(\/[^"]+\.zero\.css)";/g, (_match, cssPath) => {
60
- const absoluteCssPath = cssFileLookup.get(cssPath);
61
- if (!absoluteCssPath)
62
- return _match;
63
- let rel = path
64
- .relative(path.dirname(id), absoluteCssPath)
65
- .replace(/\\/g, '/');
66
- if (!rel.startsWith('.'))
67
- rel = `./${rel}`;
68
- return `import "${rel}?t=${Date.now()}";`;
69
- });
70
- }
71
- return result;
72
- };
73
60
  plugin.resolveId = function (id, importer) {
74
61
  const [pathId, query] = id.split('?');
75
62
  const { cssLookup } = plugin.__plumeriaInternal;
package/dist/webpack.mjs CHANGED
@@ -1,10 +1,16 @@
1
1
  import { createWebpackPlugin } from 'unplugin';
2
- import { unpluginFactory } from './core.mjs';
2
+ import { unpluginFactory, } from './core.mjs';
3
3
  import * as path from 'path';
4
4
  const ZERO_CSS_SUFFIX = '(?:$|\\?|%3F)';
5
5
  const VIRTUAL_CSS_PATH = new RegExp(`\\.zero\\.css${ZERO_CSS_SUFFIX}`);
6
6
  export function attachWebpackHooks(plugin) {
7
- const { setDev, setRoot } = plugin.__plumeriaInternal;
7
+ const { setDev, setRoot, setCssImport } = plugin.__plumeriaInternal;
8
+ setCssImport(({ id, cssFilename }) => {
9
+ let rel = path.relative(path.dirname(id), cssFilename).replace(/\\/g, '/');
10
+ if (!rel.startsWith('.'))
11
+ rel = `./${rel}`;
12
+ return `\nimport "${rel}?t=${Date.now()}";`;
13
+ });
8
14
  plugin.transformInclude = (id) => {
9
15
  const [pathId] = id.split('?', 1);
10
16
  return (/\.(ts|tsx|js|jsx)$/.test(pathId) &&
@@ -15,25 +21,6 @@ export function attachWebpackHooks(plugin) {
15
21
  const [pathId] = id.split('?', 1);
16
22
  return pathId.endsWith('.zero.css');
17
23
  };
18
- const originalTransform = plugin.transform;
19
- plugin.transform = async function (code, id) {
20
- const result = await originalTransform.call(this, code, id);
21
- if (result && typeof result === 'object' && result.code) {
22
- const { cssFileLookup } = plugin.__plumeriaInternal;
23
- result.code = result.code.replace(/import\s+"(\/[^"]+\.zero\.css)";/g, (_match, cssPath) => {
24
- const absoluteCssPath = cssFileLookup.get(cssPath);
25
- if (!absoluteCssPath)
26
- return _match;
27
- let rel = path
28
- .relative(path.dirname(id), absoluteCssPath)
29
- .replace(/\\/g, '/');
30
- if (!rel.startsWith('.'))
31
- rel = `./${rel}`;
32
- return `import "${rel}?t=${Date.now()}";`;
33
- });
34
- }
35
- return result;
36
- };
37
24
  plugin.resolveId = function (id, importer) {
38
25
  const [pathId, query] = id.split('?');
39
26
  const { cssLookup } = plugin.__plumeriaInternal;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plumeria/unplugin",
3
- "version": "19.1.2",
3
+ "version": "19.1.3",
4
4
  "description": "Universal Plumeria plugin for various build tools",
5
5
  "author": "Refirst 11",
6
6
  "license": "MIT",
@@ -94,7 +94,7 @@
94
94
  "dependencies": {
95
95
  "@rollup/pluginutils": "^5.4.0",
96
96
  "unplugin": "^3.0.0",
97
- "@plumeria/utils": "^19.1.2"
97
+ "@plumeria/utils": "^19.1.3"
98
98
  },
99
99
  "devDependencies": {
100
100
  "vite": "^8.0.13"