@plumeria/unplugin 18.2.33 → 18.3.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.
package/README.md CHANGED
@@ -196,4 +196,54 @@ If the two disagree, the prop type-checks but is never compiled away. [`@plumeri
196
196
 
197
197
  `@plumeria/unplugin` provides HMR optimized for each bundler in development mode (dev server).
198
198
 
199
- - **Vite / Farm / Webpack / Rspack**: The plugin extracts styles as CSS modules, enabling seamless updates via hot reloading.
199
+ - **Vite / Farm / Webpack / Rspack**: The plugin extracts styles as CSS modules, enabling seamless updates via hot reloading.
200
+
201
+ ## Testing
202
+
203
+ `@plumeria/unplugin/factory` exposes the compiler behind every bundler entry as a plain function. Give it a source string and it hands back the rewritten code, with the stylesheet available from `resolveId` and `load`:
204
+
205
+ ```js
206
+ // compile.test.js
207
+ const { unpluginFactory } = require('@plumeria/unplugin/factory');
208
+
209
+ const compile = async (source) => {
210
+ const plugin = unpluginFactory(undefined, { framework: 'vite' });
211
+ const result = await plugin.transform.call(
212
+ { addWatchFile: () => {} },
213
+ source,
214
+ `${__dirname}/fixture.tsx`,
215
+ );
216
+ const code = typeof result === 'string' ? result : (result?.code ?? '');
217
+ const cssId = code.match(/import "([^"]*\.zero\.css)"/)?.[1];
218
+ const resolved = await plugin.resolveId?.call({}, cssId);
219
+ const loaded = await plugin.load?.call({}, resolved?.id ?? resolved);
220
+ return { code, css: typeof loaded === 'string' ? loaded : (loaded?.code ?? '') };
221
+ };
222
+
223
+ test('two properties become two atoms', async () => {
224
+ const { code, css } = await compile(`
225
+ import * as css from '@plumeria/core';
226
+ const styles = css.create({ box: { padding: 16, color: 'red' } });
227
+ export const A = () => <div classStyle={styles.box} />;
228
+ `);
229
+
230
+ expect(code).toMatch(/className=\{"\S+ \S+"\}/);
231
+ expect(css).toContain('padding: 16px');
232
+ expect(css).toContain('color: red');
233
+ });
234
+ ```
235
+
236
+ No bundler, no DOM, and no runtime resolution of `@plumeria/core` is involved, so Jest, Vitest and `node:test` all run it as it stands. The bundler entries reach `unplugin` itself, which is ESM and cannot be required from a CommonJS runner; this subpath skips them.
237
+
238
+ Read the class names out of the returned code rather than hard-coding them. An atomic class name is one property–value pair, hashed, so a list spelled out in a test breaks the next time a property is added to the style.
239
+
240
+ See [Testing](https://plumeria.dev/docs/testing) for the layer this belongs to, and the two it does not cover.
241
+
242
+ ## API Stability
243
+
244
+ **Stability: Frozen** — the signature will not change; behaviour may still be corrected.
245
+ See [API Stability](https://github.com/zss-in-js/plumeria#api-stability).
246
+
247
+ ## License
248
+
249
+ Plumeria is [MIT licensed](https://github.com/zss-in-js/plumeria/blob/main/LICENSE).
package/dist/core.js CHANGED
@@ -958,7 +958,9 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
958
958
  given.set(String(prop.key.value), prop.value);
959
959
  }
960
960
  });
961
- const argObj = resolveObjectArg(argExpr) ?? {};
961
+ const argObj = argExpr
962
+ ? (resolveObjectArg(argExpr) ?? {})
963
+ : {};
962
964
  func.named.forEach(({ key, local }) => {
963
965
  const source = given.get(key);
964
966
  if (!source) {
package/dist/core.mjs CHANGED
@@ -922,7 +922,9 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
922
922
  given.set(String(prop.key.value), prop.value);
923
923
  }
924
924
  });
925
- const argObj = resolveObjectArg(argExpr) ?? {};
925
+ const argObj = argExpr
926
+ ? (resolveObjectArg(argExpr) ?? {})
927
+ : {};
926
928
  func.named.forEach(({ key, local }) => {
927
929
  const source = given.get(key);
928
930
  if (!source) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plumeria/unplugin",
3
- "version": "18.2.33",
3
+ "version": "18.3.0",
4
4
  "description": "Universal Plumeria plugin for various build tools",
5
5
  "author": "Refirst 11",
6
6
  "license": "MIT",
@@ -36,6 +36,11 @@
36
36
  "import": "./dist/index.mjs",
37
37
  "require": "./dist/index.js"
38
38
  },
39
+ "./factory": {
40
+ "types": "./dist/core.d.ts",
41
+ "import": "./dist/core.mjs",
42
+ "require": "./dist/core.js"
43
+ },
39
44
  "./vite": {
40
45
  "types": "./dist/vite.d.ts",
41
46
  "import": "./dist/vite.mjs",
@@ -89,7 +94,7 @@
89
94
  "dependencies": {
90
95
  "@rollup/pluginutils": "^5.4.0",
91
96
  "unplugin": "^3.0.0",
92
- "@plumeria/utils": "^18.2.33"
97
+ "@plumeria/utils": "^18.3.0"
93
98
  },
94
99
  "devDependencies": {
95
100
  "@swc/core": "1.15.47",