@ogygia/core 0.12.1 → 0.12.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.
@@ -5,6 +5,7 @@ import { debarrel } from "../compiler/debarrel/plugin.js";
5
5
  import { BuildContext, MacroContext, MacroHandler, MarkupRegions, MarkupSource, OgygiaPlugin, PluginDefinition, definePlugin } from "./plugin-api.js";
6
6
  import { DebarrelOptions, Matcher } from "../compiler/debarrel/options.js";
7
7
  import { OgygiaOptions, OgygiaPreset, OgygiaRateLimit } from "./options.js";
8
+ import { PreprocessorGroup } from "svelte/compiler";
8
9
  import { Plugin } from "vite";
9
10
  /**
10
11
  * Vite plugin: transforms `with { hydrate | defer | preset }` imports into islands,
@@ -16,4 +17,16 @@ import { Plugin } from "vite";
16
17
  * @returns Vite plugins (`ogygia` pre + island sourcemap fix post). Vite flattens the array.
17
18
  */
18
19
  export declare function ogygia(options?: OgygiaOptions): Plugin[];
20
+ export declare namespace ogygia {
21
+ /**
22
+ * @deprecated Does nothing: returns `['.svelte']`. Markdown extensions come from
23
+ * `extensions()` in `@ogygia/content/vite`.
24
+ */
25
+ export const extensions: () => string[];
26
+ /**
27
+ * @deprecated Does nothing: returns `[]`. The markdown preprocessor comes from `preprocess()` in
28
+ * `@ogygia/content/vite`.
29
+ */
30
+ export const preprocess: () => PreprocessorGroup[];
31
+ }
19
32
  export { type BuildContext, CLIENT_BINDING_STUB, DEFAULT_IMPORT_KEYS, type Matcher as DebarrelMatcher, type DebarrelOptions, type ImportKeys, type MacroContext, type MacroHandler, type MarkupRegions, type MarkupSource, type OgygiaOptions, type OgygiaPlugin, type OgygiaPreset, type OgygiaRateLimit, type PluginDefinition, debarrel, definePlugin, import_keys_hint, islandChunkFileName, islandId, islandPublicUrl, normalize_import_keys, regionId, regionIdentity, rewrite_lake_import_to_placeholder, strategyKey, wrapperVirtualId };
@@ -16,7 +16,7 @@ import { fill_profiler_maps } from "./profiler-maps.js";
16
16
  import { DEFAULT_REGION_TTL_SEC } from "../server/endpoint.js";
17
17
  import { RENEW_WINDOW_SEC } from "../server/shared-cache.js";
18
18
  import { derive_id_salt, secret_has_min_entropy } from "../server/hmac.js";
19
- import { buildFoucCssModuleSource, collectFoucCssReachable, compileFoucScopedCss, foucRelFromId, isFoucCssId, isFoucScopedId } from "../compiler/fouc-css.js";
19
+ import { buildFoucCssModuleSource, collectFoucCssReachable, compileFoucScopedCss, foucRelFromId, isFoucCssId, isFoucScopedId, svelteHasStyle } from "../compiler/fouc-css.js";
20
20
  import { preprocess_component_for_css } from "./style-preprocess.js";
21
21
  import { needs_csr_false_full_reload, needs_island_entry_full_reload } from "../compiler/dev/hmr.js";
22
22
  import { derive_css_scope_owners } from "../compiler/dev/css-scope.js";
@@ -104,6 +104,31 @@ function ogygia(options = {}) {
104
104
  let id_salt = "";
105
105
  /** content_css_key → emitted CSS asset referenceId (client leg). Resolved to hrefs in writeBundle. */
106
106
  const content_css_refs = /* @__PURE__ */ new Map();
107
+ const compiled_css = /* @__PURE__ */ new Map();
108
+ const tree_css_walk = (ctx) => {
109
+ const walk_resolve = bundler_resolve(ctx);
110
+ return async (abs, opts = {}) => {
111
+ const { own, skip } = opts;
112
+ const parts = [];
113
+ for (const e of await collectFoucCssReachable(abs, {
114
+ root,
115
+ libDir,
116
+ readFile: own == null ? readFile : (p) => p === abs ? own : readFile(p),
117
+ alias: resolve_alias,
118
+ resolve: walk_resolve
119
+ })) {
120
+ if (own != null && e.abs === abs || skip?.(e.abs)) continue;
121
+ let css = compiled_css.get(e.abs);
122
+ if (css === void 0) {
123
+ const src = readFile(e.abs);
124
+ css = src == null ? null : e.kind === "scoped" ? compileFoucScopedCss(e.abs, await preprocess_component_for_css(src, e.abs, root), { keepScript: true }) : CSS_EXT_RE.test(e.abs) ? src : null;
125
+ compiled_css.set(e.abs, css);
126
+ }
127
+ if (css) parts.push(css);
128
+ }
129
+ return parts.join("\n");
130
+ };
131
+ };
107
132
  /** router-css `rcss:<rel>` key → emitted CSS asset referenceId (client leg). A server router page
108
133
  * component's whole-tree scoped CSS, compiled + emitted as a dedicated asset (link/router-css.ts). */
109
134
  const router_css_refs = /* @__PURE__ */ new Map();
@@ -394,85 +419,32 @@ function ogygia(options = {}) {
394
419
  loaded
395
420
  });
396
421
  if (skipped && isMainThread) console.log(`[ogygia] ${skipped} island chunk(s) not emitted: their host modules are not in the server bundle (unreachable from this build's routes).`);
422
+ compiled_css.clear();
423
+ const tree_css = tree_css_walk(this);
397
424
  router_css_refs.clear();
398
- const walk_resolve = bundler_resolve(this);
399
425
  for (const abs of compiler.router_css_roots()) {
400
- const parts = [];
401
- for (const e of await collectFoucCssReachable(abs, {
402
- root,
403
- libDir,
404
- readFile,
405
- alias: resolve_alias,
406
- resolve: walk_resolve
407
- })) if (e.kind === "scoped") {
408
- const src = readFile(e.abs);
409
- if (src == null) continue;
410
- const css = compileFoucScopedCss(e.abs, await preprocess_component_for_css(src, e.abs, root), { keepScript: true });
411
- if (css) parts.push(css);
412
- } else if (CSS_EXT_RE.test(e.abs)) {
413
- const css = readFile(e.abs);
414
- if (css) parts.push(css);
415
- }
416
- if (!parts.length) continue;
417
- const ref = this.emitFile({
426
+ const source = await tree_css(abs);
427
+ if (source) router_css_refs.set(router_css_key(root, abs), this.emitFile({
418
428
  type: "asset",
419
429
  name: "og-rcss.css",
420
- source: parts.join("\n")
421
- });
422
- router_css_refs.set(router_css_key(root, abs), ref);
430
+ source
431
+ }));
423
432
  }
424
433
  hole_css_refs.clear();
425
434
  const hole_css_by_abs = /* @__PURE__ */ new Map();
426
435
  for (const { iid, abs } of compiler.server_island_css_roots()) {
427
436
  let ref = hole_css_by_abs.get(abs);
428
437
  if (ref === void 0) {
429
- const parts = [];
430
- for (const e of await collectFoucCssReachable(abs, {
431
- root,
432
- libDir,
433
- readFile,
434
- alias: resolve_alias,
435
- resolve: walk_resolve
436
- })) if (e.kind === "scoped") {
437
- const src = readFile(e.abs);
438
- if (src == null) continue;
439
- const css = compileFoucScopedCss(e.abs, await preprocess_component_for_css(src, e.abs, root), { keepScript: true });
440
- if (css) parts.push(css);
441
- } else if (CSS_EXT_RE.test(e.abs)) {
442
- const css = readFile(e.abs);
443
- if (css) parts.push(css);
444
- }
445
- ref = parts.length ? this.emitFile({
438
+ const source = await tree_css(abs);
439
+ ref = source ? this.emitFile({
446
440
  type: "asset",
447
441
  name: "og-hole.css",
448
- source: parts.join("\n")
442
+ source
449
443
  }) : "";
450
444
  hole_css_by_abs.set(abs, ref);
451
445
  }
452
446
  if (ref) hole_css_refs.set(iid, ref);
453
447
  }
454
- content_css_refs.clear();
455
- const styles = markup.flatMap((m) => m.styles ? [...m.styles] : []);
456
- if (styles.length) {
457
- const { compile } = await import("svelte/compiler");
458
- for (const [abs, source] of styles) try {
459
- const { css } = compile(source, {
460
- filename: abs,
461
- css: "external",
462
- dev: false,
463
- generate: "client",
464
- experimental: { async: true }
465
- });
466
- if (css?.code) {
467
- const ref = this.emitFile({
468
- type: "asset",
469
- name: "og-content.css",
470
- source: css.code
471
- });
472
- content_css_refs.set(content_css_key(abs), ref);
473
- }
474
- } catch {}
475
- }
476
448
  }
477
449
  },
478
450
  configureServer(server) {
@@ -699,13 +671,43 @@ function ogygia(options = {}) {
699
671
  chunkFileNames: ours(output.chunkFileNames, "[name]-[hash].js")
700
672
  };
701
673
  },
702
- generateBundle() {
674
+ async generateBundle() {
703
675
  if (!is_build || server_leg_of(this)) return;
704
676
  for (const file of compiler.location_maps((ref) => this.getFileName(ref))) this.emitFile({
705
677
  type: "asset",
706
678
  fileName: file.fileName,
707
679
  source: file.source
708
680
  });
681
+ content_css_refs.clear();
682
+ const modules = markup.flatMap((m) => m.modules ? [...m.modules] : []);
683
+ if (!modules.length) return;
684
+ const client = /* @__PURE__ */ new Set();
685
+ for (const id of this.getModuleIds()) client.add(path.normalize(id.split("?")[0]));
686
+ const tree_css = tree_css_walk(this);
687
+ const { compile } = await import("svelte/compiler");
688
+ for (const [abs, source] of modules) try {
689
+ let own = "";
690
+ if (svelteHasStyle(source)) {
691
+ const { css } = compile(source, {
692
+ filename: abs,
693
+ css: "external",
694
+ dev: false,
695
+ generate: "client",
696
+ experimental: { async: true }
697
+ });
698
+ own = css?.code ?? "";
699
+ }
700
+ const tree = await tree_css(abs, {
701
+ own: source,
702
+ skip: (p) => client.has(p)
703
+ });
704
+ const css = [own, tree].filter(Boolean).join("\n");
705
+ if (css) content_css_refs.set(content_css_key(abs), this.emitFile({
706
+ type: "asset",
707
+ name: "og-content.css",
708
+ source: css
709
+ }));
710
+ } catch {}
709
711
  },
710
712
  closeBundle: {
711
713
  order: "pre",
@@ -818,4 +820,8 @@ function ogygia(options = {}) {
818
820
  server_sourcemaps_plugin(() => measure)
819
821
  ];
820
822
  }
823
+ Object.assign(ogygia, {
824
+ extensions: () => [".svelte"],
825
+ preprocess: () => []
826
+ });
821
827
  export { CLIENT_BINDING_STUB, DEFAULT_IMPORT_KEYS, debarrel, definePlugin, import_keys_hint, islandChunkFileName, islandId, islandPublicUrl, normalize_import_keys, ogygia, regionId, regionIdentity, rewrite_lake_import_to_placeholder, strategyKey, wrapperVirtualId };
@@ -40,7 +40,7 @@ export interface MacroContext {
40
40
  readonly markupExts: readonly string[];
41
41
  }
42
42
  /** A source format that becomes Svelte only through a preprocessor (markdown → Svelte): how its
43
- * islands and its modules' own scoped CSS reach the build. */
43
+ * islands and its modules' CSS reach the build. */
44
44
  export interface MarkupSource {
45
45
  /** The format's file extensions (`['.svx', '.md']`). */
46
46
  extensions: readonly string[];
@@ -50,10 +50,11 @@ export interface MarkupSource {
50
50
  root: string;
51
51
  readFile(abs: string): string | null;
52
52
  }): void | Promise<void>;
53
- /** Modules that carry their OWN scoped `<style>`, absolute path → their post-preprocess Svelte
54
- * source: the build compiles each one's CSS and ships it as a client asset (the module itself
55
- * only ever renders on the server). The plugin keeps filling this map; the build reads it late. */
56
- styles?: ReadonlyMap<string, string>;
53
+ /** The format's modules, absolute path → their post-preprocess Svelte source. A module only ever
54
+ * renders on the server, so no client chunk carries its CSS: the build ships, as one client asset
55
+ * per module, the scoped CSS of its own `<style>` and of every component it imports (and plain
56
+ * style imports). The plugin keeps filling this map; the build reads it late. */
57
+ modules?: ReadonlyMap<string, string>;
57
58
  }
58
59
  /** What the build hands back for a markup source: run the region transform on preprocessed Svelte. */
59
60
  export interface MarkupRegions {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ogygia/core",
3
- "version": "0.12.1",
3
+ "version": "0.12.3",
4
4
  "description": "The core of ogygia (SSR islands for SvelteKit): apps install `ogygia`, plugins build on this",
5
5
  "homepage": "https://ogygiajs.dev",
6
6
  "bugs": {