@riebeckite/core 0.0.19 → 0.0.21
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 +3 -2
- package/dist/index.js +194 -125
- package/dist/src/content/content_manager.d.ts +3 -0
- package/dist/src/content/content_persistent_cache.d.ts +10 -5
- package/dist/src/content/file_system_content_source.d.ts +1 -0
- package/dist/src/pipeline.d.ts +1 -0
- package/dist/src/types/content_manifest.d.ts +7 -5
- package/dist/src/types/plugin_seo.d.ts +1 -1
- package/dist/src/utils/markdown.d.ts +5 -0
- package/package.json +2 -2
- package/dist/src/config_deprecations.d.ts +0 -8
- package/dist/src/deprecation.d.ts +0 -14
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/docs/reference/configuration.
|
|
40
|
+
[Configuration](../../docs/docs/reference/configuration.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/docs/reference/README.
|
|
92
|
-
- [Content System](../../docs/docs/framework/content-system.
|
|
93
|
-
- [Plugin System](../../docs/docs/reference/plugin-api.
|
|
94
|
-
- [Architecture](../../docs/docs/framework/architecture.
|
|
91
|
+
- [Framework Reference](../../docs/docs/reference/README.md)
|
|
92
|
+
- [Content System](../../docs/docs/framework/content-system.md)
|
|
93
|
+
- [Plugin System](../../docs/docs/reference/plugin-api.md) / [Theme System](../../docs/docs/reference/theme-api.md)
|
|
94
|
+
- [Architecture](../../docs/docs/framework/architecture.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/docs/reference/configuration.md) を参照してください。
|
|
32
|
+
コンテンツディレクトリはアプリケーションルート基準で解決します。設定項目の全体と `projectRoot` / `appRoot` / `configRoot` / `contentRoot` の解決規則は [Configuration](../../docs/docs/reference/configuration.ja.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/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)
|
|
72
|
+
- [Framework Reference](../../docs/docs/reference/README.ja.md)
|
|
73
|
+
- [Content System](../../docs/docs/framework/content-system.ja.md)
|
|
74
|
+
- [Plugin System](../../docs/docs/reference/plugin-api.ja.md) / [Theme System](../../docs/docs/reference/theme-api.ja.md)
|
|
75
|
+
- [Architecture](../../docs/docs/framework/architecture.ja.md)
|
|
76
76
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export { defineConfig, isExcluded, isPublished, resolveConfig, resolveConfigModule, } from "./src/config.js";
|
|
2
|
-
export { type ConfigDeprecationNotice, collectConfigDeprecationDiagnostics, } from "./src/config_deprecations.js";
|
|
3
2
|
export { ConfigValidationError } from "./src/config_validation.js";
|
|
4
3
|
export { ATTACHMENTS_BASE_PATH, attachmentUrl, getExtension, isAttachmentPath, isImagePath, isMarkdownPath, normalizeContentPath, } from "./src/content/attachment.js";
|
|
5
4
|
export type { ContentBuildState, FingerprintedContentEntry, } from "./src/content/content_build_state.js";
|
|
@@ -33,13 +32,13 @@ export { buildOutputInventory, determineOutputChanges, htmlOutputPath, } from ".
|
|
|
33
32
|
export type { PublishingResolutionOptions, PublishingVisibility, ResolvedPublishingState, } from "./src/content/publishing.js";
|
|
34
33
|
export { resolvePublishingBuildTime, resolvePublishingState, } from "./src/content/publishing.js";
|
|
35
34
|
export { readOnlyContentGraph } from "./src/content/read_only_content_graph.js";
|
|
36
|
-
export { createDeprecationDiagnostic, type DeprecationKind, type DeprecationNotice, formatDeprecationMessage, } from "./src/deprecation.js";
|
|
37
35
|
export type { LogContext, Logger, LogLevel, Observability, ObservabilityValue, TraceAttributes, TraceEvent, Tracer, TraceSink, TraceSpan, } from "./src/observability.js";
|
|
38
36
|
export { CompositeTraceSink, ConsoleLogger, NoopLogger, NoopTracer, SinkTracer, } from "./src/observability.js";
|
|
39
37
|
export type { PipelineOptions } from "./src/pipeline.js";
|
|
40
38
|
export { Pipeline } from "./src/pipeline.js";
|
|
41
39
|
export type { PluginCache } from "./src/plugin/plugin_cache.js";
|
|
42
40
|
export { PluginDependencyError, type PluginDependencyErrorKind, } from "./src/plugin/plugin_dependency_error.js";
|
|
41
|
+
export { PluginHookError } from "./src/plugin/plugin_lifecycle.js";
|
|
43
42
|
export type { CreatePluginMemoOptions, PluginMemo, } from "./src/plugin/plugin_memo.js";
|
|
44
43
|
export { createPluginMemo, stableStringify, } from "./src/plugin/plugin_memo.js";
|
|
45
44
|
export { resolveBuildOutputDirectory, resolveManagedStateRoot, } from "./src/project/project_layout.js";
|
|
@@ -74,5 +73,7 @@ export { defineTheme } from "./src/types/theme_config.js";
|
|
|
74
73
|
export { uniqueStrings } from "./src/utils/collections.js";
|
|
75
74
|
export { attachErrorPath } from "./src/utils/error.js";
|
|
76
75
|
export { escapeHtml, escapeHtmlAttribute, escapeScriptJson, } from "./src/utils/html.js";
|
|
76
|
+
export type { MarkdownFenceLine } from "./src/utils/markdown.js";
|
|
77
|
+
export { scanMarkdownFenceLines } from "./src/utils/markdown.js";
|
|
77
78
|
export { normalizeTag } from "./src/utils/tags.js";
|
|
78
79
|
export { calculateReadingTime, stripHtml } from "./src/utils/text.js";
|
package/dist/index.js
CHANGED
|
@@ -778,46 +778,6 @@ function globToRegExp(glob) {
|
|
|
778
778
|
return new RegExp(`^${re}$`);
|
|
779
779
|
}
|
|
780
780
|
|
|
781
|
-
// src/deprecation.ts
|
|
782
|
-
function createDeprecationDiagnostic(notice) {
|
|
783
|
-
return {
|
|
784
|
-
code: `deprecated-${notice.kind}`,
|
|
785
|
-
severity: "warning",
|
|
786
|
-
message: formatDeprecationMessage(notice),
|
|
787
|
-
target: notice.target,
|
|
788
|
-
suggestion: notice.replacement ? `Use ${notice.replacement}. ${notice.action}` : notice.action,
|
|
789
|
-
meta: { deprecation: notice }
|
|
790
|
-
};
|
|
791
|
-
}
|
|
792
|
-
function formatDeprecationMessage(notice) {
|
|
793
|
-
const lines = [
|
|
794
|
-
`Deprecated: ${notice.target}`,
|
|
795
|
-
`Deprecated since: ${notice.deprecatedSince}`
|
|
796
|
-
];
|
|
797
|
-
if (notice.replacement) lines.push(`Use: ${notice.replacement}`);
|
|
798
|
-
lines.push(`Migration: ${notice.action}`);
|
|
799
|
-
if (notice.documentationUrl) lines.push(`See: ${notice.documentationUrl}`);
|
|
800
|
-
if (notice.removedIn) lines.push(`Removal planned: ${notice.removedIn}`);
|
|
801
|
-
return lines.join("\n");
|
|
802
|
-
}
|
|
803
|
-
|
|
804
|
-
// src/config_deprecations.ts
|
|
805
|
-
var configDeprecations = [];
|
|
806
|
-
function collectConfigDeprecationDiagnostics(config, notices = configDeprecations) {
|
|
807
|
-
return notices.filter((notice) => hasConfigPath(config, notice.path)).map(createDeprecationDiagnostic);
|
|
808
|
-
}
|
|
809
|
-
function hasConfigPath(config, path6) {
|
|
810
|
-
let value = config;
|
|
811
|
-
for (const segment of path6.split(".")) {
|
|
812
|
-
if (!isRecord2(value) || !(segment in value)) return false;
|
|
813
|
-
value = value[segment];
|
|
814
|
-
}
|
|
815
|
-
return value !== void 0;
|
|
816
|
-
}
|
|
817
|
-
function isRecord2(value) {
|
|
818
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
819
|
-
}
|
|
820
|
-
|
|
821
781
|
// src/content/image_extensions.ts
|
|
822
782
|
var IMAGE_EXTENSIONS = [
|
|
823
783
|
"png",
|
|
@@ -895,7 +855,7 @@ async function readContentBuildStateStatus(statePath) {
|
|
|
895
855
|
}
|
|
896
856
|
throw error;
|
|
897
857
|
}
|
|
898
|
-
if (!
|
|
858
|
+
if (!isRecord2(parsed)) {
|
|
899
859
|
return { kind: "invalid", path: statePath, reason: "invalid-shape" };
|
|
900
860
|
}
|
|
901
861
|
if (parsed.version !== CONTENT_BUILD_STATE_VERSION) {
|
|
@@ -935,15 +895,15 @@ function resolveContentBuildStatePath(config, contentDirectory) {
|
|
|
935
895
|
);
|
|
936
896
|
}
|
|
937
897
|
function isContentBuildState(value) {
|
|
938
|
-
return
|
|
898
|
+
return isRecord2(value) && value.version === CONTENT_BUILD_STATE_VERSION && isContentBuildStateShape(value);
|
|
939
899
|
}
|
|
940
900
|
function isContentBuildStateShape(value) {
|
|
941
|
-
if (!
|
|
901
|
+
if (!isRecord2(value.entries) || !isRecord2(value.contentIndex) || value.outputs !== void 0 && !isOutputDescriptors(value.outputs)) {
|
|
942
902
|
return false;
|
|
943
903
|
}
|
|
944
904
|
return Object.values(value.entries).every(
|
|
945
|
-
(entry) =>
|
|
946
|
-
(dependency) =>
|
|
905
|
+
(entry) => isRecord2(entry) && typeof entry.fingerprint === "string" && entry.fingerprint.length > 0 && Array.isArray(entry.aliases) && entry.aliases.every((alias) => typeof alias === "string") && Array.isArray(entry.dependencies) && entry.dependencies.every(
|
|
906
|
+
(dependency) => isRecord2(dependency) && (dependency.kind === "content" || dependency.kind === "file") && typeof dependency.id === "string"
|
|
947
907
|
)
|
|
948
908
|
) && Object.values(value.contentIndex).every(
|
|
949
909
|
(entry) => typeof entry === "string"
|
|
@@ -951,7 +911,7 @@ function isContentBuildStateShape(value) {
|
|
|
951
911
|
}
|
|
952
912
|
function isOutputDescriptors(value) {
|
|
953
913
|
return Array.isArray(value) && value.every(
|
|
954
|
-
(output) =>
|
|
914
|
+
(output) => isRecord2(output) && (output.kind === "content" || output.kind === "redirect" || output.kind === "plugin-page" || output.kind === "generated") && isOutputPath(output.path) && typeof output.producer === "string" && Array.isArray(output.dependencies) && output.dependencies.every(isOutputDependency)
|
|
955
915
|
);
|
|
956
916
|
}
|
|
957
917
|
function isOutputPath(value) {
|
|
@@ -961,11 +921,11 @@ function isOutputPath(value) {
|
|
|
961
921
|
return value.split("/").every((segment) => segment !== "." && segment !== "..");
|
|
962
922
|
}
|
|
963
923
|
function isOutputDependency(value) {
|
|
964
|
-
if (!
|
|
924
|
+
if (!isRecord2(value) || typeof value.type !== "string") return false;
|
|
965
925
|
if (value.type === "global" || value.type === "unknown") return true;
|
|
966
926
|
return value.type === "content" && typeof value.slug === "string" || value.type === "tag" && typeof value.tag === "string" || value.type === "folder" && typeof value.folder === "string";
|
|
967
927
|
}
|
|
968
|
-
function
|
|
928
|
+
function isRecord2(value) {
|
|
969
929
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
970
930
|
}
|
|
971
931
|
function isNotFoundError(error) {
|
|
@@ -1727,44 +1687,25 @@ async function writeAtomically(targetPath, dir, serialized) {
|
|
|
1727
1687
|
throw error;
|
|
1728
1688
|
}
|
|
1729
1689
|
}
|
|
1690
|
+
function isMissingFileError(error) {
|
|
1691
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
1692
|
+
}
|
|
1730
1693
|
function createPersistentContentCache(options) {
|
|
1731
1694
|
const { config, logger, tracer } = options;
|
|
1732
1695
|
const baseDir = cacheDirectory(config);
|
|
1733
1696
|
const versionDir = versionDirectory(baseDir);
|
|
1734
|
-
|
|
1735
|
-
async
|
|
1736
|
-
if (!config.cache?.enabled)
|
|
1697
|
+
const cache = {
|
|
1698
|
+
async lookup(key) {
|
|
1699
|
+
if (!config.cache?.enabled) {
|
|
1700
|
+
return { status: "miss", reason: "disabled" };
|
|
1701
|
+
}
|
|
1737
1702
|
const filePath = cacheFilePath(baseDir, key);
|
|
1703
|
+
let raw;
|
|
1738
1704
|
try {
|
|
1739
|
-
|
|
1740
|
-
const entry = JSON.parse(raw);
|
|
1741
|
-
if (entry.schemaVersion !== CONTENT_CACHE_SCHEMA_VERSION) {
|
|
1742
|
-
tracer?.event("persistentContentCache.schemaMismatch", { key });
|
|
1743
|
-
return void 0;
|
|
1744
|
-
}
|
|
1745
|
-
if (entry.key !== key) {
|
|
1746
|
-
tracer?.event("persistentContentCache.keyMismatch", { key });
|
|
1747
|
-
return void 0;
|
|
1748
|
-
}
|
|
1749
|
-
if (!isValidCacheEntry(entry)) {
|
|
1750
|
-
tracer?.event("persistentContentCache.invalidShape", { key });
|
|
1751
|
-
return void 0;
|
|
1752
|
-
}
|
|
1753
|
-
tracer?.event("persistentContentCache.found", { key });
|
|
1754
|
-
return entry;
|
|
1705
|
+
raw = await fs2.readFile(filePath, "utf8");
|
|
1755
1706
|
} catch (error) {
|
|
1756
|
-
if (
|
|
1757
|
-
|
|
1758
|
-
return void 0;
|
|
1759
|
-
}
|
|
1760
|
-
if (error instanceof SyntaxError) {
|
|
1761
|
-
logger?.warn(
|
|
1762
|
-
"Persistent content cache entry is corrupted and will be ignored.",
|
|
1763
|
-
{
|
|
1764
|
-
key
|
|
1765
|
-
}
|
|
1766
|
-
);
|
|
1767
|
-
return void 0;
|
|
1707
|
+
if (isMissingFileError(error)) {
|
|
1708
|
+
return { status: "miss", reason: "no-entry" };
|
|
1768
1709
|
}
|
|
1769
1710
|
logger?.warn(
|
|
1770
1711
|
"Persistent content cache entry could not be read and will be ignored.",
|
|
@@ -1773,8 +1714,38 @@ function createPersistentContentCache(options) {
|
|
|
1773
1714
|
error: error instanceof Error ? error.message : String(error)
|
|
1774
1715
|
}
|
|
1775
1716
|
);
|
|
1776
|
-
return
|
|
1717
|
+
return { status: "miss", reason: "unreadable" };
|
|
1777
1718
|
}
|
|
1719
|
+
let entry;
|
|
1720
|
+
try {
|
|
1721
|
+
entry = JSON.parse(raw);
|
|
1722
|
+
} catch (error) {
|
|
1723
|
+
logger?.warn(
|
|
1724
|
+
"Persistent content cache entry is corrupted and will be ignored.",
|
|
1725
|
+
{
|
|
1726
|
+
key,
|
|
1727
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1728
|
+
}
|
|
1729
|
+
);
|
|
1730
|
+
return { status: "miss", reason: "corrupted" };
|
|
1731
|
+
}
|
|
1732
|
+
if (typeof entry !== "object" || entry === null) {
|
|
1733
|
+
return { status: "miss", reason: "invalid-entry" };
|
|
1734
|
+
}
|
|
1735
|
+
if (entry.schemaVersion !== CONTENT_CACHE_SCHEMA_VERSION) {
|
|
1736
|
+
return { status: "miss", reason: "schema-mismatch" };
|
|
1737
|
+
}
|
|
1738
|
+
if (entry.key !== key) {
|
|
1739
|
+
return { status: "miss", reason: "key-mismatch" };
|
|
1740
|
+
}
|
|
1741
|
+
if (!isValidCacheEntry(entry)) {
|
|
1742
|
+
return { status: "miss", reason: "invalid-entry" };
|
|
1743
|
+
}
|
|
1744
|
+
return { status: "hit", entry };
|
|
1745
|
+
},
|
|
1746
|
+
async get(key) {
|
|
1747
|
+
const result = await cache.lookup(key);
|
|
1748
|
+
return result.status === "hit" ? result.entry : void 0;
|
|
1778
1749
|
},
|
|
1779
1750
|
async set(key, value) {
|
|
1780
1751
|
if (!config.cache?.enabled) return;
|
|
@@ -1805,6 +1776,7 @@ function createPersistentContentCache(options) {
|
|
|
1805
1776
|
}
|
|
1806
1777
|
}
|
|
1807
1778
|
};
|
|
1779
|
+
return cache;
|
|
1808
1780
|
}
|
|
1809
1781
|
function isValidCacheEntry(entry) {
|
|
1810
1782
|
return typeof entry === "object" && entry !== null && typeof entry.key === "string" && typeof entry.schemaVersion === "number" && Array.isArray(entry.dependencies) && entry.dependencies.every(isValidDependency) && typeof entry.value === "object" && entry.value !== null && typeof entry.value.html === "string" && typeof entry.value.frontmatter === "object" && entry.value.frontmatter !== null && !Array.isArray(entry.value.frontmatter);
|
|
@@ -2153,41 +2125,15 @@ var Pipeline = class {
|
|
|
2153
2125
|
frontmatter,
|
|
2154
2126
|
pipelineFingerprint: this.pipelineFingerprint
|
|
2155
2127
|
});
|
|
2156
|
-
const
|
|
2157
|
-
if (
|
|
2158
|
-
const
|
|
2159
|
-
|
|
2128
|
+
const lookup = await this.persistentCache.lookup(cacheKey);
|
|
2129
|
+
if (lookup.status === "hit") {
|
|
2130
|
+
const invalidDependency = await this.findInvalidDependency(
|
|
2131
|
+
lookup.entry.dependencies
|
|
2160
2132
|
);
|
|
2161
|
-
|
|
2162
|
-
for (const dep of cachedEntry.dependencies) {
|
|
2163
|
-
if (dep.kind === "content") {
|
|
2164
|
-
const content = await validationTracker.readContent(
|
|
2165
|
-
dep.id,
|
|
2166
|
-
async () => await this.getMarkdownBySlug?.(dep.id) ?? ""
|
|
2167
|
-
);
|
|
2168
|
-
if (fingerprintContent(content) !== dep.fingerprint) {
|
|
2169
|
-
valid = false;
|
|
2170
|
-
break;
|
|
2171
|
-
}
|
|
2172
|
-
} else if (dep.kind === "file") {
|
|
2173
|
-
const fileContent = await validationTracker.contentSource.read({
|
|
2174
|
-
path: dep.id
|
|
2175
|
-
});
|
|
2176
|
-
if (fingerprintContent(fileContent) !== dep.fingerprint) {
|
|
2177
|
-
valid = false;
|
|
2178
|
-
break;
|
|
2179
|
-
}
|
|
2180
|
-
} else if (dep.kind === "link") {
|
|
2181
|
-
if (fingerprintContent(this.resolveLinkDependency(dep.id)) !== dep.fingerprint) {
|
|
2182
|
-
valid = false;
|
|
2183
|
-
break;
|
|
2184
|
-
}
|
|
2185
|
-
}
|
|
2186
|
-
}
|
|
2187
|
-
if (valid) {
|
|
2133
|
+
if (!invalidDependency) {
|
|
2188
2134
|
this.reportContentDependencies(
|
|
2189
2135
|
sourceSlug,
|
|
2190
|
-
|
|
2136
|
+
lookup.entry.dependencies
|
|
2191
2137
|
);
|
|
2192
2138
|
this.options.observability?.tracer?.event(
|
|
2193
2139
|
"persistentContentCache.hit",
|
|
@@ -2195,16 +2141,32 @@ var Pipeline = class {
|
|
|
2195
2141
|
);
|
|
2196
2142
|
this.options.onPersistentContentCacheResult?.("hit");
|
|
2197
2143
|
return {
|
|
2198
|
-
frontmatter:
|
|
2199
|
-
html:
|
|
2144
|
+
frontmatter: lookup.entry.value.frontmatter,
|
|
2145
|
+
html: lookup.entry.value.html
|
|
2200
2146
|
};
|
|
2201
2147
|
}
|
|
2148
|
+
this.options.observability?.tracer?.event(
|
|
2149
|
+
"persistentContentCache.miss",
|
|
2150
|
+
{
|
|
2151
|
+
key: cacheKey,
|
|
2152
|
+
slug: sourceSlug,
|
|
2153
|
+
reason: "dependency-changed",
|
|
2154
|
+
dependencyKind: invalidDependency.kind,
|
|
2155
|
+
dependencyId: invalidDependency.id
|
|
2156
|
+
}
|
|
2157
|
+
);
|
|
2158
|
+
this.options.onPersistentContentCacheResult?.("miss");
|
|
2159
|
+
} else {
|
|
2160
|
+
this.options.observability?.tracer?.event(
|
|
2161
|
+
"persistentContentCache.miss",
|
|
2162
|
+
{
|
|
2163
|
+
key: cacheKey,
|
|
2164
|
+
slug: sourceSlug,
|
|
2165
|
+
reason: lookup.reason
|
|
2166
|
+
}
|
|
2167
|
+
);
|
|
2168
|
+
this.options.onPersistentContentCacheResult?.("miss");
|
|
2202
2169
|
}
|
|
2203
|
-
this.options.observability?.tracer?.event(
|
|
2204
|
-
"persistentContentCache.miss",
|
|
2205
|
-
{ key: cacheKey, slug: sourceSlug }
|
|
2206
|
-
);
|
|
2207
|
-
this.options.onPersistentContentCacheResult?.("miss");
|
|
2208
2170
|
} else {
|
|
2209
2171
|
this.options.observability?.tracer?.event(
|
|
2210
2172
|
"persistentContentCache.bypass",
|
|
@@ -2316,6 +2278,30 @@ var Pipeline = class {
|
|
|
2316
2278
|
reportContentDependencies(slug, dependencies) {
|
|
2317
2279
|
this.options.onContentDependencies?.(slug, dependencies);
|
|
2318
2280
|
}
|
|
2281
|
+
async findInvalidDependency(dependencies) {
|
|
2282
|
+
const contentSource = this.options.contentSource;
|
|
2283
|
+
if (!contentSource) return null;
|
|
2284
|
+
const validationTracker = createContentDependencyTracker(contentSource);
|
|
2285
|
+
for (const dep of dependencies) {
|
|
2286
|
+
if (dep.kind === "content") {
|
|
2287
|
+
const content = await validationTracker.readContent(
|
|
2288
|
+
dep.id,
|
|
2289
|
+
async () => await this.getMarkdownBySlug?.(dep.id) ?? ""
|
|
2290
|
+
);
|
|
2291
|
+
if (fingerprintContent(content) !== dep.fingerprint) return dep;
|
|
2292
|
+
} else if (dep.kind === "file") {
|
|
2293
|
+
const fileContent = await validationTracker.contentSource.read({
|
|
2294
|
+
path: dep.id
|
|
2295
|
+
});
|
|
2296
|
+
if (fingerprintContent(fileContent) !== dep.fingerprint) return dep;
|
|
2297
|
+
} else if (dep.kind === "link") {
|
|
2298
|
+
if (fingerprintContent(this.resolveLinkDependency(dep.id)) !== dep.fingerprint) {
|
|
2299
|
+
return dep;
|
|
2300
|
+
}
|
|
2301
|
+
}
|
|
2302
|
+
}
|
|
2303
|
+
return null;
|
|
2304
|
+
}
|
|
2319
2305
|
getPermalink(slug) {
|
|
2320
2306
|
const permalink = this.permalinks.get(slug);
|
|
2321
2307
|
if (!permalink) {
|
|
@@ -3848,10 +3834,12 @@ var FileSystemContentSource = class {
|
|
|
3848
3834
|
async scanWithExclusions() {
|
|
3849
3835
|
const exclusions = [];
|
|
3850
3836
|
try {
|
|
3837
|
+
const templaterTemplateFolder = await this.resolveTemplaterTemplateFolder();
|
|
3851
3838
|
const entries = await this.scanDirectory(
|
|
3852
3839
|
this.contentDirectory,
|
|
3853
3840
|
"",
|
|
3854
|
-
exclusions
|
|
3841
|
+
exclusions,
|
|
3842
|
+
templaterTemplateFolder
|
|
3855
3843
|
);
|
|
3856
3844
|
return { entries, exclusions };
|
|
3857
3845
|
} catch (error) {
|
|
@@ -3869,7 +3857,7 @@ var FileSystemContentSource = class {
|
|
|
3869
3857
|
}
|
|
3870
3858
|
return await fs4.readFile(filePath);
|
|
3871
3859
|
}
|
|
3872
|
-
async scanDirectory(directory, parentPath2, exclusions) {
|
|
3860
|
+
async scanDirectory(directory, parentPath2, exclusions, templaterTemplateFolder) {
|
|
3873
3861
|
const directoryEntries = await fs4.readdir(directory, {
|
|
3874
3862
|
withFileTypes: true
|
|
3875
3863
|
});
|
|
@@ -3886,9 +3874,21 @@ var FileSystemContentSource = class {
|
|
|
3886
3874
|
exclusions.push({ path: logicalPath, pattern });
|
|
3887
3875
|
continue;
|
|
3888
3876
|
}
|
|
3877
|
+
if (templaterTemplateFolder && isTemplaterTemplatePath(logicalPath, templaterTemplateFolder)) {
|
|
3878
|
+
exclusions.push({
|
|
3879
|
+
path: logicalPath,
|
|
3880
|
+
pattern: `Obsidian Templater templates_folder: ${templaterTemplateFolder}`
|
|
3881
|
+
});
|
|
3882
|
+
continue;
|
|
3883
|
+
}
|
|
3889
3884
|
if (directoryEntry.isDirectory()) {
|
|
3890
3885
|
entries.push(
|
|
3891
|
-
...await this.scanDirectory(
|
|
3886
|
+
...await this.scanDirectory(
|
|
3887
|
+
filePath,
|
|
3888
|
+
logicalPath,
|
|
3889
|
+
exclusions,
|
|
3890
|
+
templaterTemplateFolder
|
|
3891
|
+
)
|
|
3892
3892
|
);
|
|
3893
3893
|
continue;
|
|
3894
3894
|
}
|
|
@@ -3913,6 +3913,28 @@ var FileSystemContentSource = class {
|
|
|
3913
3913
|
}
|
|
3914
3914
|
return filePath;
|
|
3915
3915
|
}
|
|
3916
|
+
async resolveTemplaterTemplateFolder() {
|
|
3917
|
+
const settingsPath = path4.join(
|
|
3918
|
+
this.contentDirectory,
|
|
3919
|
+
".obsidian",
|
|
3920
|
+
"plugins",
|
|
3921
|
+
"templater-obsidian",
|
|
3922
|
+
"data.json"
|
|
3923
|
+
);
|
|
3924
|
+
let raw;
|
|
3925
|
+
try {
|
|
3926
|
+
raw = await fs4.readFile(settingsPath, "utf8");
|
|
3927
|
+
} catch (error) {
|
|
3928
|
+
if (isFileNotFoundError(error)) return void 0;
|
|
3929
|
+
throw error;
|
|
3930
|
+
}
|
|
3931
|
+
try {
|
|
3932
|
+
const settings = JSON.parse(raw);
|
|
3933
|
+
return normalizeTemplaterTemplateFolder(settings.templates_folder);
|
|
3934
|
+
} catch {
|
|
3935
|
+
return void 0;
|
|
3936
|
+
}
|
|
3937
|
+
}
|
|
3916
3938
|
};
|
|
3917
3939
|
function isIgnoredContentPath(logicalPath, exclude = []) {
|
|
3918
3940
|
if (isExcluded(INTERNAL_CONTENT_IGNORE_PATTERNS, logicalPath)) return true;
|
|
@@ -3925,6 +3947,17 @@ function matchContentExcludePattern(logicalPath, exclude = []) {
|
|
|
3925
3947
|
const withoutExtension = logicalPath.slice(0, -3);
|
|
3926
3948
|
return exclude.find((pattern) => isExcluded([pattern], withoutExtension));
|
|
3927
3949
|
}
|
|
3950
|
+
function isTemplaterTemplatePath(logicalPath, templateFolder) {
|
|
3951
|
+
return logicalPath === templateFolder || logicalPath.startsWith(`${templateFolder}/`);
|
|
3952
|
+
}
|
|
3953
|
+
function normalizeTemplaterTemplateFolder(value) {
|
|
3954
|
+
if (typeof value !== "string" || value.trim().length === 0) return void 0;
|
|
3955
|
+
const normalized = normalizeContentPath(value.trim()).replace(/\/+$/, "");
|
|
3956
|
+
if (normalized.length === 0 || normalized.startsWith("/") || path4.isAbsolute(normalized) || path4.win32.isAbsolute(normalized) || normalized.split("/").some((segment) => segment === "..")) {
|
|
3957
|
+
return void 0;
|
|
3958
|
+
}
|
|
3959
|
+
return normalized;
|
|
3960
|
+
}
|
|
3928
3961
|
function normalizeLogicalPath(logicalPath) {
|
|
3929
3962
|
const normalizedPath = normalizeContentPath(logicalPath);
|
|
3930
3963
|
if (normalizedPath.length === 0 || normalizedPath.startsWith("/") || path4.isAbsolute(normalizedPath) || path4.win32.isAbsolute(normalizedPath) || normalizedPath.split("/").some((segment) => segment === "..")) {
|
|
@@ -3935,6 +3968,9 @@ function normalizeLogicalPath(logicalPath) {
|
|
|
3935
3968
|
function isMissingDirectoryError(error, directory) {
|
|
3936
3969
|
return error instanceof Error && "code" in error && error.code === "ENOENT" && "path" in error && error.path === directory;
|
|
3937
3970
|
}
|
|
3971
|
+
function isFileNotFoundError(error) {
|
|
3972
|
+
return error instanceof Error && "code" in error && error.code === "ENOENT";
|
|
3973
|
+
}
|
|
3938
3974
|
function missingContentDirectoryError(directory) {
|
|
3939
3975
|
const relative = path4.relative(process.cwd(), directory);
|
|
3940
3976
|
const display = relative && !relative.startsWith("..") ? relative : directory;
|
|
@@ -4370,6 +4406,7 @@ var ContentManager = class {
|
|
|
4370
4406
|
routableSlugs = null;
|
|
4371
4407
|
routableSlugsPromise = null;
|
|
4372
4408
|
processedContentCount = 0;
|
|
4409
|
+
reusedContentCount = 0;
|
|
4373
4410
|
outputChangeSet = null;
|
|
4374
4411
|
trackedContentDependencies = /* @__PURE__ */ new Map();
|
|
4375
4412
|
async getAllPosts() {
|
|
@@ -4597,6 +4634,12 @@ var ContentManager = class {
|
|
|
4597
4634
|
async build(options = {}) {
|
|
4598
4635
|
return await this.getManifest(options);
|
|
4599
4636
|
}
|
|
4637
|
+
getProcessedContentCount() {
|
|
4638
|
+
return this.processedContentCount;
|
|
4639
|
+
}
|
|
4640
|
+
getReusedContentCount() {
|
|
4641
|
+
return this.reusedContentCount;
|
|
4642
|
+
}
|
|
4600
4643
|
async getOutputChangeSet(options = {}) {
|
|
4601
4644
|
await this.getManifest(options);
|
|
4602
4645
|
if (!this.outputChangeSet) {
|
|
@@ -4735,6 +4778,7 @@ var ContentManager = class {
|
|
|
4735
4778
|
if (preparation.affectedContent.dependent.has(slug)) return null;
|
|
4736
4779
|
const entry = preparation.previousManifestEntriesBySlug.get(slug);
|
|
4737
4780
|
if (!entry) return null;
|
|
4781
|
+
this.reusedContentCount += 1;
|
|
4738
4782
|
this.observability().tracer.event("content.reuse", { slug });
|
|
4739
4783
|
return cloneManifestEntry(entry);
|
|
4740
4784
|
}
|
|
@@ -5218,6 +5262,32 @@ function escapeScriptJson(value) {
|
|
|
5218
5262
|
return value.replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
5219
5263
|
}
|
|
5220
5264
|
|
|
5265
|
+
// src/utils/markdown.ts
|
|
5266
|
+
var FENCE_OPEN = /^ {0,3}(`{3,}|~{3,})(.*)$/;
|
|
5267
|
+
var FENCE_CLOSE = /^ {0,3}(`{3,}|~{3,})\s*$/;
|
|
5268
|
+
function scanMarkdownFenceLines(source) {
|
|
5269
|
+
const lines = [];
|
|
5270
|
+
let fence = null;
|
|
5271
|
+
for (const value of source.split("\n")) {
|
|
5272
|
+
if (fence === null) {
|
|
5273
|
+
const open = FENCE_OPEN.exec(value);
|
|
5274
|
+
if (open && !(open[1][0] === "`" && open[2].includes("`"))) {
|
|
5275
|
+
fence = { marker: open[1][0], length: open[1].length };
|
|
5276
|
+
}
|
|
5277
|
+
lines.push({ value, inFence: false });
|
|
5278
|
+
continue;
|
|
5279
|
+
}
|
|
5280
|
+
const close = FENCE_CLOSE.exec(value);
|
|
5281
|
+
if (close && close[1][0] === fence.marker && close[1].length >= fence.length) {
|
|
5282
|
+
fence = null;
|
|
5283
|
+
lines.push({ value, inFence: false });
|
|
5284
|
+
continue;
|
|
5285
|
+
}
|
|
5286
|
+
lines.push({ value, inFence: true });
|
|
5287
|
+
}
|
|
5288
|
+
return lines;
|
|
5289
|
+
}
|
|
5290
|
+
|
|
5221
5291
|
// src/utils/text.ts
|
|
5222
5292
|
function stripHtml(html) {
|
|
5223
5293
|
return html.replace(/<script\b[\s\S]*?<\/script>/gi, " ").replace(/<style\b[\s\S]*?<\/style>/gi, " ").replace(/<[^>]+>/g, " ");
|
|
@@ -5243,6 +5313,7 @@ export {
|
|
|
5243
5313
|
NoopTracer,
|
|
5244
5314
|
Pipeline,
|
|
5245
5315
|
PluginDependencyError,
|
|
5316
|
+
PluginHookError,
|
|
5246
5317
|
SinkTracer,
|
|
5247
5318
|
appendContentBodySlot,
|
|
5248
5319
|
attachErrorPath,
|
|
@@ -5251,11 +5322,9 @@ export {
|
|
|
5251
5322
|
buildGraphEdges,
|
|
5252
5323
|
buildOutputInventory,
|
|
5253
5324
|
calculateReadingTime,
|
|
5254
|
-
collectConfigDeprecationDiagnostics,
|
|
5255
5325
|
computePipelineFingerprint,
|
|
5256
5326
|
createClientEntry,
|
|
5257
5327
|
createContentGraph,
|
|
5258
|
-
createDeprecationDiagnostic,
|
|
5259
5328
|
createPluginMemo,
|
|
5260
5329
|
createStyleAsset,
|
|
5261
5330
|
createUnavailableGeneratedOutputSink,
|
|
@@ -5269,7 +5338,6 @@ export {
|
|
|
5269
5338
|
escapeScriptJson,
|
|
5270
5339
|
extractFrontmatterAliases,
|
|
5271
5340
|
fingerprintContentEntries,
|
|
5272
|
-
formatDeprecationMessage,
|
|
5273
5341
|
getContentSourceEntry,
|
|
5274
5342
|
getEntryLanguage,
|
|
5275
5343
|
getExtension,
|
|
@@ -5312,6 +5380,7 @@ export {
|
|
|
5312
5380
|
resolvePublicFolderLocation,
|
|
5313
5381
|
resolvePublishingBuildTime,
|
|
5314
5382
|
resolvePublishingState,
|
|
5383
|
+
scanMarkdownFenceLines,
|
|
5315
5384
|
selectEntriesByLanguage,
|
|
5316
5385
|
serializePublicClientConfig,
|
|
5317
5386
|
stableStringify,
|
|
@@ -44,6 +44,7 @@ export declare class ContentManager {
|
|
|
44
44
|
private routableSlugs;
|
|
45
45
|
private routableSlugsPromise;
|
|
46
46
|
private processedContentCount;
|
|
47
|
+
private reusedContentCount;
|
|
47
48
|
private outputChangeSet;
|
|
48
49
|
private trackedContentDependencies;
|
|
49
50
|
constructor(content: string | ContentSource, exclude?: string[], pipelineOptions?: PipelineOptions);
|
|
@@ -56,6 +57,8 @@ export declare class ContentManager {
|
|
|
56
57
|
getManifest(options?: ContentBuildOptions): Promise<ContentManifest>;
|
|
57
58
|
private buildManifest;
|
|
58
59
|
build(options?: ContentBuildOptions): Promise<ContentManifest>;
|
|
60
|
+
getProcessedContentCount(): number;
|
|
61
|
+
getReusedContentCount(): number;
|
|
59
62
|
getOutputChangeSet(options?: ContentBuildOptions): Promise<OutputChangeSet>;
|
|
60
63
|
getBacklinks(targetSlug: string): Promise<Backlink[]>;
|
|
61
64
|
getContentGraph(): Promise<ContentGraph>;
|
|
@@ -18,16 +18,21 @@ export type PersistentContentCacheOptions = {
|
|
|
18
18
|
};
|
|
19
19
|
export declare const CONTENT_CACHE_SCHEMA_VERSION = 3;
|
|
20
20
|
export declare const CONTENT_CACHE_COMPATIBILITY_VERSION = 1;
|
|
21
|
-
export type
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
export type PersistentContentCacheMissReason = "disabled" | "no-entry" | "corrupted" | "unreadable" | "schema-mismatch" | "key-mismatch" | "invalid-entry";
|
|
22
|
+
export type PersistentContentCacheLookup = {
|
|
23
|
+
status: "hit";
|
|
24
|
+
entry: PersistentContentCacheEntry;
|
|
25
|
+
} | {
|
|
26
|
+
status: "miss";
|
|
27
|
+
reason: PersistentContentCacheMissReason;
|
|
25
28
|
};
|
|
26
|
-
export
|
|
29
|
+
export type PersistentContentCache = {
|
|
30
|
+
lookup(key: string): Promise<PersistentContentCacheLookup>;
|
|
27
31
|
get(key: string): Promise<PersistentContentCacheEntry | undefined>;
|
|
28
32
|
set(key: string, value: PersistentContentCacheEntry): Promise<void>;
|
|
29
33
|
clear(): Promise<void>;
|
|
30
34
|
};
|
|
35
|
+
export declare function createPersistentContentCache(options: PersistentContentCacheOptions): PersistentContentCache;
|
|
31
36
|
export type CacheKeyInputs = {
|
|
32
37
|
slug: string;
|
|
33
38
|
source: string;
|
|
@@ -17,6 +17,7 @@ export declare class FileSystemContentSource implements ContentSource {
|
|
|
17
17
|
read(entry: ContentSourceEntry): Promise<ContentSourceContent>;
|
|
18
18
|
private scanDirectory;
|
|
19
19
|
private resolveFilePath;
|
|
20
|
+
private resolveTemplaterTemplateFolder;
|
|
20
21
|
}
|
|
21
22
|
export declare function isIgnoredContentPath(logicalPath: string, exclude?: readonly string[]): boolean;
|
|
22
23
|
export declare function matchContentExcludePattern(logicalPath: string, exclude?: readonly string[]): string | undefined;
|
package/dist/src/pipeline.d.ts
CHANGED
|
@@ -27,6 +27,7 @@ export declare class Pipeline {
|
|
|
27
27
|
execute(markDownContent: string, context?: MarkdownExecutionContext): Promise<PostContent>;
|
|
28
28
|
private executeWithEmbedState;
|
|
29
29
|
private reportContentDependencies;
|
|
30
|
+
private findInvalidDependency;
|
|
30
31
|
private getPermalink;
|
|
31
32
|
private resolveLinkDependency;
|
|
32
33
|
private recordNoteLinkDependencies;
|
|
@@ -114,15 +114,17 @@ export type ContentLocationInput = {
|
|
|
114
114
|
markdown: string;
|
|
115
115
|
};
|
|
116
116
|
export type ContentManifest = {
|
|
117
|
+
/**
|
|
118
|
+
* Raw entries for every scanned content source, including drafts, scheduled,
|
|
119
|
+
* private, and otherwise nonpublic entries. This is not a publication view.
|
|
120
|
+
*/
|
|
117
121
|
entries: ContentManifestEntry[];
|
|
118
122
|
/**
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
* compatibility; plugins that emit generated output should read this view
|
|
122
|
-
* so drafts and scheduled notes never reach generated output.
|
|
123
|
+
* Routable entries for generated pages: `public` and `unlisted` notes.
|
|
124
|
+
* Plugins that emit public output must use this view rather than `entries`.
|
|
123
125
|
*/
|
|
124
126
|
publicEntries: ContentManifestEntry[];
|
|
125
|
-
/**
|
|
127
|
+
/** Public entries allowed on discovery surfaces such as navigation, search, feeds, taxonomy, and public graphs. */
|
|
126
128
|
discoverableEntries: ContentManifestEntry[];
|
|
127
129
|
bySlug: Map<string, ContentManifestEntry>;
|
|
128
130
|
/** Contains only entries with an explicit source-authored content ID. */
|
|
@@ -26,7 +26,7 @@ export type RenderableFeedEntry = ContentManifestEntry & {
|
|
|
26
26
|
};
|
|
27
27
|
export type PluginSeoExtension = {
|
|
28
28
|
buildArticleSeo(config: ResolvedRiebeckiteConfig, permalink: string, post: PostContent, headTags?: readonly PluginHeadTag[], language?: string): SeoMetadata;
|
|
29
|
-
buildWebsiteSeo(config: ResolvedRiebeckiteConfig, input: WebsiteSeoInput, headTags?: readonly PluginHeadTag[]): SeoMetadata;
|
|
29
|
+
buildWebsiteSeo(config: ResolvedRiebeckiteConfig, input: WebsiteSeoInput, headTags?: readonly PluginHeadTag[], language?: string): SeoMetadata;
|
|
30
30
|
buildAbsoluteUrl(config: ResolvedRiebeckiteConfig, pathOrUrl: string): string;
|
|
31
31
|
buildPostUrl(config: ResolvedRiebeckiteConfig, permalink: string): string;
|
|
32
32
|
getDescription(post: Pick<PostContent, "frontmatter" | "html">): string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@riebeckite/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.21",
|
|
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.21"
|
|
53
53
|
},
|
|
54
54
|
"repository": {
|
|
55
55
|
"type": "git",
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { type DeprecationNotice } from "./deprecation.js";
|
|
2
|
-
import type { Diagnostic } from "./types/diagnostic.js";
|
|
3
|
-
import type { RiebeckiteConfig } from "./types/riebeckite_config.js";
|
|
4
|
-
export type ConfigDeprecationNotice = DeprecationNotice & {
|
|
5
|
-
readonly kind: "config";
|
|
6
|
-
readonly path: string;
|
|
7
|
-
};
|
|
8
|
-
export declare function collectConfigDeprecationDiagnostics(config: RiebeckiteConfig, notices?: readonly ConfigDeprecationNotice[]): Diagnostic[];
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { Diagnostic } from "./types/diagnostic.js";
|
|
2
|
-
export type DeprecationKind = "config" | "plugin-api" | "theme-api" | "cli" | "scaffold" | "package";
|
|
3
|
-
export type DeprecationNotice = {
|
|
4
|
-
readonly kind: DeprecationKind;
|
|
5
|
-
readonly id: string;
|
|
6
|
-
readonly target: string;
|
|
7
|
-
readonly deprecatedSince: string;
|
|
8
|
-
readonly action: string;
|
|
9
|
-
readonly replacement?: string;
|
|
10
|
-
readonly documentationUrl?: string;
|
|
11
|
-
readonly removedIn?: string;
|
|
12
|
-
};
|
|
13
|
-
export declare function createDeprecationDiagnostic(notice: DeprecationNotice): Diagnostic;
|
|
14
|
-
export declare function formatDeprecationMessage(notice: DeprecationNotice): string;
|