@riebeckite/core 0.0.12 → 0.0.14
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 +94 -94
- package/README_ja.md +75 -75
- package/dist/client.d.ts +2 -0
- package/dist/client.js +43 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +249 -8
- package/dist/src/config_deprecations.d.ts +8 -0
- package/dist/src/content/content_manager.d.ts +5 -0
- package/dist/src/deprecation.d.ts +14 -0
- package/dist/src/plugin/plugin_runtime.d.ts +3 -0
- package/dist/src/types/content_manifest.d.ts +1 -0
- package/dist/src/types/plugin.d.ts +3 -0
- package/dist/src/types/plugin_page.d.ts +36 -0
- package/package.json +8 -2
package/README.md
CHANGED
|
@@ -1,94 +1,94 @@
|
|
|
1
|
-
# @riebeckite/core
|
|
2
|
-
|
|
3
|
-
The portable framework contract for Riebeckite: configuration, content sources,
|
|
4
|
-
the content manager, the Markdown/HTML pipeline, plugin and theme contracts,
|
|
5
|
-
diagnostics, and observability.
|
|
6
|
-
|
|
7
|
-
[日本語](./README_ja.md)
|
|
8
|
-
|
|
9
|
-
## Overview
|
|
10
|
-
|
|
11
|
-
`@riebeckite/core` owns content loading and interpretation and the contracts
|
|
12
|
-
that extensions build against. It is intentionally free of HonoX, Vite, and any
|
|
13
|
-
specific plugin, theme, or application: those depend on Core, never the reverse.
|
|
14
|
-
|
|
15
|
-
A site configures Core through `defineConfig`, and a framework integration such
|
|
16
|
-
as [`@riebeckite/honox`](../integrations/honox/README.md) drives the build.
|
|
17
|
-
Plugins and themes are plain objects created by `definePlugin` and `defineTheme`.
|
|
18
|
-
|
|
19
|
-
## Installation
|
|
20
|
-
|
|
21
|
-
```sh
|
|
22
|
-
pnpm add @riebeckite/core
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
Core is also installed transitively by `@riebeckite/honox` and by the
|
|
26
|
-
`@riebeckite/plugin-*` and `@riebeckite/theme-*` packages.
|
|
27
|
-
|
|
28
|
-
## Usage
|
|
29
|
-
|
|
30
|
-
```ts
|
|
31
|
-
import { defineConfig } from "@riebeckite/core";
|
|
32
|
-
|
|
33
|
-
export default defineConfig({
|
|
34
|
-
site: { title: "My notes", baseUrl: "https://example.com" },
|
|
35
|
-
content: { directory: "../../content" },
|
|
36
|
-
});
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
The content directory is resolved relative to the application root. See
|
|
40
|
-
[Configuration](../../docs/en/configuration.md) for the full field list and the
|
|
41
|
-
`projectRoot` / `appRoot` / `configRoot` / `contentRoot` resolution rules.
|
|
42
|
-
|
|
43
|
-
## Public API
|
|
44
|
-
|
|
45
|
-
### Configuration
|
|
46
|
-
|
|
47
|
-
- `defineConfig`, `resolveConfig`, `resolveConfigModule`, `isPublished`,
|
|
48
|
-
`isExcluded`
|
|
49
|
-
- `ConfigValidationError`
|
|
50
|
-
|
|
51
|
-
### Content
|
|
52
|
-
|
|
53
|
-
- `ContentManager` — interpretation, manifest, graph, plugin orchestration, and
|
|
54
|
-
public-location resolution
|
|
55
|
-
- `ContentSource`, `FileSystemContentSource`, `readContentSourceEntry`,
|
|
56
|
-
`getContentSourceEntry`
|
|
57
|
-
- `queryContentEntries` with the `ContentQuery*` filter and sort types
|
|
58
|
-
- `createContentGraph`, `readOnlyContentGraph`, `buildGraphEdges`,
|
|
59
|
-
`layoutRadialGraph`
|
|
60
|
-
- `resolveDefaultContentLocation`, `attachmentUrl`, and the content path and
|
|
61
|
-
extension helpers
|
|
62
|
-
- `readContentBuildStateStatus`, `resolveContentBuildStatePath`
|
|
63
|
-
|
|
64
|
-
### Pipeline
|
|
65
|
-
|
|
66
|
-
- `Pipeline`, `PipelineOptions`
|
|
67
|
-
|
|
68
|
-
### Plugins
|
|
69
|
-
|
|
70
|
-
- `definePlugin`, `resolvePlugins`, `getResolvedPluginMetadata`,
|
|
71
|
-
`PluginDependencyError`
|
|
72
|
-
- `defineEndpoint`, `createClientEntry`, `createStyleAsset`
|
|
73
|
-
- Plugin context, asset, endpoint, diagnostic, SEO, and pipeline types under
|
|
74
|
-
`Plugin*`
|
|
75
|
-
|
|
76
|
-
### Themes and contracts
|
|
77
|
-
|
|
78
|
-
- `defineTheme` and the `Theme*` types
|
|
79
|
-
- `RiebeckiteConfig`, `ResolvedRiebeckiteConfig`, `SiteConfig`,
|
|
80
|
-
`PostContent`, `PostFrontmatter`, `PublishStrategy`
|
|
81
|
-
|
|
82
|
-
### Utilities and observability
|
|
83
|
-
|
|
84
|
-
- `uniqueStrings`, `escapeHtml`, `escapeHtmlAttribute`, `normalizeTag`,
|
|
85
|
-
`calculateReadingTime`, `stripHtml`
|
|
86
|
-
- `ConsoleLogger`, `NoopLogger`, `NoopTracer`, `SinkTracer`,
|
|
87
|
-
`CompositeTraceSink`
|
|
88
|
-
|
|
89
|
-
## See also
|
|
90
|
-
|
|
91
|
-
- [Framework Reference](../../docs/en/
|
|
92
|
-
- [Content System](../../docs/en/content-system.md)
|
|
93
|
-
- [Plugin System](../../docs/en/plugin-
|
|
94
|
-
- [Architecture](../../docs/en/architecture.md)
|
|
1
|
+
# @riebeckite/core
|
|
2
|
+
|
|
3
|
+
The portable framework contract for Riebeckite: configuration, content sources,
|
|
4
|
+
the content manager, the Markdown/HTML pipeline, plugin and theme contracts,
|
|
5
|
+
diagnostics, and observability.
|
|
6
|
+
|
|
7
|
+
[日本語](./README_ja.md)
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
`@riebeckite/core` owns content loading and interpretation and the contracts
|
|
12
|
+
that extensions build against. It is intentionally free of HonoX, Vite, and any
|
|
13
|
+
specific plugin, theme, or application: those depend on Core, never the reverse.
|
|
14
|
+
|
|
15
|
+
A site configures Core through `defineConfig`, and a framework integration such
|
|
16
|
+
as [`@riebeckite/honox`](../integrations/honox/README.md) drives the build.
|
|
17
|
+
Plugins and themes are plain objects created by `definePlugin` and `defineTheme`.
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
pnpm add @riebeckite/core
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Core is also installed transitively by `@riebeckite/honox` and by the
|
|
26
|
+
`@riebeckite/plugin-*` and `@riebeckite/theme-*` packages.
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import { defineConfig } from "@riebeckite/core";
|
|
32
|
+
|
|
33
|
+
export default defineConfig({
|
|
34
|
+
site: { title: "My notes", baseUrl: "https://example.com" },
|
|
35
|
+
content: { directory: "../../content" },
|
|
36
|
+
});
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The content directory is resolved relative to the application root. See
|
|
40
|
+
[Configuration](../../docs/en/reference/configuration.md) for the full field list and the
|
|
41
|
+
`projectRoot` / `appRoot` / `configRoot` / `contentRoot` resolution rules.
|
|
42
|
+
|
|
43
|
+
## Public API
|
|
44
|
+
|
|
45
|
+
### Configuration
|
|
46
|
+
|
|
47
|
+
- `defineConfig`, `resolveConfig`, `resolveConfigModule`, `isPublished`,
|
|
48
|
+
`isExcluded`
|
|
49
|
+
- `ConfigValidationError`
|
|
50
|
+
|
|
51
|
+
### Content
|
|
52
|
+
|
|
53
|
+
- `ContentManager` — interpretation, manifest, graph, plugin orchestration, and
|
|
54
|
+
public-location resolution
|
|
55
|
+
- `ContentSource`, `FileSystemContentSource`, `readContentSourceEntry`,
|
|
56
|
+
`getContentSourceEntry`
|
|
57
|
+
- `queryContentEntries` with the `ContentQuery*` filter and sort types
|
|
58
|
+
- `createContentGraph`, `readOnlyContentGraph`, `buildGraphEdges`,
|
|
59
|
+
`layoutRadialGraph`
|
|
60
|
+
- `resolveDefaultContentLocation`, `attachmentUrl`, and the content path and
|
|
61
|
+
extension helpers
|
|
62
|
+
- `readContentBuildStateStatus`, `resolveContentBuildStatePath`
|
|
63
|
+
|
|
64
|
+
### Pipeline
|
|
65
|
+
|
|
66
|
+
- `Pipeline`, `PipelineOptions`
|
|
67
|
+
|
|
68
|
+
### Plugins
|
|
69
|
+
|
|
70
|
+
- `definePlugin`, `resolvePlugins`, `getResolvedPluginMetadata`,
|
|
71
|
+
`PluginDependencyError`
|
|
72
|
+
- `defineEndpoint`, `createClientEntry`, `createStyleAsset`
|
|
73
|
+
- Plugin context, asset, endpoint, diagnostic, SEO, and pipeline types under
|
|
74
|
+
`Plugin*`
|
|
75
|
+
|
|
76
|
+
### Themes and contracts
|
|
77
|
+
|
|
78
|
+
- `defineTheme` and the `Theme*` types
|
|
79
|
+
- `RiebeckiteConfig`, `ResolvedRiebeckiteConfig`, `SiteConfig`,
|
|
80
|
+
`PostContent`, `PostFrontmatter`, `PublishStrategy`
|
|
81
|
+
|
|
82
|
+
### Utilities and observability
|
|
83
|
+
|
|
84
|
+
- `uniqueStrings`, `escapeHtml`, `escapeHtmlAttribute`, `normalizeTag`,
|
|
85
|
+
`calculateReadingTime`, `stripHtml`
|
|
86
|
+
- `ConsoleLogger`, `NoopLogger`, `NoopTracer`, `SinkTracer`,
|
|
87
|
+
`CompositeTraceSink`
|
|
88
|
+
|
|
89
|
+
## See also
|
|
90
|
+
|
|
91
|
+
- [Framework Reference](../../docs/en/reference/README.md)
|
|
92
|
+
- [Content System](../../docs/en/framework/content-system.md)
|
|
93
|
+
- [Plugin System](../../docs/en/reference/plugin-api.md) / [Theme System](../../docs/en/reference/theme-api.md)
|
|
94
|
+
- [Architecture](../../docs/en/framework/architecture.md)
|
package/README_ja.md
CHANGED
|
@@ -1,75 +1,75 @@
|
|
|
1
|
-
# @riebeckite/core
|
|
2
|
-
|
|
3
|
-
Riebeckite の移植可能なフレームワーク契約です。設定、コンテンツソース、ContentManager、Markdown/HTML パイプライン、Plugin と Theme の契約、診断、可観測性を担います。
|
|
4
|
-
|
|
5
|
-
[English](./README.md)
|
|
6
|
-
|
|
7
|
-
## 概要
|
|
8
|
-
|
|
9
|
-
`@riebeckite/core` はコンテンツの読み込みと解釈、および拡張が依存する契約を所有します。HonoX や Vite、特定の Plugin・Theme・アプリケーションには依存しません。依存の向きは常に Core へ向かい、その逆には向かいません。
|
|
10
|
-
|
|
11
|
-
サイトは `defineConfig` で Core を設定し、[`@riebeckite/honox`](../integrations/honox/README_ja.md) のような integration がビルドを実行します。Plugin と Theme は `definePlugin`、`defineTheme` が返すただのオブジェクトです。
|
|
12
|
-
|
|
13
|
-
## インストール
|
|
14
|
-
|
|
15
|
-
```sh
|
|
16
|
-
pnpm add @riebeckite/core
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
`@riebeckite/honox`、`@riebeckite/plugin-*`、`@riebeckite/theme-*` をインストールすると、依存として一緒に入ります。
|
|
20
|
-
|
|
21
|
-
## 使い方
|
|
22
|
-
|
|
23
|
-
```ts
|
|
24
|
-
import { defineConfig } from "@riebeckite/core";
|
|
25
|
-
|
|
26
|
-
export default defineConfig({
|
|
27
|
-
site: { title: "My notes", baseUrl: "https://example.com" },
|
|
28
|
-
content: { directory: "../../content" },
|
|
29
|
-
});
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
コンテンツディレクトリはアプリケーションルート基準で解決します。設定項目の全体と `projectRoot` / `appRoot` / `configRoot` / `contentRoot` の解決規則は [Configuration](../../docs/ja/configuration.md) を参照してください。
|
|
33
|
-
|
|
34
|
-
## 公開 API
|
|
35
|
-
|
|
36
|
-
### 設定
|
|
37
|
-
|
|
38
|
-
- `defineConfig`、`resolveConfig`、`resolveConfigModule`、`isPublished`、`isExcluded`
|
|
39
|
-
- `ConfigValidationError`
|
|
40
|
-
|
|
41
|
-
### コンテンツ
|
|
42
|
-
|
|
43
|
-
- `ContentManager` — 解釈、マニフェスト、グラフ、Plugin の実行、公開 URL の解決
|
|
44
|
-
- `ContentSource`、`FileSystemContentSource`、`readContentSourceEntry`、`getContentSourceEntry`
|
|
45
|
-
- `queryContentEntries` と `ContentQuery*` のフィルタ・ソート型
|
|
46
|
-
- `createContentGraph`、`readOnlyContentGraph`、`buildGraphEdges`、`layoutRadialGraph`
|
|
47
|
-
- `resolveDefaultContentLocation`、`attachmentUrl`、コンテンツパスと拡張子のヘルパー
|
|
48
|
-
- `readContentBuildStateStatus`、`resolveContentBuildStatePath`
|
|
49
|
-
|
|
50
|
-
### パイプライン
|
|
51
|
-
|
|
52
|
-
- `Pipeline`、`PipelineOptions`
|
|
53
|
-
|
|
54
|
-
### Plugin
|
|
55
|
-
|
|
56
|
-
- `definePlugin`、`resolvePlugins`、`getResolvedPluginMetadata`、`PluginDependencyError`
|
|
57
|
-
- `defineEndpoint`、`createClientEntry`、`createStyleAsset`
|
|
58
|
-
- `Plugin*` のコンテキスト、アセット、エンドポイント、診断、SEO、パイプラインの型
|
|
59
|
-
|
|
60
|
-
### Theme と契約
|
|
61
|
-
|
|
62
|
-
- `defineTheme` と `Theme*` の型
|
|
63
|
-
- `RiebeckiteConfig`、`ResolvedRiebeckiteConfig`、`SiteConfig`、`PostContent`、`PostFrontmatter`、`PublishStrategy`
|
|
64
|
-
|
|
65
|
-
### ユーティリティと可観測性
|
|
66
|
-
|
|
67
|
-
- `uniqueStrings`、`escapeHtml`、`escapeHtmlAttribute`、`normalizeTag`、`calculateReadingTime`、`stripHtml`
|
|
68
|
-
- `ConsoleLogger`、`NoopLogger`、`NoopTracer`、`SinkTracer`、`CompositeTraceSink`
|
|
69
|
-
|
|
70
|
-
## 関連資料
|
|
71
|
-
|
|
72
|
-
- [Framework Reference](../../docs/ja/
|
|
73
|
-
- [Content System](../../docs/ja/content-system.md)
|
|
74
|
-
- [Plugin System](../../docs/ja/plugin-
|
|
75
|
-
- [Architecture](../../docs/ja/architecture.md)
|
|
1
|
+
# @riebeckite/core
|
|
2
|
+
|
|
3
|
+
Riebeckite の移植可能なフレームワーク契約です。設定、コンテンツソース、ContentManager、Markdown/HTML パイプライン、Plugin と Theme の契約、診断、可観測性を担います。
|
|
4
|
+
|
|
5
|
+
[English](./README.md)
|
|
6
|
+
|
|
7
|
+
## 概要
|
|
8
|
+
|
|
9
|
+
`@riebeckite/core` はコンテンツの読み込みと解釈、および拡張が依存する契約を所有します。HonoX や Vite、特定の Plugin・Theme・アプリケーションには依存しません。依存の向きは常に Core へ向かい、その逆には向かいません。
|
|
10
|
+
|
|
11
|
+
サイトは `defineConfig` で Core を設定し、[`@riebeckite/honox`](../integrations/honox/README_ja.md) のような integration がビルドを実行します。Plugin と Theme は `definePlugin`、`defineTheme` が返すただのオブジェクトです。
|
|
12
|
+
|
|
13
|
+
## インストール
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
pnpm add @riebeckite/core
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
`@riebeckite/honox`、`@riebeckite/plugin-*`、`@riebeckite/theme-*` をインストールすると、依存として一緒に入ります。
|
|
20
|
+
|
|
21
|
+
## 使い方
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import { defineConfig } from "@riebeckite/core";
|
|
25
|
+
|
|
26
|
+
export default defineConfig({
|
|
27
|
+
site: { title: "My notes", baseUrl: "https://example.com" },
|
|
28
|
+
content: { directory: "../../content" },
|
|
29
|
+
});
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
コンテンツディレクトリはアプリケーションルート基準で解決します。設定項目の全体と `projectRoot` / `appRoot` / `configRoot` / `contentRoot` の解決規則は [Configuration](../../docs/ja/reference/configuration.md) を参照してください。
|
|
33
|
+
|
|
34
|
+
## 公開 API
|
|
35
|
+
|
|
36
|
+
### 設定
|
|
37
|
+
|
|
38
|
+
- `defineConfig`、`resolveConfig`、`resolveConfigModule`、`isPublished`、`isExcluded`
|
|
39
|
+
- `ConfigValidationError`
|
|
40
|
+
|
|
41
|
+
### コンテンツ
|
|
42
|
+
|
|
43
|
+
- `ContentManager` — 解釈、マニフェスト、グラフ、Plugin の実行、公開 URL の解決
|
|
44
|
+
- `ContentSource`、`FileSystemContentSource`、`readContentSourceEntry`、`getContentSourceEntry`
|
|
45
|
+
- `queryContentEntries` と `ContentQuery*` のフィルタ・ソート型
|
|
46
|
+
- `createContentGraph`、`readOnlyContentGraph`、`buildGraphEdges`、`layoutRadialGraph`
|
|
47
|
+
- `resolveDefaultContentLocation`、`attachmentUrl`、コンテンツパスと拡張子のヘルパー
|
|
48
|
+
- `readContentBuildStateStatus`、`resolveContentBuildStatePath`
|
|
49
|
+
|
|
50
|
+
### パイプライン
|
|
51
|
+
|
|
52
|
+
- `Pipeline`、`PipelineOptions`
|
|
53
|
+
|
|
54
|
+
### Plugin
|
|
55
|
+
|
|
56
|
+
- `definePlugin`、`resolvePlugins`、`getResolvedPluginMetadata`、`PluginDependencyError`
|
|
57
|
+
- `defineEndpoint`、`createClientEntry`、`createStyleAsset`
|
|
58
|
+
- `Plugin*` のコンテキスト、アセット、エンドポイント、診断、SEO、パイプラインの型
|
|
59
|
+
|
|
60
|
+
### Theme と契約
|
|
61
|
+
|
|
62
|
+
- `defineTheme` と `Theme*` の型
|
|
63
|
+
- `RiebeckiteConfig`、`ResolvedRiebeckiteConfig`、`SiteConfig`、`PostContent`、`PostFrontmatter`、`PublishStrategy`
|
|
64
|
+
|
|
65
|
+
### ユーティリティと可観測性
|
|
66
|
+
|
|
67
|
+
- `uniqueStrings`、`escapeHtml`、`escapeHtmlAttribute`、`normalizeTag`、`calculateReadingTime`、`stripHtml`
|
|
68
|
+
- `ConsoleLogger`、`NoopLogger`、`NoopTracer`、`SinkTracer`、`CompositeTraceSink`
|
|
69
|
+
|
|
70
|
+
## 関連資料
|
|
71
|
+
|
|
72
|
+
- [Framework Reference](../../docs/ja/reference/README.md)
|
|
73
|
+
- [Content System](../../docs/ja/framework/content-system.md)
|
|
74
|
+
- [Plugin System](../../docs/ja/reference/plugin-api.md) / [Theme System](../../docs/ja/reference/theme-api.md)
|
|
75
|
+
- [Architecture](../../docs/ja/framework/architecture.md)
|
package/dist/client.d.ts
ADDED
package/dist/client.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// src/content/graph_layout.ts
|
|
2
|
+
function buildGraphEdges(nodes, visibleSlugs = new Set(nodes.map((node) => node.slug))) {
|
|
3
|
+
const edges = /* @__PURE__ */ new Map();
|
|
4
|
+
for (const node of nodes) {
|
|
5
|
+
for (const target of node.outgoing) {
|
|
6
|
+
if (!visibleSlugs.has(node.slug) || !visibleSlugs.has(target)) continue;
|
|
7
|
+
const key = `${node.slug}\0${target}`;
|
|
8
|
+
edges.set(key, { source: node.slug, target });
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return Array.from(edges.values());
|
|
12
|
+
}
|
|
13
|
+
function layoutRadialGraph(nodes, options) {
|
|
14
|
+
const layout = /* @__PURE__ */ new Map();
|
|
15
|
+
const centerX = options.width / 2;
|
|
16
|
+
const centerY = options.height / 2;
|
|
17
|
+
const radius = Math.min(options.width, options.height) * (options.radiusRatio ?? 0.36);
|
|
18
|
+
const minNodeRadius = options.minNodeRadius ?? 8;
|
|
19
|
+
const maxNodeRadius = options.maxNodeRadius ?? 14;
|
|
20
|
+
const selectedIndex = Math.max(
|
|
21
|
+
nodes.findIndex((node) => node.slug === options.centerSlug),
|
|
22
|
+
0
|
|
23
|
+
);
|
|
24
|
+
nodes.forEach((node, index) => {
|
|
25
|
+
const shiftedIndex = (index - selectedIndex + nodes.length) % nodes.length;
|
|
26
|
+
const angle = shiftedIndex / Math.max(nodes.length, 1) * Math.PI * 2;
|
|
27
|
+
const linkCount = node.outgoing.length + node.backlinks.length;
|
|
28
|
+
const isCenter = node.slug === options.centerSlug;
|
|
29
|
+
layout.set(node.slug, {
|
|
30
|
+
x: isCenter ? centerX : centerX + Math.cos(angle) * radius,
|
|
31
|
+
y: isCenter ? centerY : centerY + Math.sin(angle) * radius,
|
|
32
|
+
radius: clamp(7 + linkCount, minNodeRadius, maxNodeRadius)
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
return layout;
|
|
36
|
+
}
|
|
37
|
+
function clamp(value, min, max) {
|
|
38
|
+
return Math.min(Math.max(value, min), max);
|
|
39
|
+
}
|
|
40
|
+
export {
|
|
41
|
+
buildGraphEdges,
|
|
42
|
+
layoutRadialGraph
|
|
43
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { defineConfig, isExcluded, isPublished, resolveConfig, resolveConfigModule, } from "./src/config.js";
|
|
2
|
+
export { type ConfigDeprecationNotice, collectConfigDeprecationDiagnostics, } from "./src/config_deprecations.js";
|
|
2
3
|
export { ConfigValidationError } from "./src/config_validation.js";
|
|
3
4
|
export { ATTACHMENTS_BASE_PATH, attachmentUrl, getExtension, isAttachmentPath, isImagePath, isMarkdownPath, normalizeContentPath, } from "./src/content/attachment.js";
|
|
4
5
|
export type { ContentBuildState, FingerprintedContentEntry, } from "./src/content/content_build_state.js";
|
|
@@ -23,6 +24,7 @@ export type { GraphEdge, GraphLayoutNode, LinkableGraphNode, RadialGraphLayoutOp
|
|
|
23
24
|
export { buildGraphEdges, layoutRadialGraph, } from "./src/content/graph_layout.js";
|
|
24
25
|
export { IMAGE_EXTENSIONS } from "./src/content/image_extensions.js";
|
|
25
26
|
export { readOnlyContentGraph } from "./src/content/read_only_content_graph.js";
|
|
27
|
+
export { createDeprecationDiagnostic, type DeprecationKind, type DeprecationNotice, formatDeprecationMessage, } from "./src/deprecation.js";
|
|
26
28
|
export type { LogContext, Logger, LogLevel, Observability, ObservabilityValue, TraceAttributes, TraceEvent, Tracer, TraceSink, TraceSpan, } from "./src/observability.js";
|
|
27
29
|
export { CompositeTraceSink, ConsoleLogger, NoopLogger, NoopTracer, SinkTracer, } from "./src/observability.js";
|
|
28
30
|
export type { PipelineOptions } from "./src/pipeline.js";
|
|
@@ -47,6 +49,7 @@ export type { PluginDiagnostic, PluginDiagnosticLevel, } from "./src/types/plugi
|
|
|
47
49
|
export type { PluginEndpoint, PluginEndpointContext, PluginEndpointMethod, PluginEndpointOptions, PluginEndpointRequest, PluginEndpointResponse, } from "./src/types/plugin_endpoint.js";
|
|
48
50
|
export { defineEndpoint } from "./src/types/plugin_endpoint.js";
|
|
49
51
|
export type { PluginHeadTag } from "./src/types/plugin_head.js";
|
|
52
|
+
export type { PluginPage, PluginPageContext, PluginPageType, ResolvedPluginPage, } from "./src/types/plugin_page.js";
|
|
50
53
|
export type { HtmlPipeline, MarkdownEmbedFragment, MarkdownExecutionContext, MarkdownPipeline, MarkdownPipelineContext, PipelinePlugin, } from "./src/types/plugin_pipeline.js";
|
|
51
54
|
export type { PluginSeoExtension, RenderableFeedEntry, SeoMetadata, WebsiteSeoInput, } from "./src/types/plugin_seo.js";
|
|
52
55
|
export type { PostContent, PostFrontmatter } from "./src/types/post_content.js";
|
package/dist/index.js
CHANGED
|
@@ -693,6 +693,46 @@ function globToRegExp(glob) {
|
|
|
693
693
|
return new RegExp(`^${re}$`);
|
|
694
694
|
}
|
|
695
695
|
|
|
696
|
+
// src/deprecation.ts
|
|
697
|
+
function createDeprecationDiagnostic(notice) {
|
|
698
|
+
return {
|
|
699
|
+
code: `deprecated-${notice.kind}`,
|
|
700
|
+
severity: "warning",
|
|
701
|
+
message: formatDeprecationMessage(notice),
|
|
702
|
+
target: notice.target,
|
|
703
|
+
suggestion: notice.replacement ? `Use ${notice.replacement}. ${notice.action}` : notice.action,
|
|
704
|
+
meta: { deprecation: notice }
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
function formatDeprecationMessage(notice) {
|
|
708
|
+
const lines = [
|
|
709
|
+
`Deprecated: ${notice.target}`,
|
|
710
|
+
`Deprecated since: ${notice.deprecatedSince}`
|
|
711
|
+
];
|
|
712
|
+
if (notice.replacement) lines.push(`Use: ${notice.replacement}`);
|
|
713
|
+
lines.push(`Migration: ${notice.action}`);
|
|
714
|
+
if (notice.documentationUrl) lines.push(`See: ${notice.documentationUrl}`);
|
|
715
|
+
if (notice.removedIn) lines.push(`Removal planned: ${notice.removedIn}`);
|
|
716
|
+
return lines.join("\n");
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
// src/config_deprecations.ts
|
|
720
|
+
var configDeprecations = [];
|
|
721
|
+
function collectConfigDeprecationDiagnostics(config, notices = configDeprecations) {
|
|
722
|
+
return notices.filter((notice) => hasConfigPath(config, notice.path)).map(createDeprecationDiagnostic);
|
|
723
|
+
}
|
|
724
|
+
function hasConfigPath(config, path4) {
|
|
725
|
+
let value = config;
|
|
726
|
+
for (const segment of path4.split(".")) {
|
|
727
|
+
if (!isRecord2(value) || !(segment in value)) return false;
|
|
728
|
+
value = value[segment];
|
|
729
|
+
}
|
|
730
|
+
return value !== void 0;
|
|
731
|
+
}
|
|
732
|
+
function isRecord2(value) {
|
|
733
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
734
|
+
}
|
|
735
|
+
|
|
696
736
|
// src/content/image_extensions.ts
|
|
697
737
|
var IMAGE_EXTENSIONS = [
|
|
698
738
|
"png",
|
|
@@ -770,7 +810,7 @@ async function readContentBuildStateStatus(statePath) {
|
|
|
770
810
|
}
|
|
771
811
|
throw error;
|
|
772
812
|
}
|
|
773
|
-
if (!
|
|
813
|
+
if (!isRecord3(parsed)) {
|
|
774
814
|
return { kind: "invalid", path: statePath, reason: "invalid-shape" };
|
|
775
815
|
}
|
|
776
816
|
if (parsed.version !== CONTENT_BUILD_STATE_VERSION) {
|
|
@@ -810,19 +850,19 @@ function resolveContentBuildStatePath(config, contentDirectory) {
|
|
|
810
850
|
);
|
|
811
851
|
}
|
|
812
852
|
function isContentBuildState(value) {
|
|
813
|
-
return
|
|
853
|
+
return isRecord3(value) && value.version === CONTENT_BUILD_STATE_VERSION && isContentBuildStateShape(value);
|
|
814
854
|
}
|
|
815
855
|
function isContentBuildStateShape(value) {
|
|
816
|
-
if (!
|
|
856
|
+
if (!isRecord3(value.entries) || !isRecord3(value.contentIndex)) return false;
|
|
817
857
|
return Object.values(value.entries).every(
|
|
818
|
-
(entry) =>
|
|
858
|
+
(entry) => isRecord3(entry) && typeof entry.fingerprint === "string" && entry.fingerprint.length > 0 && Array.isArray(entry.dependencies) && entry.dependencies.every(
|
|
819
859
|
(dependency) => typeof dependency === "string"
|
|
820
860
|
)
|
|
821
861
|
) && Object.values(value.contentIndex).every(
|
|
822
862
|
(entry) => typeof entry === "string"
|
|
823
863
|
);
|
|
824
864
|
}
|
|
825
|
-
function
|
|
865
|
+
function isRecord3(value) {
|
|
826
866
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
827
867
|
}
|
|
828
868
|
function isNotFoundError(error) {
|
|
@@ -1588,6 +1628,7 @@ var Pipeline = class {
|
|
|
1588
1628
|
markdownPipelineContext
|
|
1589
1629
|
);
|
|
1590
1630
|
}
|
|
1631
|
+
this.use(processor, normalizeMarkdownLinks, markdownPipelineContext);
|
|
1591
1632
|
this.use(processor, remarkRehype, { allowDangerousHtml: true });
|
|
1592
1633
|
this.use(processor, rehypeRaw);
|
|
1593
1634
|
for (const plugin of plugins) {
|
|
@@ -1701,6 +1742,81 @@ function selectBlockFragment(markdown, blockId) {
|
|
|
1701
1742
|
const line = lines.find((currentLine) => blockIdRe.test(currentLine));
|
|
1702
1743
|
return line?.replace(blockIdRe, "").trimEnd() || null;
|
|
1703
1744
|
}
|
|
1745
|
+
function normalizeMarkdownLinks(context) {
|
|
1746
|
+
return (tree) => {
|
|
1747
|
+
visitMarkdownLinkNodes(tree, (node) => {
|
|
1748
|
+
const normalizedUrl = normalizeMarkdownLinkUrl(node.url, context);
|
|
1749
|
+
if (normalizedUrl) node.url = normalizedUrl;
|
|
1750
|
+
});
|
|
1751
|
+
};
|
|
1752
|
+
}
|
|
1753
|
+
function visitMarkdownLinkNodes(node, visitor) {
|
|
1754
|
+
const linkNode = node;
|
|
1755
|
+
if ((node.type === "link" || node.type === "definition") && typeof linkNode.url === "string") {
|
|
1756
|
+
visitor(linkNode);
|
|
1757
|
+
}
|
|
1758
|
+
for (const child of linkNode.children ?? []) {
|
|
1759
|
+
visitMarkdownLinkNodes(child, visitor);
|
|
1760
|
+
}
|
|
1761
|
+
}
|
|
1762
|
+
function normalizeMarkdownLinkUrl(url, context) {
|
|
1763
|
+
if (!context.sourceSlug) return null;
|
|
1764
|
+
if (!isMarkdownContentLink(url)) return null;
|
|
1765
|
+
const [pathAndQuery, hash3 = ""] = splitOnce(url, "#");
|
|
1766
|
+
const [rawPath, query = ""] = splitOnce(pathAndQuery, "?");
|
|
1767
|
+
const decodedPath = decodeUriPath(rawPath);
|
|
1768
|
+
if (!decodedPath?.toLowerCase().endsWith(".md")) return null;
|
|
1769
|
+
const resolvedSlug = resolveRelativeMarkdownSlug(
|
|
1770
|
+
context.sourceSlug,
|
|
1771
|
+
decodedPath
|
|
1772
|
+
);
|
|
1773
|
+
if (!resolvedSlug) return null;
|
|
1774
|
+
const indexedSlug = getExactContentSlug(context, resolvedSlug);
|
|
1775
|
+
if (!indexedSlug) return null;
|
|
1776
|
+
const suffix = `${query ? `?${query}` : ""}${hash3 ? `#${hash3}` : ""}`;
|
|
1777
|
+
return `${context.resolvePermalink(indexedSlug)}${suffix}`;
|
|
1778
|
+
}
|
|
1779
|
+
function getExactContentSlug(context, slug) {
|
|
1780
|
+
try {
|
|
1781
|
+
context.resolvePermalink(slug);
|
|
1782
|
+
return slug;
|
|
1783
|
+
} catch {
|
|
1784
|
+
return context.contentIndex.get(slug.toLowerCase()) ?? null;
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1787
|
+
function isMarkdownContentLink(url) {
|
|
1788
|
+
if (url.startsWith("#") || url.startsWith("//")) return false;
|
|
1789
|
+
if (/^[a-z][a-z0-9+.-]*:/i.test(url)) return false;
|
|
1790
|
+
return true;
|
|
1791
|
+
}
|
|
1792
|
+
function resolveRelativeMarkdownSlug(sourceSlug, targetPath) {
|
|
1793
|
+
const sourceDirectory = sourceSlug.includes("/") ? sourceSlug.slice(0, sourceSlug.lastIndexOf("/")) : "";
|
|
1794
|
+
const baseParts = targetPath.startsWith("/") ? [] : sourceDirectory.split("/");
|
|
1795
|
+
const parts = [...baseParts, ...targetPath.replace(/^\/+/, "").split("/")];
|
|
1796
|
+
const normalizedParts = [];
|
|
1797
|
+
for (const part of parts) {
|
|
1798
|
+
if (!part || part === ".") continue;
|
|
1799
|
+
if (part === "..") {
|
|
1800
|
+
if (normalizedParts.length === 0) return null;
|
|
1801
|
+
normalizedParts.pop();
|
|
1802
|
+
continue;
|
|
1803
|
+
}
|
|
1804
|
+
normalizedParts.push(part);
|
|
1805
|
+
}
|
|
1806
|
+
return normalizedParts.join("/").replace(/\.md$/i, "");
|
|
1807
|
+
}
|
|
1808
|
+
function decodeUriPath(path4) {
|
|
1809
|
+
try {
|
|
1810
|
+
return decodeURI(path4);
|
|
1811
|
+
} catch {
|
|
1812
|
+
return null;
|
|
1813
|
+
}
|
|
1814
|
+
}
|
|
1815
|
+
function splitOnce(value, separator) {
|
|
1816
|
+
const index = value.indexOf(separator);
|
|
1817
|
+
if (index < 0) return [value];
|
|
1818
|
+
return [value.slice(0, index), value.slice(index + separator.length)];
|
|
1819
|
+
}
|
|
1704
1820
|
function selectHeadingFragment(markdown, heading) {
|
|
1705
1821
|
const lines = markdown.split(/\r?\n/);
|
|
1706
1822
|
const targetHeading = heading.trim().toLowerCase();
|
|
@@ -1990,6 +2106,53 @@ var PluginRuntime = class {
|
|
|
1990
2106
|
collectGeneratedOutputs() {
|
|
1991
2107
|
return this.generatedOutputs.all();
|
|
1992
2108
|
}
|
|
2109
|
+
async resolvePage(pathname, manifest, contentIndex) {
|
|
2110
|
+
const matches = [];
|
|
2111
|
+
const normalizedPathname = normalizePagePath(pathname);
|
|
2112
|
+
const context = {
|
|
2113
|
+
...this.createContext(contentIndex),
|
|
2114
|
+
manifest,
|
|
2115
|
+
pathname: normalizedPathname
|
|
2116
|
+
};
|
|
2117
|
+
for (const plugin of this.plugins()) {
|
|
2118
|
+
for (const pageType of plugin.pageTypes ?? []) {
|
|
2119
|
+
const page = await pageType.resolve(
|
|
2120
|
+
this.createPluginContext(plugin, context)
|
|
2121
|
+
);
|
|
2122
|
+
if (page) {
|
|
2123
|
+
matches.push({
|
|
2124
|
+
page: { ...page, type: pageType.id, pluginName: plugin.name },
|
|
2125
|
+
priority: pageType.priority ?? 0
|
|
2126
|
+
});
|
|
2127
|
+
}
|
|
2128
|
+
}
|
|
2129
|
+
}
|
|
2130
|
+
if (matches.length === 0) return null;
|
|
2131
|
+
const highestPriority = Math.max(...matches.map((match) => match.priority));
|
|
2132
|
+
const highest = matches.filter(
|
|
2133
|
+
(match) => match.priority === highestPriority
|
|
2134
|
+
);
|
|
2135
|
+
if (highest.length !== 1) {
|
|
2136
|
+
throw new Error(
|
|
2137
|
+
`Multiple plugin page types match ${normalizedPathname} at priority ${highestPriority}: ${highest.map((match) => match.page.type).join(", ")}`
|
|
2138
|
+
);
|
|
2139
|
+
}
|
|
2140
|
+
return highest[0].page;
|
|
2141
|
+
}
|
|
2142
|
+
async getPagePaths(manifest, contentIndex) {
|
|
2143
|
+
const paths = [];
|
|
2144
|
+
const context = { ...this.createContext(contentIndex), manifest };
|
|
2145
|
+
for (const plugin of this.plugins()) {
|
|
2146
|
+
for (const pageType of plugin.pageTypes ?? []) {
|
|
2147
|
+
const declared = pageType.paths;
|
|
2148
|
+
if (!declared) continue;
|
|
2149
|
+
paths.push(
|
|
2150
|
+
...typeof declared === "function" ? await declared(this.createPluginContext(plugin, context)) : declared
|
|
2151
|
+
);
|
|
2152
|
+
}
|
|
2153
|
+
}
|
|
2154
|
+
return [...new Set(paths.map(normalizePagePath))];
|
|
2155
|
+
}
|
|
1993
2156
|
async collectDiagnostics(contentIndex) {
|
|
1994
2157
|
const tracer = this.observability().tracer;
|
|
1995
2158
|
return await tracer.span("diagnostics.run", {}, async () => {
|
|
@@ -2095,9 +2258,57 @@ var PluginRuntime = class {
|
|
|
2095
2258
|
return this.pipelineOptions.observability ?? noopObservability;
|
|
2096
2259
|
}
|
|
2097
2260
|
plugins() {
|
|
2098
|
-
|
|
2261
|
+
const plugins = resolvePlugins(this.pipelineOptions.plugins);
|
|
2262
|
+
const pageTypes = /* @__PURE__ */ new Map();
|
|
2263
|
+
for (const plugin of plugins) {
|
|
2264
|
+
const declaredPageTypes = plugin.pageTypes;
|
|
2265
|
+
if (declaredPageTypes !== void 0 && !Array.isArray(declaredPageTypes)) {
|
|
2266
|
+
throw new TypeError(`Plugin ${plugin.name} pageTypes must be an array`);
|
|
2267
|
+
}
|
|
2268
|
+
for (const pageType of declaredPageTypes ?? []) {
|
|
2269
|
+
validatePageType(plugin.name, pageType);
|
|
2270
|
+
const previous = pageTypes.get(pageType.id);
|
|
2271
|
+
if (previous) {
|
|
2272
|
+
throw new Error(
|
|
2273
|
+
`Plugin page type "${pageType.id}" is provided by both ${previous} and ${plugin.name}`
|
|
2274
|
+
);
|
|
2275
|
+
}
|
|
2276
|
+
pageTypes.set(pageType.id, plugin.name);
|
|
2277
|
+
}
|
|
2278
|
+
}
|
|
2279
|
+
return plugins;
|
|
2099
2280
|
}
|
|
2100
2281
|
};
|
|
2282
|
+
function validatePageType(pluginName, pageType) {
|
|
2283
|
+
if (typeof pageType !== "object" || pageType === null) {
|
|
2284
|
+
throw new TypeError(`Plugin ${pluginName} pageTypes must contain objects`);
|
|
2285
|
+
}
|
|
2286
|
+
const candidate = pageType;
|
|
2287
|
+
if (typeof candidate.id !== "string" || candidate.id.trim() === "") {
|
|
2288
|
+
throw new TypeError(
|
|
2289
|
+
`Plugin ${pluginName} page type id must be a non-empty string`
|
|
2290
|
+
);
|
|
2291
|
+
}
|
|
2292
|
+
if (typeof candidate.resolve !== "function") {
|
|
2293
|
+
throw new TypeError(
|
|
2294
|
+
`Plugin ${pluginName} page type "${candidate.id}" must provide a resolve function`
|
|
2295
|
+
);
|
|
2296
|
+
}
|
|
2297
|
+
if (candidate.paths !== void 0 && !Array.isArray(candidate.paths) && typeof candidate.paths !== "function") {
|
|
2298
|
+
throw new TypeError(
|
|
2299
|
+
`Plugin ${pluginName} page type "${candidate.id}" paths must be an array or function`
|
|
2300
|
+
);
|
|
2301
|
+
}
|
|
2302
|
+
if (candidate.priority !== void 0 && (typeof candidate.priority !== "number" || !Number.isFinite(candidate.priority))) {
|
|
2303
|
+
throw new TypeError(
|
|
2304
|
+
`Plugin ${pluginName} page type "${candidate.id}" priority must be a finite number`
|
|
2305
|
+
);
|
|
2306
|
+
}
|
|
2307
|
+
}
|
|
2308
|
+
function normalizePagePath(pathname) {
|
|
2309
|
+
const path4 = `/${pathname.split("/").filter(Boolean).join("/")}`;
|
|
2310
|
+
return path4 === "/" ? path4 : path4.replace(/\/$/, "");
|
|
2311
|
+
}
|
|
2101
2312
|
function countSeverity(diagnostics, severity) {
|
|
2102
2313
|
return diagnostics.filter((diagnostic) => diagnostic.severity === severity).length;
|
|
2103
2314
|
}
|
|
@@ -2660,7 +2871,8 @@ var ManifestBuilder = class {
|
|
|
2660
2871
|
assets: [],
|
|
2661
2872
|
clientEntries: [],
|
|
2662
2873
|
diagnostics: [],
|
|
2663
|
-
generatedOutputs: []
|
|
2874
|
+
generatedOutputs: [],
|
|
2875
|
+
pagePaths: []
|
|
2664
2876
|
};
|
|
2665
2877
|
return { ...manifest, graph: createContentGraph(manifest) };
|
|
2666
2878
|
}
|
|
@@ -2680,7 +2892,10 @@ function createContentIdIndex(entries) {
|
|
|
2680
2892
|
return byContentId;
|
|
2681
2893
|
}
|
|
2682
2894
|
function getManifestTitle(slug, title) {
|
|
2683
|
-
|
|
2895
|
+
if (typeof title === "string" && title.trim()) {
|
|
2896
|
+
return title.trim();
|
|
2897
|
+
}
|
|
2898
|
+
return slug.split("/").at(-1) ?? slug;
|
|
2684
2899
|
}
|
|
2685
2900
|
function uniqueAssets(assets) {
|
|
2686
2901
|
return Array.from(
|
|
@@ -2858,6 +3073,9 @@ var ContentManager = class {
|
|
|
2858
3073
|
this.locationResolver.populateRedirects(manifest, locations);
|
|
2859
3074
|
await this.pluginRuntime.runManifestCreated(manifest, contentIndex);
|
|
2860
3075
|
this.applyPublicView(manifest);
|
|
3076
|
+
manifest.pagePaths = [
|
|
3077
|
+
...await this.pluginRuntime.getPagePaths(manifest, contentIndex)
|
|
3078
|
+
];
|
|
2861
3079
|
manifest.assets = this.pluginRuntime.collectAssets();
|
|
2862
3080
|
manifest.clientEntries = this.pluginRuntime.collectClientEntries();
|
|
2863
3081
|
manifest.diagnostics = [
|
|
@@ -2890,6 +3108,26 @@ var ContentManager = class {
|
|
|
2890
3108
|
const manifest = await this.getManifest();
|
|
2891
3109
|
return manifest.diagnostics;
|
|
2892
3110
|
}
|
|
3111
|
+
/** Resolves a page contributed by an enabled plugin. */
|
|
3112
|
+
async resolvePage(pathname) {
|
|
3113
|
+
const [manifest, contentIndex] = await Promise.all([
|
|
3114
|
+
this.getManifest(),
|
|
3115
|
+
this.getContentIndex()
|
|
3116
|
+
]);
|
|
3117
|
+
return await this.pluginRuntime.resolvePage(
|
|
3118
|
+
pathname,
|
|
3119
|
+
manifest,
|
|
3120
|
+
contentIndex
|
|
3121
|
+
);
|
|
3122
|
+
}
|
|
3123
|
+
/** Returns plugin page paths for SSG enumeration. */
|
|
3124
|
+
async getPagePaths() {
|
|
3125
|
+
const [manifest, contentIndex] = await Promise.all([
|
|
3126
|
+
this.getManifest(),
|
|
3127
|
+
this.getContentIndex()
|
|
3128
|
+
]);
|
|
3129
|
+
return await this.pluginRuntime.getPagePaths(manifest, contentIndex);
|
|
3130
|
+
}
|
|
2893
3131
|
async inspect() {
|
|
2894
3132
|
const [entries, contentIndex] = await Promise.all([
|
|
2895
3133
|
this.entryReader.getEntries(),
|
|
@@ -3139,8 +3377,10 @@ export {
|
|
|
3139
3377
|
buildContentCollections,
|
|
3140
3378
|
buildGraphEdges,
|
|
3141
3379
|
calculateReadingTime,
|
|
3380
|
+
collectConfigDeprecationDiagnostics,
|
|
3142
3381
|
createClientEntry,
|
|
3143
3382
|
createContentGraph,
|
|
3383
|
+
createDeprecationDiagnostic,
|
|
3144
3384
|
createPluginMemo,
|
|
3145
3385
|
createStyleAsset,
|
|
3146
3386
|
createUnavailableGeneratedOutputSink,
|
|
@@ -3153,6 +3393,7 @@ export {
|
|
|
3153
3393
|
escapeScriptJson,
|
|
3154
3394
|
extractFrontmatterAliases,
|
|
3155
3395
|
fingerprintContentEntries,
|
|
3396
|
+
formatDeprecationMessage,
|
|
3156
3397
|
getContentSourceEntry,
|
|
3157
3398
|
getExtension,
|
|
3158
3399
|
getResolvedPluginMetadata,
|
|
@@ -0,0 +1,8 @@
|
|
|
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,6 +1,7 @@
|
|
|
1
1
|
import type { PipelineOptions } from "../pipeline.js";
|
|
2
2
|
import type { ContentManifest, ContentPublicLocation } from "../types/content_manifest.js";
|
|
3
3
|
import type { Diagnostic } from "../types/diagnostic.js";
|
|
4
|
+
import type { ResolvedPluginPage } from "../types/plugin_page.js";
|
|
4
5
|
import type { PostContent } from "../types/post_content.js";
|
|
5
6
|
import type { ResolvedRiebeckiteConfig } from "../types/resolved_riebeckite_config.js";
|
|
6
7
|
import { type ContentBuildPreparation } from "./content_build_coordinator.js";
|
|
@@ -45,6 +46,10 @@ export declare class ContentManager {
|
|
|
45
46
|
getBacklinks(targetSlug: string): Promise<Backlink[]>;
|
|
46
47
|
getContentGraph(): Promise<ContentGraph>;
|
|
47
48
|
getDiagnostics(): Promise<Diagnostic[]>;
|
|
49
|
+
/** Resolves a page contributed by an enabled plugin. */
|
|
50
|
+
resolvePage(pathname: string): Promise<ResolvedPluginPage | null>;
|
|
51
|
+
/** Returns plugin page paths for SSG enumeration. */
|
|
52
|
+
getPagePaths(): Promise<readonly string[]>;
|
|
48
53
|
inspect(): Promise<ContentInspection>;
|
|
49
54
|
dispose(): Promise<void>;
|
|
50
55
|
getContentLocations(): Promise<ReadonlyMap<string, ContentPublicLocation>>;
|
|
@@ -0,0 +1,14 @@
|
|
|
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;
|
|
@@ -3,6 +3,7 @@ import type { ContentLocationInput, ContentManifest, ContentManifestEntry, Conte
|
|
|
3
3
|
import type { Diagnostic } from "../types/diagnostic.js";
|
|
4
4
|
import type { GeneratedOutput } from "../types/generated_output.js";
|
|
5
5
|
import { type PluginClientEntry } from "../types/plugin_asset.js";
|
|
6
|
+
import type { ResolvedPluginPage } from "../types/plugin_page.js";
|
|
6
7
|
import type { PostContent } from "../types/post_content.js";
|
|
7
8
|
/**
|
|
8
9
|
* Explicit build lifecycle stages. `idle` means no build lifecycle has been
|
|
@@ -53,6 +54,8 @@ export declare class PluginRuntime {
|
|
|
53
54
|
collectClientEntries(): PluginClientEntry[];
|
|
54
55
|
/** Returns registered outputs sorted by path for a deterministic build. */
|
|
55
56
|
collectGeneratedOutputs(): GeneratedOutput[];
|
|
57
|
+
resolvePage(pathname: string, manifest: ContentManifest, contentIndex: Map<string, string>): Promise<ResolvedPluginPage | null>;
|
|
58
|
+
getPagePaths(manifest: ContentManifest, contentIndex: Map<string, string>): Promise<readonly string[]>;
|
|
56
59
|
collectDiagnostics(contentIndex: Map<string, string>): Promise<Diagnostic[]>;
|
|
57
60
|
private runBuildLifecycle;
|
|
58
61
|
private createContext;
|
|
@@ -3,6 +3,7 @@ import type { Diagnostic } from "./diagnostic.js";
|
|
|
3
3
|
import type { PluginAsset, PluginClientEntry } from "./plugin_asset.js";
|
|
4
4
|
import type { PluginContentContext, PluginContentLocationAugmentContext, PluginContentLocationResolver, PluginContentRenderer, PluginContext, PluginGeneratedHtmlInspector, PluginGraphContext, PluginLifecycleContext, PluginManifestContext, PluginPostContext } from "./plugin_context.js";
|
|
5
5
|
import type { PluginEndpoint } from "./plugin_endpoint.js";
|
|
6
|
+
import type { PluginPageType } from "./plugin_page.js";
|
|
6
7
|
import type { HtmlPipeline, MarkdownPipeline, MarkdownPipelineContext, PipelinePlugin } from "./plugin_pipeline.js";
|
|
7
8
|
import type { PluginSeoExtension } from "./plugin_seo.js";
|
|
8
9
|
export type RiebeckitePlugin<TOptions = unknown> = {
|
|
@@ -57,6 +58,8 @@ export type RiebeckitePlugin<TOptions = unknown> = {
|
|
|
57
58
|
seo?: PluginSeoExtension;
|
|
58
59
|
extendContentGraph?(context: PluginGraphContext): void | Promise<void>;
|
|
59
60
|
renderers?: PluginContentRenderer[];
|
|
61
|
+
/** Framework-independent page types contributed by this plugin. */
|
|
62
|
+
pageTypes?: PluginPageType[];
|
|
60
63
|
};
|
|
61
64
|
export type PluginInput = RiebeckitePlugin | false | null | undefined;
|
|
62
65
|
export type ResolvedPluginMetadata = {
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { ContentManifest } from "./content_manifest.js";
|
|
2
|
+
import type { PluginContext } from "./plugin_context.js";
|
|
3
|
+
import type { PluginHeadTag } from "./plugin_head.js";
|
|
4
|
+
/** A framework-independent page supplied by a Riebeckite plugin. */
|
|
5
|
+
export type PluginPage = {
|
|
6
|
+
/** Stable identifier of the page type that produced this page. */
|
|
7
|
+
type: string;
|
|
8
|
+
/** Canonical, absolute URL path. */
|
|
9
|
+
pathname: string;
|
|
10
|
+
/** HTML for the page body. The site owns the surrounding document frame. */
|
|
11
|
+
body: string;
|
|
12
|
+
title?: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
/** Optional document metadata rendered by the site's document frame. */
|
|
15
|
+
headTags?: readonly PluginHeadTag[];
|
|
16
|
+
};
|
|
17
|
+
export type PluginPageContext = PluginContext & {
|
|
18
|
+
/** The public manifest. Unpublished content is not exposed through pages. */
|
|
19
|
+
manifest: ContentManifest;
|
|
20
|
+
/** Request pathname, normalized to an absolute path. */
|
|
21
|
+
pathname: string;
|
|
22
|
+
};
|
|
23
|
+
export type PluginPageType = {
|
|
24
|
+
/** Globally unique, stable page type identifier. */
|
|
25
|
+
id: string;
|
|
26
|
+
/** Paths emitted by SSG for this type. */
|
|
27
|
+
paths?: readonly string[] | ((context: PluginContext & {
|
|
28
|
+
manifest: ContentManifest;
|
|
29
|
+
}) => readonly string[] | Promise<readonly string[]>);
|
|
30
|
+
/** Higher values win when more than one type matches a request. */
|
|
31
|
+
priority?: number;
|
|
32
|
+
resolve(context: PluginPageContext): PluginPage | null | Promise<PluginPage | null>;
|
|
33
|
+
};
|
|
34
|
+
export type ResolvedPluginPage = PluginPage & {
|
|
35
|
+
pluginName: string;
|
|
36
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@riebeckite/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.14",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -12,6 +12,12 @@
|
|
|
12
12
|
"source": "./index.ts",
|
|
13
13
|
"default": "./dist/index.js"
|
|
14
14
|
},
|
|
15
|
+
"./client": {
|
|
16
|
+
"types": "./dist/client.d.ts",
|
|
17
|
+
"import": "./dist/client.js",
|
|
18
|
+
"source": "./client.ts",
|
|
19
|
+
"default": "./dist/client.js"
|
|
20
|
+
},
|
|
15
21
|
"./package.json": "./package.json"
|
|
16
22
|
},
|
|
17
23
|
"files": [
|
|
@@ -43,7 +49,7 @@
|
|
|
43
49
|
},
|
|
44
50
|
"devDependencies": {
|
|
45
51
|
"tsx": "^4.22.4",
|
|
46
|
-
"@riebeckite/test": "0.0.
|
|
52
|
+
"@riebeckite/test": "0.0.14"
|
|
47
53
|
},
|
|
48
54
|
"repository": {
|
|
49
55
|
"type": "git",
|