@gjsify/rolldown-plugin-gjsify 0.3.15 → 0.3.16

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/lib/app/gjs.js CHANGED
@@ -122,7 +122,11 @@ export const setupForGjs = async (input) => {
122
122
  }),
123
123
  blueprintPlugin(),
124
124
  deepkitPlugin({ reflection: input.pluginOptions.reflection }),
125
- cssAsStringPlugin(),
125
+ // GTK4's CSS engine is much older than browser engines — its
126
+ // parser predates nesting + many modern selectors. Targeting
127
+ // `firefox: 60 << 16` makes lightningcss flatten the source
128
+ // into the subset GTK4 understands.
129
+ cssAsStringPlugin({ targets: { firefox: 60 << 16 } }),
126
130
  nodeModulesPathRewritePlugin({ bundleDir }),
127
131
  processStubPlugin({ userBanner: input.userBanner }),
128
132
  // resolveShebangLine returns null when disabled (false/undefined) and
@@ -1,2 +1,19 @@
1
1
  import type { Plugin } from 'rolldown';
2
- export declare function cssAsStringPlugin(): Plugin;
2
+ export interface CssAsStringOptions {
3
+ /**
4
+ * lightningcss browser targets passed to `bundleAsync`. When set,
5
+ * nesting + modern syntax are lowered for the given engines. The
6
+ * GJS orchestrator defaults this to `{ firefox: 60 << 16 }` to
7
+ * match the GTK4 CSS parser. Omit or leave undefined to skip
8
+ * lowering (output stays as-authored except for `@import` inlining).
9
+ */
10
+ targets?: import('lightningcss').Targets;
11
+ /**
12
+ * When true (default), `@import` statements are resolved by
13
+ * lightningcss `bundleAsync`. Set false to fall back to a plain
14
+ * `readFile` — useful only when you want to keep `@import` strings
15
+ * verbatim in the bundled JS (rare).
16
+ */
17
+ bundle?: boolean;
18
+ }
19
+ export declare function cssAsStringPlugin(options?: CssAsStringOptions): Plugin;
@@ -12,18 +12,27 @@
12
12
  //
13
13
  // — the canonical pattern for `Gtk.CssProvider` under GJS.
14
14
  //
15
- // `@import` resolution is left to the user / CSS preprocessor. For simple
16
- // app CSS this is fine; for @import-heavy CSS, run a preprocessor (e.g.
17
- // sass / postcss) ahead of `gjsify build` so the input file is already
18
- // flat.
15
+ // `@import` resolution + nesting/modern-syntax lowering are handled via
16
+ // lightningcss `bundleAsync`. The defaults work for the common case
17
+ // (resolve `@import`s, no targeting); the `--app gjs` orchestrator passes
18
+ // `targets: { firefox: 60 << 16 }` so nesting + modern selectors get
19
+ // flattened to GTK4-CSS-engine-compatible output. Targeting is opt-in —
20
+ // a missing `targets` keeps the source pristine.
21
+ //
22
+ // `lightningcss` is a regular dependency of this package; the plugin
23
+ // imports it lazily so missing-arch installs surface the underlying
24
+ // load error instead of crashing every gjsify build.
19
25
  import { readFile } from 'node:fs/promises';
20
- export function cssAsStringPlugin() {
26
+ export function cssAsStringPlugin(options = {}) {
27
+ const { targets, bundle = true } = options;
21
28
  return {
22
29
  name: 'gjsify-css-as-string',
23
30
  load: {
24
31
  filter: { id: /\.css$/ },
25
32
  async handler(id) {
26
- const code = await readFile(id, 'utf8');
33
+ const code = bundle
34
+ ? new TextDecoder('utf-8').decode(await loadAndBundleCss(id, targets))
35
+ : await readFile(id, 'utf8');
27
36
  return {
28
37
  code: `export default ${JSON.stringify(code)};`,
29
38
  moduleType: 'js',
@@ -32,3 +41,13 @@ export function cssAsStringPlugin() {
32
41
  },
33
42
  };
34
43
  }
44
+ async function loadAndBundleCss(filename, targets) {
45
+ const { bundleAsync } = await import('lightningcss');
46
+ const result = await bundleAsync({
47
+ filename,
48
+ targets,
49
+ minify: false,
50
+ errorRecovery: true,
51
+ });
52
+ return result.code;
53
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/rolldown-plugin-gjsify",
3
- "version": "0.3.15",
3
+ "version": "0.3.16",
4
4
  "description": "Rolldown / Rollup / Vite plugin orchestrator for GJS, Node, and Browser targets",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -42,10 +42,10 @@
42
42
  ],
43
43
  "license": "MIT",
44
44
  "dependencies": {
45
- "@gjsify/resolve-npm": "^0.3.15",
46
- "@gjsify/rolldown-plugin-deepkit": "^0.3.15",
47
- "@gjsify/rolldown-plugin-pnp": "^0.3.15",
48
- "@gjsify/vite-plugin-blueprint": "^0.3.15",
45
+ "@gjsify/resolve-npm": "^0.3.16",
46
+ "@gjsify/rolldown-plugin-deepkit": "^0.3.16",
47
+ "@gjsify/rolldown-plugin-pnp": "^0.3.16",
48
+ "@gjsify/vite-plugin-blueprint": "^0.3.16",
49
49
  "@rollup/pluginutils": "^5.1.4",
50
50
  "acorn": "^8.14.0",
51
51
  "acorn-walk": "^8.3.4",
package/src/app/gjs.ts CHANGED
@@ -165,7 +165,11 @@ export const setupForGjs = async (input: GjsFactoryInput): Promise<GjsBuildConfi
165
165
  }),
166
166
  blueprintPlugin() as RolldownPluginOption,
167
167
  deepkitPlugin({ reflection: input.pluginOptions.reflection }),
168
- cssAsStringPlugin(),
168
+ // GTK4's CSS engine is much older than browser engines — its
169
+ // parser predates nesting + many modern selectors. Targeting
170
+ // `firefox: 60 << 16` makes lightningcss flatten the source
171
+ // into the subset GTK4 understands.
172
+ cssAsStringPlugin({ targets: { firefox: 60 << 16 } }),
169
173
  nodeModulesPathRewritePlugin({ bundleDir }),
170
174
  processStubPlugin({ userBanner: input.userBanner }),
171
175
  // resolveShebangLine returns null when disabled (false/undefined) and
@@ -12,21 +12,48 @@
12
12
  //
13
13
  // — the canonical pattern for `Gtk.CssProvider` under GJS.
14
14
  //
15
- // `@import` resolution is left to the user / CSS preprocessor. For simple
16
- // app CSS this is fine; for @import-heavy CSS, run a preprocessor (e.g.
17
- // sass / postcss) ahead of `gjsify build` so the input file is already
18
- // flat.
15
+ // `@import` resolution + nesting/modern-syntax lowering are handled via
16
+ // lightningcss `bundleAsync`. The defaults work for the common case
17
+ // (resolve `@import`s, no targeting); the `--app gjs` orchestrator passes
18
+ // `targets: { firefox: 60 << 16 }` so nesting + modern selectors get
19
+ // flattened to GTK4-CSS-engine-compatible output. Targeting is opt-in —
20
+ // a missing `targets` keeps the source pristine.
21
+ //
22
+ // `lightningcss` is a regular dependency of this package; the plugin
23
+ // imports it lazily so missing-arch installs surface the underlying
24
+ // load error instead of crashing every gjsify build.
19
25
 
20
26
  import { readFile } from 'node:fs/promises';
21
27
  import type { Plugin } from 'rolldown';
22
28
 
23
- export function cssAsStringPlugin(): Plugin {
29
+ export interface CssAsStringOptions {
30
+ /**
31
+ * lightningcss browser targets passed to `bundleAsync`. When set,
32
+ * nesting + modern syntax are lowered for the given engines. The
33
+ * GJS orchestrator defaults this to `{ firefox: 60 << 16 }` to
34
+ * match the GTK4 CSS parser. Omit or leave undefined to skip
35
+ * lowering (output stays as-authored except for `@import` inlining).
36
+ */
37
+ targets?: import('lightningcss').Targets;
38
+ /**
39
+ * When true (default), `@import` statements are resolved by
40
+ * lightningcss `bundleAsync`. Set false to fall back to a plain
41
+ * `readFile` — useful only when you want to keep `@import` strings
42
+ * verbatim in the bundled JS (rare).
43
+ */
44
+ bundle?: boolean;
45
+ }
46
+
47
+ export function cssAsStringPlugin(options: CssAsStringOptions = {}): Plugin {
48
+ const { targets, bundle = true } = options;
24
49
  return {
25
50
  name: 'gjsify-css-as-string',
26
51
  load: {
27
52
  filter: { id: /\.css$/ },
28
53
  async handler(id: string) {
29
- const code = await readFile(id, 'utf8');
54
+ const code = bundle
55
+ ? new TextDecoder('utf-8').decode(await loadAndBundleCss(id, targets))
56
+ : await readFile(id, 'utf8');
30
57
  return {
31
58
  code: `export default ${JSON.stringify(code)};`,
32
59
  moduleType: 'js' as const,
@@ -35,3 +62,17 @@ export function cssAsStringPlugin(): Plugin {
35
62
  },
36
63
  };
37
64
  }
65
+
66
+ async function loadAndBundleCss(
67
+ filename: string,
68
+ targets: import('lightningcss').Targets | undefined,
69
+ ): Promise<Uint8Array> {
70
+ const { bundleAsync } = await import('lightningcss');
71
+ const result = await bundleAsync({
72
+ filename,
73
+ targets,
74
+ minify: false,
75
+ errorRecovery: true,
76
+ });
77
+ return result.code;
78
+ }