@riebeckite/core 0.0.18 → 0.0.20
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 +5 -4
- package/dist/index.js +231 -130
- package/dist/src/content/content_entry_reader.d.ts +1 -0
- 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 +31 -6
- package/dist/src/types/plugin_page.d.ts +5 -1
- 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,19 +32,19 @@ 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";
|
|
46
45
|
export type { ConfigValidationIssue, PluginOptionsValidator, } from "./src/types/config_validation.js";
|
|
47
|
-
export type { ContentAsset, ContentBodySlot, ContentLink, ContentLinkKind, ContentLocationInput, ContentManifest, ContentManifestEntry, ContentManifestPluginClientEntry, ContentPublicLocation, ContentRedirect, FolderLocation, PluginPageRoute, } from "./src/types/content_manifest.js";
|
|
48
|
-
export { appendContentBodySlot } from "./src/types/content_manifest.js";
|
|
46
|
+
export type { ContentAsset, ContentBodySlot, ContentBodySlots, ContentLink, ContentLinkKind, ContentLocationInput, ContentManifest, ContentManifestEntry, ContentManifestPluginClientEntry, ContentPublicLocation, ContentRedirect, FolderLocation, PluginPageRoute, } from "./src/types/content_manifest.js";
|
|
47
|
+
export { ARTICLE_SLOT, appendContentBodySlot, } from "./src/types/content_manifest.js";
|
|
49
48
|
export type { Diagnostic, DiagnosticCode, DiagnosticSeverity, } from "./src/types/diagnostic.js";
|
|
50
49
|
export type { ContentAssetOutputInput, GeneratedOutput, GeneratedOutputContent, GeneratedOutputInput, GeneratedOutputSink, } from "./src/types/generated_output.js";
|
|
51
50
|
export { createUnavailableGeneratedOutputSink, normalizeContentAssetOutputPath, normalizeGeneratedOutputPath, } from "./src/types/generated_output.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,47 +1687,65 @@ 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;
|
|
1707
|
+
if (isMissingFileError(error)) {
|
|
1708
|
+
return { status: "miss", reason: "no-entry" };
|
|
1759
1709
|
}
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
}
|
|
1769
|
-
throw error;
|
|
1710
|
+
logger?.warn(
|
|
1711
|
+
"Persistent content cache entry could not be read and will be ignored.",
|
|
1712
|
+
{
|
|
1713
|
+
key,
|
|
1714
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1715
|
+
}
|
|
1716
|
+
);
|
|
1717
|
+
return { status: "miss", reason: "unreadable" };
|
|
1770
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;
|
|
1771
1749
|
},
|
|
1772
1750
|
async set(key, value) {
|
|
1773
1751
|
if (!config.cache?.enabled) return;
|
|
@@ -1778,8 +1756,18 @@ function createPersistentContentCache(options) {
|
|
|
1778
1756
|
"Persistent content cache values must be JSON serializable."
|
|
1779
1757
|
);
|
|
1780
1758
|
}
|
|
1781
|
-
|
|
1782
|
-
|
|
1759
|
+
try {
|
|
1760
|
+
await writeAtomically(filePath, versionDir, serialized);
|
|
1761
|
+
tracer?.event("persistentContentCache.write", { key });
|
|
1762
|
+
} catch (error) {
|
|
1763
|
+
logger?.warn(
|
|
1764
|
+
"Persistent content cache entry could not be written and will be ignored.",
|
|
1765
|
+
{
|
|
1766
|
+
key,
|
|
1767
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1768
|
+
}
|
|
1769
|
+
);
|
|
1770
|
+
}
|
|
1783
1771
|
},
|
|
1784
1772
|
async clear() {
|
|
1785
1773
|
try {
|
|
@@ -1788,6 +1776,7 @@ function createPersistentContentCache(options) {
|
|
|
1788
1776
|
}
|
|
1789
1777
|
}
|
|
1790
1778
|
};
|
|
1779
|
+
return cache;
|
|
1791
1780
|
}
|
|
1792
1781
|
function isValidCacheEntry(entry) {
|
|
1793
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);
|
|
@@ -2136,41 +2125,15 @@ var Pipeline = class {
|
|
|
2136
2125
|
frontmatter,
|
|
2137
2126
|
pipelineFingerprint: this.pipelineFingerprint
|
|
2138
2127
|
});
|
|
2139
|
-
const
|
|
2140
|
-
if (
|
|
2141
|
-
const
|
|
2142
|
-
|
|
2128
|
+
const lookup = await this.persistentCache.lookup(cacheKey);
|
|
2129
|
+
if (lookup.status === "hit") {
|
|
2130
|
+
const invalidDependency = await this.findInvalidDependency(
|
|
2131
|
+
lookup.entry.dependencies
|
|
2143
2132
|
);
|
|
2144
|
-
|
|
2145
|
-
for (const dep of cachedEntry.dependencies) {
|
|
2146
|
-
if (dep.kind === "content") {
|
|
2147
|
-
const content = await validationTracker.readContent(
|
|
2148
|
-
dep.id,
|
|
2149
|
-
async () => await this.getMarkdownBySlug?.(dep.id) ?? ""
|
|
2150
|
-
);
|
|
2151
|
-
if (fingerprintContent(content) !== dep.fingerprint) {
|
|
2152
|
-
valid = false;
|
|
2153
|
-
break;
|
|
2154
|
-
}
|
|
2155
|
-
} else if (dep.kind === "file") {
|
|
2156
|
-
const fileContent = await validationTracker.contentSource.read({
|
|
2157
|
-
path: dep.id
|
|
2158
|
-
});
|
|
2159
|
-
if (fingerprintContent(fileContent) !== dep.fingerprint) {
|
|
2160
|
-
valid = false;
|
|
2161
|
-
break;
|
|
2162
|
-
}
|
|
2163
|
-
} else if (dep.kind === "link") {
|
|
2164
|
-
if (fingerprintContent(this.resolveLinkDependency(dep.id)) !== dep.fingerprint) {
|
|
2165
|
-
valid = false;
|
|
2166
|
-
break;
|
|
2167
|
-
}
|
|
2168
|
-
}
|
|
2169
|
-
}
|
|
2170
|
-
if (valid) {
|
|
2133
|
+
if (!invalidDependency) {
|
|
2171
2134
|
this.reportContentDependencies(
|
|
2172
2135
|
sourceSlug,
|
|
2173
|
-
|
|
2136
|
+
lookup.entry.dependencies
|
|
2174
2137
|
);
|
|
2175
2138
|
this.options.observability?.tracer?.event(
|
|
2176
2139
|
"persistentContentCache.hit",
|
|
@@ -2178,16 +2141,32 @@ var Pipeline = class {
|
|
|
2178
2141
|
);
|
|
2179
2142
|
this.options.onPersistentContentCacheResult?.("hit");
|
|
2180
2143
|
return {
|
|
2181
|
-
frontmatter:
|
|
2182
|
-
html:
|
|
2144
|
+
frontmatter: lookup.entry.value.frontmatter,
|
|
2145
|
+
html: lookup.entry.value.html
|
|
2183
2146
|
};
|
|
2184
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");
|
|
2185
2169
|
}
|
|
2186
|
-
this.options.observability?.tracer?.event(
|
|
2187
|
-
"persistentContentCache.miss",
|
|
2188
|
-
{ key: cacheKey, slug: sourceSlug }
|
|
2189
|
-
);
|
|
2190
|
-
this.options.onPersistentContentCacheResult?.("miss");
|
|
2191
2170
|
} else {
|
|
2192
2171
|
this.options.observability?.tracer?.event(
|
|
2193
2172
|
"persistentContentCache.bypass",
|
|
@@ -2299,6 +2278,30 @@ var Pipeline = class {
|
|
|
2299
2278
|
reportContentDependencies(slug, dependencies) {
|
|
2300
2279
|
this.options.onContentDependencies?.(slug, dependencies);
|
|
2301
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
|
+
}
|
|
2302
2305
|
getPermalink(slug) {
|
|
2303
2306
|
const permalink = this.permalinks.get(slug);
|
|
2304
2307
|
if (!permalink) {
|
|
@@ -3680,9 +3683,14 @@ var ContentEntryReader = class {
|
|
|
3680
3683
|
if (cached) return cached;
|
|
3681
3684
|
const content = this.source.read(entry).then(
|
|
3682
3685
|
(value) => typeof value === "string" ? value : new TextDecoder().decode(value)
|
|
3683
|
-
)
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
+
);
|
|
3687
|
+
const retain = entry.path.endsWith(".md");
|
|
3688
|
+
const tracked = retain ? content : content.finally(() => this.texts.delete(entry.path));
|
|
3689
|
+
this.texts.set(entry.path, tracked);
|
|
3690
|
+
return tracked;
|
|
3691
|
+
}
|
|
3692
|
+
clearReadCache() {
|
|
3693
|
+
this.texts.clear();
|
|
3686
3694
|
}
|
|
3687
3695
|
};
|
|
3688
3696
|
|
|
@@ -3826,10 +3834,12 @@ var FileSystemContentSource = class {
|
|
|
3826
3834
|
async scanWithExclusions() {
|
|
3827
3835
|
const exclusions = [];
|
|
3828
3836
|
try {
|
|
3837
|
+
const templaterTemplateFolder = await this.resolveTemplaterTemplateFolder();
|
|
3829
3838
|
const entries = await this.scanDirectory(
|
|
3830
3839
|
this.contentDirectory,
|
|
3831
3840
|
"",
|
|
3832
|
-
exclusions
|
|
3841
|
+
exclusions,
|
|
3842
|
+
templaterTemplateFolder
|
|
3833
3843
|
);
|
|
3834
3844
|
return { entries, exclusions };
|
|
3835
3845
|
} catch (error) {
|
|
@@ -3847,7 +3857,7 @@ var FileSystemContentSource = class {
|
|
|
3847
3857
|
}
|
|
3848
3858
|
return await fs4.readFile(filePath);
|
|
3849
3859
|
}
|
|
3850
|
-
async scanDirectory(directory, parentPath2, exclusions) {
|
|
3860
|
+
async scanDirectory(directory, parentPath2, exclusions, templaterTemplateFolder) {
|
|
3851
3861
|
const directoryEntries = await fs4.readdir(directory, {
|
|
3852
3862
|
withFileTypes: true
|
|
3853
3863
|
});
|
|
@@ -3864,9 +3874,21 @@ var FileSystemContentSource = class {
|
|
|
3864
3874
|
exclusions.push({ path: logicalPath, pattern });
|
|
3865
3875
|
continue;
|
|
3866
3876
|
}
|
|
3877
|
+
if (templaterTemplateFolder && isTemplaterTemplatePath(logicalPath, templaterTemplateFolder)) {
|
|
3878
|
+
exclusions.push({
|
|
3879
|
+
path: logicalPath,
|
|
3880
|
+
pattern: `Obsidian Templater templates_folder: ${templaterTemplateFolder}`
|
|
3881
|
+
});
|
|
3882
|
+
continue;
|
|
3883
|
+
}
|
|
3867
3884
|
if (directoryEntry.isDirectory()) {
|
|
3868
3885
|
entries.push(
|
|
3869
|
-
...await this.scanDirectory(
|
|
3886
|
+
...await this.scanDirectory(
|
|
3887
|
+
filePath,
|
|
3888
|
+
logicalPath,
|
|
3889
|
+
exclusions,
|
|
3890
|
+
templaterTemplateFolder
|
|
3891
|
+
)
|
|
3870
3892
|
);
|
|
3871
3893
|
continue;
|
|
3872
3894
|
}
|
|
@@ -3891,6 +3913,28 @@ var FileSystemContentSource = class {
|
|
|
3891
3913
|
}
|
|
3892
3914
|
return filePath;
|
|
3893
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
|
+
}
|
|
3894
3938
|
};
|
|
3895
3939
|
function isIgnoredContentPath(logicalPath, exclude = []) {
|
|
3896
3940
|
if (isExcluded(INTERNAL_CONTENT_IGNORE_PATTERNS, logicalPath)) return true;
|
|
@@ -3903,6 +3947,17 @@ function matchContentExcludePattern(logicalPath, exclude = []) {
|
|
|
3903
3947
|
const withoutExtension = logicalPath.slice(0, -3);
|
|
3904
3948
|
return exclude.find((pattern) => isExcluded([pattern], withoutExtension));
|
|
3905
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
|
+
}
|
|
3906
3961
|
function normalizeLogicalPath(logicalPath) {
|
|
3907
3962
|
const normalizedPath = normalizeContentPath(logicalPath);
|
|
3908
3963
|
if (normalizedPath.length === 0 || normalizedPath.startsWith("/") || path4.isAbsolute(normalizedPath) || path4.win32.isAbsolute(normalizedPath) || normalizedPath.split("/").some((segment) => segment === "..")) {
|
|
@@ -3913,6 +3968,9 @@ function normalizeLogicalPath(logicalPath) {
|
|
|
3913
3968
|
function isMissingDirectoryError(error, directory) {
|
|
3914
3969
|
return error instanceof Error && "code" in error && error.code === "ENOENT" && "path" in error && error.path === directory;
|
|
3915
3970
|
}
|
|
3971
|
+
function isFileNotFoundError(error) {
|
|
3972
|
+
return error instanceof Error && "code" in error && error.code === "ENOENT";
|
|
3973
|
+
}
|
|
3916
3974
|
function missingContentDirectoryError(directory) {
|
|
3917
3975
|
const relative = path4.relative(process.cwd(), directory);
|
|
3918
3976
|
const display = relative && !relative.startsWith("..") ? relative : directory;
|
|
@@ -4348,6 +4406,7 @@ var ContentManager = class {
|
|
|
4348
4406
|
routableSlugs = null;
|
|
4349
4407
|
routableSlugsPromise = null;
|
|
4350
4408
|
processedContentCount = 0;
|
|
4409
|
+
reusedContentCount = 0;
|
|
4351
4410
|
outputChangeSet = null;
|
|
4352
4411
|
trackedContentDependencies = /* @__PURE__ */ new Map();
|
|
4353
4412
|
async getAllPosts() {
|
|
@@ -4575,6 +4634,12 @@ var ContentManager = class {
|
|
|
4575
4634
|
async build(options = {}) {
|
|
4576
4635
|
return await this.getManifest(options);
|
|
4577
4636
|
}
|
|
4637
|
+
getProcessedContentCount() {
|
|
4638
|
+
return this.processedContentCount;
|
|
4639
|
+
}
|
|
4640
|
+
getReusedContentCount() {
|
|
4641
|
+
return this.reusedContentCount;
|
|
4642
|
+
}
|
|
4578
4643
|
async getOutputChangeSet(options = {}) {
|
|
4579
4644
|
await this.getManifest(options);
|
|
4580
4645
|
if (!this.outputChangeSet) {
|
|
@@ -4650,6 +4715,7 @@ var ContentManager = class {
|
|
|
4650
4715
|
return { entries, contentIndex, diagnostics };
|
|
4651
4716
|
}
|
|
4652
4717
|
async dispose() {
|
|
4718
|
+
this.entryReader.clearReadCache();
|
|
4653
4719
|
if (!this.contentIndex) return;
|
|
4654
4720
|
await this.pluginRuntime.dispose(this.contentIndex);
|
|
4655
4721
|
}
|
|
@@ -4712,6 +4778,7 @@ var ContentManager = class {
|
|
|
4712
4778
|
if (preparation.affectedContent.dependent.has(slug)) return null;
|
|
4713
4779
|
const entry = preparation.previousManifestEntriesBySlug.get(slug);
|
|
4714
4780
|
if (!entry) return null;
|
|
4781
|
+
this.reusedContentCount += 1;
|
|
4715
4782
|
this.observability().tracer.event("content.reuse", { slug });
|
|
4716
4783
|
return cloneManifestEntry(entry);
|
|
4717
4784
|
}
|
|
@@ -5148,6 +5215,14 @@ function resolveBuildOutputDirectory(config) {
|
|
|
5148
5215
|
}
|
|
5149
5216
|
|
|
5150
5217
|
// src/types/content_manifest.ts
|
|
5218
|
+
var ARTICLE_SLOT = {
|
|
5219
|
+
header: "article.header",
|
|
5220
|
+
metadata: "article.metadata",
|
|
5221
|
+
aside: "article.aside",
|
|
5222
|
+
beforeContent: "article.before-content",
|
|
5223
|
+
afterContent: "article.after-content",
|
|
5224
|
+
footer: "article.footer"
|
|
5225
|
+
};
|
|
5151
5226
|
function appendContentBodySlot(entry, slot, html) {
|
|
5152
5227
|
if (!html.trim()) return;
|
|
5153
5228
|
const previous = entry.bodySlots?.[slot];
|
|
@@ -5187,6 +5262,32 @@ function escapeScriptJson(value) {
|
|
|
5187
5262
|
return value.replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
5188
5263
|
}
|
|
5189
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
|
+
|
|
5190
5291
|
// src/utils/text.ts
|
|
5191
5292
|
function stripHtml(html) {
|
|
5192
5293
|
return html.replace(/<script\b[\s\S]*?<\/script>/gi, " ").replace(/<style\b[\s\S]*?<\/style>/gi, " ").replace(/<[^>]+>/g, " ");
|
|
@@ -5199,6 +5300,7 @@ function calculateReadingTime(html) {
|
|
|
5199
5300
|
return Math.max(1, Math.ceil(cjkCharacters / 500 + latinWords / 220));
|
|
5200
5301
|
}
|
|
5201
5302
|
export {
|
|
5303
|
+
ARTICLE_SLOT,
|
|
5202
5304
|
ATTACHMENTS_BASE_PATH,
|
|
5203
5305
|
CompositeTraceSink,
|
|
5204
5306
|
ConfigValidationError,
|
|
@@ -5211,6 +5313,7 @@ export {
|
|
|
5211
5313
|
NoopTracer,
|
|
5212
5314
|
Pipeline,
|
|
5213
5315
|
PluginDependencyError,
|
|
5316
|
+
PluginHookError,
|
|
5214
5317
|
SinkTracer,
|
|
5215
5318
|
appendContentBodySlot,
|
|
5216
5319
|
attachErrorPath,
|
|
@@ -5219,11 +5322,9 @@ export {
|
|
|
5219
5322
|
buildGraphEdges,
|
|
5220
5323
|
buildOutputInventory,
|
|
5221
5324
|
calculateReadingTime,
|
|
5222
|
-
collectConfigDeprecationDiagnostics,
|
|
5223
5325
|
computePipelineFingerprint,
|
|
5224
5326
|
createClientEntry,
|
|
5225
5327
|
createContentGraph,
|
|
5226
|
-
createDeprecationDiagnostic,
|
|
5227
5328
|
createPluginMemo,
|
|
5228
5329
|
createStyleAsset,
|
|
5229
5330
|
createUnavailableGeneratedOutputSink,
|
|
@@ -5237,7 +5338,6 @@ export {
|
|
|
5237
5338
|
escapeScriptJson,
|
|
5238
5339
|
extractFrontmatterAliases,
|
|
5239
5340
|
fingerprintContentEntries,
|
|
5240
|
-
formatDeprecationMessage,
|
|
5241
5341
|
getContentSourceEntry,
|
|
5242
5342
|
getEntryLanguage,
|
|
5243
5343
|
getExtension,
|
|
@@ -5280,6 +5380,7 @@ export {
|
|
|
5280
5380
|
resolvePublicFolderLocation,
|
|
5281
5381
|
resolvePublishingBuildTime,
|
|
5282
5382
|
resolvePublishingState,
|
|
5383
|
+
scanMarkdownFenceLines,
|
|
5283
5384
|
selectEntriesByLanguage,
|
|
5284
5385
|
serializePublicClientConfig,
|
|
5285
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;
|
|
@@ -18,13 +18,36 @@ export type ContentAsset = {
|
|
|
18
18
|
export type ContentManifestPluginAsset = PluginAsset & {
|
|
19
19
|
path: string;
|
|
20
20
|
};
|
|
21
|
+
/**
|
|
22
|
+
* The standard `article.*` positions the article consumer recognizes.
|
|
23
|
+
*
|
|
24
|
+
* These constants are a convenience for Sites that prefer named references;
|
|
25
|
+
* writing the slot string inline (for example `name="article.metadata"`) stays
|
|
26
|
+
* the recommended, most readable form in TSX layouts.
|
|
27
|
+
*/
|
|
28
|
+
export declare const ARTICLE_SLOT: {
|
|
29
|
+
readonly header: "article.header";
|
|
30
|
+
readonly metadata: "article.metadata";
|
|
31
|
+
readonly aside: "article.aside";
|
|
32
|
+
readonly beforeContent: "article.before-content";
|
|
33
|
+
readonly afterContent: "article.after-content";
|
|
34
|
+
readonly footer: "article.footer";
|
|
35
|
+
};
|
|
21
36
|
/**
|
|
22
37
|
* A semantic position in a Site-owned article layout.
|
|
23
38
|
*
|
|
24
39
|
* The standard article consumer recognizes the `article.*` positions below.
|
|
25
40
|
* Other names remain valid so a custom Site can define its own layout slots.
|
|
26
41
|
*/
|
|
27
|
-
export type ContentBodySlot =
|
|
42
|
+
export type ContentBodySlot = (typeof ARTICLE_SLOT)[keyof typeof ARTICLE_SLOT] | (string & {});
|
|
43
|
+
/**
|
|
44
|
+
* A map of Plugin-provided HTML fragments keyed by slot name.
|
|
45
|
+
*
|
|
46
|
+
* The standard `article.*` names autocomplete while any custom slot name
|
|
47
|
+
* remains valid, so custom Plugins keep working. A slot is considered empty
|
|
48
|
+
* when its value is missing or whitespace-only.
|
|
49
|
+
*/
|
|
50
|
+
export type ContentBodySlots = Partial<Record<(typeof ARTICLE_SLOT)[keyof typeof ARTICLE_SLOT], string>> & Readonly<Record<string, string | undefined>>;
|
|
28
51
|
/** Client entries and their explicitly public configuration. */
|
|
29
52
|
export type ContentManifestPluginClientEntry = PluginClientEntry;
|
|
30
53
|
export type ContentManifestEntry = {
|
|
@@ -91,15 +114,17 @@ export type ContentLocationInput = {
|
|
|
91
114
|
markdown: string;
|
|
92
115
|
};
|
|
93
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
|
+
*/
|
|
94
121
|
entries: ContentManifestEntry[];
|
|
95
122
|
/**
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
* compatibility; plugins that emit generated output should read this view
|
|
99
|
-
* 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`.
|
|
100
125
|
*/
|
|
101
126
|
publicEntries: ContentManifestEntry[];
|
|
102
|
-
/**
|
|
127
|
+
/** Public entries allowed on discovery surfaces such as navigation, search, feeds, taxonomy, and public graphs. */
|
|
103
128
|
discoverableEntries: ContentManifestEntry[];
|
|
104
129
|
bySlug: Map<string, ContentManifestEntry>;
|
|
105
130
|
/** Contains only entries with an explicit source-authored content ID. */
|
|
@@ -18,7 +18,11 @@ export type PluginPage = {
|
|
|
18
18
|
language?: string;
|
|
19
19
|
};
|
|
20
20
|
export type PluginPageContext = PluginContext & {
|
|
21
|
-
/**
|
|
21
|
+
/**
|
|
22
|
+
* The resolved manifest. `manifest.entries` still contains `draft` and
|
|
23
|
+
* `scheduled` entries, so page output must read `publicEntries` (routable) or
|
|
24
|
+
* `discoverableEntries` (public only) instead of `entries`.
|
|
25
|
+
*/
|
|
22
26
|
manifest: ContentManifest;
|
|
23
27
|
/** Request pathname, normalized to an absolute path. */
|
|
24
28
|
pathname: string;
|
|
@@ -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.20",
|
|
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.20"
|
|
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;
|