@riebeckite/core 0.0.17 → 0.0.18
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 +5 -5
- package/README_ja.md +5 -5
- package/dist/index.d.ts +2 -0
- package/dist/index.js +307 -233
- package/dist/src/config.d.ts +3 -1
- package/dist/src/content/content_build_coordinator.d.ts +1 -0
- package/dist/src/content/content_build_state.d.ts +1 -1
- package/dist/src/content/content_index_builder.d.ts +6 -2
- package/dist/src/content/content_manager.d.ts +2 -0
- package/dist/src/content/folder_entry.d.ts +1 -1
- package/dist/src/content/manifest_builder.d.ts +1 -1
- package/dist/src/plugin/plugin_lifecycle.d.ts +1 -0
- package/dist/src/project/project_layout.d.ts +11 -0
- package/dist/src/types/content_manifest.d.ts +9 -0
- package/dist/src/types/plugin_seo.d.ts +1 -1
- package/dist/src/types/resolved_riebeckite_config.d.ts +5 -0
- package/dist/src/utils/error.d.ts +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -37,7 +37,7 @@ export default defineConfig({
|
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
The content directory is resolved relative to the application root. See
|
|
40
|
-
[Configuration](../../docs/
|
|
40
|
+
[Configuration](../../docs/docs/reference/configuration.en.md) for the full field list and the
|
|
41
41
|
`projectRoot` / `appRoot` / `configRoot` / `contentRoot` resolution rules.
|
|
42
42
|
|
|
43
43
|
## Public API
|
|
@@ -88,8 +88,8 @@ The content directory is resolved relative to the application root. See
|
|
|
88
88
|
|
|
89
89
|
## See also
|
|
90
90
|
|
|
91
|
-
- [Framework Reference](../../docs/
|
|
92
|
-
- [Content System](../../docs/
|
|
93
|
-
- [Plugin System](../../docs/
|
|
94
|
-
- [Architecture](../../docs/
|
|
91
|
+
- [Framework Reference](../../docs/docs/reference/README.en.md)
|
|
92
|
+
- [Content System](../../docs/docs/framework/content-system.en.md)
|
|
93
|
+
- [Plugin System](../../docs/docs/reference/plugin-api.en.md) / [Theme System](../../docs/docs/reference/theme-api.en.md)
|
|
94
|
+
- [Architecture](../../docs/docs/framework/architecture.en.md)
|
|
95
95
|
|
package/README_ja.md
CHANGED
|
@@ -29,7 +29,7 @@ export default defineConfig({
|
|
|
29
29
|
});
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
コンテンツディレクトリはアプリケーションルート基準で解決します。設定項目の全体と `projectRoot` / `appRoot` / `configRoot` / `contentRoot` の解決規則は [Configuration](../../docs/
|
|
32
|
+
コンテンツディレクトリはアプリケーションルート基準で解決します。設定項目の全体と `projectRoot` / `appRoot` / `configRoot` / `contentRoot` の解決規則は [Configuration](../../docs/docs/reference/configuration.md) を参照してください。
|
|
33
33
|
|
|
34
34
|
## 公開 API
|
|
35
35
|
|
|
@@ -69,8 +69,8 @@ export default defineConfig({
|
|
|
69
69
|
|
|
70
70
|
## 関連資料
|
|
71
71
|
|
|
72
|
-
- [Framework Reference](../../docs/
|
|
73
|
-
- [Content System](../../docs/
|
|
74
|
-
- [Plugin System](../../docs/
|
|
75
|
-
- [Architecture](../../docs/
|
|
72
|
+
- [Framework Reference](../../docs/docs/reference/README.md)
|
|
73
|
+
- [Content System](../../docs/docs/framework/content-system.md)
|
|
74
|
+
- [Plugin System](../../docs/docs/reference/plugin-api.md) / [Theme System](../../docs/docs/reference/theme-api.md)
|
|
75
|
+
- [Architecture](../../docs/docs/framework/architecture.md)
|
|
76
76
|
|
package/dist/index.d.ts
CHANGED
|
@@ -42,6 +42,7 @@ export type { PluginCache } from "./src/plugin/plugin_cache.js";
|
|
|
42
42
|
export { PluginDependencyError, type PluginDependencyErrorKind, } from "./src/plugin/plugin_dependency_error.js";
|
|
43
43
|
export type { CreatePluginMemoOptions, PluginMemo, } from "./src/plugin/plugin_memo.js";
|
|
44
44
|
export { createPluginMemo, stableStringify, } from "./src/plugin/plugin_memo.js";
|
|
45
|
+
export { resolveBuildOutputDirectory, resolveManagedStateRoot, } from "./src/project/project_layout.js";
|
|
45
46
|
export type { ConfigValidationIssue, PluginOptionsValidator, } from "./src/types/config_validation.js";
|
|
46
47
|
export type { ContentAsset, ContentBodySlot, ContentLink, ContentLinkKind, ContentLocationInput, ContentManifest, ContentManifestEntry, ContentManifestPluginClientEntry, ContentPublicLocation, ContentRedirect, FolderLocation, PluginPageRoute, } from "./src/types/content_manifest.js";
|
|
47
48
|
export { appendContentBodySlot } from "./src/types/content_manifest.js";
|
|
@@ -71,6 +72,7 @@ export type { SiteConfig } from "./src/types/site_config.js";
|
|
|
71
72
|
export type { RiebeckiteTheme, ThemeArticleLayoutPreset, ThemeAttributes, ThemeColorMode, ThemeConfig, ThemeDesignTokens, ThemeInput, ThemeStyle, ThemeTypographyPreset, } from "./src/types/theme_config.js";
|
|
72
73
|
export { defineTheme } from "./src/types/theme_config.js";
|
|
73
74
|
export { uniqueStrings } from "./src/utils/collections.js";
|
|
75
|
+
export { attachErrorPath } from "./src/utils/error.js";
|
|
74
76
|
export { escapeHtml, escapeHtmlAttribute, escapeScriptJson, } from "./src/utils/html.js";
|
|
75
77
|
export { normalizeTag } from "./src/utils/tags.js";
|
|
76
78
|
export { calculateReadingTime, stripHtml } from "./src/utils/text.js";
|
package/dist/index.js
CHANGED
|
@@ -119,41 +119,41 @@ function validateTheme(value, issues) {
|
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
121
|
}
|
|
122
|
-
function validateThemeConfig(value,
|
|
123
|
-
validateOptionalString(value.name, `${
|
|
122
|
+
function validateThemeConfig(value, path6, issues) {
|
|
123
|
+
validateOptionalString(value.name, `${path6}.name`, issues);
|
|
124
124
|
validateOneOf(
|
|
125
125
|
value.colorMode,
|
|
126
|
-
`${
|
|
126
|
+
`${path6}.colorMode`,
|
|
127
127
|
["light", "dark", "system"],
|
|
128
128
|
issues
|
|
129
129
|
);
|
|
130
130
|
validateOneOf(
|
|
131
131
|
value.typography,
|
|
132
|
-
`${
|
|
132
|
+
`${path6}.typography`,
|
|
133
133
|
["system", "serif", "sans"],
|
|
134
134
|
issues
|
|
135
135
|
);
|
|
136
136
|
validateOneOf(
|
|
137
137
|
value.articleLayout,
|
|
138
|
-
`${
|
|
138
|
+
`${path6}.articleLayout`,
|
|
139
139
|
["article", "sidebar", "full-width"],
|
|
140
140
|
issues
|
|
141
141
|
);
|
|
142
|
-
validateStringArray(value.userCss, `${
|
|
142
|
+
validateStringArray(value.userCss, `${path6}.userCss`, issues);
|
|
143
143
|
if (value.attributes !== void 0 && !isRecord(value.attributes)) {
|
|
144
|
-
issues.push({ path: `${
|
|
144
|
+
issues.push({ path: `${path6}.attributes`, message: "Expected an object." });
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
|
-
function validateThemeStyles(value,
|
|
147
|
+
function validateThemeStyles(value, path6, issues) {
|
|
148
148
|
if (value === void 0) return;
|
|
149
149
|
if (!Array.isArray(value)) {
|
|
150
|
-
issues.push({ path:
|
|
150
|
+
issues.push({ path: path6, message: "Expected an array." });
|
|
151
151
|
return;
|
|
152
152
|
}
|
|
153
153
|
for (const [index, style] of value.entries()) {
|
|
154
154
|
if (!isRecord(style) || !isNonEmptyString(style.moduleSpecifier)) {
|
|
155
155
|
issues.push({
|
|
156
|
-
path: `${
|
|
156
|
+
path: `${path6}[${index}].moduleSpecifier`,
|
|
157
157
|
message: "Expected a non-empty string."
|
|
158
158
|
});
|
|
159
159
|
}
|
|
@@ -173,69 +173,69 @@ function validatePlugins(value, issues) {
|
|
|
173
173
|
continue;
|
|
174
174
|
}
|
|
175
175
|
const plugin = input;
|
|
176
|
-
const
|
|
176
|
+
const path6 = `plugins[${index}]`;
|
|
177
177
|
if (!isNonEmptyString(plugin.name)) {
|
|
178
178
|
issues.push({
|
|
179
|
-
path: `${
|
|
179
|
+
path: `${path6}.name`,
|
|
180
180
|
message: "Expected a non-empty string."
|
|
181
181
|
});
|
|
182
182
|
} else if (plugin.enabled !== false) {
|
|
183
183
|
const duplicateIndex = names.get(plugin.name);
|
|
184
184
|
if (duplicateIndex !== void 0) {
|
|
185
185
|
issues.push({
|
|
186
|
-
path: `${
|
|
186
|
+
path: `${path6}.name`,
|
|
187
187
|
message: `Duplicate plugin name "${plugin.name}" (also plugins[${duplicateIndex}]).`
|
|
188
188
|
});
|
|
189
189
|
} else {
|
|
190
190
|
names.set(plugin.name, index);
|
|
191
191
|
}
|
|
192
192
|
}
|
|
193
|
-
validateOptionalBoolean(plugin.enabled, `${
|
|
194
|
-
validateCapabilityMetadata(plugin,
|
|
195
|
-
if (plugin.enabled !== false) validatePluginOptions(plugin,
|
|
193
|
+
validateOptionalBoolean(plugin.enabled, `${path6}.enabled`, issues);
|
|
194
|
+
validateCapabilityMetadata(plugin, path6, issues);
|
|
195
|
+
if (plugin.enabled !== false) validatePluginOptions(plugin, path6, issues);
|
|
196
196
|
}
|
|
197
197
|
}
|
|
198
|
-
function validateCapabilityMetadata(plugin,
|
|
199
|
-
validateStringArray(plugin.provides, `${
|
|
200
|
-
validateStringArray(plugin.requires, `${
|
|
201
|
-
validateStringArray(plugin.optional, `${
|
|
198
|
+
function validateCapabilityMetadata(plugin, path6, issues) {
|
|
199
|
+
validateStringArray(plugin.provides, `${path6}.provides`, issues, true);
|
|
200
|
+
validateStringArray(plugin.requires, `${path6}.requires`, issues, true);
|
|
201
|
+
validateStringArray(plugin.optional, `${path6}.optional`, issues, true);
|
|
202
202
|
}
|
|
203
|
-
function validatePluginOptions(plugin,
|
|
203
|
+
function validatePluginOptions(plugin, path6, issues) {
|
|
204
204
|
if (!plugin.validateOptions) return;
|
|
205
205
|
try {
|
|
206
206
|
const optionIssues = plugin.validateOptions(plugin.options) ?? [];
|
|
207
207
|
for (const issue of optionIssues) {
|
|
208
208
|
issues.push({
|
|
209
|
-
path: issue.path ? `${
|
|
209
|
+
path: issue.path ? `${path6}.options.${issue.path}` : `${path6}.options`,
|
|
210
210
|
message: issue.message
|
|
211
211
|
});
|
|
212
212
|
}
|
|
213
213
|
} catch (error) {
|
|
214
214
|
issues.push({
|
|
215
|
-
path: `${
|
|
215
|
+
path: `${path6}.options`,
|
|
216
216
|
message: `Validator failed: ${toErrorMessage(error)}`
|
|
217
217
|
});
|
|
218
218
|
}
|
|
219
219
|
}
|
|
220
|
-
function validateRequiredString(value,
|
|
220
|
+
function validateRequiredString(value, path6, issues) {
|
|
221
221
|
if (!isNonEmptyString(value)) {
|
|
222
|
-
issues.push({ path:
|
|
222
|
+
issues.push({ path: path6, message: "Expected a non-empty string." });
|
|
223
223
|
}
|
|
224
224
|
}
|
|
225
|
-
function validateOptionalString(value,
|
|
225
|
+
function validateOptionalString(value, path6, issues) {
|
|
226
226
|
if (value !== void 0 && typeof value !== "string") {
|
|
227
|
-
issues.push({ path:
|
|
227
|
+
issues.push({ path: path6, message: "Expected a string." });
|
|
228
228
|
}
|
|
229
229
|
}
|
|
230
|
-
function validateOptionalBoolean(value,
|
|
230
|
+
function validateOptionalBoolean(value, path6, issues) {
|
|
231
231
|
if (value !== void 0 && typeof value !== "boolean") {
|
|
232
|
-
issues.push({ path:
|
|
232
|
+
issues.push({ path: path6, message: "Expected a boolean." });
|
|
233
233
|
}
|
|
234
234
|
}
|
|
235
|
-
function validateAbsoluteUrl(value,
|
|
235
|
+
function validateAbsoluteUrl(value, path6, issues) {
|
|
236
236
|
if (value === void 0 || value === "") return;
|
|
237
237
|
if (typeof value !== "string") {
|
|
238
|
-
issues.push({ path:
|
|
238
|
+
issues.push({ path: path6, message: "Expected an absolute URL." });
|
|
239
239
|
return;
|
|
240
240
|
}
|
|
241
241
|
try {
|
|
@@ -243,27 +243,27 @@ function validateAbsoluteUrl(value, path5, issues) {
|
|
|
243
243
|
if (url.protocol !== "http:" && url.protocol !== "https:")
|
|
244
244
|
throw new Error();
|
|
245
245
|
} catch {
|
|
246
|
-
issues.push({ path:
|
|
246
|
+
issues.push({ path: path6, message: "Expected an absolute HTTP(S) URL." });
|
|
247
247
|
}
|
|
248
248
|
}
|
|
249
|
-
function validateStringArray(value,
|
|
249
|
+
function validateStringArray(value, path6, issues, nonEmpty = false) {
|
|
250
250
|
if (value === void 0) return;
|
|
251
251
|
if (!Array.isArray(value)) {
|
|
252
|
-
issues.push({ path:
|
|
252
|
+
issues.push({ path: path6, message: "Expected an array." });
|
|
253
253
|
return;
|
|
254
254
|
}
|
|
255
255
|
for (const [index, item] of value.entries()) {
|
|
256
256
|
if (typeof item !== "string" || nonEmpty && !item.trim()) {
|
|
257
257
|
issues.push({
|
|
258
|
-
path: `${
|
|
258
|
+
path: `${path6}[${index}]`,
|
|
259
259
|
message: nonEmpty ? "Expected a non-empty string." : "Expected a string."
|
|
260
260
|
});
|
|
261
261
|
}
|
|
262
262
|
}
|
|
263
263
|
}
|
|
264
|
-
function validateOneOf(value,
|
|
264
|
+
function validateOneOf(value, path6, choices, issues) {
|
|
265
265
|
if (value !== void 0 && (typeof value !== "string" || !choices.includes(value))) {
|
|
266
|
-
issues.push({ path:
|
|
266
|
+
issues.push({ path: path6, message: `Expected one of: ${choices.join(", ")}.` });
|
|
267
267
|
}
|
|
268
268
|
}
|
|
269
269
|
function formatValidationIssues(issues) {
|
|
@@ -284,6 +284,74 @@ function toErrorMessage(error) {
|
|
|
284
284
|
return error instanceof Error ? error.message : String(error);
|
|
285
285
|
}
|
|
286
286
|
|
|
287
|
+
// src/types/publish_strategy.ts
|
|
288
|
+
function isPublishable(strategy, frontmatter) {
|
|
289
|
+
if (strategy === "explicit") {
|
|
290
|
+
return frontmatter?.publish === true;
|
|
291
|
+
}
|
|
292
|
+
return !(frontmatter?.private === true || frontmatter?.draft === true);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// src/content/publishing.ts
|
|
296
|
+
function resolvePublishingState(frontmatter, options) {
|
|
297
|
+
const explicitVisibility = resolveExplicitVisibility(frontmatter?.visibility);
|
|
298
|
+
const publishAt = resolvePublishAt(frontmatter?.publishAt);
|
|
299
|
+
if (explicitVisibility === "draft")
|
|
300
|
+
return state("draft", false, false, publishAt);
|
|
301
|
+
if (publishAt && publishAt.getTime() > options.buildTime.getTime()) {
|
|
302
|
+
return state("scheduled", false, false, publishAt);
|
|
303
|
+
}
|
|
304
|
+
if (explicitVisibility === "unlisted") {
|
|
305
|
+
return state("unlisted", true, false, publishAt);
|
|
306
|
+
}
|
|
307
|
+
if (explicitVisibility === "public" || publishAt) {
|
|
308
|
+
return state("public", true, true, publishAt);
|
|
309
|
+
}
|
|
310
|
+
const routable = isPublishable(options.strategy, frontmatter);
|
|
311
|
+
return state(routable ? "public" : "draft", routable, routable, publishAt);
|
|
312
|
+
}
|
|
313
|
+
function resolvePublishingBuildTime(input) {
|
|
314
|
+
if (input === void 0) return /* @__PURE__ */ new Date();
|
|
315
|
+
if (input instanceof Date) {
|
|
316
|
+
if (Number.isNaN(input.getTime()))
|
|
317
|
+
throw new Error("Invalid publishing build time.");
|
|
318
|
+
return new Date(input.getTime());
|
|
319
|
+
}
|
|
320
|
+
const parsed = new Date(input);
|
|
321
|
+
if (Number.isNaN(parsed.getTime()))
|
|
322
|
+
throw new Error("Invalid publishing build time.");
|
|
323
|
+
return parsed;
|
|
324
|
+
}
|
|
325
|
+
function resolveExplicitVisibility(value) {
|
|
326
|
+
if (value === void 0) return void 0;
|
|
327
|
+
if (value === "public" || value === "unlisted" || value === "draft")
|
|
328
|
+
return value;
|
|
329
|
+
throw new Error(
|
|
330
|
+
`Invalid content visibility "${String(value)}". Expected public, unlisted, or draft.`
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
function resolvePublishAt(value) {
|
|
334
|
+
if (value === void 0) return void 0;
|
|
335
|
+
if (!(typeof value === "string" || value instanceof Date)) {
|
|
336
|
+
throw new Error("Invalid publishAt. Expected an ISO 8601 date string.");
|
|
337
|
+
}
|
|
338
|
+
const parsed = value instanceof Date ? value : new Date(value);
|
|
339
|
+
if (Number.isNaN(parsed.getTime())) {
|
|
340
|
+
throw new Error(
|
|
341
|
+
`Invalid publishAt "${String(value)}". Expected an ISO 8601 date string.`
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
return new Date(parsed.getTime());
|
|
345
|
+
}
|
|
346
|
+
function state(visibility, routable, discoverable, publishAt) {
|
|
347
|
+
return {
|
|
348
|
+
visibility,
|
|
349
|
+
routable,
|
|
350
|
+
discoverable,
|
|
351
|
+
...publishAt ? { publishAt } : {}
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
|
|
287
355
|
// src/plugin/plugin_dependency_error.ts
|
|
288
356
|
var PluginDependencyError = class extends Error {
|
|
289
357
|
kind;
|
|
@@ -573,14 +641,6 @@ function getResolvedPluginMetadata(plugins) {
|
|
|
573
641
|
}));
|
|
574
642
|
}
|
|
575
643
|
|
|
576
|
-
// src/types/publish_strategy.ts
|
|
577
|
-
function isPublishable(strategy, frontmatter) {
|
|
578
|
-
if (strategy === "explicit") {
|
|
579
|
-
return frontmatter?.publish === true;
|
|
580
|
-
}
|
|
581
|
-
return !(frontmatter?.private === true || frontmatter?.draft === true);
|
|
582
|
-
}
|
|
583
|
-
|
|
584
644
|
// src/types/theme_config.ts
|
|
585
645
|
function defineTheme(theme) {
|
|
586
646
|
return theme;
|
|
@@ -680,10 +740,11 @@ function sanitizeThemeAttributes(attributes) {
|
|
|
680
740
|
).filter(([name]) => !reservedAttributes.has(name))
|
|
681
741
|
);
|
|
682
742
|
}
|
|
683
|
-
function isPublished(config, frontmatter) {
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
743
|
+
function isPublished(config, frontmatter, options = {}) {
|
|
744
|
+
return resolvePublishingState(frontmatter, {
|
|
745
|
+
strategy: config.content.filters.publishStrategy,
|
|
746
|
+
buildTime: resolvePublishingBuildTime(options.buildTime)
|
|
747
|
+
}).routable;
|
|
687
748
|
}
|
|
688
749
|
function isExcluded(patterns, relativePath) {
|
|
689
750
|
const normalized = relativePath.replace(/\\/g, "/");
|
|
@@ -745,9 +806,9 @@ var configDeprecations = [];
|
|
|
745
806
|
function collectConfigDeprecationDiagnostics(config, notices = configDeprecations) {
|
|
746
807
|
return notices.filter((notice) => hasConfigPath(config, notice.path)).map(createDeprecationDiagnostic);
|
|
747
808
|
}
|
|
748
|
-
function hasConfigPath(config,
|
|
809
|
+
function hasConfigPath(config, path6) {
|
|
749
810
|
let value = config;
|
|
750
|
-
for (const segment of
|
|
811
|
+
for (const segment of path6.split(".")) {
|
|
751
812
|
if (!isRecord2(value) || !(segment in value)) return false;
|
|
752
813
|
value = value[segment];
|
|
753
814
|
}
|
|
@@ -810,7 +871,7 @@ import fs from "node:fs/promises";
|
|
|
810
871
|
import path from "node:path";
|
|
811
872
|
|
|
812
873
|
// src/content/content_build_state.ts
|
|
813
|
-
var CONTENT_BUILD_STATE_VERSION =
|
|
874
|
+
var CONTENT_BUILD_STATE_VERSION = 8;
|
|
814
875
|
var CONTENT_BUILD_STATE_DIRECTORY = ".riebeckite";
|
|
815
876
|
var CONTENT_BUILD_STATE_EXCLUDE = `${CONTENT_BUILD_STATE_DIRECTORY}/**`;
|
|
816
877
|
|
|
@@ -1215,9 +1276,9 @@ function buildContentCollections(entries, definitions) {
|
|
|
1215
1276
|
function normalizePageSize(value) {
|
|
1216
1277
|
return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : 0;
|
|
1217
1278
|
}
|
|
1218
|
-
function withPage(
|
|
1219
|
-
if (index === 0) return
|
|
1220
|
-
const base =
|
|
1279
|
+
function withPage(path6, index) {
|
|
1280
|
+
if (index === 0) return path6;
|
|
1281
|
+
const base = path6 === "/" ? "" : path6;
|
|
1221
1282
|
return normalizePath(`${base}/page/${index + 1}`);
|
|
1222
1283
|
}
|
|
1223
1284
|
function defaultPath(context) {
|
|
@@ -2463,9 +2524,9 @@ function resolveRelativeMarkdownSlug(sourceSlug, targetPath) {
|
|
|
2463
2524
|
}
|
|
2464
2525
|
return normalizedParts.join("/").replace(/\.md$/i, "");
|
|
2465
2526
|
}
|
|
2466
|
-
function decodeUriPath(
|
|
2527
|
+
function decodeUriPath(path6) {
|
|
2467
2528
|
try {
|
|
2468
|
-
return decodeURI(
|
|
2529
|
+
return decodeURI(path6);
|
|
2469
2530
|
} catch {
|
|
2470
2531
|
return null;
|
|
2471
2532
|
}
|
|
@@ -2553,16 +2614,16 @@ var GeneratedOutputRegistry = class {
|
|
|
2553
2614
|
outputs = [];
|
|
2554
2615
|
owners = /* @__PURE__ */ new Map();
|
|
2555
2616
|
sinkFor(pluginName) {
|
|
2556
|
-
const register = (
|
|
2557
|
-
const owner = this.owners.get(
|
|
2617
|
+
const register = (path6, output) => {
|
|
2618
|
+
const owner = this.owners.get(path6);
|
|
2558
2619
|
if (owner) {
|
|
2559
2620
|
throw new Error(
|
|
2560
|
-
`Duplicate generated output path "${
|
|
2621
|
+
`Duplicate generated output path "${path6}" declared by "${owner}" and "${pluginName}".`
|
|
2561
2622
|
);
|
|
2562
2623
|
}
|
|
2563
|
-
this.owners.set(
|
|
2624
|
+
this.owners.set(path6, pluginName);
|
|
2564
2625
|
this.outputs.push({
|
|
2565
|
-
path:
|
|
2626
|
+
path: path6,
|
|
2566
2627
|
content: output.content,
|
|
2567
2628
|
dependencies: output.dependencies,
|
|
2568
2629
|
owner: pluginName
|
|
@@ -2586,9 +2647,12 @@ var GeneratedOutputRegistry = class {
|
|
|
2586
2647
|
|
|
2587
2648
|
// src/plugin/plugin_lifecycle.ts
|
|
2588
2649
|
var PluginHookError = class extends Error {
|
|
2650
|
+
path;
|
|
2589
2651
|
constructor(pluginName, hookName, cause) {
|
|
2590
2652
|
super(`Plugin "${pluginName}" failed during "${hookName}"`, { cause });
|
|
2591
2653
|
this.name = "PluginHookError";
|
|
2654
|
+
const path6 = cause?.path;
|
|
2655
|
+
if (typeof path6 === "string") this.path = path6;
|
|
2592
2656
|
}
|
|
2593
2657
|
};
|
|
2594
2658
|
async function runPluginHook(plugin, hookName, context, hook) {
|
|
@@ -3073,12 +3137,12 @@ function normalizePageTypePath(pathname, pageType) {
|
|
|
3073
3137
|
return pageType.directoryIndex ? normalizeDirectoryPagePath(pathname) : normalizePagePath(pathname);
|
|
3074
3138
|
}
|
|
3075
3139
|
function normalizeDirectoryPagePath(pathname) {
|
|
3076
|
-
const
|
|
3077
|
-
return
|
|
3140
|
+
const path6 = normalizePagePath(pathname);
|
|
3141
|
+
return path6 === "/" ? path6 : `${path6}/`;
|
|
3078
3142
|
}
|
|
3079
3143
|
function normalizePagePath(pathname) {
|
|
3080
|
-
const
|
|
3081
|
-
return
|
|
3144
|
+
const path6 = `/${pathname.split("/").filter(Boolean).join("/")}`;
|
|
3145
|
+
return path6 === "/" ? path6 : path6.replace(/\/$/, "");
|
|
3082
3146
|
}
|
|
3083
3147
|
function countSeverity(diagnostics, severity) {
|
|
3084
3148
|
return diagnostics.filter((diagnostic) => diagnostic.severity === severity).length;
|
|
@@ -3101,6 +3165,14 @@ function uniqueOutputs(outputs) {
|
|
|
3101
3165
|
return [...byPath.values()].map(({ output }) => output).sort((left, right) => left.path.localeCompare(right.path));
|
|
3102
3166
|
}
|
|
3103
3167
|
|
|
3168
|
+
// src/utils/error.ts
|
|
3169
|
+
function attachErrorPath(error, path6) {
|
|
3170
|
+
if (error instanceof Error && error.path === void 0) {
|
|
3171
|
+
error.path = path6;
|
|
3172
|
+
}
|
|
3173
|
+
return error;
|
|
3174
|
+
}
|
|
3175
|
+
|
|
3104
3176
|
// src/content/affected_content.ts
|
|
3105
3177
|
function determineAffectedContent(changeSet, previousState, currentPaths, currentContentIndex) {
|
|
3106
3178
|
const changedPaths = [
|
|
@@ -3121,9 +3193,9 @@ function determineAffectedContent(changeSet, previousState, currentPaths, curren
|
|
|
3121
3193
|
previousState.contentIndex,
|
|
3122
3194
|
currentContentIndex
|
|
3123
3195
|
);
|
|
3124
|
-
for (const [
|
|
3125
|
-
if (!isMarkdownPath2(
|
|
3126
|
-
const slug = toDependencyId(
|
|
3196
|
+
for (const [path6, entry] of Object.entries(previousState.entries)) {
|
|
3197
|
+
if (!isMarkdownPath2(path6)) continue;
|
|
3198
|
+
const slug = toDependencyId(path6);
|
|
3127
3199
|
if (direct.has(slug) || dependent.has(slug)) continue;
|
|
3128
3200
|
if (!entry.linkTargets?.some((target) => changedIndexKeys.has(target))) {
|
|
3129
3201
|
continue;
|
|
@@ -3160,27 +3232,27 @@ function findChangedIndexKeys(previousIndex, currentIndex) {
|
|
|
3160
3232
|
return changed;
|
|
3161
3233
|
}
|
|
3162
3234
|
function addAllNotes(target, currentPaths, exclude) {
|
|
3163
|
-
for (const
|
|
3164
|
-
if (!isMarkdownPath2(
|
|
3165
|
-
const slug = toDependencyId(
|
|
3235
|
+
for (const path6 of currentPaths) {
|
|
3236
|
+
if (!isMarkdownPath2(path6)) continue;
|
|
3237
|
+
const slug = toDependencyId(path6);
|
|
3166
3238
|
if (exclude?.has(slug)) continue;
|
|
3167
3239
|
target.add(slug);
|
|
3168
3240
|
}
|
|
3169
3241
|
}
|
|
3170
|
-
function isMarkdownPath2(
|
|
3171
|
-
return
|
|
3242
|
+
function isMarkdownPath2(path6) {
|
|
3243
|
+
return path6.endsWith(".md");
|
|
3172
3244
|
}
|
|
3173
|
-
function toDependencyId(
|
|
3174
|
-
return
|
|
3245
|
+
function toDependencyId(path6) {
|
|
3246
|
+
return path6.replace(/\.md$/, "");
|
|
3175
3247
|
}
|
|
3176
|
-
function toDependency(
|
|
3177
|
-
return isMarkdownPath2(
|
|
3248
|
+
function toDependency(path6) {
|
|
3249
|
+
return isMarkdownPath2(path6) ? { kind: "content", id: toDependencyId(path6) } : { kind: "file", id: path6.replace(/\\/g, "/") };
|
|
3178
3250
|
}
|
|
3179
3251
|
function buildDependentsByDependency(state2) {
|
|
3180
3252
|
const dependents = /* @__PURE__ */ new Map();
|
|
3181
|
-
for (const [
|
|
3182
|
-
if (!isMarkdownPath2(
|
|
3183
|
-
const slug = toDependencyId(
|
|
3253
|
+
for (const [path6, entry] of Object.entries(state2.entries)) {
|
|
3254
|
+
if (!isMarkdownPath2(path6)) continue;
|
|
3255
|
+
const slug = toDependencyId(path6);
|
|
3184
3256
|
for (const dependency of entry.dependencies) {
|
|
3185
3257
|
const key = dependencyKey2(dependency);
|
|
3186
3258
|
const values = dependents.get(key) ?? /* @__PURE__ */ new Set();
|
|
@@ -3202,18 +3274,18 @@ function diffContentEntries(previous, current) {
|
|
|
3202
3274
|
const added = [];
|
|
3203
3275
|
const changed = [];
|
|
3204
3276
|
const unchanged = [];
|
|
3205
|
-
for (const [
|
|
3206
|
-
const previousEntry = previous.entries[
|
|
3277
|
+
for (const [path6, fingerprint] of currentFingerprints) {
|
|
3278
|
+
const previousEntry = previous.entries[path6];
|
|
3207
3279
|
if (!previousEntry) {
|
|
3208
|
-
added.push(
|
|
3280
|
+
added.push(path6);
|
|
3209
3281
|
} else if (previousEntry.fingerprint !== fingerprint) {
|
|
3210
|
-
changed.push(
|
|
3282
|
+
changed.push(path6);
|
|
3211
3283
|
} else {
|
|
3212
|
-
unchanged.push(
|
|
3284
|
+
unchanged.push(path6);
|
|
3213
3285
|
}
|
|
3214
3286
|
}
|
|
3215
3287
|
const removed = Object.keys(previous.entries).filter(
|
|
3216
|
-
(
|
|
3288
|
+
(path6) => !currentFingerprints.has(path6)
|
|
3217
3289
|
);
|
|
3218
3290
|
return sortChangeSet({ added, changed, removed, unchanged });
|
|
3219
3291
|
}
|
|
@@ -3225,9 +3297,6 @@ function allContentChanged(entries) {
|
|
|
3225
3297
|
unchanged: []
|
|
3226
3298
|
});
|
|
3227
3299
|
}
|
|
3228
|
-
function hasContentChanges(changeSet) {
|
|
3229
|
-
return changeSet.added.length > 0 || changeSet.changed.length > 0 || changeSet.removed.length > 0;
|
|
3230
|
-
}
|
|
3231
3300
|
function sortChangeSet(changeSet) {
|
|
3232
3301
|
return {
|
|
3233
3302
|
added: [...changeSet.added].sort(),
|
|
@@ -3303,54 +3372,73 @@ var ContentIndexBuilder = class _ContentIndexBuilder {
|
|
|
3303
3372
|
}
|
|
3304
3373
|
source;
|
|
3305
3374
|
async build(contentEntries, read = (entry) => this.source.read(entry)) {
|
|
3306
|
-
const
|
|
3375
|
+
const candidates = /* @__PURE__ */ new Map();
|
|
3307
3376
|
for (const contentEntry of contentEntries) {
|
|
3308
|
-
await this.indexContentEntry(
|
|
3377
|
+
await this.indexContentEntry(candidates, contentEntry, read);
|
|
3309
3378
|
}
|
|
3310
|
-
return
|
|
3379
|
+
return resolveContentIndex(candidates);
|
|
3311
3380
|
}
|
|
3312
3381
|
static buildFromAliases(contentEntries, aliasesByPath) {
|
|
3313
|
-
const
|
|
3382
|
+
const candidates = /* @__PURE__ */ new Map();
|
|
3314
3383
|
for (const contentEntry of contentEntries) {
|
|
3315
3384
|
_ContentIndexBuilder.indexContentEntryFromAliases(
|
|
3316
|
-
|
|
3385
|
+
candidates,
|
|
3317
3386
|
contentEntry,
|
|
3318
3387
|
aliasesByPath.get(contentEntry.path) ?? []
|
|
3319
3388
|
);
|
|
3320
3389
|
}
|
|
3321
|
-
return
|
|
3390
|
+
return resolveContentIndex(candidates);
|
|
3322
3391
|
}
|
|
3323
|
-
async indexContentEntry(
|
|
3392
|
+
async indexContentEntry(candidates, contentEntry, read) {
|
|
3324
3393
|
const aliases = contentEntry.path.toLowerCase().endsWith(".md") ? extractFrontmatterAliases(readText(await read(contentEntry))) : [];
|
|
3325
3394
|
_ContentIndexBuilder.indexContentEntryFromAliases(
|
|
3326
|
-
|
|
3395
|
+
candidates,
|
|
3327
3396
|
contentEntry,
|
|
3328
3397
|
aliases
|
|
3329
3398
|
);
|
|
3330
3399
|
}
|
|
3331
|
-
static indexContentEntryFromAliases(
|
|
3400
|
+
static indexContentEntryFromAliases(candidates, contentEntry, aliases) {
|
|
3332
3401
|
const contentPath = contentEntry.path;
|
|
3333
3402
|
const ext = contentPath.split(".").pop()?.toLowerCase() ?? "";
|
|
3334
3403
|
const value = ext === "md" ? contentPath.replace(/\.md$/, "") : contentPath;
|
|
3335
3404
|
const parts = value.split("/");
|
|
3336
3405
|
for (let i = parts.length - 1; i >= 0; i--) {
|
|
3337
3406
|
const rawSuffix = parts.slice(i).join("/");
|
|
3338
|
-
|
|
3407
|
+
addCandidate(candidates, rawSuffix, value);
|
|
3339
3408
|
if (ext !== "md") {
|
|
3340
|
-
|
|
3409
|
+
addCandidate(candidates, rawSuffix.replace(/\.[^/.]+$/, ""), value);
|
|
3341
3410
|
}
|
|
3342
3411
|
}
|
|
3343
3412
|
if (ext === "md") {
|
|
3344
|
-
for (const alias of aliases)
|
|
3413
|
+
for (const alias of aliases) addCandidate(candidates, alias, value);
|
|
3345
3414
|
}
|
|
3346
3415
|
}
|
|
3347
3416
|
};
|
|
3417
|
+
function resolveContentIndex(candidates) {
|
|
3418
|
+
const index = /* @__PURE__ */ new Map();
|
|
3419
|
+
const ambiguities = /* @__PURE__ */ new Map();
|
|
3420
|
+
for (const [key, values] of candidates) {
|
|
3421
|
+
const list = [...values].sort(compareCandidates);
|
|
3422
|
+
const [only] = list;
|
|
3423
|
+
if (list.length === 1 && only !== void 0) {
|
|
3424
|
+
index.set(key, only);
|
|
3425
|
+
continue;
|
|
3426
|
+
}
|
|
3427
|
+
ambiguities.set(key, list);
|
|
3428
|
+
}
|
|
3429
|
+
return { index, ambiguities };
|
|
3430
|
+
}
|
|
3431
|
+
function compareCandidates(left, right) {
|
|
3432
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
3433
|
+
}
|
|
3348
3434
|
function readText(content) {
|
|
3349
3435
|
return typeof content === "string" ? content : new TextDecoder().decode(content);
|
|
3350
3436
|
}
|
|
3351
|
-
function
|
|
3437
|
+
function addCandidate(candidates, key, value) {
|
|
3352
3438
|
const normalizedKey = key.toLowerCase();
|
|
3353
|
-
|
|
3439
|
+
const values = candidates.get(normalizedKey) ?? /* @__PURE__ */ new Set();
|
|
3440
|
+
values.add(value);
|
|
3441
|
+
candidates.set(normalizedKey, values);
|
|
3354
3442
|
}
|
|
3355
3443
|
|
|
3356
3444
|
// src/content/content_build_coordinator.ts
|
|
@@ -3433,7 +3521,10 @@ var ContentBuildCoordinator = class {
|
|
|
3433
3521
|
previousState,
|
|
3434
3522
|
changeSet
|
|
3435
3523
|
);
|
|
3436
|
-
const
|
|
3524
|
+
const {
|
|
3525
|
+
index: currentContentIndex,
|
|
3526
|
+
ambiguities: currentContentIndexAmbiguities
|
|
3527
|
+
} = await this.dependencies.observability.tracer.span(
|
|
3437
3528
|
"content.index",
|
|
3438
3529
|
{},
|
|
3439
3530
|
() => ContentIndexBuilder.buildFromAliases(
|
|
@@ -3471,6 +3562,7 @@ var ContentBuildCoordinator = class {
|
|
|
3471
3562
|
currentEntries,
|
|
3472
3563
|
currentContentAliases,
|
|
3473
3564
|
currentContentIndex,
|
|
3565
|
+
currentContentIndexAmbiguities,
|
|
3474
3566
|
changeSet,
|
|
3475
3567
|
affectedContent: affected
|
|
3476
3568
|
};
|
|
@@ -3498,8 +3590,8 @@ var ContentBuildCoordinator = class {
|
|
|
3498
3590
|
function readText2(content) {
|
|
3499
3591
|
return typeof content === "string" ? content : new TextDecoder().decode(content);
|
|
3500
3592
|
}
|
|
3501
|
-
function toSlug(
|
|
3502
|
-
return
|
|
3593
|
+
function toSlug(path6) {
|
|
3594
|
+
return path6.replace(/\.md$/, "");
|
|
3503
3595
|
}
|
|
3504
3596
|
function collectDependencies2(manifestEntry, trackedDependencies) {
|
|
3505
3597
|
if (!manifestEntry) return [];
|
|
@@ -3682,8 +3774,8 @@ var ContentLocationResolver = class {
|
|
|
3682
3774
|
}
|
|
3683
3775
|
}
|
|
3684
3776
|
};
|
|
3685
|
-
function toSlug2(
|
|
3686
|
-
return
|
|
3777
|
+
function toSlug2(path6) {
|
|
3778
|
+
return path6.replace(/\.md$/, "");
|
|
3687
3779
|
}
|
|
3688
3780
|
async function mapConcurrent2(values, concurrency, map) {
|
|
3689
3781
|
const results = new Array(values.length);
|
|
@@ -3881,7 +3973,7 @@ var ManifestBuilder = class {
|
|
|
3881
3973
|
assets: uniqueAssets(assets)
|
|
3882
3974
|
};
|
|
3883
3975
|
}
|
|
3884
|
-
build(entries, contentIndex) {
|
|
3976
|
+
build(entries, contentIndex, contentIndexAmbiguities = /* @__PURE__ */ new Map()) {
|
|
3885
3977
|
const bySlug = new Map(entries.map((entry) => [entry.slug, entry]));
|
|
3886
3978
|
const byContentId = createContentIdIndex(entries);
|
|
3887
3979
|
const byAlias = createAliasIndex(entries);
|
|
@@ -3922,6 +4014,7 @@ var ManifestBuilder = class {
|
|
|
3922
4014
|
outgoingLinks,
|
|
3923
4015
|
incomingLinks,
|
|
3924
4016
|
contentIndex,
|
|
4017
|
+
contentIndexAmbiguities,
|
|
3925
4018
|
assets: [],
|
|
3926
4019
|
clientEntries: [],
|
|
3927
4020
|
diagnostics: [],
|
|
@@ -4038,10 +4131,10 @@ function buildOutputInventory(manifest, pluginPageOutputs = [], contentOutputDep
|
|
|
4038
4131
|
for (const entry of manifest.publicEntries) {
|
|
4039
4132
|
addOutput(outputs, contentOutput(entry, contentOutputDependencies));
|
|
4040
4133
|
}
|
|
4041
|
-
for (const [
|
|
4134
|
+
for (const [path6, redirect] of manifest.publicRedirects) {
|
|
4042
4135
|
addOutput(outputs, {
|
|
4043
4136
|
kind: "redirect",
|
|
4044
|
-
path: htmlOutputPath(
|
|
4137
|
+
path: htmlOutputPath(path6),
|
|
4045
4138
|
producer: `content:${redirect.slug}:redirect`,
|
|
4046
4139
|
dependencies: [{ type: "content", slug: redirect.slug }]
|
|
4047
4140
|
});
|
|
@@ -4170,79 +4263,19 @@ function assertNoGeneratedOutputCollision(existing, incoming) {
|
|
|
4170
4263
|
);
|
|
4171
4264
|
}
|
|
4172
4265
|
function normalizePublicPath(pathname) {
|
|
4173
|
-
const
|
|
4174
|
-
return
|
|
4266
|
+
const path6 = `/${pathname.split("/").filter(Boolean).join("/")}`;
|
|
4267
|
+
return path6 === "/" ? path6 : path6.replace(/\/$/, "");
|
|
4175
4268
|
}
|
|
4176
|
-
function isMarkdownPath3(
|
|
4177
|
-
return
|
|
4269
|
+
function isMarkdownPath3(path6) {
|
|
4270
|
+
return path6.endsWith(".md");
|
|
4178
4271
|
}
|
|
4179
|
-
function toSlug3(
|
|
4180
|
-
return
|
|
4272
|
+
function toSlug3(path6) {
|
|
4273
|
+
return path6.replace(/\.md$/, "");
|
|
4181
4274
|
}
|
|
4182
4275
|
function compareOutput(left, right) {
|
|
4183
4276
|
return left.path.localeCompare(right.path) || left.kind.localeCompare(right.kind);
|
|
4184
4277
|
}
|
|
4185
4278
|
|
|
4186
|
-
// src/content/publishing.ts
|
|
4187
|
-
function resolvePublishingState(frontmatter, options) {
|
|
4188
|
-
const explicitVisibility = resolveExplicitVisibility(frontmatter?.visibility);
|
|
4189
|
-
const publishAt = resolvePublishAt(frontmatter?.publishAt);
|
|
4190
|
-
if (explicitVisibility === "draft")
|
|
4191
|
-
return state("draft", false, false, publishAt);
|
|
4192
|
-
if (publishAt && publishAt.getTime() > options.buildTime.getTime()) {
|
|
4193
|
-
return state("scheduled", false, false, publishAt);
|
|
4194
|
-
}
|
|
4195
|
-
if (explicitVisibility === "unlisted") {
|
|
4196
|
-
return state("unlisted", true, false, publishAt);
|
|
4197
|
-
}
|
|
4198
|
-
if (explicitVisibility === "public" || publishAt) {
|
|
4199
|
-
return state("public", true, true, publishAt);
|
|
4200
|
-
}
|
|
4201
|
-
const routable = isPublishable(options.strategy, frontmatter);
|
|
4202
|
-
return state(routable ? "public" : "draft", routable, routable, publishAt);
|
|
4203
|
-
}
|
|
4204
|
-
function resolvePublishingBuildTime(input) {
|
|
4205
|
-
if (input === void 0) return /* @__PURE__ */ new Date();
|
|
4206
|
-
if (input instanceof Date) {
|
|
4207
|
-
if (Number.isNaN(input.getTime()))
|
|
4208
|
-
throw new Error("Invalid publishing build time.");
|
|
4209
|
-
return new Date(input.getTime());
|
|
4210
|
-
}
|
|
4211
|
-
const parsed = new Date(input);
|
|
4212
|
-
if (Number.isNaN(parsed.getTime()))
|
|
4213
|
-
throw new Error("Invalid publishing build time.");
|
|
4214
|
-
return parsed;
|
|
4215
|
-
}
|
|
4216
|
-
function resolveExplicitVisibility(value) {
|
|
4217
|
-
if (value === void 0) return void 0;
|
|
4218
|
-
if (value === "public" || value === "unlisted" || value === "draft")
|
|
4219
|
-
return value;
|
|
4220
|
-
throw new Error(
|
|
4221
|
-
`Invalid content visibility "${String(value)}". Expected public, unlisted, or draft.`
|
|
4222
|
-
);
|
|
4223
|
-
}
|
|
4224
|
-
function resolvePublishAt(value) {
|
|
4225
|
-
if (value === void 0) return void 0;
|
|
4226
|
-
if (!(typeof value === "string" || value instanceof Date)) {
|
|
4227
|
-
throw new Error("Invalid publishAt. Expected an ISO 8601 date string.");
|
|
4228
|
-
}
|
|
4229
|
-
const parsed = value instanceof Date ? value : new Date(value);
|
|
4230
|
-
if (Number.isNaN(parsed.getTime())) {
|
|
4231
|
-
throw new Error(
|
|
4232
|
-
`Invalid publishAt "${String(value)}". Expected an ISO 8601 date string.`
|
|
4233
|
-
);
|
|
4234
|
-
}
|
|
4235
|
-
return new Date(parsed.getTime());
|
|
4236
|
-
}
|
|
4237
|
-
function state(visibility, routable, discoverable, publishAt) {
|
|
4238
|
-
return {
|
|
4239
|
-
visibility,
|
|
4240
|
-
routable,
|
|
4241
|
-
discoverable,
|
|
4242
|
-
...publishAt ? { publishAt } : {}
|
|
4243
|
-
};
|
|
4244
|
-
}
|
|
4245
|
-
|
|
4246
4279
|
// src/content/content_manager.ts
|
|
4247
4280
|
var CONTENT_PROCESSING_CONCURRENCY = 16;
|
|
4248
4281
|
var ContentManager = class {
|
|
@@ -4300,6 +4333,7 @@ var ContentManager = class {
|
|
|
4300
4333
|
manifestBuilder = new ManifestBuilder();
|
|
4301
4334
|
pluginRuntime;
|
|
4302
4335
|
contentIndex = null;
|
|
4336
|
+
contentIndexAmbiguities = /* @__PURE__ */ new Map();
|
|
4303
4337
|
contentIndexPromise = null;
|
|
4304
4338
|
contentCache = /* @__PURE__ */ new Map();
|
|
4305
4339
|
manifest = null;
|
|
@@ -4328,15 +4362,10 @@ var ContentManager = class {
|
|
|
4328
4362
|
async getContentIndex(preparation) {
|
|
4329
4363
|
if (this.contentIndex) return this.contentIndex;
|
|
4330
4364
|
if (!preparation && this.contentIndexPromise)
|
|
4331
|
-
return await this.contentIndexPromise;
|
|
4332
|
-
if (preparation?.previousState && !hasContentChanges(preparation.changeSet)) {
|
|
4333
|
-
this.contentIndex = new Map(
|
|
4334
|
-
Object.entries(preparation.previousState.contentIndex)
|
|
4335
|
-
);
|
|
4336
|
-
return this.contentIndex;
|
|
4337
|
-
}
|
|
4365
|
+
return (await this.contentIndexPromise).index;
|
|
4338
4366
|
if (preparation) {
|
|
4339
4367
|
this.contentIndex = preparation.currentContentIndex;
|
|
4368
|
+
this.contentIndexAmbiguities = preparation.currentContentIndexAmbiguities;
|
|
4340
4369
|
return this.contentIndex;
|
|
4341
4370
|
}
|
|
4342
4371
|
const promise = this.observability().tracer.span(
|
|
@@ -4349,7 +4378,9 @@ var ContentManager = class {
|
|
|
4349
4378
|
);
|
|
4350
4379
|
if (!preparation) this.contentIndexPromise = promise;
|
|
4351
4380
|
try {
|
|
4352
|
-
|
|
4381
|
+
const built = await promise;
|
|
4382
|
+
this.contentIndex = built.index;
|
|
4383
|
+
this.contentIndexAmbiguities = built.ambiguities;
|
|
4353
4384
|
return this.contentIndex;
|
|
4354
4385
|
} finally {
|
|
4355
4386
|
if (!preparation) this.contentIndexPromise = null;
|
|
@@ -4364,48 +4395,55 @@ var ContentManager = class {
|
|
|
4364
4395
|
contentPath: `${slug}.md`
|
|
4365
4396
|
},
|
|
4366
4397
|
async () => {
|
|
4367
|
-
|
|
4368
|
-
this.
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
await this.pluginRuntime.startBuild(contentIndex);
|
|
4372
|
-
await this.pluginRuntime.runContentLoaded(slug, rawPost, contentIndex);
|
|
4373
|
-
await this.ensureRoutableSlugs();
|
|
4374
|
-
this.pipeline ??= new Pipeline(
|
|
4375
|
-
contentIndex,
|
|
4376
|
-
await this.locationResolver.getPermalinks(),
|
|
4377
|
-
(postSlug) => this.getPost(postSlug),
|
|
4378
|
-
this.pipelineOptions,
|
|
4379
|
-
this.isBuildTime
|
|
4380
|
-
);
|
|
4381
|
-
const content = await this.pipeline.execute(rawPost, {
|
|
4382
|
-
sourceSlug: slug
|
|
4383
|
-
});
|
|
4384
|
-
this.processedContentCount += 1;
|
|
4385
|
-
if (this.processedContentCount % 100 === 0) {
|
|
4386
|
-
this.observability().tracer.event("content.process.sample", {
|
|
4387
|
-
processed: this.processedContentCount
|
|
4388
|
-
});
|
|
4398
|
+
try {
|
|
4399
|
+
return await this.processContent(slug);
|
|
4400
|
+
} catch (error) {
|
|
4401
|
+
throw attachErrorPath(error, `${slug}.md`);
|
|
4389
4402
|
}
|
|
4390
|
-
await this.pluginRuntime.runPostHook(
|
|
4391
|
-
"onPostParsed",
|
|
4392
|
-
slug,
|
|
4393
|
-
rawPost,
|
|
4394
|
-
content,
|
|
4395
|
-
contentIndex
|
|
4396
|
-
);
|
|
4397
|
-
await this.pluginRuntime.runPostHook(
|
|
4398
|
-
"onPostProcessed",
|
|
4399
|
-
slug,
|
|
4400
|
-
rawPost,
|
|
4401
|
-
content,
|
|
4402
|
-
contentIndex
|
|
4403
|
-
);
|
|
4404
|
-
this.contentCache.set(slug, content);
|
|
4405
|
-
return content;
|
|
4406
4403
|
}
|
|
4407
4404
|
);
|
|
4408
4405
|
}
|
|
4406
|
+
async processContent(slug) {
|
|
4407
|
+
const [contentIndex, rawPost] = await Promise.all([
|
|
4408
|
+
this.getContentIndex(),
|
|
4409
|
+
this.getPost(slug)
|
|
4410
|
+
]);
|
|
4411
|
+
await this.pluginRuntime.startBuild(contentIndex);
|
|
4412
|
+
await this.pluginRuntime.runContentLoaded(slug, rawPost, contentIndex);
|
|
4413
|
+
await this.ensureRoutableSlugs();
|
|
4414
|
+
this.pipeline ??= new Pipeline(
|
|
4415
|
+
contentIndex,
|
|
4416
|
+
await this.locationResolver.getPermalinks(),
|
|
4417
|
+
(postSlug) => this.getPost(postSlug),
|
|
4418
|
+
this.pipelineOptions,
|
|
4419
|
+
this.isBuildTime
|
|
4420
|
+
);
|
|
4421
|
+
const content = await this.pipeline.execute(rawPost, {
|
|
4422
|
+
sourceSlug: slug
|
|
4423
|
+
});
|
|
4424
|
+
this.processedContentCount += 1;
|
|
4425
|
+
if (this.processedContentCount % 100 === 0) {
|
|
4426
|
+
this.observability().tracer.event("content.process.sample", {
|
|
4427
|
+
processed: this.processedContentCount
|
|
4428
|
+
});
|
|
4429
|
+
}
|
|
4430
|
+
await this.pluginRuntime.runPostHook(
|
|
4431
|
+
"onPostParsed",
|
|
4432
|
+
slug,
|
|
4433
|
+
rawPost,
|
|
4434
|
+
content,
|
|
4435
|
+
contentIndex
|
|
4436
|
+
);
|
|
4437
|
+
await this.pluginRuntime.runPostHook(
|
|
4438
|
+
"onPostProcessed",
|
|
4439
|
+
slug,
|
|
4440
|
+
rawPost,
|
|
4441
|
+
content,
|
|
4442
|
+
contentIndex
|
|
4443
|
+
);
|
|
4444
|
+
this.contentCache.set(slug, content);
|
|
4445
|
+
return content;
|
|
4446
|
+
}
|
|
4409
4447
|
async getManifest(options) {
|
|
4410
4448
|
if (this.manifest) return this.manifest;
|
|
4411
4449
|
if (this.manifestPromise) return await this.manifestPromise;
|
|
@@ -4471,7 +4509,11 @@ var ContentManager = class {
|
|
|
4471
4509
|
const manifest = await this.observability().tracer.span(
|
|
4472
4510
|
"content.graph",
|
|
4473
4511
|
{},
|
|
4474
|
-
() => this.manifestBuilder.build(
|
|
4512
|
+
() => this.manifestBuilder.build(
|
|
4513
|
+
entries,
|
|
4514
|
+
contentIndex,
|
|
4515
|
+
this.contentIndexAmbiguities
|
|
4516
|
+
)
|
|
4475
4517
|
);
|
|
4476
4518
|
const cacheManifestEntries = structuredClone(manifest.entries);
|
|
4477
4519
|
this.locationResolver.populateRedirects(manifest, locations);
|
|
@@ -4707,7 +4749,13 @@ var ContentManager = class {
|
|
|
4707
4749
|
const routableSlugs = /* @__PURE__ */ new Set();
|
|
4708
4750
|
await mapConcurrent3(posts, CONTENT_PROCESSING_CONCURRENCY, async (post) => {
|
|
4709
4751
|
const markdown = await this.getPost(post.slug);
|
|
4710
|
-
|
|
4752
|
+
let frontmatter;
|
|
4753
|
+
try {
|
|
4754
|
+
frontmatter = readFrontmatter(markdown);
|
|
4755
|
+
} catch (error) {
|
|
4756
|
+
throw attachErrorPath(error, `${post.slug}.md`);
|
|
4757
|
+
}
|
|
4758
|
+
const publishing = resolvePublishingState(frontmatter, {
|
|
4711
4759
|
strategy,
|
|
4712
4760
|
buildTime: this.publishingBuildTime
|
|
4713
4761
|
});
|
|
@@ -4797,7 +4845,12 @@ function resolveFolderLocation(manifest, folder) {
|
|
|
4797
4845
|
if (candidate) return { type: "content", entry: candidate.entry };
|
|
4798
4846
|
}
|
|
4799
4847
|
if (candidates.length > 1) return { type: "ambiguous", candidates };
|
|
4800
|
-
const
|
|
4848
|
+
const normalizedFolder = normalizeFolder2(folder);
|
|
4849
|
+
const direct = manifest.folderLocations.get(normalizedFolder);
|
|
4850
|
+
if (direct) return { type: "generated", pathname: direct.pathname };
|
|
4851
|
+
const location = [...manifest.folderLocations.values()].find(
|
|
4852
|
+
(candidate) => candidate.folder === normalizedFolder
|
|
4853
|
+
);
|
|
4801
4854
|
return location ? { type: "generated", pathname: location.pathname } : { type: "none" };
|
|
4802
4855
|
}
|
|
4803
4856
|
function resolvePublicFolderLocation(manifest, pathname) {
|
|
@@ -4811,12 +4864,15 @@ function resolvePublicFolderLocation(manifest, pathname) {
|
|
|
4811
4864
|
);
|
|
4812
4865
|
return location ? { type: "generated", pathname: location.pathname } : { type: "none" };
|
|
4813
4866
|
}
|
|
4814
|
-
function resolveGeneratedFolderLocation(manifest, folder) {
|
|
4867
|
+
function resolveGeneratedFolderLocation(manifest, folder, language) {
|
|
4815
4868
|
const normalizedFolder = normalizeFolder2(folder);
|
|
4816
4869
|
if (!normalizedFolder) return null;
|
|
4817
4870
|
const candidates = /* @__PURE__ */ new Set();
|
|
4818
4871
|
const prefix = `${normalizedFolder}/`;
|
|
4819
4872
|
for (const entry of manifest.publicEntries) {
|
|
4873
|
+
if (language !== void 0 && entry.publicLocation.language !== language) {
|
|
4874
|
+
continue;
|
|
4875
|
+
}
|
|
4820
4876
|
if (!entry.slug.startsWith(prefix)) continue;
|
|
4821
4877
|
const remainder = entry.slug.slice(prefix.length).split("/").filter(Boolean);
|
|
4822
4878
|
const pathname = parentPath(
|
|
@@ -5031,7 +5087,7 @@ function clampFinite(value, min, max) {
|
|
|
5031
5087
|
// src/content/read_only_content_graph.ts
|
|
5032
5088
|
async function readOnlyContentGraph(source, locations) {
|
|
5033
5089
|
const entries = await source.scan();
|
|
5034
|
-
const contentIndex = await new ContentIndexBuilder(source).build(entries);
|
|
5090
|
+
const { index: contentIndex, ambiguities: contentIndexAmbiguities } = await new ContentIndexBuilder(source).build(entries);
|
|
5035
5091
|
const markdownEntries = entries.filter((entry) => entry.path.endsWith(".md")).toSorted((left, right) => left.path.localeCompare(right.path));
|
|
5036
5092
|
const markdownContents = await Promise.all(
|
|
5037
5093
|
markdownEntries.map(async (entry) => ({
|
|
@@ -5042,7 +5098,11 @@ async function readOnlyContentGraph(source, locations) {
|
|
|
5042
5098
|
const graphEntries = markdownContents.map(
|
|
5043
5099
|
({ entry, markdown }) => createGraphEntry(entry, markdown, contentIndex, locations)
|
|
5044
5100
|
);
|
|
5045
|
-
return new ManifestBuilder().build(
|
|
5101
|
+
return new ManifestBuilder().build(
|
|
5102
|
+
graphEntries,
|
|
5103
|
+
contentIndex,
|
|
5104
|
+
contentIndexAmbiguities
|
|
5105
|
+
).graph;
|
|
5046
5106
|
}
|
|
5047
5107
|
function createGraphEntry(entry, markdown, contentIndex, locations) {
|
|
5048
5108
|
const slug = entry.path.replace(/\.md$/, "");
|
|
@@ -5076,6 +5136,17 @@ async function readText3(source, entry) {
|
|
|
5076
5136
|
return typeof content === "string" ? content : new TextDecoder().decode(content);
|
|
5077
5137
|
}
|
|
5078
5138
|
|
|
5139
|
+
// src/project/project_layout.ts
|
|
5140
|
+
import path5 from "node:path";
|
|
5141
|
+
function resolveManagedStateRoot(config) {
|
|
5142
|
+
const directory = config?.buildDirectory;
|
|
5143
|
+
return directory ? path5.resolve(directory) : void 0;
|
|
5144
|
+
}
|
|
5145
|
+
function resolveBuildOutputDirectory(config) {
|
|
5146
|
+
const directory = config?.outputDirectory;
|
|
5147
|
+
return directory ? path5.resolve(directory) : void 0;
|
|
5148
|
+
}
|
|
5149
|
+
|
|
5079
5150
|
// src/types/content_manifest.ts
|
|
5080
5151
|
function appendContentBodySlot(entry, slot, html) {
|
|
5081
5152
|
if (!html.trim()) return;
|
|
@@ -5088,12 +5159,12 @@ ${html}` : html
|
|
|
5088
5159
|
}
|
|
5089
5160
|
|
|
5090
5161
|
// src/types/plugin_endpoint.ts
|
|
5091
|
-
function defineEndpoint(
|
|
5162
|
+
function defineEndpoint(path6, handler, options = {}) {
|
|
5092
5163
|
if (options.cacheControl === void 0) {
|
|
5093
|
-
return { path:
|
|
5164
|
+
return { path: path6, handler };
|
|
5094
5165
|
}
|
|
5095
5166
|
return {
|
|
5096
|
-
path:
|
|
5167
|
+
path: path6,
|
|
5097
5168
|
handler: async (context) => {
|
|
5098
5169
|
const response = await handler(context);
|
|
5099
5170
|
const headers = { ...response.headers };
|
|
@@ -5142,6 +5213,7 @@ export {
|
|
|
5142
5213
|
PluginDependencyError,
|
|
5143
5214
|
SinkTracer,
|
|
5144
5215
|
appendContentBodySlot,
|
|
5216
|
+
attachErrorPath,
|
|
5145
5217
|
attachmentUrl,
|
|
5146
5218
|
buildContentCollections,
|
|
5147
5219
|
buildGraphEdges,
|
|
@@ -5193,6 +5265,7 @@ export {
|
|
|
5193
5265
|
readContentBuildStateStatus,
|
|
5194
5266
|
readContentSourceEntry,
|
|
5195
5267
|
readOnlyContentGraph,
|
|
5268
|
+
resolveBuildOutputDirectory,
|
|
5196
5269
|
resolveConfig,
|
|
5197
5270
|
resolveConfigModule,
|
|
5198
5271
|
resolveContentBuildStatePath,
|
|
@@ -5202,6 +5275,7 @@ export {
|
|
|
5202
5275
|
resolveFolderEntry,
|
|
5203
5276
|
resolveFolderLocation,
|
|
5204
5277
|
resolveGeneratedFolderLocation,
|
|
5278
|
+
resolveManagedStateRoot,
|
|
5205
5279
|
resolvePlugins,
|
|
5206
5280
|
resolvePublicFolderLocation,
|
|
5207
5281
|
resolvePublishingBuildTime,
|
package/dist/src/config.d.ts
CHANGED
|
@@ -4,5 +4,7 @@ import type { RiebeckiteConfig } from "./types/riebeckite_config.js";
|
|
|
4
4
|
export declare function defineConfig(config: RiebeckiteConfig): RiebeckiteConfig;
|
|
5
5
|
export declare function resolveConfigModule(configModule: unknown): ResolvedRiebeckiteConfig;
|
|
6
6
|
export declare function resolveConfig(config: RiebeckiteConfig): ResolvedRiebeckiteConfig;
|
|
7
|
-
export declare function isPublished(config: ResolvedRiebeckiteConfig, frontmatter: PostFrontmatter | undefined
|
|
7
|
+
export declare function isPublished(config: ResolvedRiebeckiteConfig, frontmatter: PostFrontmatter | undefined, options?: {
|
|
8
|
+
buildTime?: Date | string;
|
|
9
|
+
}): boolean;
|
|
8
10
|
export declare function isExcluded(patterns: readonly string[], relativePath: string): boolean;
|
|
@@ -12,6 +12,7 @@ export type ContentBuildPreparation = {
|
|
|
12
12
|
readonly currentEntries: readonly FingerprintedContentEntry[];
|
|
13
13
|
readonly currentContentAliases: ReadonlyMap<string, readonly string[]>;
|
|
14
14
|
readonly currentContentIndex: Map<string, string>;
|
|
15
|
+
readonly currentContentIndexAmbiguities: ReadonlyMap<string, readonly string[]>;
|
|
15
16
|
readonly changeSet: ContentChangeSet;
|
|
16
17
|
readonly affectedContent: ReturnType<typeof determineAffectedContent>;
|
|
17
18
|
};
|
|
@@ -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 = 8;
|
|
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
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import type { ContentSource, ContentSourceEntry } from "./content_source.js";
|
|
2
|
+
export type ContentIndexBuild = {
|
|
3
|
+
readonly index: Map<string, string>;
|
|
4
|
+
readonly ambiguities: ReadonlyMap<string, readonly string[]>;
|
|
5
|
+
};
|
|
2
6
|
export declare class ContentIndexBuilder {
|
|
3
7
|
private source;
|
|
4
8
|
constructor(source: ContentSource);
|
|
5
|
-
build(contentEntries: readonly ContentSourceEntry[], read?: (entry: ContentSourceEntry) => Promise<import("./content_source.js").ContentSourceContent>): Promise<
|
|
6
|
-
static buildFromAliases(contentEntries: readonly ContentSourceEntry[], aliasesByPath: ReadonlyMap<string, readonly string[]>):
|
|
9
|
+
build(contentEntries: readonly ContentSourceEntry[], read?: (entry: ContentSourceEntry) => Promise<import("./content_source.js").ContentSourceContent>): Promise<ContentIndexBuild>;
|
|
10
|
+
static buildFromAliases(contentEntries: readonly ContentSourceEntry[], aliasesByPath: ReadonlyMap<string, readonly string[]>): ContentIndexBuild;
|
|
7
11
|
private indexContentEntry;
|
|
8
12
|
private static indexContentEntryFromAliases;
|
|
9
13
|
}
|
|
@@ -29,6 +29,7 @@ export declare class ContentManager {
|
|
|
29
29
|
private manifestBuilder;
|
|
30
30
|
private pluginRuntime;
|
|
31
31
|
private contentIndex;
|
|
32
|
+
private contentIndexAmbiguities;
|
|
32
33
|
private contentIndexPromise;
|
|
33
34
|
private contentCache;
|
|
34
35
|
private manifest;
|
|
@@ -51,6 +52,7 @@ export declare class ContentManager {
|
|
|
51
52
|
getPost(slug: string): Promise<string>;
|
|
52
53
|
getContentIndex(preparation?: ContentBuildPreparation): Promise<Map<string, string>>;
|
|
53
54
|
getProcessedContent(slug: string): Promise<PostContent>;
|
|
55
|
+
private processContent;
|
|
54
56
|
getManifest(options?: ContentBuildOptions): Promise<ContentManifest>;
|
|
55
57
|
private buildManifest;
|
|
56
58
|
build(options?: ContentBuildOptions): Promise<ContentManifest>;
|
|
@@ -33,4 +33,4 @@ export type FolderLocationResolution = {
|
|
|
33
33
|
export declare function resolveFolderEntry(manifest: ContentManifest, folder: string, options?: ResolveFolderEntryOptions): FolderEntryResolution;
|
|
34
34
|
export declare function resolveFolderLocation(manifest: ContentManifest, folder: string): FolderLocationResolution;
|
|
35
35
|
export declare function resolvePublicFolderLocation(manifest: ContentManifest, pathname: string): FolderLocationResolution;
|
|
36
|
-
export declare function resolveGeneratedFolderLocation(manifest: ContentManifest, folder: string): string | null;
|
|
36
|
+
export declare function resolveGeneratedFolderLocation(manifest: ContentManifest, folder: string, language?: string): string | null;
|
|
@@ -3,5 +3,5 @@ import type { PostContent } from "../types/post_content.js";
|
|
|
3
3
|
import type { ResolvedPublishingState } from "./publishing.js";
|
|
4
4
|
export declare class ManifestBuilder {
|
|
5
5
|
createEntry(slug: string, markdown: string, processed: PostContent, contentIndex: Map<string, string>, location: ContentPublicLocation, publishing: ResolvedPublishingState): ContentManifestEntry;
|
|
6
|
-
build(entries: ContentManifestEntry[], contentIndex: Map<string, string>): ContentManifest;
|
|
6
|
+
build(entries: ContentManifestEntry[], contentIndex: Map<string, string>, contentIndexAmbiguities?: ReadonlyMap<string, readonly string[]>): ContentManifest;
|
|
7
7
|
}
|
|
@@ -2,6 +2,7 @@ import type { Tracer } from "../observability.js";
|
|
|
2
2
|
import type { RiebeckitePlugin } from "../types/plugin.js";
|
|
3
3
|
import type { PluginLifecycleContext, PluginManifestContext } from "../types/plugin_context.js";
|
|
4
4
|
export declare class PluginHookError extends Error {
|
|
5
|
+
readonly path?: string;
|
|
5
6
|
constructor(pluginName: string, hookName: string, cause: unknown);
|
|
6
7
|
}
|
|
7
8
|
export declare function runPluginHook<TContext extends {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ResolvedRiebeckiteConfig } from "../types/resolved_riebeckite_config.js";
|
|
2
|
+
/**
|
|
3
|
+
* Root directory for Riebeckite-managed persistent state: content build state,
|
|
4
|
+
* plugin cache, persistent content cache, and the SSG output cache. The root is
|
|
5
|
+
* reproducible and safe to remove; missing paths are not an error.
|
|
6
|
+
*/
|
|
7
|
+
export declare function resolveManagedStateRoot(config: ResolvedRiebeckiteConfig | undefined): string | undefined;
|
|
8
|
+
/**
|
|
9
|
+
* Directory for the built site. Missing paths are not an error.
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolveBuildOutputDirectory(config: ResolvedRiebeckiteConfig | undefined): string | undefined;
|
|
@@ -77,6 +77,8 @@ export type ContentPublicLocation = {
|
|
|
77
77
|
};
|
|
78
78
|
export type FolderLocation = {
|
|
79
79
|
pathname: string;
|
|
80
|
+
folder?: string;
|
|
81
|
+
language?: string;
|
|
80
82
|
};
|
|
81
83
|
export type PluginPageRoute = {
|
|
82
84
|
pathname: string;
|
|
@@ -121,6 +123,13 @@ export type ContentManifest = {
|
|
|
121
123
|
outgoingLinks: Map<string, ContentLink[]>;
|
|
122
124
|
incomingLinks: Map<string, string[]>;
|
|
123
125
|
contentIndex: Map<string, string>;
|
|
126
|
+
/**
|
|
127
|
+
* Lookup keys that matched more than one candidate, mapped to their
|
|
128
|
+
* candidates (sorted). These keys are intentionally absent from
|
|
129
|
+
* `contentIndex` so links stay unresolved instead of picking a target by
|
|
130
|
+
* discovery order. Used to report actionable ambiguity diagnostics.
|
|
131
|
+
*/
|
|
132
|
+
contentIndexAmbiguities?: ReadonlyMap<string, readonly string[]>;
|
|
124
133
|
graph: ContentGraph;
|
|
125
134
|
assets: ContentManifestPluginAsset[];
|
|
126
135
|
/**
|
|
@@ -25,7 +25,7 @@ export type RenderableFeedEntry = ContentManifestEntry & {
|
|
|
25
25
|
html?: string;
|
|
26
26
|
};
|
|
27
27
|
export type PluginSeoExtension = {
|
|
28
|
-
buildArticleSeo(config: ResolvedRiebeckiteConfig, permalink: string, post: PostContent, headTags?: readonly PluginHeadTag[]): SeoMetadata;
|
|
28
|
+
buildArticleSeo(config: ResolvedRiebeckiteConfig, permalink: string, post: PostContent, headTags?: readonly PluginHeadTag[], language?: string): SeoMetadata;
|
|
29
29
|
buildWebsiteSeo(config: ResolvedRiebeckiteConfig, input: WebsiteSeoInput, headTags?: readonly PluginHeadTag[]): SeoMetadata;
|
|
30
30
|
buildAbsoluteUrl(config: ResolvedRiebeckiteConfig, pathOrUrl: string): string;
|
|
31
31
|
buildPostUrl(config: ResolvedRiebeckiteConfig, permalink: string): string;
|
|
@@ -9,6 +9,11 @@ export type ResolvedRiebeckiteConfig = {
|
|
|
9
9
|
* relative to their application root.
|
|
10
10
|
*/
|
|
11
11
|
buildDirectory?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Directory for the built site. Host integrations resolve this relative to
|
|
14
|
+
* their application root.
|
|
15
|
+
*/
|
|
16
|
+
outputDirectory?: string;
|
|
12
17
|
site: Omit<Required<SiteConfig>, "feed"> & {
|
|
13
18
|
feed: {
|
|
14
19
|
title: string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function attachErrorPath<T>(error: T, path: string): T;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@riebeckite/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.18",
|
|
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.18"
|
|
53
53
|
},
|
|
54
54
|
"repository": {
|
|
55
55
|
"type": "git",
|