@riebeckite/core 0.0.30 → 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 +2 -0
- package/dist/client.js +177 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +111 -35
- package/dist/src/client_lifecycle.d.ts +45 -0
- package/dist/src/content/content_build_state.d.ts +2 -1
- package/dist/src/content/manifest_hook_cache.d.ts +1 -1
- package/dist/src/plugin/manifest_hooks.d.ts +1 -0
- package/dist/src/plugin/plugin_pages.d.ts +1 -0
- package/dist/src/plugin/plugin_runtime.d.ts +2 -0
- package/dist/src/types/content_manifest.d.ts +0 -7
- package/dist/src/types/plugin.d.ts +3 -0
- package/dist/src/types/plugin_asset.d.ts +5 -1
- package/dist/src/types/plugin_context.d.ts +2 -0
- package/dist/src/types/plugin_endpoint.d.ts +2 -0
- package/dist/src/types/plugin_page.d.ts +1 -0
- package/dist/src/types/resolved_riebeckite_config.d.ts +2 -0
- package/dist/src/types/riebeckite_config.d.ts +6 -0
- package/dist/src/types/theme_config.d.ts +5 -0
- package/package.json +2 -2
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];
|
|
@@ -826,7 +839,7 @@ function getFileName(filePath) {
|
|
|
826
839
|
}
|
|
827
840
|
|
|
828
841
|
// src/content/content_build_state.ts
|
|
829
|
-
var CONTENT_BUILD_STATE_VERSION =
|
|
842
|
+
var CONTENT_BUILD_STATE_VERSION = 20;
|
|
830
843
|
var CONTENT_BUILD_STATE_DIRECTORY = ".riebeckite";
|
|
831
844
|
var CONTENT_BUILD_STATE_EXCLUDE = `${CONTENT_BUILD_STATE_DIRECTORY}/**`;
|
|
832
845
|
|
|
@@ -834,8 +847,11 @@ var CONTENT_BUILD_STATE_EXCLUDE = `${CONTENT_BUILD_STATE_DIRECTORY}/**`;
|
|
|
834
847
|
import { randomUUID } from "node:crypto";
|
|
835
848
|
import fs from "node:fs/promises";
|
|
836
849
|
import path from "node:path";
|
|
850
|
+
var MAX_CONTENT_BUILD_STATE_BYTES = 64 * 1024 * 1024;
|
|
837
851
|
async function loadContentBuildState(statePath) {
|
|
838
852
|
try {
|
|
853
|
+
const metadata = await fs.stat(statePath);
|
|
854
|
+
if (metadata.size > MAX_CONTENT_BUILD_STATE_BYTES) return void 0;
|
|
839
855
|
const parsed = JSON.parse(await fs.readFile(statePath, "utf8"));
|
|
840
856
|
return isContentBuildState(parsed) ? parsed : void 0;
|
|
841
857
|
} catch {
|
|
@@ -922,7 +938,7 @@ function isContentBuildStateShape(value) {
|
|
|
922
938
|
}
|
|
923
939
|
function isManifestHookCache(value) {
|
|
924
940
|
return Array.isArray(value) && value.every(
|
|
925
|
-
(entry) => isRecord2(entry) && typeof entry.pluginName === "string" && typeof entry.cacheable === "boolean" && (entry.pipelineFingerprint === void 0 || typeof entry.pipelineFingerprint === "string") && typeof entry.inputFingerprint === "string" && (entry.outputFingerprint === void 0 || typeof entry.outputFingerprint === "string") && (entry.snapshot === void 0 || isManifestHookSnapshot(entry.snapshot))
|
|
941
|
+
(entry) => isRecord2(entry) && typeof entry.pluginName === "string" && typeof entry.cacheVersion === "string" && typeof entry.cacheable === "boolean" && (entry.pipelineFingerprint === void 0 || typeof entry.pipelineFingerprint === "string") && typeof entry.inputFingerprint === "string" && (entry.outputFingerprint === void 0 || typeof entry.outputFingerprint === "string") && (entry.snapshot === void 0 || isManifestHookSnapshot(entry.snapshot))
|
|
926
942
|
);
|
|
927
943
|
}
|
|
928
944
|
function isManifestHookSnapshot(value) {
|
|
@@ -2516,6 +2532,34 @@ function rejectInternalRiebeckitePath(normalized, input) {
|
|
|
2516
2532
|
}
|
|
2517
2533
|
|
|
2518
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
|
+
}
|
|
2519
2563
|
var Pipeline = class {
|
|
2520
2564
|
constructor(contentIndex, permalinks, getMarkdownBySlug, options = {}, isBuildTime = false) {
|
|
2521
2565
|
this.contentIndex = contentIndex;
|
|
@@ -2691,6 +2735,7 @@ var Pipeline = class {
|
|
|
2691
2735
|
}
|
|
2692
2736
|
});
|
|
2693
2737
|
}
|
|
2738
|
+
this.use(processor, wrapMarkdownTables);
|
|
2694
2739
|
this.use(processor, rehypeSlug);
|
|
2695
2740
|
this.use(processor, rehypeKatex, { output: "mathml", strict: false });
|
|
2696
2741
|
this.use(processor, rehypeFormat);
|
|
@@ -2900,12 +2945,14 @@ function createStyleAsset(pluginName, moduleSpecifier) {
|
|
|
2900
2945
|
moduleSpecifier
|
|
2901
2946
|
};
|
|
2902
2947
|
}
|
|
2903
|
-
function createClientEntry(pluginName, moduleSpecifier, exportName, publicConfig) {
|
|
2948
|
+
function createClientEntry(pluginName, moduleSpecifier, exportName, publicConfig, scope, initializerArguments) {
|
|
2904
2949
|
return {
|
|
2905
2950
|
pluginName,
|
|
2906
2951
|
moduleSpecifier,
|
|
2907
2952
|
...exportName === void 0 ? {} : { exportName },
|
|
2908
|
-
...publicConfig === void 0 ? {} : { publicConfig }
|
|
2953
|
+
...publicConfig === void 0 ? {} : { publicConfig },
|
|
2954
|
+
...scope === void 0 ? {} : { scope },
|
|
2955
|
+
...initializerArguments === void 0 ? {} : { initializerArguments }
|
|
2909
2956
|
};
|
|
2910
2957
|
}
|
|
2911
2958
|
function serializePublicClientConfig(value) {
|
|
@@ -2991,16 +3038,18 @@ function serializeManifestEntries(entries) {
|
|
|
2991
3038
|
serialized.set(entry.slug, JSON.stringify(entry));
|
|
2992
3039
|
return serialized;
|
|
2993
3040
|
}
|
|
2994
|
-
function createManifestHookCacheEntry(pluginName, cacheable, pipelineFingerprint, inputFingerprint, manifest, beforeEntries, afterEntries) {
|
|
3041
|
+
function createManifestHookCacheEntry(pluginName, cacheVersion, cacheable, pipelineFingerprint, inputFingerprint, manifest, beforeEntries, afterEntries) {
|
|
2995
3042
|
if (!cacheable)
|
|
2996
3043
|
return {
|
|
2997
3044
|
pluginName,
|
|
3045
|
+
cacheVersion,
|
|
2998
3046
|
cacheable,
|
|
2999
3047
|
pipelineFingerprint,
|
|
3000
3048
|
inputFingerprint
|
|
3001
3049
|
};
|
|
3002
3050
|
return {
|
|
3003
3051
|
pluginName,
|
|
3052
|
+
cacheVersion,
|
|
3004
3053
|
cacheable,
|
|
3005
3054
|
pipelineFingerprint,
|
|
3006
3055
|
inputFingerprint,
|
|
@@ -3282,9 +3331,10 @@ var ManifestHookRunner = class {
|
|
|
3282
3331
|
if (plugin.buildEnd) return "plugin-build-end";
|
|
3283
3332
|
if (plugin.planGeneratedOutputs) return "plugin-generated-output-plan";
|
|
3284
3333
|
if (!plugin.onManifestCreated) continue;
|
|
3334
|
+
if (!plugin.manifestHookCache) return "manifest-hook-cache-disabled";
|
|
3285
3335
|
const cached = previousCache[cacheIndex];
|
|
3286
3336
|
cacheIndex += 1;
|
|
3287
|
-
if (cached?.pluginName !== plugin.name || !cached.cacheable || cached.pipelineFingerprint !== pipelineFingerprint)
|
|
3337
|
+
if (cached?.pluginName !== plugin.name || cached.cacheVersion !== plugin.manifestHookCache.version || !cached.cacheable || cached.pipelineFingerprint !== pipelineFingerprint)
|
|
3288
3338
|
return "manifest-hook-cache-miss";
|
|
3289
3339
|
}
|
|
3290
3340
|
return void 0;
|
|
@@ -3298,10 +3348,14 @@ var ManifestHookRunner = class {
|
|
|
3298
3348
|
manifest
|
|
3299
3349
|
};
|
|
3300
3350
|
let cacheIndex = 0;
|
|
3301
|
-
let entriesBeforeHook = serializeManifestEntries(manifest.entries);
|
|
3302
3351
|
for (const plugin of this.options.plugins()) {
|
|
3303
3352
|
const hook = plugin.onManifestCreated;
|
|
3304
3353
|
if (!hook) continue;
|
|
3354
|
+
const cacheVersion = plugin.manifestHookCache?.version;
|
|
3355
|
+
if (!cacheVersion) {
|
|
3356
|
+
await this.runManifestHook(plugin, hook, context, "cache-disabled");
|
|
3357
|
+
continue;
|
|
3358
|
+
}
|
|
3305
3359
|
const inputFingerprint = fingerprintManifestHookInput(manifest);
|
|
3306
3360
|
const cached = previousCache[cacheIndex];
|
|
3307
3361
|
cacheIndex += 1;
|
|
@@ -3313,46 +3367,29 @@ var ManifestHookRunner = class {
|
|
|
3313
3367
|
);
|
|
3314
3368
|
let restored = false;
|
|
3315
3369
|
let restorePoint;
|
|
3316
|
-
if (cached !== void 0 && cached.pluginName === plugin.name && cached.cacheable && cached.pipelineFingerprint === pipelineFingerprint && cached.inputFingerprint === inputFingerprint && cached.snapshot !== void 0 && cached.outputFingerprint !== void 0) {
|
|
3370
|
+
if (cached !== void 0 && cached.pluginName === plugin.name && cached.cacheVersion === cacheVersion && cached.cacheable && cached.pipelineFingerprint === pipelineFingerprint && cached.inputFingerprint === inputFingerprint && cached.snapshot !== void 0 && cached.outputFingerprint !== void 0) {
|
|
3317
3371
|
restorePoint = captureManifestHookRestorePoint(manifest);
|
|
3318
3372
|
restored = applyManifestHookSnapshot(manifest, cached.snapshot);
|
|
3319
3373
|
if (restored && fingerprintManifestHookSnapshot(manifest) === cached.outputFingerprint) {
|
|
3320
3374
|
this.manifestHooksReused += 1;
|
|
3321
3375
|
this.manifestHookCache.push(cached);
|
|
3322
3376
|
this.recordManifestHookMetric(plugin.name, "reused", "cache-hit", 0);
|
|
3323
|
-
entriesBeforeHook = serializeManifestEntries(manifest.entries);
|
|
3324
3377
|
continue;
|
|
3325
3378
|
}
|
|
3326
3379
|
}
|
|
3327
3380
|
if (restored && restorePoint)
|
|
3328
3381
|
restoreManifestHookEntries(manifest, restorePoint);
|
|
3382
|
+
const entriesBeforeHook = serializeManifestEntries(manifest.entries);
|
|
3329
3383
|
const sideEffectsBefore = fingerprintManifestHookSideEffects(manifest);
|
|
3330
3384
|
const outputCountBefore = this.options.generatedOutputCount();
|
|
3331
3385
|
const diagnosticCountBefore = this.options.diagnosticCount();
|
|
3332
3386
|
const manifestDiagnosticCountBefore = manifest.diagnostics.length;
|
|
3333
|
-
|
|
3334
|
-
this.manifestHooksExecuted += 1;
|
|
3335
|
-
try {
|
|
3336
|
-
await runPluginHook(
|
|
3337
|
-
plugin,
|
|
3338
|
-
"onManifestCreated",
|
|
3339
|
-
this.options.createPluginContext(plugin, context),
|
|
3340
|
-
hook
|
|
3341
|
-
);
|
|
3342
|
-
} finally {
|
|
3343
|
-
const durationMs = performance.now() - started;
|
|
3344
|
-
this.manifestHookDurationMs += durationMs;
|
|
3345
|
-
this.recordManifestHookMetric(
|
|
3346
|
-
plugin.name,
|
|
3347
|
-
"executed",
|
|
3348
|
-
reason,
|
|
3349
|
-
durationMs
|
|
3350
|
-
);
|
|
3351
|
-
}
|
|
3387
|
+
await this.runManifestHook(plugin, hook, context, reason);
|
|
3352
3388
|
const entriesAfterHook = serializeManifestEntries(manifest.entries);
|
|
3353
3389
|
this.manifestHookCache.push(
|
|
3354
3390
|
createManifestHookCacheEntry(
|
|
3355
3391
|
plugin.name,
|
|
3392
|
+
cacheVersion,
|
|
3356
3393
|
plugin.resolveExternalDependencies === void 0 && sideEffectsBefore === fingerprintManifestHookSideEffects(manifest) && outputCountBefore === this.options.generatedOutputCount() && diagnosticCountBefore === this.options.diagnosticCount() && manifestDiagnosticCountBefore === manifest.diagnostics.length,
|
|
3357
3394
|
pipelineFingerprint,
|
|
3358
3395
|
inputFingerprint,
|
|
@@ -3361,7 +3398,27 @@ var ManifestHookRunner = class {
|
|
|
3361
3398
|
entriesAfterHook
|
|
3362
3399
|
)
|
|
3363
3400
|
);
|
|
3364
|
-
|
|
3401
|
+
}
|
|
3402
|
+
}
|
|
3403
|
+
async runManifestHook(plugin, hook, context, reason) {
|
|
3404
|
+
const started = performance.now();
|
|
3405
|
+
this.manifestHooksExecuted += 1;
|
|
3406
|
+
try {
|
|
3407
|
+
await runPluginHook(
|
|
3408
|
+
plugin,
|
|
3409
|
+
"onManifestCreated",
|
|
3410
|
+
this.options.createPluginContext(plugin, context),
|
|
3411
|
+
hook
|
|
3412
|
+
);
|
|
3413
|
+
} finally {
|
|
3414
|
+
const durationMs = performance.now() - started;
|
|
3415
|
+
this.manifestHookDurationMs += durationMs;
|
|
3416
|
+
this.recordManifestHookMetric(
|
|
3417
|
+
plugin.name,
|
|
3418
|
+
"executed",
|
|
3419
|
+
reason,
|
|
3420
|
+
durationMs
|
|
3421
|
+
);
|
|
3365
3422
|
}
|
|
3366
3423
|
}
|
|
3367
3424
|
recordManifestHookMetric(pluginName, outcome, reason, durationMs) {
|
|
@@ -3410,7 +3467,8 @@ var PluginPageResolver = class {
|
|
|
3410
3467
|
const context = {
|
|
3411
3468
|
...this.options.createContext(contentIndex),
|
|
3412
3469
|
manifest,
|
|
3413
|
-
pathname: pagePathname
|
|
3470
|
+
pathname: pagePathname,
|
|
3471
|
+
renderMarkdown: this.options.renderMarkdown
|
|
3414
3472
|
};
|
|
3415
3473
|
const page = await pageType.resolve(
|
|
3416
3474
|
this.options.createPluginContext(plugin, context)
|
|
@@ -3465,7 +3523,8 @@ var PluginPageResolver = class {
|
|
|
3465
3523
|
const context = {
|
|
3466
3524
|
...this.options.createContext(contentIndex),
|
|
3467
3525
|
manifest,
|
|
3468
|
-
pathname
|
|
3526
|
+
pathname,
|
|
3527
|
+
renderMarkdown: this.options.renderMarkdown
|
|
3469
3528
|
};
|
|
3470
3529
|
const dependencies = pageType.outputDependencies ? typeof pageType.outputDependencies === "function" ? await pageType.outputDependencies(
|
|
3471
3530
|
this.options.createPluginContext(plugin, context)
|
|
@@ -3605,7 +3664,13 @@ var PluginRuntime = class {
|
|
|
3605
3664
|
this.pageResolver = new PluginPageResolver({
|
|
3606
3665
|
plugins: () => this.plugins(),
|
|
3607
3666
|
createContext: (contentIndex) => this.createContext(contentIndex),
|
|
3608
|
-
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
|
+
}
|
|
3609
3674
|
});
|
|
3610
3675
|
this.manifestHooks = new ManifestHookRunner({
|
|
3611
3676
|
plugins: () => this.plugins(),
|
|
@@ -3628,9 +3693,13 @@ var PluginRuntime = class {
|
|
|
3628
3693
|
externalDependenciesResolved = false;
|
|
3629
3694
|
pageResolver;
|
|
3630
3695
|
manifestHooks;
|
|
3696
|
+
pageMarkdownRenderer = null;
|
|
3631
3697
|
getDiagnostics() {
|
|
3632
3698
|
return this.diagnostics;
|
|
3633
3699
|
}
|
|
3700
|
+
setPageMarkdownRenderer(renderer) {
|
|
3701
|
+
this.pageMarkdownRenderer = renderer;
|
|
3702
|
+
}
|
|
3634
3703
|
getManifestHookMetrics() {
|
|
3635
3704
|
return this.manifestHooks.getMetrics();
|
|
3636
3705
|
}
|
|
@@ -5628,6 +5697,12 @@ var ContentManager = class {
|
|
|
5628
5697
|
this.contentIndexBuilder = new ContentIndexBuilder(this.source);
|
|
5629
5698
|
this.manifestAssembler = new ManifestAssembler(this.contentCache);
|
|
5630
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
|
+
});
|
|
5631
5706
|
const buildStatePath = resolveContentBuildStatePath(
|
|
5632
5707
|
pipelineOptions.config,
|
|
5633
5708
|
typeof content === "string" ? content : void 0
|
|
@@ -6026,7 +6101,7 @@ var ContentManager = class {
|
|
|
6026
6101
|
/** Resolves a page contributed by an enabled plugin. */
|
|
6027
6102
|
async resolvePage(pathname) {
|
|
6028
6103
|
const [manifest, contentIndex] = await Promise.all([
|
|
6029
|
-
this.getManifest(),
|
|
6104
|
+
this.getManifest({ incremental: false }),
|
|
6030
6105
|
this.getContentIndex()
|
|
6031
6106
|
]);
|
|
6032
6107
|
return await this.pluginRuntime.resolvePage(
|
|
@@ -6089,7 +6164,7 @@ var ContentManager = class {
|
|
|
6089
6164
|
}
|
|
6090
6165
|
requestBuildStateCommit(options) {
|
|
6091
6166
|
if (this.pipelineOptions.commitBuildState === false) return;
|
|
6092
|
-
if (options?.incremental
|
|
6167
|
+
if (options?.incremental !== false) this.buildStateCommitRequested = true;
|
|
6093
6168
|
}
|
|
6094
6169
|
async commitBuildState() {
|
|
6095
6170
|
if (this.buildStateCommitted || !this.buildStateCommitRequested || !this.manifest || !this.outputChangeSet) {
|
|
@@ -6834,6 +6909,7 @@ export {
|
|
|
6834
6909
|
Pipeline,
|
|
6835
6910
|
PluginDependencyError,
|
|
6836
6911
|
PluginHookError,
|
|
6912
|
+
PluginRuntime,
|
|
6837
6913
|
SinkTracer,
|
|
6838
6914
|
attachErrorPath,
|
|
6839
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
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ContentManifestEntry } from "../types/content_manifest.js";
|
|
2
2
|
import type { ContentSourceEntry } from "./content_source.js";
|
|
3
3
|
import type { OutputDescriptor } from "./output_dependency.js";
|
|
4
|
-
export declare const CONTENT_BUILD_STATE_VERSION =
|
|
4
|
+
export declare const CONTENT_BUILD_STATE_VERSION = 20;
|
|
5
5
|
/**
|
|
6
6
|
* Build state lives under `<content directory>/.riebeckite`. That directory is
|
|
7
7
|
* build-time state, not content, so content sources must exclude it from scans
|
|
@@ -33,6 +33,7 @@ export type ContentBuildState = {
|
|
|
33
33
|
};
|
|
34
34
|
export type ManifestHookCacheEntry = {
|
|
35
35
|
readonly pluginName: string;
|
|
36
|
+
readonly cacheVersion: string;
|
|
36
37
|
readonly cacheable: boolean;
|
|
37
38
|
readonly pipelineFingerprint: string | undefined;
|
|
38
39
|
readonly inputFingerprint: string;
|
|
@@ -2,7 +2,7 @@ import type { ContentManifest, ContentManifestEntry } from "../types/content_man
|
|
|
2
2
|
import type { ManifestHookCacheEntry, ManifestHookSnapshot } from "./content_build_state.js";
|
|
3
3
|
export declare function fingerprintManifestHookInput(manifest: ContentManifest): string;
|
|
4
4
|
export declare function serializeManifestEntries(entries: readonly ContentManifestEntry[]): Map<string, string>;
|
|
5
|
-
export declare function createManifestHookCacheEntry(pluginName: string, cacheable: boolean, pipelineFingerprint: string | undefined, inputFingerprint: string, manifest: ContentManifest, beforeEntries: ReadonlyMap<string, string>, afterEntries: ReadonlyMap<string, string>): ManifestHookCacheEntry;
|
|
5
|
+
export declare function createManifestHookCacheEntry(pluginName: string, cacheVersion: string, cacheable: boolean, pipelineFingerprint: string | undefined, inputFingerprint: string, manifest: ContentManifest, beforeEntries: ReadonlyMap<string, string>, afterEntries: ReadonlyMap<string, string>): ManifestHookCacheEntry;
|
|
6
6
|
export declare function fingerprintManifestHookSideEffects(manifest: ContentManifest): string;
|
|
7
7
|
export declare function fingerprintManifestHookSnapshot(manifest: ContentManifest): string;
|
|
8
8
|
export type ManifestHookRestorePoint = {
|
|
@@ -37,6 +37,7 @@ export declare class ManifestHookRunner {
|
|
|
37
37
|
getNoChangeFastPathBlockReason(previousCache: readonly ManifestHookCacheEntry[], pipelineFingerprint: string | undefined): string | undefined;
|
|
38
38
|
getCache(): readonly ManifestHookCacheEntry[];
|
|
39
39
|
runManifestCreated(manifest: ContentManifest, contentIndex: Map<string, string>, previousCache: readonly ManifestHookCacheEntry[], pipelineFingerprint: string | undefined): Promise<void>;
|
|
40
|
+
private runManifestHook;
|
|
40
41
|
private recordManifestHookMetric;
|
|
41
42
|
}
|
|
42
43
|
export {};
|
|
@@ -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[];
|
|
@@ -23,13 +23,6 @@ export type ContentAsset = {
|
|
|
23
23
|
export type ContentManifestPluginAsset = PluginAsset & {
|
|
24
24
|
path: string;
|
|
25
25
|
};
|
|
26
|
-
/**
|
|
27
|
-
* The standard `article.*` positions the article consumer recognizes.
|
|
28
|
-
*
|
|
29
|
-
* These constants are a convenience for Sites that prefer named references;
|
|
30
|
-
* writing the slot string inline (for example `name="article.metadata"`) stays
|
|
31
|
-
* the recommended, most readable form in TSX layouts.
|
|
32
|
-
*/
|
|
33
26
|
/** Client entries and their explicitly public configuration. */
|
|
34
27
|
export type ContentManifestPluginClientEntry = PluginClientEntry;
|
|
35
28
|
export type ContentManifestEntry = {
|
|
@@ -74,6 +74,9 @@ export type RiebeckitePlugin<TOptions = unknown> = {
|
|
|
74
74
|
extendContentLocations?(context: PluginContentLocationAugmentContext): void | Promise<void>;
|
|
75
75
|
onPostParsed?(context: PluginPostContext): void | Promise<void>;
|
|
76
76
|
onPostProcessed?(context: PluginPostContext): void | Promise<void>;
|
|
77
|
+
manifestHookCache?: {
|
|
78
|
+
version: string;
|
|
79
|
+
};
|
|
77
80
|
onManifestCreated?(context: PluginManifestContext): void | Promise<void>;
|
|
78
81
|
extendMarkdownPipeline?(pipeline: MarkdownPipeline, context: MarkdownPipelineContext): void;
|
|
79
82
|
extendHtmlPipeline?(pipeline: HtmlPipeline): void;
|
|
@@ -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"). */
|
|
@@ -36,6 +36,8 @@ export type PluginEndpoint = {
|
|
|
36
36
|
path: string;
|
|
37
37
|
/** Defaults to `GET` when omitted. */
|
|
38
38
|
method?: PluginEndpointMethod;
|
|
39
|
+
/** Defaults to `true`; set to `false` for endpoints that only use configuration. */
|
|
40
|
+
requiresManifest?: boolean;
|
|
39
41
|
handler(context: PluginEndpointContext): PluginEndpointResponse | Promise<PluginEndpointResponse>;
|
|
40
42
|
};
|
|
41
43
|
export type PluginEndpointOptions = {
|
|
@@ -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.
|
|
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.
|
|
52
|
+
"@riebeckite/test": "0.0.32"
|
|
53
53
|
},
|
|
54
54
|
"repository": {
|
|
55
55
|
"type": "git",
|