@riebeckite/core 0.0.15 → 0.0.17
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 +1 -1
- package/README_ja.md +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.js +313 -160
- package/dist/src/content/content_build_coordinator.d.ts +1 -1
- package/dist/src/content/content_build_state.d.ts +1 -1
- package/dist/src/content/content_dependency_tracker.d.ts +2 -0
- package/dist/src/content/content_language.d.ts +3 -0
- package/dist/src/content/content_stable_id.d.ts +1 -4
- package/dist/src/content/file_system_content_source.d.ts +10 -1
- package/dist/src/content/folder_entry.d.ts +1 -0
- package/dist/src/pipeline.d.ts +1 -0
- package/dist/src/plugin/plugin_lifecycle.d.ts +6 -4
- package/dist/src/plugin/plugin_runtime.d.ts +5 -2
- package/dist/src/types/content_manifest.d.ts +8 -4
- package/dist/src/types/plugin.d.ts +0 -2
- package/dist/src/types/plugin_page.d.ts +2 -0
- package/dist/src/types/plugin_seo.d.ts +3 -2
- package/dist/src/types/post_content.d.ts +0 -2
- package/dist/src/types/resolved_riebeckite_config.d.ts +7 -6
- package/dist/src/types/riebeckite_config.d.ts +0 -5
- package/package.json +2 -2
package/README.md
CHANGED
package/README_ja.md
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -10,18 +10,21 @@ export { buildContentCollections } from "./src/content/content_collection.js";
|
|
|
10
10
|
export { fingerprintContentEntries } from "./src/content/content_fingerprint.js";
|
|
11
11
|
export type { ContentGraph, ContentGraphNeighbors, } from "./src/content/content_graph.js";
|
|
12
12
|
export { createContentGraph } from "./src/content/content_graph.js";
|
|
13
|
+
export { getEntryLanguage, selectEntriesByLanguage, } from "./src/content/content_language.js";
|
|
13
14
|
export { resolveDefaultContentLocation } from "./src/content/content_location.js";
|
|
14
15
|
export type { ContentBuildOptions, ContentInspection, } from "./src/content/content_manager.js";
|
|
15
16
|
export { ContentManager } from "./src/content/content_manager.js";
|
|
16
17
|
export { extractFrontmatterAliases } from "./src/content/content_metadata.js";
|
|
18
|
+
export { computePipelineFingerprint, isPersistentlyCacheable, } from "./src/content/content_persistent_cache.js";
|
|
17
19
|
export type { ContentQueryDateFilter, ContentQueryDateGranularity, ContentQueryFilter, ContentQueryFrontmatterFilter, ContentQueryGroup, ContentQueryGroupBy, ContentQueryGroupOptions, ContentQueryPage, ContentQueryPagination, ContentQueryScalar, ContentQuerySort, ContentQuerySortOrder, ContentQuerySpec, ContentQueryTagFilter, } from "./src/content/content_query.js";
|
|
18
20
|
export { groupContentEntries, queryContentEntries, queryContentPage, resolveContentQueryPagination, } from "./src/content/content_query.js";
|
|
19
21
|
export type { ContentSource, ContentSourceContent, ContentSourceEntry, ContentSourceMetadata, } from "./src/content/content_source.js";
|
|
20
22
|
export { getContentSourceEntry, readContentSourceEntry, } from "./src/content/content_source.js";
|
|
21
23
|
export { resolveContentStableId } from "./src/content/content_stable_id.js";
|
|
22
|
-
export {
|
|
24
|
+
export type { ContentSourceExclusion, ContentSourceScan, } from "./src/content/file_system_content_source.js";
|
|
25
|
+
export { FileSystemContentSource, INTERNAL_CONTENT_IGNORE_PATTERNS, isIgnoredContentPath, matchContentExcludePattern, } from "./src/content/file_system_content_source.js";
|
|
23
26
|
export type { FolderEntryCandidate, FolderEntryKind, FolderEntryResolution, FolderEntryScope, FolderLocationResolution, ResolveFolderEntryOptions, } from "./src/content/folder_entry.js";
|
|
24
|
-
export { resolveFolderEntry, resolveFolderLocation, resolveGeneratedFolderLocation, } from "./src/content/folder_entry.js";
|
|
27
|
+
export { resolveFolderEntry, resolveFolderLocation, resolveGeneratedFolderLocation, resolvePublicFolderLocation, } from "./src/content/folder_entry.js";
|
|
25
28
|
export type { ForceGraphLayoutOptions, GraphEdge, GraphLayoutNode, LinkableGraphNode, RadialGraphLayoutOptions, } from "./src/content/graph_layout.js";
|
|
26
29
|
export { buildGraphEdges, layoutForceGraph, layoutRadialGraph, } from "./src/content/graph_layout.js";
|
|
27
30
|
export { IMAGE_EXTENSIONS } from "./src/content/image_extensions.js";
|
package/dist/index.js
CHANGED
|
@@ -19,6 +19,7 @@ function validateConfigIssues(config) {
|
|
|
19
19
|
}
|
|
20
20
|
validateSite(value.site, issues);
|
|
21
21
|
validateContent(value.content, issues);
|
|
22
|
+
validateCache(value.cache, issues);
|
|
22
23
|
validateTheme(value.theme, issues);
|
|
23
24
|
validatePlugins(value.plugins, issues);
|
|
24
25
|
return issues;
|
|
@@ -93,6 +94,15 @@ function validatePublishStrategy(value, issues) {
|
|
|
93
94
|
});
|
|
94
95
|
}
|
|
95
96
|
}
|
|
97
|
+
function validateCache(value, issues) {
|
|
98
|
+
if (value === void 0) return;
|
|
99
|
+
if (!isRecord(value)) {
|
|
100
|
+
issues.push({ path: "cache", message: "Expected an object." });
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
validateOptionalBoolean(value.enabled, "cache.enabled", issues);
|
|
104
|
+
validateOptionalString(value.directory, "cache.directory", issues);
|
|
105
|
+
}
|
|
96
106
|
function validateTheme(value, issues) {
|
|
97
107
|
if (value === void 0) return;
|
|
98
108
|
if (!isRecord(value)) {
|
|
@@ -626,18 +636,13 @@ function resolveConfig(config) {
|
|
|
626
636
|
}
|
|
627
637
|
},
|
|
628
638
|
content: {
|
|
629
|
-
directory: config.content?.directory ?? "
|
|
639
|
+
directory: config.content?.directory ?? "content",
|
|
630
640
|
source: config.content?.source,
|
|
631
641
|
exclude: config.content?.exclude ?? [],
|
|
632
642
|
filters: {
|
|
633
643
|
publishStrategy: config.content?.filters?.publishStrategy ?? "explicit"
|
|
634
644
|
}
|
|
635
645
|
},
|
|
636
|
-
markdown: {
|
|
637
|
-
syntaxHighlight: {
|
|
638
|
-
theme: config.markdown?.syntaxHighlight?.theme ?? ""
|
|
639
|
-
}
|
|
640
|
-
},
|
|
641
646
|
theme,
|
|
642
647
|
plugins: resolvePlugins(config.plugins),
|
|
643
648
|
cache: {
|
|
@@ -805,7 +810,7 @@ import fs from "node:fs/promises";
|
|
|
805
810
|
import path from "node:path";
|
|
806
811
|
|
|
807
812
|
// src/content/content_build_state.ts
|
|
808
|
-
var CONTENT_BUILD_STATE_VERSION =
|
|
813
|
+
var CONTENT_BUILD_STATE_VERSION = 7;
|
|
809
814
|
var CONTENT_BUILD_STATE_DIRECTORY = ".riebeckite";
|
|
810
815
|
var CONTENT_BUILD_STATE_EXCLUDE = `${CONTENT_BUILD_STATE_DIRECTORY}/**`;
|
|
811
816
|
|
|
@@ -1322,6 +1327,23 @@ function isResolvedNoteLink(link) {
|
|
|
1322
1327
|
return link.kind === "note" && link.slug !== null;
|
|
1323
1328
|
}
|
|
1324
1329
|
|
|
1330
|
+
// src/content/content_language.ts
|
|
1331
|
+
function getEntryLanguage(entry) {
|
|
1332
|
+
return entry.publicLocation.language;
|
|
1333
|
+
}
|
|
1334
|
+
function selectEntriesByLanguage(entries, language) {
|
|
1335
|
+
if (!language) {
|
|
1336
|
+
return entries;
|
|
1337
|
+
}
|
|
1338
|
+
const localized = entries.filter(
|
|
1339
|
+
(entry) => getEntryLanguage(entry) !== void 0
|
|
1340
|
+
);
|
|
1341
|
+
if (localized.length === 0) {
|
|
1342
|
+
return entries;
|
|
1343
|
+
}
|
|
1344
|
+
return localized.filter((entry) => getEntryLanguage(entry) === language);
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1325
1347
|
// src/content/content_location.ts
|
|
1326
1348
|
function resolveDefaultContentLocation(content) {
|
|
1327
1349
|
return {
|
|
@@ -1479,6 +1501,8 @@ import { matter as matter2 } from "vfile-matter";
|
|
|
1479
1501
|
|
|
1480
1502
|
// src/content/content_dependency_tracker.ts
|
|
1481
1503
|
import { createHash as createHash2 } from "node:crypto";
|
|
1504
|
+
var LINK_INDEX_PREFIX = "index:";
|
|
1505
|
+
var LINK_LOCATION_PREFIX = "location:";
|
|
1482
1506
|
function createContentDependencyTracker(source) {
|
|
1483
1507
|
const dependencies = /* @__PURE__ */ new Map();
|
|
1484
1508
|
const record = (identity, content) => {
|
|
@@ -1524,6 +1548,30 @@ function dependencyKey(dependency) {
|
|
|
1524
1548
|
return `${normalized.kind}:${normalized.id}`;
|
|
1525
1549
|
}
|
|
1526
1550
|
|
|
1551
|
+
// src/content/content_links.ts
|
|
1552
|
+
var WIKILINK_PATTERN = /(!)?\[\[([^\]|#^]+)(?:[#^][^\]|]+)?(?:\|[^\]]+)?\]\]/g;
|
|
1553
|
+
function extractContentLinks(markdown, contentIndex) {
|
|
1554
|
+
WIKILINK_PATTERN.lastIndex = 0;
|
|
1555
|
+
const links = [];
|
|
1556
|
+
for (let match = WIKILINK_PATTERN.exec(markdown); match !== null; match = WIKILINK_PATTERN.exec(markdown)) {
|
|
1557
|
+
const rawTarget = match[2]?.trim();
|
|
1558
|
+
if (!rawTarget) continue;
|
|
1559
|
+
const resolved = contentIndex.get(rawTarget.toLowerCase()) ?? null;
|
|
1560
|
+
links.push({
|
|
1561
|
+
raw: rawTarget,
|
|
1562
|
+
slug: resolved,
|
|
1563
|
+
kind: resolved ? linkKind(resolved) : "unresolved",
|
|
1564
|
+
embed: match[1] === "!"
|
|
1565
|
+
});
|
|
1566
|
+
}
|
|
1567
|
+
return links;
|
|
1568
|
+
}
|
|
1569
|
+
function linkKind(value) {
|
|
1570
|
+
if (isImagePath(value)) return "image";
|
|
1571
|
+
if (isAttachmentPath(value)) return "attachment";
|
|
1572
|
+
return "note";
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1527
1575
|
// src/content/content_persistent_cache.ts
|
|
1528
1576
|
import { createHash as createHash4 } from "node:crypto";
|
|
1529
1577
|
import fs2 from "node:fs/promises";
|
|
@@ -1720,7 +1768,6 @@ function computePipelineFingerprint(config) {
|
|
|
1720
1768
|
const fingerprintData = {
|
|
1721
1769
|
compatibilityVersion: CONTENT_CACHE_COMPATIBILITY_VERSION,
|
|
1722
1770
|
plugins: plugins.map((p) => pluginFingerprint(p)),
|
|
1723
|
-
markdown: config.markdown,
|
|
1724
1771
|
content: {
|
|
1725
1772
|
filters: config.content.filters
|
|
1726
1773
|
}
|
|
@@ -1885,6 +1932,7 @@ async function writeAtomically2(targetPath, versionDirectory2, serialized) {
|
|
|
1885
1932
|
}
|
|
1886
1933
|
function resolvePluginCacheDirectory(config) {
|
|
1887
1934
|
if (!config) return path3.resolve(process.cwd(), ".riebeckite", "cache");
|
|
1935
|
+
if (config.cache?.directory) return config.cache.directory;
|
|
1888
1936
|
if (config.buildDirectory) return path3.join(config.buildDirectory, "cache");
|
|
1889
1937
|
return path3.resolve(config.content.directory, "..", ".riebeckite", "cache");
|
|
1890
1938
|
}
|
|
@@ -2153,6 +2201,9 @@ var Pipeline = class {
|
|
|
2153
2201
|
frontmatter: file.data.matter || {},
|
|
2154
2202
|
html: String(file.value)
|
|
2155
2203
|
};
|
|
2204
|
+
if (embedDepth === 0 && sourceSlug && dependencyTracker) {
|
|
2205
|
+
this.recordNoteLinkDependencies(markDownContent, dependencyTracker);
|
|
2206
|
+
}
|
|
2156
2207
|
if (sourceSlug && dependencyTracker) {
|
|
2157
2208
|
this.reportContentDependencies(
|
|
2158
2209
|
sourceSlug,
|
|
@@ -2202,6 +2253,25 @@ var Pipeline = class {
|
|
|
2202
2253
|
this.options.isRoutable
|
|
2203
2254
|
);
|
|
2204
2255
|
}
|
|
2256
|
+
recordNoteLinkDependencies(markdown, dependencyTracker) {
|
|
2257
|
+
for (const link of extractContentLinks(markdown, this.contentIndex)) {
|
|
2258
|
+
if (link.slug !== null && link.kind === "note") {
|
|
2259
|
+
const id = `${LINK_LOCATION_PREFIX}${link.slug}`;
|
|
2260
|
+
dependencyTracker.recordLinkResolution(
|
|
2261
|
+
id,
|
|
2262
|
+
this.resolveLinkDependency(id)
|
|
2263
|
+
);
|
|
2264
|
+
continue;
|
|
2265
|
+
}
|
|
2266
|
+
if (link.kind === "unresolved") {
|
|
2267
|
+
const id = `${LINK_INDEX_PREFIX}${link.raw.toLowerCase()}`;
|
|
2268
|
+
dependencyTracker.recordLinkResolution(
|
|
2269
|
+
id,
|
|
2270
|
+
this.resolveLinkDependency(id)
|
|
2271
|
+
);
|
|
2272
|
+
}
|
|
2273
|
+
}
|
|
2274
|
+
}
|
|
2205
2275
|
use(processor, plugin, options) {
|
|
2206
2276
|
const register = processor.use.bind(processor);
|
|
2207
2277
|
if (options === void 0) {
|
|
@@ -2305,8 +2375,6 @@ function normalizeMarkdownLinks(context) {
|
|
|
2305
2375
|
});
|
|
2306
2376
|
};
|
|
2307
2377
|
}
|
|
2308
|
-
var LINK_INDEX_PREFIX = "index:";
|
|
2309
|
-
var LINK_LOCATION_PREFIX = "location:";
|
|
2310
2378
|
function resolveLinkDependencyValue(id, contentIndex, lookupPermalink, isRoutable) {
|
|
2311
2379
|
if (id.startsWith(LINK_INDEX_PREFIX)) {
|
|
2312
2380
|
return contentIndex.get(id.slice(LINK_INDEX_PREFIX.length)) ?? "";
|
|
@@ -2517,12 +2585,26 @@ var GeneratedOutputRegistry = class {
|
|
|
2517
2585
|
};
|
|
2518
2586
|
|
|
2519
2587
|
// src/plugin/plugin_lifecycle.ts
|
|
2520
|
-
var
|
|
2588
|
+
var PluginHookError = class extends Error {
|
|
2521
2589
|
constructor(pluginName, hookName, cause) {
|
|
2522
2590
|
super(`Plugin "${pluginName}" failed during "${hookName}"`, { cause });
|
|
2523
|
-
this.name = "
|
|
2591
|
+
this.name = "PluginHookError";
|
|
2524
2592
|
}
|
|
2525
2593
|
};
|
|
2594
|
+
async function runPluginHook(plugin, hookName, context, hook) {
|
|
2595
|
+
try {
|
|
2596
|
+
return await context.tracer.span(
|
|
2597
|
+
`plugin.${hookName}`,
|
|
2598
|
+
{
|
|
2599
|
+
plugin: plugin.name,
|
|
2600
|
+
hook: hookName
|
|
2601
|
+
},
|
|
2602
|
+
() => hook(context)
|
|
2603
|
+
);
|
|
2604
|
+
} catch (error) {
|
|
2605
|
+
throw new PluginHookError(plugin.name, hookName, error);
|
|
2606
|
+
}
|
|
2607
|
+
}
|
|
2526
2608
|
async function runSetup(plugins, createContext) {
|
|
2527
2609
|
await runLifecycleHook(
|
|
2528
2610
|
plugins,
|
|
@@ -2559,19 +2641,7 @@ async function runLifecycleHook(plugins, hookName, getHook, createContext) {
|
|
|
2559
2641
|
for (const plugin of plugins) {
|
|
2560
2642
|
const hook = getHook(plugin);
|
|
2561
2643
|
if (!hook) continue;
|
|
2562
|
-
|
|
2563
|
-
const context = createContext(plugin);
|
|
2564
|
-
await context.tracer.span(
|
|
2565
|
-
`plugin.${hookName}`,
|
|
2566
|
-
{
|
|
2567
|
-
plugin: plugin.name,
|
|
2568
|
-
hook: hookName
|
|
2569
|
-
},
|
|
2570
|
-
() => hook(context)
|
|
2571
|
-
);
|
|
2572
|
-
} catch (error) {
|
|
2573
|
-
throw new PluginLifecycleError(plugin.name, hookName, error);
|
|
2574
|
-
}
|
|
2644
|
+
await runPluginHook(plugin, hookName, createContext(plugin), hook);
|
|
2575
2645
|
}
|
|
2576
2646
|
}
|
|
2577
2647
|
|
|
@@ -2589,6 +2659,7 @@ var PluginRuntime = class {
|
|
|
2589
2659
|
generatedOutputs = new GeneratedOutputRegistry();
|
|
2590
2660
|
isBuildTime = false;
|
|
2591
2661
|
resolvedPlugins = null;
|
|
2662
|
+
pageDeclarations = /* @__PURE__ */ new WeakMap();
|
|
2592
2663
|
getDiagnostics() {
|
|
2593
2664
|
return this.diagnostics;
|
|
2594
2665
|
}
|
|
@@ -2599,7 +2670,7 @@ var PluginRuntime = class {
|
|
|
2599
2670
|
* Starts the plugin build lifecycle exactly once, regardless of which public
|
|
2600
2671
|
* entry point (content processing or location resolution) reaches it first.
|
|
2601
2672
|
* Concurrent callers await the same run, so the ordered hooks
|
|
2602
|
-
* (`setup` → `buildStart` → `
|
|
2673
|
+
* (`setup` → `buildStart` → `onConfigResolved`) are never
|
|
2603
2674
|
* duplicated and no caller proceeds before the lifecycle completes.
|
|
2604
2675
|
*/
|
|
2605
2676
|
startBuild(contentIndex) {
|
|
@@ -2607,7 +2678,7 @@ var PluginRuntime = class {
|
|
|
2607
2678
|
return this.buildLifecycle;
|
|
2608
2679
|
}
|
|
2609
2680
|
async runContentLoaded(slug, markdown, contentIndex) {
|
|
2610
|
-
await this.runHook((plugin) => plugin.onContentLoaded, {
|
|
2681
|
+
await this.runHook("onContentLoaded", (plugin) => plugin.onContentLoaded, {
|
|
2611
2682
|
...this.createContext(contentIndex),
|
|
2612
2683
|
slug,
|
|
2613
2684
|
markdown
|
|
@@ -2619,22 +2690,30 @@ var PluginRuntime = class {
|
|
|
2619
2690
|
for (const plugin of this.plugins()) {
|
|
2620
2691
|
const resolver = plugin.resolveContentLocations;
|
|
2621
2692
|
if (!resolver) continue;
|
|
2622
|
-
const
|
|
2623
|
-
|
|
2693
|
+
const pluginContext = this.createPluginContext(plugin, context);
|
|
2694
|
+
const resolved = await runPluginHook(
|
|
2695
|
+
plugin,
|
|
2696
|
+
"resolveContentLocations",
|
|
2697
|
+
pluginContext,
|
|
2698
|
+
resolver
|
|
2624
2699
|
);
|
|
2625
2700
|
locations.push(...resolved);
|
|
2626
2701
|
}
|
|
2627
2702
|
return locations;
|
|
2628
2703
|
}
|
|
2629
2704
|
async extendContentLocations(entries, locations, contentIndex) {
|
|
2630
|
-
await this.runHook(
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2705
|
+
await this.runHook(
|
|
2706
|
+
"extendContentLocations",
|
|
2707
|
+
(plugin) => plugin.extendContentLocations,
|
|
2708
|
+
{
|
|
2709
|
+
...this.createContext(contentIndex),
|
|
2710
|
+
entries,
|
|
2711
|
+
locations
|
|
2712
|
+
}
|
|
2713
|
+
);
|
|
2635
2714
|
}
|
|
2636
2715
|
async runPostHook(hookName, slug, markdown, content, contentIndex) {
|
|
2637
|
-
await this.runHook((plugin) => plugin[hookName], {
|
|
2716
|
+
await this.runHook(hookName, (plugin) => plugin[hookName], {
|
|
2638
2717
|
...this.createContext(contentIndex),
|
|
2639
2718
|
slug,
|
|
2640
2719
|
markdown,
|
|
@@ -2642,16 +2721,24 @@ var PluginRuntime = class {
|
|
|
2642
2721
|
});
|
|
2643
2722
|
}
|
|
2644
2723
|
async runGraphHook(entries, contentIndex) {
|
|
2645
|
-
await this.runHook(
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2724
|
+
await this.runHook(
|
|
2725
|
+
"extendContentGraph",
|
|
2726
|
+
(plugin) => plugin.extendContentGraph,
|
|
2727
|
+
{
|
|
2728
|
+
...this.createContext(contentIndex),
|
|
2729
|
+
entries
|
|
2730
|
+
}
|
|
2731
|
+
);
|
|
2649
2732
|
}
|
|
2650
2733
|
async runManifestCreated(manifest, contentIndex) {
|
|
2651
|
-
await this.runHook(
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2734
|
+
await this.runHook(
|
|
2735
|
+
"onManifestCreated",
|
|
2736
|
+
(plugin) => plugin.onManifestCreated,
|
|
2737
|
+
{
|
|
2738
|
+
...this.createContext(contentIndex),
|
|
2739
|
+
manifest
|
|
2740
|
+
}
|
|
2741
|
+
);
|
|
2655
2742
|
}
|
|
2656
2743
|
async runBuildEnd(manifest, contentIndex) {
|
|
2657
2744
|
const context = {
|
|
@@ -2662,10 +2749,6 @@ var PluginRuntime = class {
|
|
|
2662
2749
|
this.plugins(),
|
|
2663
2750
|
(plugin) => this.createPluginContext(plugin, context)
|
|
2664
2751
|
);
|
|
2665
|
-
await this.runHook((plugin) => plugin.onBuildEnd, {
|
|
2666
|
-
...this.createContext(contentIndex),
|
|
2667
|
-
manifest
|
|
2668
|
-
});
|
|
2669
2752
|
}
|
|
2670
2753
|
enableBuildTime() {
|
|
2671
2754
|
this.isBuildTime = true;
|
|
@@ -2747,63 +2830,74 @@ var PluginRuntime = class {
|
|
|
2747
2830
|
return highest[0].page;
|
|
2748
2831
|
}
|
|
2749
2832
|
async getPagePaths(manifest, contentIndex) {
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
for (const rawPath of resolved) {
|
|
2758
|
-
paths.push(normalizePageTypePath(rawPath, pageType));
|
|
2759
|
-
}
|
|
2760
|
-
}
|
|
2761
|
-
}
|
|
2762
|
-
return [...new Set(paths)];
|
|
2833
|
+
return [
|
|
2834
|
+
...new Set(
|
|
2835
|
+
(await this.getPageDeclarations(manifest, contentIndex)).map(
|
|
2836
|
+
(declaration) => declaration.pathname
|
|
2837
|
+
)
|
|
2838
|
+
)
|
|
2839
|
+
];
|
|
2763
2840
|
}
|
|
2764
2841
|
async getPageRoutes(manifest, contentIndex) {
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
for (const pathname of paths) {
|
|
2773
|
-
routes.push({
|
|
2774
|
-
pathname: normalizePageTypePath(pathname, pageType),
|
|
2775
|
-
pluginName: plugin.name,
|
|
2776
|
-
pageType: pageType.id
|
|
2777
|
-
});
|
|
2778
|
-
}
|
|
2779
|
-
}
|
|
2780
|
-
}
|
|
2781
|
-
return routes;
|
|
2842
|
+
return (await this.getPageDeclarations(manifest, contentIndex)).map(
|
|
2843
|
+
({ pathname, plugin, pageType }) => ({
|
|
2844
|
+
pathname,
|
|
2845
|
+
pluginName: plugin.name,
|
|
2846
|
+
pageType: pageType.id
|
|
2847
|
+
})
|
|
2848
|
+
);
|
|
2782
2849
|
}
|
|
2783
2850
|
async getPageOutputs(manifest, contentIndex) {
|
|
2784
|
-
const outputs =
|
|
2851
|
+
const outputs = await Promise.all(
|
|
2852
|
+
(await this.getPageDeclarations(manifest, contentIndex)).map(
|
|
2853
|
+
async ({ pathname, plugin, pageType }) => {
|
|
2854
|
+
const context = {
|
|
2855
|
+
...this.createContext(contentIndex),
|
|
2856
|
+
manifest,
|
|
2857
|
+
pathname
|
|
2858
|
+
};
|
|
2859
|
+
const dependencies = pageType.outputDependencies ? typeof pageType.outputDependencies === "function" ? await pageType.outputDependencies(
|
|
2860
|
+
this.createPluginContext(plugin, context)
|
|
2861
|
+
) : pageType.outputDependencies : [{ type: "unknown" }];
|
|
2862
|
+
return {
|
|
2863
|
+
output: {
|
|
2864
|
+
kind: "plugin-page",
|
|
2865
|
+
path: pathname,
|
|
2866
|
+
producer: `plugin:${plugin.name}:page:${pageType.id}`,
|
|
2867
|
+
dependencies
|
|
2868
|
+
},
|
|
2869
|
+
priority: pageType.priority ?? 0
|
|
2870
|
+
};
|
|
2871
|
+
}
|
|
2872
|
+
)
|
|
2873
|
+
);
|
|
2874
|
+
return uniqueOutputs(outputs);
|
|
2875
|
+
}
|
|
2876
|
+
async getPageDeclarations(manifest, contentIndex) {
|
|
2877
|
+
const existing = this.pageDeclarations.get(manifest);
|
|
2878
|
+
if (existing) return await existing;
|
|
2879
|
+
const declarations = this.resolvePageDeclarations(manifest, contentIndex);
|
|
2880
|
+
this.pageDeclarations.set(manifest, declarations);
|
|
2881
|
+
return await declarations;
|
|
2882
|
+
}
|
|
2883
|
+
async resolvePageDeclarations(manifest, contentIndex) {
|
|
2884
|
+
const declarations = [];
|
|
2785
2885
|
const context = { ...this.createContext(contentIndex), manifest };
|
|
2786
2886
|
for (const plugin of this.plugins()) {
|
|
2787
2887
|
for (const pageType of plugin.pageTypes ?? []) {
|
|
2788
|
-
const
|
|
2789
|
-
if (!
|
|
2790
|
-
const
|
|
2791
|
-
for (const
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
) : pageType.outputDependencies : [{ type: "unknown" }];
|
|
2797
|
-
outputs.push({
|
|
2798
|
-
kind: "plugin-page",
|
|
2799
|
-
path: pathname,
|
|
2800
|
-
producer: `plugin:${plugin.name}:page:${pageType.id}`,
|
|
2801
|
-
dependencies
|
|
2888
|
+
const paths = pageType.paths;
|
|
2889
|
+
if (!paths) continue;
|
|
2890
|
+
const resolved = typeof paths === "function" ? await paths(this.createPluginContext(plugin, context)) : paths;
|
|
2891
|
+
for (const pathname of resolved) {
|
|
2892
|
+
declarations.push({
|
|
2893
|
+
pathname: normalizePageTypePath(pathname, pageType),
|
|
2894
|
+
plugin,
|
|
2895
|
+
pageType
|
|
2802
2896
|
});
|
|
2803
2897
|
}
|
|
2804
2898
|
}
|
|
2805
2899
|
}
|
|
2806
|
-
return
|
|
2900
|
+
return declarations;
|
|
2807
2901
|
}
|
|
2808
2902
|
getContentOutputDependencies() {
|
|
2809
2903
|
return this.plugins().flatMap((plugin) => plugin.outputDependencies ?? []);
|
|
@@ -2814,9 +2908,13 @@ var PluginRuntime = class {
|
|
|
2814
2908
|
const results = [];
|
|
2815
2909
|
const context = this.createContext(contentIndex);
|
|
2816
2910
|
for (const plugin of this.plugins()) {
|
|
2817
|
-
const
|
|
2818
|
-
|
|
2819
|
-
|
|
2911
|
+
const hook = plugin.addDiagnostics;
|
|
2912
|
+
const diagnostics = hook ? await runPluginHook(
|
|
2913
|
+
plugin,
|
|
2914
|
+
"addDiagnostics",
|
|
2915
|
+
this.createPluginContext(plugin, context),
|
|
2916
|
+
hook
|
|
2917
|
+
) : void 0;
|
|
2820
2918
|
for (const diagnostic of diagnostics ?? []) {
|
|
2821
2919
|
results.push({
|
|
2822
2920
|
...diagnostic,
|
|
@@ -2845,13 +2943,13 @@ var PluginRuntime = class {
|
|
|
2845
2943
|
stage: "buildStart",
|
|
2846
2944
|
run: () => runBuildStart(this.plugins(), createPluginContext)
|
|
2847
2945
|
},
|
|
2848
|
-
{
|
|
2849
|
-
stage: "onBuildStart",
|
|
2850
|
-
run: () => this.runHook((plugin) => plugin.onBuildStart, context)
|
|
2851
|
-
},
|
|
2852
2946
|
{
|
|
2853
2947
|
stage: "onConfigResolved",
|
|
2854
|
-
run: () => this.runHook(
|
|
2948
|
+
run: () => this.runHook(
|
|
2949
|
+
"onConfigResolved",
|
|
2950
|
+
(plugin) => plugin.onConfigResolved,
|
|
2951
|
+
context
|
|
2952
|
+
)
|
|
2855
2953
|
}
|
|
2856
2954
|
];
|
|
2857
2955
|
for (const { stage, run } of stages) {
|
|
@@ -2896,18 +2994,12 @@ var PluginRuntime = class {
|
|
|
2896
2994
|
this.pluginCaches.set(plugin.name, cache);
|
|
2897
2995
|
return cache;
|
|
2898
2996
|
}
|
|
2899
|
-
async runHook(hook, context) {
|
|
2997
|
+
async runHook(hookName, hook, context) {
|
|
2900
2998
|
for (const plugin of this.plugins()) {
|
|
2901
2999
|
const pluginHook = hook(plugin);
|
|
2902
3000
|
if (!pluginHook) continue;
|
|
2903
3001
|
const pluginContext = this.createPluginContext(plugin, context);
|
|
2904
|
-
await pluginContext
|
|
2905
|
-
"plugin.hook",
|
|
2906
|
-
{
|
|
2907
|
-
plugin: plugin.name
|
|
2908
|
-
},
|
|
2909
|
-
() => pluginHook(pluginContext)
|
|
2910
|
-
);
|
|
3002
|
+
await runPluginHook(plugin, hookName, pluginContext, pluginHook);
|
|
2911
3003
|
}
|
|
2912
3004
|
}
|
|
2913
3005
|
observability() {
|
|
@@ -2993,10 +3085,20 @@ function countSeverity(diagnostics, severity) {
|
|
|
2993
3085
|
}
|
|
2994
3086
|
function uniqueOutputs(outputs) {
|
|
2995
3087
|
const byPath = /* @__PURE__ */ new Map();
|
|
2996
|
-
for (const output of outputs)
|
|
2997
|
-
|
|
2998
|
-
(
|
|
2999
|
-
|
|
3088
|
+
for (const output of outputs) {
|
|
3089
|
+
const previous = byPath.get(output.output.path);
|
|
3090
|
+
if (!previous || output.priority > previous.priority) {
|
|
3091
|
+
byPath.set(output.output.path, output);
|
|
3092
|
+
continue;
|
|
3093
|
+
}
|
|
3094
|
+
if (output.output.producer === previous.output.producer) continue;
|
|
3095
|
+
if (output.priority === previous.priority) {
|
|
3096
|
+
throw new Error(
|
|
3097
|
+
`Multiple plugin page types declare ${output.output.path} at priority ${output.priority}: ${previous.output.producer}, ${output.output.producer}`
|
|
3098
|
+
);
|
|
3099
|
+
}
|
|
3100
|
+
}
|
|
3101
|
+
return [...byPath.values()].map(({ output }) => output).sort((left, right) => left.path.localeCompare(right.path));
|
|
3000
3102
|
}
|
|
3001
3103
|
|
|
3002
3104
|
// src/content/affected_content.ts
|
|
@@ -3411,8 +3513,8 @@ function collectDependencies2(manifestEntry, trackedDependencies) {
|
|
|
3411
3513
|
kind: "file",
|
|
3412
3514
|
id: asset.path.replace(/\\/g, "/")
|
|
3413
3515
|
})),
|
|
3414
|
-
...trackedDependencies.filter(
|
|
3415
|
-
(dependency) => dependency
|
|
3516
|
+
...trackedDependencies.map(toBuildDependency).filter(
|
|
3517
|
+
(dependency) => dependency !== null
|
|
3416
3518
|
).map((dependency) => ({
|
|
3417
3519
|
kind: dependency.kind,
|
|
3418
3520
|
id: dependency.id.replace(/\\/g, "/")
|
|
@@ -3426,6 +3528,18 @@ function collectDependencies2(manifestEntry, trackedDependencies) {
|
|
|
3426
3528
|
(left, right) => `${left.kind}:${left.id}`.localeCompare(`${right.kind}:${right.id}`)
|
|
3427
3529
|
);
|
|
3428
3530
|
}
|
|
3531
|
+
function toBuildDependency(dependency) {
|
|
3532
|
+
if (dependency.kind === "content" || dependency.kind === "file") {
|
|
3533
|
+
return { kind: dependency.kind, id: dependency.id };
|
|
3534
|
+
}
|
|
3535
|
+
if (dependency.id.startsWith(LINK_LOCATION_PREFIX)) {
|
|
3536
|
+
return {
|
|
3537
|
+
kind: "content",
|
|
3538
|
+
id: dependency.id.slice(LINK_LOCATION_PREFIX.length)
|
|
3539
|
+
};
|
|
3540
|
+
}
|
|
3541
|
+
return null;
|
|
3542
|
+
}
|
|
3429
3543
|
function collectLinkTargets(manifestEntry) {
|
|
3430
3544
|
if (!manifestEntry) return [];
|
|
3431
3545
|
return [
|
|
@@ -3615,8 +3729,17 @@ var FileSystemContentSource = class {
|
|
|
3615
3729
|
contentDirectory;
|
|
3616
3730
|
exclude;
|
|
3617
3731
|
async scan() {
|
|
3732
|
+
return (await this.scanWithExclusions()).entries;
|
|
3733
|
+
}
|
|
3734
|
+
async scanWithExclusions() {
|
|
3735
|
+
const exclusions = [];
|
|
3618
3736
|
try {
|
|
3619
|
-
|
|
3737
|
+
const entries = await this.scanDirectory(
|
|
3738
|
+
this.contentDirectory,
|
|
3739
|
+
"",
|
|
3740
|
+
exclusions
|
|
3741
|
+
);
|
|
3742
|
+
return { entries, exclusions };
|
|
3620
3743
|
} catch (error) {
|
|
3621
3744
|
if (isMissingDirectoryError(error, this.contentDirectory)) {
|
|
3622
3745
|
throw missingContentDirectoryError(this.contentDirectory);
|
|
@@ -3632,7 +3755,7 @@ var FileSystemContentSource = class {
|
|
|
3632
3755
|
}
|
|
3633
3756
|
return await fs4.readFile(filePath);
|
|
3634
3757
|
}
|
|
3635
|
-
async scanDirectory(directory, parentPath2) {
|
|
3758
|
+
async scanDirectory(directory, parentPath2, exclusions) {
|
|
3636
3759
|
const directoryEntries = await fs4.readdir(directory, {
|
|
3637
3760
|
withFileTypes: true
|
|
3638
3761
|
});
|
|
@@ -3643,9 +3766,16 @@ var FileSystemContentSource = class {
|
|
|
3643
3766
|
parentPath2 ? `${parentPath2}/${directoryEntry.name}` : directoryEntry.name
|
|
3644
3767
|
);
|
|
3645
3768
|
const filePath = path4.join(directory, directoryEntry.name);
|
|
3646
|
-
if (
|
|
3769
|
+
if (isExcluded(INTERNAL_CONTENT_IGNORE_PATTERNS, logicalPath)) continue;
|
|
3770
|
+
const pattern = matchContentExcludePattern(logicalPath, this.exclude);
|
|
3771
|
+
if (pattern !== void 0) {
|
|
3772
|
+
exclusions.push({ path: logicalPath, pattern });
|
|
3773
|
+
continue;
|
|
3774
|
+
}
|
|
3647
3775
|
if (directoryEntry.isDirectory()) {
|
|
3648
|
-
entries.push(
|
|
3776
|
+
entries.push(
|
|
3777
|
+
...await this.scanDirectory(filePath, logicalPath, exclusions)
|
|
3778
|
+
);
|
|
3649
3779
|
continue;
|
|
3650
3780
|
}
|
|
3651
3781
|
if (!directoryEntry.isFile()) continue;
|
|
@@ -3660,9 +3790,6 @@ var FileSystemContentSource = class {
|
|
|
3660
3790
|
}
|
|
3661
3791
|
return entries;
|
|
3662
3792
|
}
|
|
3663
|
-
isExcluded(logicalPath) {
|
|
3664
|
-
return isIgnoredContentPath(logicalPath, this.exclude);
|
|
3665
|
-
}
|
|
3666
3793
|
resolveFilePath(logicalPath) {
|
|
3667
3794
|
const normalizedPath = normalizeLogicalPath(logicalPath);
|
|
3668
3795
|
const filePath = path4.resolve(this.contentDirectory, normalizedPath);
|
|
@@ -3675,8 +3802,14 @@ var FileSystemContentSource = class {
|
|
|
3675
3802
|
};
|
|
3676
3803
|
function isIgnoredContentPath(logicalPath, exclude = []) {
|
|
3677
3804
|
if (isExcluded(INTERNAL_CONTENT_IGNORE_PATTERNS, logicalPath)) return true;
|
|
3678
|
-
|
|
3679
|
-
|
|
3805
|
+
return matchContentExcludePattern(logicalPath, exclude) !== void 0;
|
|
3806
|
+
}
|
|
3807
|
+
function matchContentExcludePattern(logicalPath, exclude = []) {
|
|
3808
|
+
const direct = exclude.find((pattern) => isExcluded([pattern], logicalPath));
|
|
3809
|
+
if (direct !== void 0) return direct;
|
|
3810
|
+
if (!logicalPath.endsWith(".md")) return void 0;
|
|
3811
|
+
const withoutExtension = logicalPath.slice(0, -3);
|
|
3812
|
+
return exclude.find((pattern) => isExcluded([pattern], withoutExtension));
|
|
3680
3813
|
}
|
|
3681
3814
|
function normalizeLogicalPath(logicalPath) {
|
|
3682
3815
|
const normalizedPath = normalizeContentPath(logicalPath);
|
|
@@ -3700,53 +3833,22 @@ function missingContentDirectoryError(directory) {
|
|
|
3700
3833
|
return error;
|
|
3701
3834
|
}
|
|
3702
3835
|
|
|
3703
|
-
// src/content/content_links.ts
|
|
3704
|
-
var WIKILINK_PATTERN = /(!)?\[\[([^\]|#^]+)(?:[#^][^\]|]+)?(?:\|[^\]]+)?\]\]/g;
|
|
3705
|
-
function extractContentLinks(markdown, contentIndex) {
|
|
3706
|
-
WIKILINK_PATTERN.lastIndex = 0;
|
|
3707
|
-
const links = [];
|
|
3708
|
-
for (let match = WIKILINK_PATTERN.exec(markdown); match !== null; match = WIKILINK_PATTERN.exec(markdown)) {
|
|
3709
|
-
const rawTarget = match[2]?.trim();
|
|
3710
|
-
if (!rawTarget) continue;
|
|
3711
|
-
const resolved = contentIndex.get(rawTarget.toLowerCase()) ?? null;
|
|
3712
|
-
links.push({
|
|
3713
|
-
raw: rawTarget,
|
|
3714
|
-
slug: resolved,
|
|
3715
|
-
kind: resolved ? linkKind(resolved) : "unresolved",
|
|
3716
|
-
embed: match[1] === "!"
|
|
3717
|
-
});
|
|
3718
|
-
}
|
|
3719
|
-
return links;
|
|
3720
|
-
}
|
|
3721
|
-
function linkKind(value) {
|
|
3722
|
-
if (isImagePath(value)) return "image";
|
|
3723
|
-
if (isAttachmentPath(value)) return "attachment";
|
|
3724
|
-
return "note";
|
|
3725
|
-
}
|
|
3726
|
-
|
|
3727
3836
|
// src/content/content_stable_id.ts
|
|
3728
3837
|
var MAX_STABLE_CONTENT_ID_LENGTH = 160;
|
|
3729
3838
|
function resolveContentStableId(frontmatter) {
|
|
3730
|
-
|
|
3731
|
-
const uid = readOptionalStableId(frontmatter.uid, "uid");
|
|
3732
|
-
if (id !== void 0 && uid !== void 0 && id !== uid) {
|
|
3733
|
-
throw new Error(
|
|
3734
|
-
'Content frontmatter fields "id" and "uid" must have the same value.'
|
|
3735
|
-
);
|
|
3736
|
-
}
|
|
3737
|
-
return id ?? uid;
|
|
3839
|
+
return readOptionalStableId(frontmatter.id);
|
|
3738
3840
|
}
|
|
3739
|
-
function readOptionalStableId(value
|
|
3841
|
+
function readOptionalStableId(value) {
|
|
3740
3842
|
if (value === void 0) return void 0;
|
|
3741
3843
|
if (typeof value !== "string") {
|
|
3742
|
-
throw new Error(`Content frontmatter field "
|
|
3844
|
+
throw new Error(`Content frontmatter field "id" must be a string.`);
|
|
3743
3845
|
}
|
|
3744
3846
|
if (value.length === 0 || value.length > MAX_STABLE_CONTENT_ID_LENGTH || value.trim() !== value || [...value].some((character) => {
|
|
3745
3847
|
const code = character.codePointAt(0) ?? 0;
|
|
3746
3848
|
return code <= 31 || code === 127;
|
|
3747
3849
|
})) {
|
|
3748
3850
|
throw new Error(
|
|
3749
|
-
`Content frontmatter field "
|
|
3851
|
+
`Content frontmatter field "id" must be a non-empty, trimmed string of at most ${MAX_STABLE_CONTENT_ID_LENGTH} characters without control characters.`
|
|
3750
3852
|
);
|
|
3751
3853
|
}
|
|
3752
3854
|
return value;
|
|
@@ -3766,6 +3868,7 @@ var ManifestBuilder = class {
|
|
|
3766
3868
|
permalink: location.permalink,
|
|
3767
3869
|
publicLocation: location,
|
|
3768
3870
|
title: getManifestTitle(slug, processed.frontmatter.title),
|
|
3871
|
+
aliases: extractFrontmatterAliases(markdown),
|
|
3769
3872
|
frontmatter: processed.frontmatter,
|
|
3770
3873
|
publishing,
|
|
3771
3874
|
html: processed.html,
|
|
@@ -3781,6 +3884,7 @@ var ManifestBuilder = class {
|
|
|
3781
3884
|
build(entries, contentIndex) {
|
|
3782
3885
|
const bySlug = new Map(entries.map((entry) => [entry.slug, entry]));
|
|
3783
3886
|
const byContentId = createContentIdIndex(entries);
|
|
3887
|
+
const byAlias = createAliasIndex(entries);
|
|
3784
3888
|
const byPermalink = new Map(
|
|
3785
3889
|
entries.map((entry) => [entry.permalink, entry])
|
|
3786
3890
|
);
|
|
@@ -3808,6 +3912,7 @@ var ManifestBuilder = class {
|
|
|
3808
3912
|
discoverableEntries: [...entries],
|
|
3809
3913
|
bySlug,
|
|
3810
3914
|
byContentId,
|
|
3915
|
+
byAlias,
|
|
3811
3916
|
byPermalink,
|
|
3812
3917
|
byRoutablePermalink: new Map(byPermalink),
|
|
3813
3918
|
redirects: /* @__PURE__ */ new Map(),
|
|
@@ -3828,6 +3933,14 @@ var ManifestBuilder = class {
|
|
|
3828
3933
|
return { ...manifest, graph: createContentGraph(manifest) };
|
|
3829
3934
|
}
|
|
3830
3935
|
};
|
|
3936
|
+
function createAliasIndex(entries) {
|
|
3937
|
+
const byAlias = /* @__PURE__ */ new Map();
|
|
3938
|
+
for (const entry of entries) {
|
|
3939
|
+
for (const alias of entry.aliases ?? [])
|
|
3940
|
+
appendToMap(byAlias, alias.toLowerCase(), entry);
|
|
3941
|
+
}
|
|
3942
|
+
return byAlias;
|
|
3943
|
+
}
|
|
3831
3944
|
function createContentIdIndex(entries) {
|
|
3832
3945
|
const byContentId = /* @__PURE__ */ new Map();
|
|
3833
3946
|
for (const entry of entries) {
|
|
@@ -4042,8 +4155,20 @@ function linkTargets(entry) {
|
|
|
4042
4155
|
).map((link) => link.slug);
|
|
4043
4156
|
}
|
|
4044
4157
|
function addOutput(outputs, output) {
|
|
4158
|
+
const existing = outputs.get(output.path);
|
|
4159
|
+
if (existing) {
|
|
4160
|
+
assertNoGeneratedOutputCollision(existing, output);
|
|
4161
|
+
}
|
|
4045
4162
|
outputs.set(output.path, output);
|
|
4046
4163
|
}
|
|
4164
|
+
function assertNoGeneratedOutputCollision(existing, incoming) {
|
|
4165
|
+
if (existing.kind !== "generated" && incoming.kind !== "generated") return;
|
|
4166
|
+
if (existing.kind === incoming.kind && existing.producer === incoming.producer)
|
|
4167
|
+
return;
|
|
4168
|
+
throw new Error(
|
|
4169
|
+
`Generated output path "${incoming.path}" collides with ${existing.kind} output owned by "${existing.producer}" and ${incoming.kind} output owned by "${incoming.producer}".`
|
|
4170
|
+
);
|
|
4171
|
+
}
|
|
4047
4172
|
function normalizePublicPath(pathname) {
|
|
4048
4173
|
const path5 = `/${pathname.split("/").filter(Boolean).join("/")}`;
|
|
4049
4174
|
return path5 === "/" ? path5 : path5.replace(/\/$/, "");
|
|
@@ -4123,9 +4248,14 @@ var CONTENT_PROCESSING_CONCURRENCY = 16;
|
|
|
4123
4248
|
var ContentManager = class {
|
|
4124
4249
|
constructor(content, exclude = [], pipelineOptions = {}) {
|
|
4125
4250
|
this.pipelineOptions = pipelineOptions;
|
|
4251
|
+
const config = pipelineOptions.config ? {
|
|
4252
|
+
...pipelineOptions.config,
|
|
4253
|
+
plugins: pipelineOptions.plugins ?? pipelineOptions.config.plugins
|
|
4254
|
+
} : void 0;
|
|
4126
4255
|
this.pipelineOptions = {
|
|
4127
4256
|
...pipelineOptions,
|
|
4128
|
-
|
|
4257
|
+
config,
|
|
4258
|
+
plugins: pipelineOptions.plugins ?? config?.plugins,
|
|
4129
4259
|
isRoutable: (slug) => this.isRoutable(slug)
|
|
4130
4260
|
};
|
|
4131
4261
|
this.publishingBuildTime = resolvePublishingBuildTime(
|
|
@@ -4603,6 +4733,7 @@ function cloneManifestEntry(entry) {
|
|
|
4603
4733
|
...entry,
|
|
4604
4734
|
publicLocation: { ...entry.publicLocation },
|
|
4605
4735
|
frontmatter: { ...entry.frontmatter },
|
|
4736
|
+
aliases: [...entry.aliases ?? []],
|
|
4606
4737
|
tags: [...entry.tags],
|
|
4607
4738
|
links: entry.links.map((link) => ({ ...link })),
|
|
4608
4739
|
backlinks: [...entry.backlinks],
|
|
@@ -4669,6 +4800,17 @@ function resolveFolderLocation(manifest, folder) {
|
|
|
4669
4800
|
const location = manifest.folderLocations.get(normalizeFolder2(folder));
|
|
4670
4801
|
return location ? { type: "generated", pathname: location.pathname } : { type: "none" };
|
|
4671
4802
|
}
|
|
4803
|
+
function resolvePublicFolderLocation(manifest, pathname) {
|
|
4804
|
+
const normalizedPathname = normalizePathname(pathname);
|
|
4805
|
+
const entry = manifest.publicEntries.find(
|
|
4806
|
+
(candidate) => normalizePathname(candidate.publicLocation.permalink) === normalizedPathname
|
|
4807
|
+
);
|
|
4808
|
+
if (entry) return { type: "content", entry };
|
|
4809
|
+
const location = [...manifest.folderLocations.values()].find(
|
|
4810
|
+
(candidate) => normalizePathname(candidate.pathname) === normalizedPathname
|
|
4811
|
+
);
|
|
4812
|
+
return location ? { type: "generated", pathname: location.pathname } : { type: "none" };
|
|
4813
|
+
}
|
|
4672
4814
|
function resolveGeneratedFolderLocation(manifest, folder) {
|
|
4673
4815
|
const normalizedFolder = normalizeFolder2(folder);
|
|
4674
4816
|
if (!normalizedFolder) return null;
|
|
@@ -4701,6 +4843,10 @@ function isInScope(entry, scope) {
|
|
|
4701
4843
|
function normalizeFolder2(folder) {
|
|
4702
4844
|
return folder.split("/").filter(Boolean).join("/");
|
|
4703
4845
|
}
|
|
4846
|
+
function normalizePathname(pathname) {
|
|
4847
|
+
const segments = pathname.split("/").filter(Boolean);
|
|
4848
|
+
return segments.length === 0 ? "/" : `/${segments.join("/")}`;
|
|
4849
|
+
}
|
|
4704
4850
|
function parentPath(pathname, levels) {
|
|
4705
4851
|
const segments = pathname.split("/").filter(Boolean);
|
|
4706
4852
|
if (segments.length < levels) return null;
|
|
@@ -4909,6 +5055,7 @@ function createGraphEntry(entry, markdown, contentIndex, locations) {
|
|
|
4909
5055
|
permalink: location.permalink,
|
|
4910
5056
|
publicLocation: location,
|
|
4911
5057
|
title: slug,
|
|
5058
|
+
aliases: [],
|
|
4912
5059
|
frontmatter: {},
|
|
4913
5060
|
publishing: resolvePublishingState(
|
|
4914
5061
|
{},
|
|
@@ -5001,6 +5148,7 @@ export {
|
|
|
5001
5148
|
buildOutputInventory,
|
|
5002
5149
|
calculateReadingTime,
|
|
5003
5150
|
collectConfigDeprecationDiagnostics,
|
|
5151
|
+
computePipelineFingerprint,
|
|
5004
5152
|
createClientEntry,
|
|
5005
5153
|
createContentGraph,
|
|
5006
5154
|
createDeprecationDiagnostic,
|
|
@@ -5019,6 +5167,7 @@ export {
|
|
|
5019
5167
|
fingerprintContentEntries,
|
|
5020
5168
|
formatDeprecationMessage,
|
|
5021
5169
|
getContentSourceEntry,
|
|
5170
|
+
getEntryLanguage,
|
|
5022
5171
|
getExtension,
|
|
5023
5172
|
getResolvedPluginMetadata,
|
|
5024
5173
|
groupContentEntries,
|
|
@@ -5028,11 +5177,13 @@ export {
|
|
|
5028
5177
|
isIgnoredContentPath,
|
|
5029
5178
|
isImagePath,
|
|
5030
5179
|
isMarkdownPath,
|
|
5180
|
+
isPersistentlyCacheable,
|
|
5031
5181
|
isPublishable,
|
|
5032
5182
|
isPublished,
|
|
5033
5183
|
layoutForceGraph,
|
|
5034
5184
|
layoutRadialGraph,
|
|
5035
5185
|
loadContentBuildState,
|
|
5186
|
+
matchContentExcludePattern,
|
|
5036
5187
|
normalizeContentAssetOutputPath,
|
|
5037
5188
|
normalizeContentPath,
|
|
5038
5189
|
normalizeGeneratedOutputPath,
|
|
@@ -5052,8 +5203,10 @@ export {
|
|
|
5052
5203
|
resolveFolderLocation,
|
|
5053
5204
|
resolveGeneratedFolderLocation,
|
|
5054
5205
|
resolvePlugins,
|
|
5206
|
+
resolvePublicFolderLocation,
|
|
5055
5207
|
resolvePublishingBuildTime,
|
|
5056
5208
|
resolvePublishingState,
|
|
5209
|
+
selectEntriesByLanguage,
|
|
5057
5210
|
serializePublicClientConfig,
|
|
5058
5211
|
stableStringify,
|
|
5059
5212
|
stripHtml,
|
|
@@ -3,7 +3,7 @@ import type { ContentManifest, ContentManifestEntry } from "../types/content_man
|
|
|
3
3
|
import { determineAffectedContent } from "./affected_content.js";
|
|
4
4
|
import { type ContentBuildState, type FingerprintedContentEntry } from "./content_build_state.js";
|
|
5
5
|
import { type ContentChangeSet } from "./content_change_set.js";
|
|
6
|
-
import type
|
|
6
|
+
import { type CachedContentDependency } from "./content_dependency_tracker.js";
|
|
7
7
|
import type { ContentSourceEntry } from "./content_source.js";
|
|
8
8
|
import type { OutputDescriptor } from "./output_dependency.js";
|
|
9
9
|
export type ContentBuildPreparation = {
|
|
@@ -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 = 7;
|
|
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,4 +1,6 @@
|
|
|
1
1
|
import type { ContentSource, ContentSourceContent } from "./content_source.js";
|
|
2
|
+
export declare const LINK_INDEX_PREFIX = "index:";
|
|
3
|
+
export declare const LINK_LOCATION_PREFIX = "location:";
|
|
2
4
|
export type CachedContentDependency = {
|
|
3
5
|
readonly kind: "content" | "file" | "link";
|
|
4
6
|
readonly id: string;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { ContentManifestEntry } from "../types/content_manifest.js";
|
|
2
|
+
export declare function getEntryLanguage(entry: ContentManifestEntry): string | undefined;
|
|
3
|
+
export declare function selectEntriesByLanguage(entries: readonly ContentManifestEntry[], language: string | undefined): readonly ContentManifestEntry[];
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import type { PostFrontmatter } from "../types/post_content.js";
|
|
2
2
|
/**
|
|
3
|
-
* Reads the optional, source-authored stable content ID.
|
|
4
|
-
*
|
|
5
|
-
* `id` is the canonical frontmatter field. `uid` is accepted only for
|
|
6
|
-
* compatibility with existing content that used it before `id` was standard.
|
|
3
|
+
* Reads the optional, source-authored stable content ID from frontmatter.
|
|
7
4
|
*/
|
|
8
5
|
export declare function resolveContentStableId(frontmatter: PostFrontmatter): string | undefined;
|
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
import type { ContentSource, ContentSourceContent, ContentSourceEntry } from "./content_source.js";
|
|
2
2
|
export declare const INTERNAL_CONTENT_IGNORE_PATTERNS: readonly [".git", ".git/**", ".github", ".github/**", ".obsidian", ".obsidian/**", "node_modules", "node_modules/**", "**/.DS_Store", "**/Thumbs.db", "**/desktop.ini"];
|
|
3
|
+
export type ContentSourceExclusion = {
|
|
4
|
+
readonly path: string;
|
|
5
|
+
readonly pattern: string;
|
|
6
|
+
};
|
|
7
|
+
export type ContentSourceScan = {
|
|
8
|
+
readonly entries: readonly ContentSourceEntry[];
|
|
9
|
+
readonly exclusions: readonly ContentSourceExclusion[];
|
|
10
|
+
};
|
|
3
11
|
export declare class FileSystemContentSource implements ContentSource {
|
|
4
12
|
private contentDirectory;
|
|
5
13
|
private exclude;
|
|
6
14
|
constructor(contentDirectory: string, exclude?: readonly string[]);
|
|
7
15
|
scan(): Promise<readonly ContentSourceEntry[]>;
|
|
16
|
+
scanWithExclusions(): Promise<ContentSourceScan>;
|
|
8
17
|
read(entry: ContentSourceEntry): Promise<ContentSourceContent>;
|
|
9
18
|
private scanDirectory;
|
|
10
|
-
private isExcluded;
|
|
11
19
|
private resolveFilePath;
|
|
12
20
|
}
|
|
13
21
|
export declare function isIgnoredContentPath(logicalPath: string, exclude?: readonly string[]): boolean;
|
|
22
|
+
export declare function matchContentExcludePattern(logicalPath: string, exclude?: readonly string[]): string | undefined;
|
|
@@ -32,4 +32,5 @@ export type FolderLocationResolution = {
|
|
|
32
32
|
};
|
|
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
|
+
export declare function resolvePublicFolderLocation(manifest: ContentManifest, pathname: string): FolderLocationResolution;
|
|
35
36
|
export declare function resolveGeneratedFolderLocation(manifest: ContentManifest, folder: string): string | null;
|
package/dist/src/pipeline.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
+
import type { Tracer } from "../observability.js";
|
|
1
2
|
import type { RiebeckitePlugin } from "../types/plugin.js";
|
|
2
3
|
import type { PluginLifecycleContext, PluginManifestContext } from "../types/plugin_context.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
constructor(pluginName: string, hookName: LifecycleHookName, cause: unknown);
|
|
4
|
+
export declare class PluginHookError extends Error {
|
|
5
|
+
constructor(pluginName: string, hookName: string, cause: unknown);
|
|
6
6
|
}
|
|
7
|
+
export declare function runPluginHook<TContext extends {
|
|
8
|
+
tracer: Tracer;
|
|
9
|
+
}, TResult>(plugin: RiebeckitePlugin, hookName: string, context: TContext, hook: (context: TContext) => TResult | Promise<TResult>): Promise<TResult>;
|
|
7
10
|
export declare function runSetup(plugins: readonly RiebeckitePlugin[], createContext: (plugin: RiebeckitePlugin) => PluginLifecycleContext): Promise<void>;
|
|
8
11
|
export declare function runBuildStart(plugins: readonly RiebeckitePlugin[], createContext: (plugin: RiebeckitePlugin) => PluginLifecycleContext): Promise<void>;
|
|
9
12
|
export declare function runBuildEnd(plugins: readonly RiebeckitePlugin[], createContext: (plugin: RiebeckitePlugin) => PluginManifestContext): Promise<void>;
|
|
10
13
|
export declare function runDispose(plugins: readonly RiebeckitePlugin[], createContext: (plugin: RiebeckitePlugin) => PluginLifecycleContext): Promise<void>;
|
|
11
|
-
export {};
|
|
@@ -12,7 +12,7 @@ import type { PostContent } from "../types/post_content.js";
|
|
|
12
12
|
* requested yet; the remaining values name the stage currently executing.
|
|
13
13
|
* Once `started` is reached the lifecycle never runs again.
|
|
14
14
|
*/
|
|
15
|
-
export type PluginBuildStage = "idle" | "setup" | "buildStart" | "
|
|
15
|
+
export type PluginBuildStage = "idle" | "setup" | "buildStart" | "onConfigResolved" | "started";
|
|
16
16
|
export declare class PluginRuntime {
|
|
17
17
|
private pipelineOptions;
|
|
18
18
|
private buildLifecycle;
|
|
@@ -23,6 +23,7 @@ export declare class PluginRuntime {
|
|
|
23
23
|
private generatedOutputs;
|
|
24
24
|
private isBuildTime;
|
|
25
25
|
private resolvedPlugins;
|
|
26
|
+
private pageDeclarations;
|
|
26
27
|
constructor(pipelineOptions?: PipelineOptions);
|
|
27
28
|
getDiagnostics(): Diagnostic[];
|
|
28
29
|
getBuildStage(): PluginBuildStage;
|
|
@@ -30,7 +31,7 @@ export declare class PluginRuntime {
|
|
|
30
31
|
* Starts the plugin build lifecycle exactly once, regardless of which public
|
|
31
32
|
* entry point (content processing or location resolution) reaches it first.
|
|
32
33
|
* Concurrent callers await the same run, so the ordered hooks
|
|
33
|
-
* (`setup` → `buildStart` → `
|
|
34
|
+
* (`setup` → `buildStart` → `onConfigResolved`) are never
|
|
34
35
|
* duplicated and no caller proceeds before the lifecycle completes.
|
|
35
36
|
*/
|
|
36
37
|
startBuild(contentIndex: Map<string, string>): Promise<void>;
|
|
@@ -61,6 +62,8 @@ export declare class PluginRuntime {
|
|
|
61
62
|
getPagePaths(manifest: ContentManifest, contentIndex: Map<string, string>): Promise<readonly string[]>;
|
|
62
63
|
getPageRoutes(manifest: ContentManifest, contentIndex: Map<string, string>): Promise<readonly PluginPageRoute[]>;
|
|
63
64
|
getPageOutputs(manifest: ContentManifest, contentIndex: Map<string, string>): Promise<readonly OutputDescriptor[]>;
|
|
65
|
+
private getPageDeclarations;
|
|
66
|
+
private resolvePageDeclarations;
|
|
64
67
|
getContentOutputDependencies(): readonly OutputDependency[];
|
|
65
68
|
collectDiagnostics(contentIndex: Map<string, string>): Promise<Diagnostic[]>;
|
|
66
69
|
private runBuildLifecycle;
|
|
@@ -24,7 +24,7 @@ export type ContentManifestPluginAsset = PluginAsset & {
|
|
|
24
24
|
* The standard article consumer recognizes the `article.*` positions below.
|
|
25
25
|
* Other names remain valid so a custom Site can define its own layout slots.
|
|
26
26
|
*/
|
|
27
|
-
export type ContentBodySlot = "article.
|
|
27
|
+
export type ContentBodySlot = "article.header" | "article.metadata" | "article.aside" | "article.before-content" | "article.after-content" | "article.footer" | (string & {});
|
|
28
28
|
/** Client entries and their explicitly public configuration. */
|
|
29
29
|
export type ContentManifestPluginClientEntry = PluginClientEntry;
|
|
30
30
|
export type ContentManifestEntry = {
|
|
@@ -37,6 +37,7 @@ export type ContentManifestEntry = {
|
|
|
37
37
|
permalink: string;
|
|
38
38
|
publicLocation: ContentPublicLocation;
|
|
39
39
|
title: string;
|
|
40
|
+
aliases?: readonly string[];
|
|
40
41
|
frontmatter: PostFrontmatter;
|
|
41
42
|
publishing: ResolvedPublishingState;
|
|
42
43
|
html: string;
|
|
@@ -70,6 +71,7 @@ export type ContentRedirect = {
|
|
|
70
71
|
export type ContentPublicLocation = {
|
|
71
72
|
slug: string;
|
|
72
73
|
permalink: string;
|
|
74
|
+
language?: string;
|
|
73
75
|
redirects?: readonly ContentRedirect[];
|
|
74
76
|
metadata?: Readonly<Record<string, string>>;
|
|
75
77
|
};
|
|
@@ -89,9 +91,10 @@ export type ContentLocationInput = {
|
|
|
89
91
|
export type ContentManifest = {
|
|
90
92
|
entries: ContentManifestEntry[];
|
|
91
93
|
/**
|
|
92
|
-
* Entries that
|
|
93
|
-
*
|
|
94
|
-
*
|
|
94
|
+
* Entries that are routable and therefore get a generated page: `public`
|
|
95
|
+
* and `unlisted` notes. `entries` keeps every scanned note for backward
|
|
96
|
+
* compatibility; plugins that emit generated output should read this view
|
|
97
|
+
* so drafts and scheduled notes never reach generated output.
|
|
95
98
|
*/
|
|
96
99
|
publicEntries: ContentManifestEntry[];
|
|
97
100
|
/** Entries that may appear on discovery surfaces such as navigation, search, feeds, taxonomy, and public graphs. */
|
|
@@ -99,6 +102,7 @@ export type ContentManifest = {
|
|
|
99
102
|
bySlug: Map<string, ContentManifestEntry>;
|
|
100
103
|
/** Contains only entries with an explicit source-authored content ID. */
|
|
101
104
|
byContentId: Map<string, ContentManifestEntry>;
|
|
105
|
+
byAlias: Map<string, ContentManifestEntry[]>;
|
|
102
106
|
byPermalink: Map<string, ContentManifestEntry>;
|
|
103
107
|
/** Contains only routable entries: public and unlisted, excluding draft and scheduled-before entries. */
|
|
104
108
|
byRoutablePermalink: Map<string, ContentManifestEntry>;
|
|
@@ -59,8 +59,6 @@ export type RiebeckitePlugin<TOptions = unknown> = {
|
|
|
59
59
|
onPostParsed?(context: PluginPostContext): void | Promise<void>;
|
|
60
60
|
onPostProcessed?(context: PluginPostContext): void | Promise<void>;
|
|
61
61
|
onManifestCreated?(context: PluginManifestContext): void | Promise<void>;
|
|
62
|
-
onBuildStart?(context: PluginContext): void | Promise<void>;
|
|
63
|
-
onBuildEnd?(context: PluginManifestContext): void | Promise<void>;
|
|
64
62
|
extendMarkdownPipeline?(pipeline: MarkdownPipeline, context: MarkdownPipelineContext): void;
|
|
65
63
|
extendHtmlPipeline?(pipeline: HtmlPipeline): void;
|
|
66
64
|
addDiagnostics?(context: PluginContext): Diagnostic[] | Promise<Diagnostic[]>;
|
|
@@ -14,6 +14,8 @@ export type PluginPage = {
|
|
|
14
14
|
description?: string;
|
|
15
15
|
/** Optional document metadata rendered by the site's document frame. */
|
|
16
16
|
headTags?: readonly PluginHeadTag[];
|
|
17
|
+
/** Language of the page when the page type resolved one. */
|
|
18
|
+
language?: string;
|
|
17
19
|
};
|
|
18
20
|
export type PluginPageContext = PluginContext & {
|
|
19
21
|
/** The public manifest. Unpublished content is not exposed through pages. */
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ContentManifestEntry } from "./content_manifest.js";
|
|
2
|
+
import type { PluginHeadTag } from "./plugin_head.js";
|
|
2
3
|
import type { PostContent } from "./post_content.js";
|
|
3
4
|
import type { ResolvedRiebeckiteConfig } from "./resolved_riebeckite_config.js";
|
|
4
5
|
export type SeoMetadata = {
|
|
@@ -24,8 +25,8 @@ export type RenderableFeedEntry = ContentManifestEntry & {
|
|
|
24
25
|
html?: string;
|
|
25
26
|
};
|
|
26
27
|
export type PluginSeoExtension = {
|
|
27
|
-
buildArticleSeo(config: ResolvedRiebeckiteConfig, permalink: string, post: PostContent): SeoMetadata;
|
|
28
|
-
buildWebsiteSeo(config: ResolvedRiebeckiteConfig, input: WebsiteSeoInput): SeoMetadata;
|
|
28
|
+
buildArticleSeo(config: ResolvedRiebeckiteConfig, permalink: string, post: PostContent, headTags?: readonly PluginHeadTag[]): SeoMetadata;
|
|
29
|
+
buildWebsiteSeo(config: ResolvedRiebeckiteConfig, input: WebsiteSeoInput, headTags?: readonly PluginHeadTag[]): SeoMetadata;
|
|
29
30
|
buildAbsoluteUrl(config: ResolvedRiebeckiteConfig, pathOrUrl: string): string;
|
|
30
31
|
buildPostUrl(config: ResolvedRiebeckiteConfig, permalink: string): string;
|
|
31
32
|
getDescription(post: Pick<PostContent, "frontmatter" | "html">): string;
|
|
@@ -8,8 +8,6 @@ export type PostFrontmatter = Record<string, unknown> & {
|
|
|
8
8
|
* this value survives a rename or public-location change.
|
|
9
9
|
*/
|
|
10
10
|
id?: string;
|
|
11
|
-
/** @deprecated Use `id`. Read only as a compatibility fallback. */
|
|
12
|
-
uid?: string;
|
|
13
11
|
title?: string;
|
|
14
12
|
description?: string;
|
|
15
13
|
date?: string | Date;
|
|
@@ -9,7 +9,13 @@ export type ResolvedRiebeckiteConfig = {
|
|
|
9
9
|
* relative to their application root.
|
|
10
10
|
*/
|
|
11
11
|
buildDirectory?: string;
|
|
12
|
-
site: Required<SiteConfig
|
|
12
|
+
site: Omit<Required<SiteConfig>, "feed"> & {
|
|
13
|
+
feed: {
|
|
14
|
+
title: string;
|
|
15
|
+
description: string;
|
|
16
|
+
language: string;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
13
19
|
content: {
|
|
14
20
|
directory: string;
|
|
15
21
|
source?: ContentSource;
|
|
@@ -18,11 +24,6 @@ export type ResolvedRiebeckiteConfig = {
|
|
|
18
24
|
publishStrategy: PublishStrategy;
|
|
19
25
|
};
|
|
20
26
|
};
|
|
21
|
-
markdown: {
|
|
22
|
-
syntaxHighlight: {
|
|
23
|
-
theme: string;
|
|
24
|
-
};
|
|
25
|
-
};
|
|
26
27
|
theme: Required<Omit<ThemeConfig, "tokens">> & {
|
|
27
28
|
tokens: NonNullable<ThemeConfig["tokens"]>;
|
|
28
29
|
styles: ThemeStyle[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@riebeckite/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.17",
|
|
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.17"
|
|
53
53
|
},
|
|
54
54
|
"repository": {
|
|
55
55
|
"type": "git",
|