@riebeckite/core 0.0.31 → 0.0.32

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/client.d.ts CHANGED
@@ -1,2 +1,4 @@
1
+ export type { ClientCleanup, ClientInitializer, ClientInitializerContext, ClientLifecycleErrorContext, ClientLifecycleMount, ClientLifecycleOptions, ClientLifecycleScope, ClientResourceScope, } from "./src/client_lifecycle.js";
2
+ export { ClientLifecycle } from "./src/client_lifecycle.js";
1
3
  export type { ForceGraphLayoutOptions, ForceLayoutGuardOptions, GraphEdge, GraphLayoutNode, LinkableGraphNode, RadialGraphLayoutOptions, } from "./src/content/graph_layout.js";
2
4
  export { buildGraphEdges, FORCE_LAYOUT_CONFIRM_NODE_COUNT, layoutForceGraph, layoutRadialGraph, shouldGuardForceLayout, } from "./src/content/graph_layout.js";
package/dist/client.js CHANGED
@@ -1,3 +1,179 @@
1
+ // src/client_lifecycle.ts
2
+ var ClientLifecycle = class {
3
+ mounted = /* @__PURE__ */ new Map();
4
+ scopes = /* @__PURE__ */ new Map();
5
+ onError;
6
+ constructor(options = {}) {
7
+ this.onError = options.onError ?? defaultErrorReporter;
8
+ }
9
+ mount(mount) {
10
+ const scoped = this.scoped(mount.scope);
11
+ const current = scoped.get(mount.name);
12
+ if (current) {
13
+ if (current.root === mount.root) return current.ready;
14
+ throw new Error(
15
+ `Client initializer "${mount.name}" is already mounted in ${mount.scope} scope.`
16
+ );
17
+ }
18
+ const scope = this.scopeState(mount.scope);
19
+ const resources = new InitializerResources(
20
+ scope.controller,
21
+ (error) => this.report(error, {
22
+ scope: mount.scope,
23
+ name: mount.name,
24
+ phase: "cleanup"
25
+ })
26
+ );
27
+ const cleanup = this.initialize(mount, resources);
28
+ const ready = cleanup.then(() => void 0);
29
+ const mounted = { root: mount.root, resources, cleanup, ready };
30
+ scoped.set(mount.name, mounted);
31
+ return ready;
32
+ }
33
+ async unmount(scope) {
34
+ const scoped = this.mounted.get(scope);
35
+ const state = this.scopes.get(scope);
36
+ this.mounted.delete(scope);
37
+ this.scopes.delete(scope);
38
+ state?.controller.abort();
39
+ if (!scoped) return;
40
+ await Promise.all(
41
+ [...scoped.entries()].map(
42
+ ([name, mounted]) => this.cleanupMounted(scope, name, mounted)
43
+ )
44
+ );
45
+ }
46
+ async dispose() {
47
+ await Promise.all([this.unmount("page"), this.unmount("app")]);
48
+ }
49
+ scoped(scope) {
50
+ let scoped = this.mounted.get(scope);
51
+ if (!scoped) {
52
+ scoped = /* @__PURE__ */ new Map();
53
+ this.mounted.set(scope, scoped);
54
+ }
55
+ return scoped;
56
+ }
57
+ scopeState(scope) {
58
+ let state = this.scopes.get(scope);
59
+ if (!state) {
60
+ state = { controller: new AbortController() };
61
+ this.scopes.set(scope, state);
62
+ }
63
+ return state;
64
+ }
65
+ async initialize(mount, resources) {
66
+ try {
67
+ const result = await mount.initialize({
68
+ root: mount.root,
69
+ signal: resources.signal,
70
+ scope: resources,
71
+ config: mount.config
72
+ });
73
+ return typeof result === "function" ? result : void 0;
74
+ } catch (error) {
75
+ await resources.dispose();
76
+ this.report(error, {
77
+ scope: mount.scope,
78
+ name: mount.name,
79
+ phase: "initialize"
80
+ });
81
+ return void 0;
82
+ }
83
+ }
84
+ async cleanupMounted(scope, name, mounted) {
85
+ const [cleanup] = await Promise.all([
86
+ mounted.cleanup,
87
+ mounted.resources.dispose()
88
+ ]);
89
+ try {
90
+ await cleanup?.();
91
+ } catch (error) {
92
+ this.report(error, { scope, name, phase: "cleanup" });
93
+ }
94
+ }
95
+ report(error, context) {
96
+ try {
97
+ this.onError(error, context);
98
+ } catch {
99
+ return;
100
+ }
101
+ }
102
+ };
103
+ var InitializerResources = class {
104
+ constructor(controller, report) {
105
+ this.controller = controller;
106
+ this.report = report;
107
+ }
108
+ controller;
109
+ report;
110
+ cleanups = [];
111
+ listeners = [];
112
+ timers = /* @__PURE__ */ new Set();
113
+ intervals = /* @__PURE__ */ new Set();
114
+ disposed = false;
115
+ get signal() {
116
+ return this.controller.signal;
117
+ }
118
+ on(target, type, listener, options) {
119
+ if (this.disposed || this.signal.aborted) return;
120
+ target.addEventListener(type, listener, {
121
+ ...options,
122
+ signal: this.signal
123
+ });
124
+ this.listeners.push({ target, type, listener, options });
125
+ }
126
+ timeout(callback, delay = 0) {
127
+ if (this.disposed || this.signal.aborted) return;
128
+ const timer = setTimeout(() => {
129
+ this.timers.delete(timer);
130
+ if (!this.disposed && !this.signal.aborted) callback();
131
+ }, delay);
132
+ this.timers.add(timer);
133
+ }
134
+ interval(callback, delay = 0) {
135
+ if (this.disposed || this.signal.aborted) return;
136
+ const interval = setInterval(() => {
137
+ if (!this.disposed && !this.signal.aborted) callback();
138
+ }, delay);
139
+ this.intervals.add(interval);
140
+ }
141
+ cleanup(cleanup) {
142
+ if (this.disposed) {
143
+ void this.run(cleanup);
144
+ return;
145
+ }
146
+ this.cleanups.push(cleanup);
147
+ }
148
+ async dispose() {
149
+ if (this.disposed) return;
150
+ this.disposed = true;
151
+ for (const { target, type, listener, options } of this.listeners) {
152
+ target.removeEventListener(type, listener, options);
153
+ }
154
+ this.listeners.length = 0;
155
+ for (const timer of this.timers) clearTimeout(timer);
156
+ for (const interval of this.intervals) clearInterval(interval);
157
+ this.timers.clear();
158
+ this.intervals.clear();
159
+ const cleanups = this.cleanups.splice(0).reverse();
160
+ await Promise.all(cleanups.map((cleanup) => this.run(cleanup)));
161
+ }
162
+ async run(cleanup) {
163
+ try {
164
+ await cleanup();
165
+ } catch (error) {
166
+ this.report(error);
167
+ }
168
+ }
169
+ };
170
+ function defaultErrorReporter(error, context) {
171
+ console.error(
172
+ `[riebeckite] Client initializer ${context.phase} failed: ${context.name}`,
173
+ error
174
+ );
175
+ }
176
+
1
177
  // src/content/graph_layout.ts
2
178
  var FORCE_LAYOUT_CONFIRM_NODE_COUNT = 500;
3
179
  function shouldGuardForceLayout(options) {
@@ -176,6 +352,7 @@ function clampFinite(value, min, max) {
176
352
  return clamp(value, min, max);
177
353
  }
178
354
  export {
355
+ ClientLifecycle,
179
356
  FORCE_LAYOUT_CONFIRM_NODE_COUNT,
180
357
  buildGraphEdges,
181
358
  layoutForceGraph,
package/dist/index.d.ts CHANGED
@@ -47,6 +47,7 @@ export { PluginDependencyError, type PluginDependencyErrorKind, } from "./src/pl
47
47
  export { PluginHookError } from "./src/plugin/plugin_lifecycle.js";
48
48
  export type { CreatePluginMemoOptions, PluginMemo, } from "./src/plugin/plugin_memo.js";
49
49
  export { createPluginMemo, stableStringify, } from "./src/plugin/plugin_memo.js";
50
+ export { PluginRuntime } from "./src/plugin/plugin_runtime.js";
50
51
  export { resolveBuildOutputDirectory, resolveManagedStateRoot, } from "./src/project/project_layout.js";
51
52
  export type { ConfigValidationIssue, PluginOptionsValidator, } from "./src/types/config_validation.js";
52
53
  export type { ContentAsset, ContentFileMetadata, ContentLink, ContentLinkKind, ContentLocationInput, ContentManifest, ContentManifestEntry, ContentManifestPluginClientEntry, ContentPublicLocation, ContentRedirect, FolderLocation, PluginPageRoute, } from "./src/types/content_manifest.js";
@@ -73,7 +74,7 @@ export type { PostContent, PostFrontmatter } from "./src/types/post_content.js";
73
74
  export type { PublishFrontmatter, PublishStrategy, } from "./src/types/publish_strategy.js";
74
75
  export { isPublishable } from "./src/types/publish_strategy.js";
75
76
  export type { ResolvedRiebeckiteConfig } from "./src/types/resolved_riebeckite_config.js";
76
- export type { RiebeckiteConfig } from "./src/types/riebeckite_config.js";
77
+ export type { RiebeckiteConfig, SpaConfig, } from "./src/types/riebeckite_config.js";
77
78
  export type { SiteConfig } from "./src/types/site_config.js";
78
79
  export type { RiebeckiteTheme, ThemeArticleLayoutPreset, ThemeAttributes, ThemeColorMode, ThemeConfig, ThemeDesignTokens, ThemeInput, ThemeStyle, ThemeTypographyPreset, } from "./src/types/theme_config.js";
79
80
  export { defineTheme } from "./src/types/theme_config.js";
package/dist/index.js CHANGED
@@ -20,6 +20,7 @@ function validateConfigIssues(config) {
20
20
  validateSite(value.site, issues);
21
21
  validateContent(value.content, issues);
22
22
  validateCache(value.cache, issues);
23
+ validateSpa(value.spa, issues);
23
24
  validateTheme(value.theme, issues);
24
25
  validatePlugins(value.plugins, issues);
25
26
  return issues;
@@ -103,6 +104,12 @@ function validateCache(value, issues) {
103
104
  validateOptionalBoolean(value.enabled, "cache.enabled", issues);
104
105
  validateOptionalString(value.directory, "cache.directory", issues);
105
106
  }
107
+ function validateSpa(value, issues) {
108
+ if (value === void 0 || typeof value === "boolean" || isRecord(value)) {
109
+ return;
110
+ }
111
+ issues.push({ path: "spa", message: "Expected a boolean or an object." });
112
+ }
106
113
  function validateTheme(value, issues) {
107
114
  if (value === void 0) return;
108
115
  if (!isRecord(value)) {
@@ -680,6 +687,7 @@ function isConfigModuleWrapper(value) {
680
687
  function resolveConfig(config) {
681
688
  validateConfig(config);
682
689
  const theme = resolveThemeConfig(config.theme);
690
+ const spa = resolveSpaConfig(config.spa);
683
691
  return {
684
692
  site: {
685
693
  title: config.site?.title ?? "",
@@ -708,9 +716,14 @@ function resolveConfig(config) {
708
716
  cache: {
709
717
  enabled: config.cache?.enabled ?? true,
710
718
  directory: config.cache?.directory ?? ""
711
- }
719
+ },
720
+ ...spa === void 0 ? {} : { spa }
712
721
  };
713
722
  }
723
+ function resolveSpaConfig(spa) {
724
+ if (spa === void 0 || spa === false) return void 0;
725
+ return spa === true ? {} : spa;
726
+ }
714
727
  function resolveThemeConfig(themeInput) {
715
728
  const theme = themeInput ? isRiebeckiteTheme(themeInput) ? { name: themeInput.name, ...themeInput.config } : themeInput : void 0;
716
729
  const styles = themeInput ? isRiebeckiteTheme(themeInput) ? themeInput.styles ?? [] : [defaultThemeStyle] : [defaultThemeStyle];
@@ -2519,6 +2532,34 @@ function rejectInternalRiebeckitePath(normalized, input) {
2519
2532
  }
2520
2533
 
2521
2534
  // src/pipeline.ts
2535
+ function isPluginTable(node) {
2536
+ const className = node.properties?.className;
2537
+ const names = Array.isArray(className) ? className : [className];
2538
+ return names.some(
2539
+ (name) => typeof name === "string" && (name.startsWith("rb-") || name.startsWith("rr-"))
2540
+ );
2541
+ }
2542
+ function wrapMarkdownTables() {
2543
+ return (tree) => {
2544
+ wrapTableChildren(tree);
2545
+ };
2546
+ }
2547
+ function wrapTableChildren(parent) {
2548
+ if (!parent.children) return;
2549
+ parent.children = parent.children.map((child) => {
2550
+ const node = child;
2551
+ if (node.type === "element" && node.tagName === "table" && !isPluginTable(node)) {
2552
+ return {
2553
+ type: "element",
2554
+ tagName: "div",
2555
+ properties: { className: ["rb-table-scroll"] },
2556
+ children: [child]
2557
+ };
2558
+ }
2559
+ wrapTableChildren(node);
2560
+ return child;
2561
+ });
2562
+ }
2522
2563
  var Pipeline = class {
2523
2564
  constructor(contentIndex, permalinks, getMarkdownBySlug, options = {}, isBuildTime = false) {
2524
2565
  this.contentIndex = contentIndex;
@@ -2694,6 +2735,7 @@ var Pipeline = class {
2694
2735
  }
2695
2736
  });
2696
2737
  }
2738
+ this.use(processor, wrapMarkdownTables);
2697
2739
  this.use(processor, rehypeSlug);
2698
2740
  this.use(processor, rehypeKatex, { output: "mathml", strict: false });
2699
2741
  this.use(processor, rehypeFormat);
@@ -2903,12 +2945,14 @@ function createStyleAsset(pluginName, moduleSpecifier) {
2903
2945
  moduleSpecifier
2904
2946
  };
2905
2947
  }
2906
- function createClientEntry(pluginName, moduleSpecifier, exportName, publicConfig) {
2948
+ function createClientEntry(pluginName, moduleSpecifier, exportName, publicConfig, scope, initializerArguments) {
2907
2949
  return {
2908
2950
  pluginName,
2909
2951
  moduleSpecifier,
2910
2952
  ...exportName === void 0 ? {} : { exportName },
2911
- ...publicConfig === void 0 ? {} : { publicConfig }
2953
+ ...publicConfig === void 0 ? {} : { publicConfig },
2954
+ ...scope === void 0 ? {} : { scope },
2955
+ ...initializerArguments === void 0 ? {} : { initializerArguments }
2912
2956
  };
2913
2957
  }
2914
2958
  function serializePublicClientConfig(value) {
@@ -3423,7 +3467,8 @@ var PluginPageResolver = class {
3423
3467
  const context = {
3424
3468
  ...this.options.createContext(contentIndex),
3425
3469
  manifest,
3426
- pathname: pagePathname
3470
+ pathname: pagePathname,
3471
+ renderMarkdown: this.options.renderMarkdown
3427
3472
  };
3428
3473
  const page = await pageType.resolve(
3429
3474
  this.options.createPluginContext(plugin, context)
@@ -3478,7 +3523,8 @@ var PluginPageResolver = class {
3478
3523
  const context = {
3479
3524
  ...this.options.createContext(contentIndex),
3480
3525
  manifest,
3481
- pathname
3526
+ pathname,
3527
+ renderMarkdown: this.options.renderMarkdown
3482
3528
  };
3483
3529
  const dependencies = pageType.outputDependencies ? typeof pageType.outputDependencies === "function" ? await pageType.outputDependencies(
3484
3530
  this.options.createPluginContext(plugin, context)
@@ -3618,7 +3664,13 @@ var PluginRuntime = class {
3618
3664
  this.pageResolver = new PluginPageResolver({
3619
3665
  plugins: () => this.plugins(),
3620
3666
  createContext: (contentIndex) => this.createContext(contentIndex),
3621
- createPluginContext: (plugin, context) => this.createPluginContext(plugin, context)
3667
+ createPluginContext: (plugin, context) => this.createPluginContext(plugin, context),
3668
+ renderMarkdown: async (markdown) => {
3669
+ if (!this.pageMarkdownRenderer) {
3670
+ throw new Error("Plugin page Markdown renderer is unavailable.");
3671
+ }
3672
+ return await this.pageMarkdownRenderer(markdown);
3673
+ }
3622
3674
  });
3623
3675
  this.manifestHooks = new ManifestHookRunner({
3624
3676
  plugins: () => this.plugins(),
@@ -3641,9 +3693,13 @@ var PluginRuntime = class {
3641
3693
  externalDependenciesResolved = false;
3642
3694
  pageResolver;
3643
3695
  manifestHooks;
3696
+ pageMarkdownRenderer = null;
3644
3697
  getDiagnostics() {
3645
3698
  return this.diagnostics;
3646
3699
  }
3700
+ setPageMarkdownRenderer(renderer) {
3701
+ this.pageMarkdownRenderer = renderer;
3702
+ }
3647
3703
  getManifestHookMetrics() {
3648
3704
  return this.manifestHooks.getMetrics();
3649
3705
  }
@@ -5641,6 +5697,12 @@ var ContentManager = class {
5641
5697
  this.contentIndexBuilder = new ContentIndexBuilder(this.source);
5642
5698
  this.manifestAssembler = new ManifestAssembler(this.contentCache);
5643
5699
  this.pluginRuntime = new PluginRuntime(this.pipelineOptions);
5700
+ this.pluginRuntime.setPageMarkdownRenderer(async (markdown) => {
5701
+ if (!this.pipeline) {
5702
+ throw new Error("Markdown pipeline is unavailable for plugin pages.");
5703
+ }
5704
+ return (await this.pipeline.execute(markdown)).html;
5705
+ });
5644
5706
  const buildStatePath = resolveContentBuildStatePath(
5645
5707
  pipelineOptions.config,
5646
5708
  typeof content === "string" ? content : void 0
@@ -6847,6 +6909,7 @@ export {
6847
6909
  Pipeline,
6848
6910
  PluginDependencyError,
6849
6911
  PluginHookError,
6912
+ PluginRuntime,
6850
6913
  SinkTracer,
6851
6914
  attachErrorPath,
6852
6915
  attachmentUrl,
@@ -0,0 +1,45 @@
1
+ export type ClientLifecycleScope = "app" | "page";
2
+ export type ClientCleanup = () => void | Promise<void>;
3
+ export type ClientResourceScope = {
4
+ readonly signal: AbortSignal;
5
+ on(target: EventTarget, type: string, listener: EventListenerOrEventListenerObject, options?: Omit<AddEventListenerOptions, "signal">): void;
6
+ timeout(callback: () => void, delay?: number): void;
7
+ interval(callback: () => void, delay?: number): void;
8
+ cleanup(cleanup: ClientCleanup): void;
9
+ };
10
+ export type ClientInitializerContext<TRoot, TConfig> = {
11
+ root: TRoot;
12
+ signal: AbortSignal;
13
+ scope: ClientResourceScope;
14
+ config: TConfig;
15
+ };
16
+ export type ClientInitializer<TRoot, TConfig> = (context: ClientInitializerContext<TRoot, TConfig>) => undefined | ClientCleanup | Promise<undefined | ClientCleanup>;
17
+ export type ClientLifecycleErrorContext = {
18
+ scope: ClientLifecycleScope;
19
+ name: string;
20
+ phase: "initialize" | "cleanup";
21
+ };
22
+ export type ClientLifecycleOptions = {
23
+ onError?: (error: unknown, context: ClientLifecycleErrorContext) => void;
24
+ };
25
+ export type ClientLifecycleMount<TRoot, TConfig> = {
26
+ scope: ClientLifecycleScope;
27
+ name: string;
28
+ root: TRoot;
29
+ config: TConfig;
30
+ initialize: ClientInitializer<TRoot, TConfig>;
31
+ };
32
+ export declare class ClientLifecycle<TRoot> {
33
+ private readonly mounted;
34
+ private readonly scopes;
35
+ private readonly onError;
36
+ constructor(options?: ClientLifecycleOptions);
37
+ mount<TConfig>(mount: ClientLifecycleMount<TRoot, TConfig>): Promise<void>;
38
+ unmount(scope: ClientLifecycleScope): Promise<void>;
39
+ dispose(): Promise<void>;
40
+ private scoped;
41
+ private scopeState;
42
+ private initialize;
43
+ private cleanupMounted;
44
+ private report;
45
+ }
@@ -7,6 +7,7 @@ type PluginPageResolverOptions = {
7
7
  readonly plugins: () => readonly RiebeckitePlugin[];
8
8
  readonly createContext: (contentIndex: Map<string, string>) => PluginContextBase;
9
9
  readonly createPluginContext: <TContext extends PluginContextBase>(plugin: RiebeckitePlugin, context: TContext) => PluginContextWithCache<TContext>;
10
+ readonly renderMarkdown: (markdown: string) => Promise<string>;
10
11
  };
11
12
  export declare class PluginPageResolver {
12
13
  private readonly options;
@@ -25,8 +25,10 @@ export declare class PluginRuntime {
25
25
  private externalDependenciesResolved;
26
26
  private readonly pageResolver;
27
27
  private readonly manifestHooks;
28
+ private pageMarkdownRenderer;
28
29
  constructor(pipelineOptions?: PipelineOptions);
29
30
  getDiagnostics(): Diagnostic[];
31
+ setPageMarkdownRenderer(renderer: (markdown: string) => Promise<string>): void;
30
32
  getManifestHookMetrics(): ManifestHookMetrics;
31
33
  getNoChangeFastPathBlockReason(previousCache: readonly ManifestHookCacheEntry[], pipelineFingerprint: string | undefined): string | undefined;
32
34
  getManifestHookCache(): readonly ManifestHookCacheEntry[];
@@ -1,3 +1,4 @@
1
+ import type { ClientLifecycleScope } from "../client_lifecycle.js";
1
2
  import type { JsonValue } from "./json_value.js";
2
3
  export type PluginAssetKind = "style" | "script";
3
4
  export type PluginAsset = {
@@ -9,6 +10,8 @@ export type PluginClientEntry<TPublicConfig extends JsonValue = JsonValue> = {
9
10
  pluginName: string;
10
11
  moduleSpecifier: string;
11
12
  exportName?: string;
13
+ scope?: ClientLifecycleScope;
14
+ initializerArguments?: ClientInitializerArguments;
12
15
  /**
13
16
  * Configuration intentionally made available to this browser entry.
14
17
  *
@@ -18,8 +21,9 @@ export type PluginClientEntry<TPublicConfig extends JsonValue = JsonValue> = {
18
21
  */
19
22
  publicConfig?: TPublicConfig;
20
23
  };
24
+ export type ClientInitializerArguments = "config" | "root" | "context";
21
25
  export declare function createStyleAsset(pluginName: string, moduleSpecifier: string): PluginAsset;
22
- export declare function createClientEntry<TPublicConfig extends JsonValue>(pluginName: string, moduleSpecifier: string, exportName?: string, publicConfig?: TPublicConfig): PluginClientEntry<TPublicConfig>;
26
+ export declare function createClientEntry<TPublicConfig extends JsonValue>(pluginName: string, moduleSpecifier: string, exportName?: string, publicConfig?: TPublicConfig, scope?: ClientLifecycleScope, initializerArguments?: ClientInitializerArguments): PluginClientEntry<TPublicConfig>;
23
27
  /**
24
28
  * Serializes explicitly registered client configuration for code generation.
25
29
  * Rejecting non-JSON values prevents generated client modules from silently
@@ -59,6 +59,7 @@ export type PluginRenderTarget = {
59
59
  label: string;
60
60
  url: string;
61
61
  embed: boolean;
62
+ fragment?: string;
62
63
  };
63
64
  export type PluginRenderContext = PluginContext & PluginRenderTarget;
64
65
  export type PluginContentRenderer = {
@@ -72,6 +73,7 @@ export type PluginRenderInput = {
72
73
  label: string;
73
74
  url: string;
74
75
  embed: boolean;
76
+ fragment?: string;
75
77
  };
76
78
  export type PluginGeneratedHtml = {
77
79
  /** Output-relative path of the generated HTML file (e.g. "index.html"). */
@@ -26,6 +26,7 @@ export type PluginPageContext = PluginContext & {
26
26
  manifest: ContentManifest;
27
27
  /** Request pathname, normalized to an absolute path. */
28
28
  pathname: string;
29
+ renderMarkdown(markdown: string): Promise<string>;
29
30
  };
30
31
  export type PluginPageType = {
31
32
  /** Globally unique, stable page type identifier. */
@@ -1,6 +1,7 @@
1
1
  import type { ContentSource } from "../content/content_source.js";
2
2
  import type { RiebeckitePlugin } from "./plugin.js";
3
3
  import type { PublishStrategy } from "./publish_strategy.js";
4
+ import type { SpaConfig } from "./riebeckite_config.js";
4
5
  import type { SiteConfig } from "./site_config.js";
5
6
  import type { ThemeConfig, ThemeStyle } from "./theme_config.js";
6
7
  export type ResolvedRiebeckiteConfig = {
@@ -38,4 +39,5 @@ export type ResolvedRiebeckiteConfig = {
38
39
  enabled: boolean;
39
40
  directory: string;
40
41
  };
42
+ spa?: SpaConfig;
41
43
  };
@@ -3,6 +3,11 @@ import type { PluginInput } from "./plugin.js";
3
3
  import type { PublishStrategy } from "./publish_strategy.js";
4
4
  import type { SiteConfig } from "./site_config.js";
5
5
  import type { ThemeInput } from "./theme_config.js";
6
+ export type SpaConfig = {
7
+ prefetch?: false | "hover";
8
+ scrollRestoration?: boolean;
9
+ viewTransitions?: boolean;
10
+ };
6
11
  export interface RiebeckiteConfig {
7
12
  site: SiteConfig;
8
13
  content?: {
@@ -19,4 +24,5 @@ export interface RiebeckiteConfig {
19
24
  enabled?: boolean;
20
25
  directory?: string;
21
26
  };
27
+ spa?: boolean | SpaConfig;
22
28
  }
@@ -7,6 +7,9 @@ export type ThemeDesignTokens = {
7
7
  ink?: string;
8
8
  muted?: string;
9
9
  accent?: string;
10
+ link?: string;
11
+ focus?: string;
12
+ selected?: string;
10
13
  border?: string;
11
14
  borderStrong?: string;
12
15
  surface?: string;
@@ -15,6 +18,8 @@ export type ThemeDesignTokens = {
15
18
  danger?: string;
16
19
  success?: string;
17
20
  codeBackground?: string;
21
+ codeInk?: string;
22
+ codeInline?: string;
18
23
  };
19
24
  typography?: {
20
25
  bodyFont?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riebeckite/core",
3
- "version": "0.0.31",
3
+ "version": "0.0.32",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -49,7 +49,7 @@
49
49
  },
50
50
  "devDependencies": {
51
51
  "tsx": "^4.22.4",
52
- "@riebeckite/test": "0.0.31"
52
+ "@riebeckite/test": "0.0.32"
53
53
  },
54
54
  "repository": {
55
55
  "type": "git",