@riebeckite/core 0.0.1
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/LICENSE +201 -0
- package/README.md +94 -0
- package/README_ja.md +75 -0
- package/dist/index.d.ts +61 -0
- package/dist/index.js +3040 -0
- package/dist/src/config.d.ts +8 -0
- package/dist/src/config_validation.d.ts +7 -0
- package/dist/src/content/affected_content.d.ts +7 -0
- package/dist/src/content/attachment.d.ts +7 -0
- package/dist/src/content/content_build_coordinator.d.ts +25 -0
- package/dist/src/content/content_build_state.d.ts +22 -0
- package/dist/src/content/content_build_state_store.d.ts +20 -0
- package/dist/src/content/content_change_set.d.ts +10 -0
- package/dist/src/content/content_collection.d.ts +78 -0
- package/dist/src/content/content_entry_reader.d.ts +12 -0
- package/dist/src/content/content_fingerprint.d.ts +3 -0
- package/dist/src/content/content_graph.d.ts +23 -0
- package/dist/src/content/content_index_builder.d.ts +7 -0
- package/dist/src/content/content_links.d.ts +2 -0
- package/dist/src/content/content_location.d.ts +2 -0
- package/dist/src/content/content_location_resolver.d.ts +18 -0
- package/dist/src/content/content_manager.d.ts +59 -0
- package/dist/src/content/content_metadata.d.ts +3 -0
- package/dist/src/content/content_query.d.ts +76 -0
- package/dist/src/content/content_source.d.ts +17 -0
- package/dist/src/content/file_system_content_source.d.ts +11 -0
- package/dist/src/content/graph_layout.d.ts +24 -0
- package/dist/src/content/image_extensions.d.ts +1 -0
- package/dist/src/content/manifest_builder.d.ts +6 -0
- package/dist/src/content/read_only_content_graph.d.ts +4 -0
- package/dist/src/observability.d.ts +70 -0
- package/dist/src/pipeline.d.ts +25 -0
- package/dist/src/plugin/plugin_cache.d.ts +22 -0
- package/dist/src/plugin/plugin_dependency.d.ts +2 -0
- package/dist/src/plugin/plugin_dependency_error.d.ts +20 -0
- package/dist/src/plugin/plugin_lifecycle.d.ts +11 -0
- package/dist/src/plugin/plugin_memo.d.ts +20 -0
- package/dist/src/plugin/plugin_runtime.d.ts +59 -0
- package/dist/src/types/config_validation.d.ts +7 -0
- package/dist/src/types/content_manifest.d.ts +87 -0
- package/dist/src/types/diagnostic.d.ts +15 -0
- package/dist/src/types/generated_output.d.ts +28 -0
- package/dist/src/types/plugin.d.ts +71 -0
- package/dist/src/types/plugin_asset.d.ts +13 -0
- package/dist/src/types/plugin_context.d.ts +85 -0
- package/dist/src/types/plugin_diagnostic.d.ts +5 -0
- package/dist/src/types/plugin_endpoint.d.ts +22 -0
- package/dist/src/types/plugin_head.d.ts +18 -0
- package/dist/src/types/plugin_pipeline.d.ts +20 -0
- package/dist/src/types/plugin_seo.d.ts +40 -0
- package/dist/src/types/post_content.d.ts +20 -0
- package/dist/src/types/publish_strategy.d.ts +19 -0
- package/dist/src/types/resolved_riebeckite_config.d.ts +26 -0
- package/dist/src/types/riebeckite_config.d.ts +23 -0
- package/dist/src/types/site_config.d.ts +14 -0
- package/dist/src/types/theme_config.d.ts +55 -0
- package/dist/src/utils/collections.d.ts +1 -0
- package/dist/src/utils/html.d.ts +2 -0
- package/dist/src/utils/tags.d.ts +1 -0
- package/dist/src/utils/text.d.ts +2 -0
- package/package.json +71 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Logger } from "../observability.js";
|
|
2
|
+
import type { JsonValue, PluginCache } from "./plugin_cache.js";
|
|
3
|
+
/**
|
|
4
|
+
* Dependency-aware memoization on top of the existing `PluginCache`. The cache
|
|
5
|
+
* key is derived from the caller-supplied key plus a stable hash of the
|
|
6
|
+
* declared dependencies, so a cache hit only happens when everything the value
|
|
7
|
+
* depends on is unchanged. No separate cache backend is introduced.
|
|
8
|
+
*/
|
|
9
|
+
export type PluginMemo = {
|
|
10
|
+
memo<T extends JsonValue>(key: string, dependencies: JsonValue, compute: () => T | Promise<T>): Promise<T>;
|
|
11
|
+
};
|
|
12
|
+
export type CreatePluginMemoOptions = {
|
|
13
|
+
logger?: Logger;
|
|
14
|
+
};
|
|
15
|
+
export declare function createPluginMemo(cache: PluginCache, options?: CreatePluginMemoOptions): PluginMemo;
|
|
16
|
+
/**
|
|
17
|
+
* Serializes JSON values with sorted object keys so that logically identical
|
|
18
|
+
* dependency sets hash identically regardless of key insertion order.
|
|
19
|
+
*/
|
|
20
|
+
export declare function stableStringify(value: JsonValue): string;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { PipelineOptions } from "../pipeline.js";
|
|
2
|
+
import type { ContentLocationInput, ContentManifest, ContentManifestEntry, ContentPublicLocation } from "../types/content_manifest.js";
|
|
3
|
+
import type { Diagnostic } from "../types/diagnostic.js";
|
|
4
|
+
import type { GeneratedOutput } from "../types/generated_output.js";
|
|
5
|
+
import type { PostContent } from "../types/post_content.js";
|
|
6
|
+
/**
|
|
7
|
+
* Explicit build lifecycle stages. `idle` means no build lifecycle has been
|
|
8
|
+
* requested yet; the remaining values name the stage currently executing.
|
|
9
|
+
* Once `started` is reached the lifecycle never runs again.
|
|
10
|
+
*/
|
|
11
|
+
export type PluginBuildStage = "idle" | "setup" | "buildStart" | "onBuildStart" | "onConfigResolved" | "started";
|
|
12
|
+
export declare class PluginRuntime {
|
|
13
|
+
private pipelineOptions;
|
|
14
|
+
private buildLifecycle;
|
|
15
|
+
private buildStage;
|
|
16
|
+
private disposed;
|
|
17
|
+
private diagnostics;
|
|
18
|
+
private pluginCaches;
|
|
19
|
+
private generatedOutputs;
|
|
20
|
+
private generatedOutputOwners;
|
|
21
|
+
private isBuildTime;
|
|
22
|
+
constructor(pipelineOptions?: PipelineOptions);
|
|
23
|
+
getDiagnostics(): Diagnostic[];
|
|
24
|
+
getBuildStage(): PluginBuildStage;
|
|
25
|
+
/**
|
|
26
|
+
* Starts the plugin build lifecycle exactly once, regardless of which public
|
|
27
|
+
* entry point (content processing or location resolution) reaches it first.
|
|
28
|
+
* Concurrent callers await the same run, so the ordered hooks
|
|
29
|
+
* (`setup` → `buildStart` → `onBuildStart` → `onConfigResolved`) are never
|
|
30
|
+
* duplicated and no caller proceeds before the lifecycle completes.
|
|
31
|
+
*/
|
|
32
|
+
startBuild(contentIndex: Map<string, string>): Promise<void>;
|
|
33
|
+
runContentLoaded(slug: string, markdown: string, contentIndex: Map<string, string>): Promise<void>;
|
|
34
|
+
resolveContentLocations(entries: readonly ContentLocationInput[], contentIndex: Map<string, string>): Promise<readonly ContentPublicLocation[]>;
|
|
35
|
+
extendContentLocations(entries: readonly ContentLocationInput[], locations: Map<string, ContentPublicLocation>, contentIndex: Map<string, string>): Promise<void>;
|
|
36
|
+
runPostHook(hookName: "onPostParsed" | "onPostProcessed", slug: string, markdown: string, content: PostContent, contentIndex: Map<string, string>): Promise<void>;
|
|
37
|
+
runGraphHook(entries: ContentManifestEntry[], contentIndex: Map<string, string>): Promise<void>;
|
|
38
|
+
runManifestCreated(manifest: ContentManifest, contentIndex: Map<string, string>): Promise<void>;
|
|
39
|
+
runBuildEnd(manifest: ContentManifest, contentIndex: Map<string, string>): Promise<void>;
|
|
40
|
+
enableBuildTime(): void;
|
|
41
|
+
dispose(contentIndex: Map<string, string>): Promise<void>;
|
|
42
|
+
collectAssets(): {
|
|
43
|
+
path: string;
|
|
44
|
+
pluginName: string;
|
|
45
|
+
kind: import("../types/plugin_asset.js").PluginAssetKind;
|
|
46
|
+
moduleSpecifier: string;
|
|
47
|
+
}[];
|
|
48
|
+
/** Returns registered outputs sorted by path for a deterministic build. */
|
|
49
|
+
collectGeneratedOutputs(): GeneratedOutput[];
|
|
50
|
+
collectDiagnostics(contentIndex: Map<string, string>): Promise<Diagnostic[]>;
|
|
51
|
+
private runBuildLifecycle;
|
|
52
|
+
private createContext;
|
|
53
|
+
private createPluginContext;
|
|
54
|
+
private generatedOutputSinkFor;
|
|
55
|
+
private cacheFor;
|
|
56
|
+
private runHook;
|
|
57
|
+
private observability;
|
|
58
|
+
private plugins;
|
|
59
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { ContentGraph } from "../content/content_graph.js";
|
|
2
|
+
import type { Diagnostic } from "./diagnostic.js";
|
|
3
|
+
import type { GeneratedOutput } from "./generated_output.js";
|
|
4
|
+
import type { PluginAsset } from "./plugin_asset.js";
|
|
5
|
+
import type { PluginHeadTag } from "./plugin_head.js";
|
|
6
|
+
import type { PostFrontmatter } from "./post_content.js";
|
|
7
|
+
export type ContentLinkKind = "note" | "image" | "attachment" | "unresolved";
|
|
8
|
+
export type ContentLink = {
|
|
9
|
+
raw: string;
|
|
10
|
+
slug: string | null;
|
|
11
|
+
kind: ContentLinkKind;
|
|
12
|
+
embed: boolean;
|
|
13
|
+
};
|
|
14
|
+
export type ContentAsset = {
|
|
15
|
+
path: string;
|
|
16
|
+
};
|
|
17
|
+
export type ContentManifestPluginAsset = PluginAsset & {
|
|
18
|
+
path: string;
|
|
19
|
+
};
|
|
20
|
+
export type ContentManifestEntry = {
|
|
21
|
+
slug: string;
|
|
22
|
+
permalink: string;
|
|
23
|
+
publicLocation: ContentPublicLocation;
|
|
24
|
+
title: string;
|
|
25
|
+
frontmatter: PostFrontmatter;
|
|
26
|
+
html: string;
|
|
27
|
+
/**
|
|
28
|
+
* Head tags a plugin wants the Site shell to render for this entry.
|
|
29
|
+
* The Site owns the shell, so it decides whether to render them.
|
|
30
|
+
*/
|
|
31
|
+
headTags?: readonly PluginHeadTag[];
|
|
32
|
+
/**
|
|
33
|
+
* Plugin-provided HTML fragments the Site renders in named body slots.
|
|
34
|
+
* The Site owns its layout, so it decides where (and whether) each slot is
|
|
35
|
+
* rendered; a plugin only supplies the fragment, keyed by slot name.
|
|
36
|
+
*/
|
|
37
|
+
bodySlots?: Readonly<Record<string, string>>;
|
|
38
|
+
tags: string[];
|
|
39
|
+
links: ContentLink[];
|
|
40
|
+
backlinks: string[];
|
|
41
|
+
assets: ContentAsset[];
|
|
42
|
+
};
|
|
43
|
+
export type ContentRedirect = {
|
|
44
|
+
path: string;
|
|
45
|
+
status: 301 | 302 | 307 | 308;
|
|
46
|
+
};
|
|
47
|
+
export type ContentPublicLocation = {
|
|
48
|
+
slug: string;
|
|
49
|
+
permalink: string;
|
|
50
|
+
redirects?: readonly ContentRedirect[];
|
|
51
|
+
metadata?: Readonly<Record<string, string>>;
|
|
52
|
+
};
|
|
53
|
+
export type ContentLocationInput = {
|
|
54
|
+
slug: string;
|
|
55
|
+
path: string;
|
|
56
|
+
markdown: string;
|
|
57
|
+
};
|
|
58
|
+
export type ContentManifest = {
|
|
59
|
+
entries: ContentManifestEntry[];
|
|
60
|
+
/**
|
|
61
|
+
* Entries that pass the configured publish strategy. `entries` keeps every
|
|
62
|
+
* scanned note for backward compatibility; publishing plugins should read
|
|
63
|
+
* this view so unpublished notes never reach generated output.
|
|
64
|
+
*/
|
|
65
|
+
publicEntries: ContentManifestEntry[];
|
|
66
|
+
bySlug: Map<string, ContentManifestEntry>;
|
|
67
|
+
byPermalink: Map<string, ContentManifestEntry>;
|
|
68
|
+
redirects: Map<string, ContentRedirect & {
|
|
69
|
+
slug: string;
|
|
70
|
+
}>;
|
|
71
|
+
/**
|
|
72
|
+
* Redirects whose owning entry is public. Prevents unpublished notes from
|
|
73
|
+
* leaking their previous paths into deploy files.
|
|
74
|
+
*/
|
|
75
|
+
publicRedirects: Map<string, ContentRedirect & {
|
|
76
|
+
slug: string;
|
|
77
|
+
}>;
|
|
78
|
+
byTag: Map<string, ContentManifestEntry[]>;
|
|
79
|
+
byAsset: Map<string, ContentManifestEntry[]>;
|
|
80
|
+
outgoingLinks: Map<string, ContentLink[]>;
|
|
81
|
+
incomingLinks: Map<string, string[]>;
|
|
82
|
+
contentIndex: Map<string, string>;
|
|
83
|
+
graph: ContentGraph;
|
|
84
|
+
assets: ContentManifestPluginAsset[];
|
|
85
|
+
diagnostics: Diagnostic[];
|
|
86
|
+
generatedOutputs: GeneratedOutput[];
|
|
87
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type DiagnosticSeverity = "info" | "warning" | "error";
|
|
2
|
+
export type DiagnosticCode = "broken-wikilink" | "broken-image" | "broken-link" | "unused-asset" | "orphan-note" | "missing-frontmatter" | "publish-conflict" | "duplicate-title" | "slug-collision" | "excluded-public" | "publish-boundary" | "internal-error" | (string & {});
|
|
3
|
+
export type Diagnostic = {
|
|
4
|
+
code: DiagnosticCode;
|
|
5
|
+
severity: DiagnosticSeverity;
|
|
6
|
+
message: string;
|
|
7
|
+
pluginName?: string;
|
|
8
|
+
filePath?: string;
|
|
9
|
+
slug?: string;
|
|
10
|
+
line?: number;
|
|
11
|
+
column?: number;
|
|
12
|
+
target?: string;
|
|
13
|
+
suggestion?: string;
|
|
14
|
+
meta?: Record<string, unknown>;
|
|
15
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type GeneratedOutputContent = string | Uint8Array;
|
|
2
|
+
/**
|
|
3
|
+
* A file a plugin wants written to the build output directory. Content is kept
|
|
4
|
+
* in memory until the integration layer forwards it to the build tool, so
|
|
5
|
+
* plugins never touch the filesystem themselves.
|
|
6
|
+
*/
|
|
7
|
+
export type GeneratedOutputInput = {
|
|
8
|
+
/**
|
|
9
|
+
* Output path relative to the build output directory, for example
|
|
10
|
+
* `_redirects`, `.nojekyll` or `daily/feed.xml`.
|
|
11
|
+
*/
|
|
12
|
+
path: string;
|
|
13
|
+
content: GeneratedOutputContent;
|
|
14
|
+
};
|
|
15
|
+
export type GeneratedOutput = GeneratedOutputInput & {
|
|
16
|
+
/** Name of the plugin that registered the output. */
|
|
17
|
+
owner: string;
|
|
18
|
+
};
|
|
19
|
+
export type GeneratedOutputSink = {
|
|
20
|
+
emit(output: GeneratedOutputInput): void;
|
|
21
|
+
};
|
|
22
|
+
export declare function createUnavailableGeneratedOutputSink(): GeneratedOutputSink;
|
|
23
|
+
/**
|
|
24
|
+
* Normalizes a plugin-provided output path and rejects anything that could
|
|
25
|
+
* escape the output directory or collide with reserved namespaces. Rejecting
|
|
26
|
+
* (rather than silently rewriting) keeps `..` traversal from being laundered.
|
|
27
|
+
*/
|
|
28
|
+
export declare function normalizeGeneratedOutputPath(input: string): string;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { PluginOptionsValidator } from "./config_validation.js";
|
|
2
|
+
import type { Diagnostic } from "./diagnostic.js";
|
|
3
|
+
import type { PluginAsset, PluginClientEntry } from "./plugin_asset.js";
|
|
4
|
+
import type { PluginContentContext, PluginContentLocationAugmentContext, PluginContentLocationResolver, PluginContentRenderer, PluginContext, PluginGeneratedHtmlInspector, PluginGraphContext, PluginLifecycleContext, PluginManifestContext, PluginPostContext } from "./plugin_context.js";
|
|
5
|
+
import type { PluginEndpoint } from "./plugin_endpoint.js";
|
|
6
|
+
import type { HtmlPipeline, MarkdownPipeline, MarkdownPipelineContext, PipelinePlugin } from "./plugin_pipeline.js";
|
|
7
|
+
import type { PluginSeoExtension } from "./plugin_seo.js";
|
|
8
|
+
export type RiebeckitePlugin<TOptions = unknown> = {
|
|
9
|
+
name: string;
|
|
10
|
+
options?: TOptions;
|
|
11
|
+
order?: number;
|
|
12
|
+
enabled?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Capabilities this plugin exposes to other plugins. A capability must have
|
|
15
|
+
* exactly one enabled provider; duplicate providers fail resolution.
|
|
16
|
+
*/
|
|
17
|
+
provides?: string[];
|
|
18
|
+
/**
|
|
19
|
+
* Capabilities this plugin depends on. Resolution orders each provider
|
|
20
|
+
* before this plugin and fails with a diagnostic when none is available.
|
|
21
|
+
*/
|
|
22
|
+
requires?: string[];
|
|
23
|
+
/**
|
|
24
|
+
* Capabilities this plugin uses when available. A missing capability is
|
|
25
|
+
* ignored, while a present provider is still ordered before this plugin.
|
|
26
|
+
*/
|
|
27
|
+
optional?: string[];
|
|
28
|
+
cacheVersion?: string;
|
|
29
|
+
validateOptions?: PluginOptionsValidator<TOptions>;
|
|
30
|
+
remarkPlugins?: PipelinePlugin[];
|
|
31
|
+
rehypePlugins?: PipelinePlugin[];
|
|
32
|
+
setup?(context: PluginLifecycleContext): void | Promise<void>;
|
|
33
|
+
buildStart?(context: PluginLifecycleContext): void | Promise<void>;
|
|
34
|
+
buildEnd?(context: PluginManifestContext): void | Promise<void>;
|
|
35
|
+
dispose?(context: PluginLifecycleContext): void | Promise<void>;
|
|
36
|
+
onConfigResolved?(context: PluginContext): void | Promise<void>;
|
|
37
|
+
onContentLoaded?(context: PluginContentContext): void | Promise<void>;
|
|
38
|
+
resolveContentLocations?: PluginContentLocationResolver;
|
|
39
|
+
extendContentLocations?(context: PluginContentLocationAugmentContext): void | Promise<void>;
|
|
40
|
+
onPostParsed?(context: PluginPostContext): void | Promise<void>;
|
|
41
|
+
onPostProcessed?(context: PluginPostContext): void | Promise<void>;
|
|
42
|
+
onManifestCreated?(context: PluginManifestContext): void | Promise<void>;
|
|
43
|
+
onBuildStart?(context: PluginContext): void | Promise<void>;
|
|
44
|
+
onBuildEnd?(context: PluginManifestContext): void | Promise<void>;
|
|
45
|
+
extendMarkdownPipeline?(pipeline: MarkdownPipeline, context: MarkdownPipelineContext): void;
|
|
46
|
+
extendHtmlPipeline?(pipeline: HtmlPipeline): void;
|
|
47
|
+
addDiagnostics?(context: PluginContext): Diagnostic[] | Promise<Diagnostic[]>;
|
|
48
|
+
/**
|
|
49
|
+
* Inspects final HTML pages after the SSG stage. Integrations that finish HTML
|
|
50
|
+
* generation call this for every emitted `.html` file. Prefer `addDiagnostics`
|
|
51
|
+
* for article-body rules; use this when the rule needs the whole document.
|
|
52
|
+
*/
|
|
53
|
+
inspectGeneratedHtml?: PluginGeneratedHtmlInspector;
|
|
54
|
+
assets?: PluginAsset[];
|
|
55
|
+
clientEntries?: PluginClientEntry[];
|
|
56
|
+
endpoints?: PluginEndpoint[];
|
|
57
|
+
seo?: PluginSeoExtension;
|
|
58
|
+
extendContentGraph?(context: PluginGraphContext): void | Promise<void>;
|
|
59
|
+
renderers?: PluginContentRenderer[];
|
|
60
|
+
};
|
|
61
|
+
export type PluginInput = RiebeckitePlugin | false | null | undefined;
|
|
62
|
+
export type ResolvedPluginMetadata = {
|
|
63
|
+
readonly name: string;
|
|
64
|
+
readonly enabled: boolean;
|
|
65
|
+
readonly provides: readonly string[];
|
|
66
|
+
readonly requires: readonly string[];
|
|
67
|
+
readonly optional: readonly string[];
|
|
68
|
+
};
|
|
69
|
+
export declare function definePlugin<TOptions>(plugin: RiebeckitePlugin<TOptions>): RiebeckitePlugin<TOptions>;
|
|
70
|
+
export declare function resolvePlugins(plugins?: PluginInput[]): RiebeckitePlugin[];
|
|
71
|
+
export declare function getResolvedPluginMetadata(plugins: readonly RiebeckitePlugin[]): readonly ResolvedPluginMetadata[];
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type PluginAssetKind = "style" | "script";
|
|
2
|
+
export type PluginAsset = {
|
|
3
|
+
pluginName: string;
|
|
4
|
+
kind: PluginAssetKind;
|
|
5
|
+
moduleSpecifier: string;
|
|
6
|
+
};
|
|
7
|
+
export type PluginClientEntry = {
|
|
8
|
+
pluginName: string;
|
|
9
|
+
moduleSpecifier: string;
|
|
10
|
+
exportName?: string;
|
|
11
|
+
};
|
|
12
|
+
export declare function createStyleAsset(pluginName: string): PluginAsset;
|
|
13
|
+
export declare function createClientEntry(pluginName: string, exportName?: string): PluginClientEntry;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { ContentSource } from "../content/content_source.js";
|
|
2
|
+
import type { Logger, Tracer } from "../observability.js";
|
|
3
|
+
import type { PluginCache } from "../plugin/plugin_cache.js";
|
|
4
|
+
import type { ContentLocationInput, ContentManifest, ContentManifestEntry, ContentPublicLocation } from "./content_manifest.js";
|
|
5
|
+
import type { Diagnostic } from "./diagnostic.js";
|
|
6
|
+
import type { GeneratedOutputSink } from "./generated_output.js";
|
|
7
|
+
import type { PostContent } from "./post_content.js";
|
|
8
|
+
import type { ResolvedRiebeckiteConfig } from "./resolved_riebeckite_config.js";
|
|
9
|
+
export type PluginContext = {
|
|
10
|
+
config?: ResolvedRiebeckiteConfig;
|
|
11
|
+
contentIndex: Map<string, string>;
|
|
12
|
+
diagnostics: Diagnostic[];
|
|
13
|
+
cache: PluginCache;
|
|
14
|
+
/**
|
|
15
|
+
* Registers a file to be written to the build output directory. Available
|
|
16
|
+
* during build lifecycle hooks; the integration layer forwards each entry to
|
|
17
|
+
* the build tool.
|
|
18
|
+
*/
|
|
19
|
+
output: GeneratedOutputSink;
|
|
20
|
+
logger: Logger;
|
|
21
|
+
tracer: Tracer;
|
|
22
|
+
contentSource?: ContentSource;
|
|
23
|
+
};
|
|
24
|
+
export type PluginLifecycleContext = PluginContext;
|
|
25
|
+
export type PluginContentContext = PluginContext & {
|
|
26
|
+
slug: string;
|
|
27
|
+
markdown: string;
|
|
28
|
+
};
|
|
29
|
+
export type PluginPostContext = PluginContentContext & {
|
|
30
|
+
content: PostContent;
|
|
31
|
+
};
|
|
32
|
+
export type PluginManifestContext = PluginContext & {
|
|
33
|
+
manifest: ContentManifest;
|
|
34
|
+
};
|
|
35
|
+
export type PluginGraphContext = PluginContext & {
|
|
36
|
+
entries: ContentManifestEntry[];
|
|
37
|
+
};
|
|
38
|
+
export type PluginContentLocationContext = PluginContext & {
|
|
39
|
+
entries: readonly ContentLocationInput[];
|
|
40
|
+
};
|
|
41
|
+
export type PluginContentLocationResolver = (context: PluginContentLocationContext) => readonly ContentPublicLocation[] | Promise<readonly ContentPublicLocation[]>;
|
|
42
|
+
/**
|
|
43
|
+
* Context for augmenting already-resolved public locations.
|
|
44
|
+
*
|
|
45
|
+
* Runs after every `resolveContentLocations` resolver, so a plugin can add
|
|
46
|
+
* redirects or metadata without replacing (and therefore without needing to
|
|
47
|
+
* reproduce) the canonical permalink another plugin resolved.
|
|
48
|
+
*/
|
|
49
|
+
export type PluginContentLocationAugmentContext = PluginContext & {
|
|
50
|
+
entries: readonly ContentLocationInput[];
|
|
51
|
+
locations: Map<string, ContentPublicLocation>;
|
|
52
|
+
};
|
|
53
|
+
export type PluginRenderTarget = {
|
|
54
|
+
kind: string;
|
|
55
|
+
path: string;
|
|
56
|
+
raw: string;
|
|
57
|
+
label: string;
|
|
58
|
+
url: string;
|
|
59
|
+
embed: boolean;
|
|
60
|
+
};
|
|
61
|
+
export type PluginRenderContext = PluginContext & PluginRenderTarget;
|
|
62
|
+
export type PluginContentRenderer = {
|
|
63
|
+
name?: string;
|
|
64
|
+
render(context: PluginRenderContext): string | null | Promise<string | null>;
|
|
65
|
+
};
|
|
66
|
+
export type PluginRenderInput = {
|
|
67
|
+
kind: string;
|
|
68
|
+
path: string;
|
|
69
|
+
raw: string;
|
|
70
|
+
label: string;
|
|
71
|
+
url: string;
|
|
72
|
+
embed: boolean;
|
|
73
|
+
};
|
|
74
|
+
export type PluginGeneratedHtml = {
|
|
75
|
+
/** Output-relative path of the generated HTML file (e.g. "index.html"). */
|
|
76
|
+
path: string;
|
|
77
|
+
/** Final page HTML produced by the SSG build. */
|
|
78
|
+
html: string;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Inspects a fully rendered HTML page after the SSG stage. Use this instead of
|
|
82
|
+
* `addDiagnostics` when the rule needs the final document (head, layout,
|
|
83
|
+
* navigation) rather than the article body HTML only.
|
|
84
|
+
*/
|
|
85
|
+
export type PluginGeneratedHtmlInspector = (page: PluginGeneratedHtml) => readonly Diagnostic[];
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ContentManifest } from "./content_manifest.js";
|
|
2
|
+
import type { ResolvedRiebeckiteConfig } from "./resolved_riebeckite_config.js";
|
|
3
|
+
export type PluginEndpointMethod = "GET";
|
|
4
|
+
export type PluginEndpointContext = {
|
|
5
|
+
config: ResolvedRiebeckiteConfig;
|
|
6
|
+
manifest: ContentManifest;
|
|
7
|
+
};
|
|
8
|
+
export type PluginEndpointResponse = {
|
|
9
|
+
status?: number;
|
|
10
|
+
headers?: Record<string, string>;
|
|
11
|
+
body?: string;
|
|
12
|
+
json?: unknown;
|
|
13
|
+
};
|
|
14
|
+
export type PluginEndpoint = {
|
|
15
|
+
path: string;
|
|
16
|
+
method?: PluginEndpointMethod;
|
|
17
|
+
handler(context: PluginEndpointContext): PluginEndpointResponse | Promise<PluginEndpointResponse>;
|
|
18
|
+
};
|
|
19
|
+
export type PluginEndpointOptions = {
|
|
20
|
+
cacheControl?: string;
|
|
21
|
+
};
|
|
22
|
+
export declare function defineEndpoint(path: string, handler: PluginEndpoint["handler"], options?: PluginEndpointOptions): PluginEndpoint;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A document `<head>` element contributed by a plugin.
|
|
3
|
+
*
|
|
4
|
+
* A plugin provides these on a `ContentManifestEntry` (see
|
|
5
|
+
* `headTags`) and the Site shell decides whether and how to render them.
|
|
6
|
+
* Plugins still do not own the shell; they only describe tags.
|
|
7
|
+
*/
|
|
8
|
+
export type PluginHeadTag = {
|
|
9
|
+
tag: "meta";
|
|
10
|
+
attrs: Record<string, string>;
|
|
11
|
+
} | {
|
|
12
|
+
tag: "link";
|
|
13
|
+
attrs: Record<string, string>;
|
|
14
|
+
} | {
|
|
15
|
+
tag: "script";
|
|
16
|
+
attrs?: Record<string, string>;
|
|
17
|
+
children?: string;
|
|
18
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Plugin } from "unified";
|
|
2
|
+
import type { Node } from "unist";
|
|
3
|
+
import type { ContentSource } from "../content/content_source.js";
|
|
4
|
+
import type { PluginRenderInput } from "./plugin_context.js";
|
|
5
|
+
export type PipelinePlugin = Plugin<[unknown?], Node, Node>;
|
|
6
|
+
export type MarkdownPipeline = {
|
|
7
|
+
use(plugin: PipelinePlugin, options?: unknown): void;
|
|
8
|
+
};
|
|
9
|
+
export type HtmlPipeline = MarkdownPipeline;
|
|
10
|
+
export type MarkdownPipelineContext = {
|
|
11
|
+
contentIndex: Map<string, string>;
|
|
12
|
+
resolvePermalink: (slug: string) => string;
|
|
13
|
+
renderNoteEmbed?: (slug: string, fragment: MarkdownEmbedFragment | null) => Promise<string | null>;
|
|
14
|
+
renderContent?: (input: PluginRenderInput) => Promise<string | null>;
|
|
15
|
+
contentSource?: ContentSource;
|
|
16
|
+
};
|
|
17
|
+
export type MarkdownEmbedFragment = {
|
|
18
|
+
kind: "heading" | "block";
|
|
19
|
+
value: string;
|
|
20
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { ContentManifestEntry } from "./content_manifest.js";
|
|
2
|
+
import type { PostContent } from "./post_content.js";
|
|
3
|
+
import type { ResolvedRiebeckiteConfig } from "./resolved_riebeckite_config.js";
|
|
4
|
+
export type SeoMetadata = {
|
|
5
|
+
title: string;
|
|
6
|
+
description: string;
|
|
7
|
+
canonicalUrl: string;
|
|
8
|
+
imageUrl: string;
|
|
9
|
+
type: "website" | "article";
|
|
10
|
+
noindex: boolean;
|
|
11
|
+
publishedTime?: string;
|
|
12
|
+
modifiedTime?: string;
|
|
13
|
+
tags: string[];
|
|
14
|
+
readingTimeMinutes?: number;
|
|
15
|
+
jsonLd?: Record<string, unknown> | Record<string, unknown>[];
|
|
16
|
+
};
|
|
17
|
+
export type WebsiteSeoInput = {
|
|
18
|
+
title: string;
|
|
19
|
+
description?: string;
|
|
20
|
+
path: string;
|
|
21
|
+
kind?: "index" | "tag" | "article" | "website";
|
|
22
|
+
};
|
|
23
|
+
export type RenderableFeedEntry = ContentManifestEntry & {
|
|
24
|
+
html?: string;
|
|
25
|
+
};
|
|
26
|
+
export type PluginSeoExtension = {
|
|
27
|
+
buildArticleSeo(config: ResolvedRiebeckiteConfig, permalink: string, post: PostContent): SeoMetadata;
|
|
28
|
+
buildWebsiteSeo(config: ResolvedRiebeckiteConfig, input: WebsiteSeoInput): SeoMetadata;
|
|
29
|
+
buildAbsoluteUrl(config: ResolvedRiebeckiteConfig, pathOrUrl: string): string;
|
|
30
|
+
buildPostUrl(config: ResolvedRiebeckiteConfig, permalink: string): string;
|
|
31
|
+
getDescription(post: Pick<PostContent, "frontmatter" | "html">): string;
|
|
32
|
+
getEntryPublishedTime(entry: ContentManifestEntry): string | null;
|
|
33
|
+
getEntryUpdatedTime(entry: ContentManifestEntry): string | null;
|
|
34
|
+
getHtmlLanguage(config: ResolvedRiebeckiteConfig): string;
|
|
35
|
+
renderSitemap(config: ResolvedRiebeckiteConfig, entries: ContentManifestEntry[]): string;
|
|
36
|
+
renderRobots(config: ResolvedRiebeckiteConfig): string;
|
|
37
|
+
renderRssFeed(config: ResolvedRiebeckiteConfig, entries: RenderableFeedEntry[]): string;
|
|
38
|
+
renderAtomFeed(config: ResolvedRiebeckiteConfig, entries: RenderableFeedEntry[]): string;
|
|
39
|
+
renderJsonFeed(config: ResolvedRiebeckiteConfig, entries: RenderableFeedEntry[]): string;
|
|
40
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type PostContent = {
|
|
2
|
+
frontmatter: PostFrontmatter;
|
|
3
|
+
html: string;
|
|
4
|
+
};
|
|
5
|
+
export type PostFrontmatter = Record<string, unknown> & {
|
|
6
|
+
title?: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
date?: string | Date;
|
|
9
|
+
created?: string | Date;
|
|
10
|
+
published?: string | Date;
|
|
11
|
+
updated?: string | Date;
|
|
12
|
+
publish?: boolean;
|
|
13
|
+
private?: boolean;
|
|
14
|
+
draft?: boolean;
|
|
15
|
+
tags?: string[];
|
|
16
|
+
image?: string;
|
|
17
|
+
ogImage?: string;
|
|
18
|
+
canonical?: string;
|
|
19
|
+
noindex?: boolean;
|
|
20
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type PublishStrategy = "explicit" | "selective";
|
|
2
|
+
/**
|
|
3
|
+
* The frontmatter fields that decide publication. Notes, diagnostics, and
|
|
4
|
+
* build tooling all share this shape so the publish decision is applied
|
|
5
|
+
* consistently.
|
|
6
|
+
*/
|
|
7
|
+
export type PublishFrontmatter = {
|
|
8
|
+
readonly publish?: unknown;
|
|
9
|
+
readonly private?: unknown;
|
|
10
|
+
readonly draft?: unknown;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Single source of truth for the publish decision.
|
|
14
|
+
*
|
|
15
|
+
* - `explicit`: only notes opted in with `publish: true` are public.
|
|
16
|
+
* - `selective`: notes are public unless opted out with `private: true` or
|
|
17
|
+
* `draft: true`.
|
|
18
|
+
*/
|
|
19
|
+
export declare function isPublishable(strategy: PublishStrategy, frontmatter: PublishFrontmatter | undefined): boolean;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ContentSource } from "../content/content_source.js";
|
|
2
|
+
import type { RiebeckitePlugin } from "./plugin.js";
|
|
3
|
+
import type { PublishStrategy } from "./publish_strategy.js";
|
|
4
|
+
import type { SiteConfig } from "./site_config.js";
|
|
5
|
+
import type { ThemeConfig, ThemeStyle } from "./theme_config.js";
|
|
6
|
+
export type ResolvedRiebeckiteConfig = {
|
|
7
|
+
site: Required<SiteConfig>;
|
|
8
|
+
content: {
|
|
9
|
+
directory: string;
|
|
10
|
+
source?: ContentSource;
|
|
11
|
+
exclude: string[];
|
|
12
|
+
filters: {
|
|
13
|
+
publishStrategy: PublishStrategy;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
markdown: {
|
|
17
|
+
syntaxHighlight: {
|
|
18
|
+
theme: string;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
theme: Required<Omit<ThemeConfig, "tokens">> & {
|
|
22
|
+
tokens: NonNullable<ThemeConfig["tokens"]>;
|
|
23
|
+
styles: ThemeStyle[];
|
|
24
|
+
};
|
|
25
|
+
plugins: RiebeckitePlugin[];
|
|
26
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ContentSource } from "../content/content_source.js";
|
|
2
|
+
import type { PluginInput } from "./plugin.js";
|
|
3
|
+
import type { PublishStrategy } from "./publish_strategy.js";
|
|
4
|
+
import type { SiteConfig } from "./site_config.js";
|
|
5
|
+
import type { ThemeInput } from "./theme_config.js";
|
|
6
|
+
export interface RiebeckiteConfig {
|
|
7
|
+
site: SiteConfig;
|
|
8
|
+
content?: {
|
|
9
|
+
directory?: string;
|
|
10
|
+
source?: ContentSource;
|
|
11
|
+
exclude?: string[];
|
|
12
|
+
filters?: {
|
|
13
|
+
publishStrategy?: PublishStrategy;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
markdown?: {
|
|
17
|
+
syntaxHighlight?: {
|
|
18
|
+
theme?: string;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
theme?: ThemeInput;
|
|
22
|
+
plugins?: PluginInput[];
|
|
23
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface SiteConfig {
|
|
2
|
+
title: string;
|
|
3
|
+
description?: string;
|
|
4
|
+
author?: string;
|
|
5
|
+
baseUrl?: string;
|
|
6
|
+
locale?: string;
|
|
7
|
+
twitterSite?: string;
|
|
8
|
+
defaultOgImage?: string;
|
|
9
|
+
feed?: {
|
|
10
|
+
title?: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
language?: string;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export type ThemeColorMode = "light" | "dark" | "system";
|
|
2
|
+
export type ThemeTypographyPreset = "system" | "serif" | "sans";
|
|
3
|
+
export type ThemeArticleLayoutPreset = "article" | "sidebar" | "full-width";
|
|
4
|
+
export type ThemeDesignTokens = {
|
|
5
|
+
color?: {
|
|
6
|
+
paper?: string;
|
|
7
|
+
ink?: string;
|
|
8
|
+
muted?: string;
|
|
9
|
+
accent?: string;
|
|
10
|
+
border?: string;
|
|
11
|
+
borderStrong?: string;
|
|
12
|
+
surface?: string;
|
|
13
|
+
surfaceHover?: string;
|
|
14
|
+
overlay?: string;
|
|
15
|
+
danger?: string;
|
|
16
|
+
success?: string;
|
|
17
|
+
codeBackground?: string;
|
|
18
|
+
};
|
|
19
|
+
typography?: {
|
|
20
|
+
bodyFont?: string;
|
|
21
|
+
headingFont?: string;
|
|
22
|
+
monoFont?: string;
|
|
23
|
+
};
|
|
24
|
+
layout?: {
|
|
25
|
+
pageMaxWidth?: string;
|
|
26
|
+
articleMaxWidth?: string;
|
|
27
|
+
sidebarWidth?: string;
|
|
28
|
+
contentGap?: string;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
export type ThemeStyle = {
|
|
32
|
+
moduleSpecifier: string;
|
|
33
|
+
};
|
|
34
|
+
export type ThemeAttributes = Record<`data-${string}`, string | undefined>;
|
|
35
|
+
export type ThemeConfig = {
|
|
36
|
+
name?: string;
|
|
37
|
+
colorMode?: ThemeColorMode;
|
|
38
|
+
typography?: ThemeTypographyPreset;
|
|
39
|
+
articleLayout?: ThemeArticleLayoutPreset;
|
|
40
|
+
tokens?: ThemeDesignTokens;
|
|
41
|
+
attributes?: ThemeAttributes;
|
|
42
|
+
userCss?: string[];
|
|
43
|
+
};
|
|
44
|
+
export type RiebeckiteTheme<TOptions = unknown> = {
|
|
45
|
+
name: string;
|
|
46
|
+
options?: TOptions;
|
|
47
|
+
styles?: ThemeStyle[];
|
|
48
|
+
config?: Omit<ThemeConfig, "name" | "userCss"> & {
|
|
49
|
+
userCss?: string[];
|
|
50
|
+
};
|
|
51
|
+
attributes?: ThemeAttributes;
|
|
52
|
+
};
|
|
53
|
+
export type ThemeInput = ThemeConfig | RiebeckiteTheme;
|
|
54
|
+
export declare function defineTheme<TOptions>(theme: RiebeckiteTheme<TOptions>): RiebeckiteTheme<TOptions>;
|
|
55
|
+
export declare function isRiebeckiteTheme(theme: ThemeInput): theme is RiebeckiteTheme;
|