@riebeckite/plugin-local-graph 0.0.22 → 0.0.23

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 CHANGED
@@ -11,22 +11,12 @@ outgoing links and backlinks.
11
11
 
12
12
  `localGraph()` provides a `LocalGraph` component that renders the current note
13
13
  plus its direct links as an SVG radial graph. `getLocalGraph()` collects the
14
- note's note-type outgoing links and backlinks from the manifest, keeps only
15
- published neighbors, and caps each direction at `MAX_NEIGHBORS_PER_DIRECTION`
16
- (10) notes.
14
+ note's outgoing links and backlinks from the manifest, keeps only published
15
+ neighbors, and caps each direction at `MAX_NEIGHBORS_PER_DIRECTION` (10) notes.
17
16
 
18
- Relations are tagged per node:
19
-
20
- - `current` — the selected note (center)
21
- - `outgoing` — linked from the current note
22
- - `backlink` — links to the current note
23
- - `both` — linked in both directions
24
-
25
- The component renders nothing when there is no published neighbor.
26
-
27
- `localGraphPlugin()` automatically contributes this component to
28
- `article.footer`. The Site decides where that semantic slot is rendered; the
29
- official Starter renders it after article content.
17
+ The Site places the `<LocalGraph />` component itself, normally once after
18
+ article content. The component renders nothing when there is no published
19
+ neighbor.
30
20
 
31
21
  ## Quick Start
32
22
 
@@ -41,13 +31,13 @@ export default defineConfig({
41
31
  ```
42
32
 
43
33
  `localGraphPlugin()` registers the plugin and bundles `style.css` into the app
44
- stylesheet. Render `<ContentSlot slots={bodySlots} name="article.footer" />`
45
- once in the article layout to show automatic output.
34
+ stylesheet. The Site renders `<LocalGraph />` component itself, normally once
35
+ after article content, to display the graph output.
46
36
 
47
37
  ## Advanced customization
48
38
 
49
- Set `render: false` to use the public data resolver and component in a
50
- Site-owned location without duplicating the automatic footer. This leaves graph
39
+ Set `render: false` to use the public data resolver `<getLocalGraph>` in a
40
+ Site-owned location without duplicating the automatic graph. This leaves graph
51
41
  generation and published-neighbor filtering intact.
52
42
 
53
43
  ```tsx
@@ -69,17 +59,12 @@ return (
69
59
  );
70
60
  ```
71
61
 
72
- ```ts
73
- plugins: [localGraphPlugin({ render: false })];
74
- ```
75
-
76
62
  Remove the component to remove manually placed UI.
77
63
 
78
64
  ## Configuration
79
65
 
80
- | Option | Type | Default | Description |
81
- | --- | --- | --- | --- |
82
- | `render` | `boolean` | `true` | Append the graph to `article.footer`. Set `false` for manual placement. |
66
+ There are no plugin options for `localGraphPlugin`. The `LocalGraph` component
67
+ accepts `graph` as a required prop.
83
68
 
84
69
  ## Graph layout
85
70
 
package/README_ja.md CHANGED
@@ -8,11 +8,7 @@
8
8
 
9
9
  ## 推奨配置
10
10
 
11
- `getLocalGraph()` はマニフェストからリンク先と被リンク元を集め、公開済みノートだけを残します。各方向は最大 10 件です。`LocalGraph` はそのデータを SVG として描画し、周辺ノートがなければ何も表示しません。
12
-
13
- `localGraphPlugin()` は既定で `article.footer` slot に自動追加します。物理的な位置は Site が決め、公式 Starter は記事本文の後でこの slot を描画します。
14
-
15
- ノードには `current`、`outgoing`、`backlink`、`both` の関係が付きます。中央が現在のノート、周囲が直接つながるノートです。
11
+ `getLocalGraph()` はマニフェストからリンク先と被リンク元を集め、公開済みノートだけを残します。各方向は最大 10 件です。`LocalGraph` はそのデータを SVG として描画し、周辺ノートがなければ何も表示しません。Site は `<LocalGraph />` コンポーネントを記事の後などに配置します。
16
12
 
17
13
  ## クイックスタート
18
14
 
@@ -23,29 +19,22 @@ import { localGraphPlugin } from "@riebeckite/plugin-local-graph";
23
19
  export default defineConfig({ plugins: [localGraphPlugin()] });
24
20
  ```
25
21
 
26
- 記事レイアウトで `<ContentSlot slots={bodySlots} name="article.footer" />` を一度描画します。
22
+ 記事レイアウトで `<LocalGraph />` コンポーネントを一度描画します。
23
+
24
+ ## 設定
25
+
26
+ `localGraphPlugin()` にはプラグイン用のオプションがありません。`LocalGraph` コンポーネントは `graph` 必須プロップを受け取ります。
27
27
 
28
28
  ## 高度なカスタマイズ
29
29
 
30
- 重複させずに Site 側で配置を決めるには、`render: false` を指定します。グラフの生成と公開済み近傍だけを残すフィルタリングは維持されます。
30
+ サイト側で配置を決めるには、`getLocalGraph` を使ってデータを取得し、`<LocalGraph graph={...} />` コンポーネントを一度だけ描画してください。グラフの生成と公開済み近傍だけを残すフィルタリングは維持されます。
31
31
 
32
32
  ```tsx
33
33
  import LocalGraph, { getLocalGraph } from "@riebeckite/plugin-local-graph";
34
-
35
34
  const graph = getLocalGraph({ manifest: await content.getManifest(), config, slug, resolveTitle });
36
35
  return <Article footerContent={graph && <LocalGraph graph={graph} />} />;
37
36
  ```
38
37
 
39
- ```ts
40
- plugins: [localGraphPlugin({ render: false })];
41
- ```
42
-
43
- ## 設定
44
-
45
- | オプション | 型 | 既定値 | 説明 |
46
- | --- | --- | --- | --- |
47
- | `render` | `boolean` | `true` | `article.footer` への自動追加。手動配置では `false`。 |
48
-
49
38
  グラフのノード位置は `layoutRadialGraph()`、辺は `buildGraphEdges()` が計算します。各ノードのリンクは解決済みの `permalink` を使い、見出しは internal selection key `/explore?note=<slug>` で Explorer を開きます。
50
39
 
51
40
  ## 公開 API
@@ -1,6 +1,6 @@
1
1
  import type { LocalGraphData } from "../src/local-graph.js";
2
- type Props = {
2
+ export type LocalGraphProps = {
3
3
  graph: LocalGraphData;
4
4
  };
5
- export default function LocalGraph(props: Props): import("hono/jsx/jsx-dev-runtime").JSX.Element;
6
- export {};
5
+ declare const LocalGraph: (props: Readonly<LocalGraphProps>) => import("hono/jsx/jsx-dev-runtime").JSX.Element;
6
+ export default LocalGraph;
@@ -3,7 +3,7 @@ import { buildGraphEdges, layoutRadialGraph } from "@riebeckite/core";
3
3
  import { jsx, jsxs } from "hono/jsx/jsx-runtime";
4
4
  var GRAPH_WIDTH = 640;
5
5
  var GRAPH_HEIGHT = 320;
6
- function LocalGraph(props) {
6
+ var LocalGraph = ((props) => {
7
7
  if (props.graph.nodes.length <= 1) return null;
8
8
  const edges = buildGraphEdges(props.graph.nodes);
9
9
  const layout = layoutRadialGraph(props.graph.nodes, {
@@ -14,112 +14,106 @@ function LocalGraph(props) {
14
14
  minNodeRadius: 7,
15
15
  maxNodeRadius: 12
16
16
  });
17
- return /* @__PURE__ */ jsxs(
18
- "section",
19
- {
20
- class: "rr-local-graph max-w-4xl mx-auto px-4",
21
- "aria-labelledby": "local-graph-title",
22
- children: [
23
- /* @__PURE__ */ jsxs("div", { class: "rr-local-graph__header", children: [
24
- /* @__PURE__ */ jsxs("div", { children: [
25
- /* @__PURE__ */ jsx("p", { class: "rr-local-graph__eyebrow", children: "Local Graph" }),
26
- /* @__PURE__ */ jsx("h2", { id: "local-graph-title", children: "Nearby Notes" })
27
- ] }),
28
- /* @__PURE__ */ jsx(
29
- "a",
30
- {
31
- class: "rr-local-graph__explorer-link",
32
- href: `/explore?note=${encodeURIComponent(props.graph.currentSlug)}`,
33
- children: "Open in Explorer →"
34
- }
35
- )
36
- ] }),
37
- /* @__PURE__ */ jsxs(
38
- "svg",
39
- {
40
- class: "rr-local-graph__canvas",
41
- viewBox: `0 0 ${GRAPH_WIDTH} ${GRAPH_HEIGHT}`,
42
- role: "img",
43
- "aria-label": "Local graph of outgoing links and backlinks",
44
- children: [
45
- edges.map((edge) => {
46
- const source = layout.get(edge.source);
47
- const target = layout.get(edge.target);
48
- if (!source || !target) return null;
49
- return /* @__PURE__ */ jsx(
50
- "line",
17
+ return /* @__PURE__ */ jsxs("section", { class: "rr-local-graph", "aria-labelledby": "local-graph-title", children: [
18
+ /* @__PURE__ */ jsxs("div", { class: "rr-local-graph__header", children: [
19
+ /* @__PURE__ */ jsxs("div", { children: [
20
+ /* @__PURE__ */ jsx("p", { class: "rr-local-graph__eyebrow", children: "Local Graph" }),
21
+ /* @__PURE__ */ jsx("h2", { id: "local-graph-title", children: "Nearby Notes" })
22
+ ] }),
23
+ /* @__PURE__ */ jsx(
24
+ "a",
25
+ {
26
+ class: "rr-local-graph__explorer-link",
27
+ href: `/explore?note=${encodeURIComponent(props.graph.currentSlug)}`,
28
+ children: "Open in Explorer →"
29
+ }
30
+ )
31
+ ] }),
32
+ /* @__PURE__ */ jsxs(
33
+ "svg",
34
+ {
35
+ class: "rr-local-graph__canvas",
36
+ viewBox: `0 0 ${GRAPH_WIDTH} ${GRAPH_HEIGHT}`,
37
+ role: "img",
38
+ "aria-label": "Local graph of outgoing links and backlinks",
39
+ children: [
40
+ edges.map((edge) => {
41
+ const source = layout.get(edge.source);
42
+ const target = layout.get(edge.target);
43
+ if (!source || !target) return null;
44
+ return /* @__PURE__ */ jsx(
45
+ "line",
46
+ {
47
+ class: "rr-local-graph__edge",
48
+ "data-direction": edge.source === props.graph.currentSlug ? "outgoing" : "backlink",
49
+ x1: source.x,
50
+ y1: source.y,
51
+ x2: target.x,
52
+ y2: target.y
53
+ },
54
+ `${edge.source}-${edge.target}`
55
+ );
56
+ }),
57
+ props.graph.nodes.map((node) => {
58
+ const point = layout.get(node.slug);
59
+ if (!point) return null;
60
+ const isCurrent = node.slug === props.graph.currentSlug;
61
+ return /* @__PURE__ */ jsx(
62
+ "g",
63
+ {
64
+ class: "rr-local-graph__node",
65
+ "data-relation": node.relation,
66
+ children: /* @__PURE__ */ jsxs(
67
+ "a",
51
68
  {
52
- class: "rr-local-graph__edge",
53
- "data-direction": edge.source === props.graph.currentSlug ? "outgoing" : "backlink",
54
- x1: source.x,
55
- y1: source.y,
56
- x2: target.x,
57
- y2: target.y
58
- },
59
- `${edge.source}-${edge.target}`
60
- );
61
- }),
62
- props.graph.nodes.map((node) => {
63
- const point = layout.get(node.slug);
64
- if (!point) return null;
65
- const isCurrent = node.slug === props.graph.currentSlug;
66
- return /* @__PURE__ */ jsx(
67
- "g",
68
- {
69
- class: "rr-local-graph__node",
70
- "data-relation": node.relation,
71
- children: /* @__PURE__ */ jsxs(
72
- "a",
73
- {
74
- href: node.permalink,
75
- "aria-label": isCurrent ? `Current note: ${node.title}` : `Open ${node.title}`,
76
- children: [
77
- /* @__PURE__ */ jsx(
78
- "circle",
79
- {
80
- cx: point.x,
81
- cy: point.y,
82
- r: isCurrent ? 16 : point.radius
83
- }
84
- ),
85
- /* @__PURE__ */ jsx(
86
- "text",
87
- {
88
- x: point.x + (isCurrent ? 20 : 16),
89
- y: point.y + 5,
90
- "text-anchor": point.x > GRAPH_WIDTH * 0.78 ? "end" : "start",
91
- dx: point.x > GRAPH_WIDTH * 0.78 ? -32 : 0,
92
- children: node.title
93
- }
94
- )
95
- ]
96
- }
97
- )
98
- },
99
- node.slug
100
- );
101
- })
102
- ]
103
- }
104
- ),
105
- /* @__PURE__ */ jsxs("div", { class: "rr-local-graph__legend", children: [
106
- /* @__PURE__ */ jsxs("span", { children: [
107
- /* @__PURE__ */ jsx("i", { "data-kind": "current" }),
108
- "Current"
109
- ] }),
110
- /* @__PURE__ */ jsxs("span", { children: [
111
- /* @__PURE__ */ jsx("i", { "data-kind": "outgoing" }),
112
- "Outgoing"
113
- ] }),
114
- /* @__PURE__ */ jsxs("span", { children: [
115
- /* @__PURE__ */ jsx("i", { "data-kind": "backlink" }),
116
- "Backlink"
117
- ] })
118
- ] })
119
- ]
120
- }
121
- );
122
- }
69
+ href: node.permalink,
70
+ "aria-label": isCurrent ? `Current note: ${node.title}` : `Open ${node.title}`,
71
+ children: [
72
+ /* @__PURE__ */ jsx(
73
+ "circle",
74
+ {
75
+ cx: point.x,
76
+ cy: point.y,
77
+ r: isCurrent ? 16 : point.radius
78
+ }
79
+ ),
80
+ /* @__PURE__ */ jsx(
81
+ "text",
82
+ {
83
+ x: point.x + (isCurrent ? 20 : 16),
84
+ y: point.y + 5,
85
+ "text-anchor": point.x > GRAPH_WIDTH * 0.78 ? "end" : "start",
86
+ dx: point.x > GRAPH_WIDTH * 0.78 ? -32 : 0,
87
+ children: node.title
88
+ }
89
+ )
90
+ ]
91
+ }
92
+ )
93
+ },
94
+ node.slug
95
+ );
96
+ })
97
+ ]
98
+ }
99
+ ),
100
+ /* @__PURE__ */ jsxs("div", { class: "rr-local-graph__legend", children: [
101
+ /* @__PURE__ */ jsxs("span", { children: [
102
+ /* @__PURE__ */ jsx("i", { "data-kind": "current" }),
103
+ "Current"
104
+ ] }),
105
+ /* @__PURE__ */ jsxs("span", { children: [
106
+ /* @__PURE__ */ jsx("i", { "data-kind": "outgoing" }),
107
+ "Outgoing"
108
+ ] }),
109
+ /* @__PURE__ */ jsxs("span", { children: [
110
+ /* @__PURE__ */ jsx("i", { "data-kind": "backlink" }),
111
+ "Backlink"
112
+ ] })
113
+ ] })
114
+ ] });
115
+ });
116
+ var local_graph_default = LocalGraph;
123
117
  export {
124
- LocalGraph as default
118
+ local_graph_default as default
125
119
  };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,8 @@
1
1
  import { buildGraphEdges, layoutRadialGraph } from "@riebeckite/core";
2
+ export type { LocalGraphProps } from "./components/local-graph.js";
2
3
  export { default as LocalGraph } from "./components/local-graph.js";
3
4
  export type { LocalGraphData, LocalGraphNode, LocalGraphNodeRelation, } from "./src/local-graph.js";
4
- export { getLocalGraph } from "./src/local-graph.server.js";
5
+ export { buildLocalGraph, getLocalGraph, } from "./src/local-graph.server.js";
5
6
  export { buildGraphEdges, layoutRadialGraph };
6
- export type LocalGraphOptions = {
7
- render?: boolean;
8
- };
7
+ export type LocalGraphOptions = Record<never, never>;
9
8
  export declare function localGraphPlugin(options?: LocalGraphOptions): import("@riebeckite/core").RiebeckitePlugin<LocalGraphOptions>;
package/dist/index.js CHANGED
@@ -1,18 +1,16 @@
1
1
  // index.ts
2
2
  import {
3
- appendContentBodySlot,
4
3
  buildGraphEdges as buildGraphEdges2,
5
4
  definePlugin,
6
5
  layoutRadialGraph as layoutRadialGraph2
7
6
  } from "@riebeckite/core";
8
- import { renderToString } from "hono/jsx/dom/server";
9
7
 
10
8
  // components/local-graph.tsx
11
9
  import { buildGraphEdges, layoutRadialGraph } from "@riebeckite/core";
12
10
  import { jsx, jsxs } from "hono/jsx/jsx-runtime";
13
11
  var GRAPH_WIDTH = 640;
14
12
  var GRAPH_HEIGHT = 320;
15
- function LocalGraph(props) {
13
+ var LocalGraph = ((props) => {
16
14
  if (props.graph.nodes.length <= 1) return null;
17
15
  const edges = buildGraphEdges(props.graph.nodes);
18
16
  const layout = layoutRadialGraph(props.graph.nodes, {
@@ -23,116 +21,110 @@ function LocalGraph(props) {
23
21
  minNodeRadius: 7,
24
22
  maxNodeRadius: 12
25
23
  });
26
- return /* @__PURE__ */ jsxs(
27
- "section",
28
- {
29
- class: "rr-local-graph max-w-4xl mx-auto px-4",
30
- "aria-labelledby": "local-graph-title",
31
- children: [
32
- /* @__PURE__ */ jsxs("div", { class: "rr-local-graph__header", children: [
33
- /* @__PURE__ */ jsxs("div", { children: [
34
- /* @__PURE__ */ jsx("p", { class: "rr-local-graph__eyebrow", children: "Local Graph" }),
35
- /* @__PURE__ */ jsx("h2", { id: "local-graph-title", children: "Nearby Notes" })
36
- ] }),
37
- /* @__PURE__ */ jsx(
38
- "a",
39
- {
40
- class: "rr-local-graph__explorer-link",
41
- href: `/explore?note=${encodeURIComponent(props.graph.currentSlug)}`,
42
- children: "Open in Explorer →"
43
- }
44
- )
45
- ] }),
46
- /* @__PURE__ */ jsxs(
47
- "svg",
48
- {
49
- class: "rr-local-graph__canvas",
50
- viewBox: `0 0 ${GRAPH_WIDTH} ${GRAPH_HEIGHT}`,
51
- role: "img",
52
- "aria-label": "Local graph of outgoing links and backlinks",
53
- children: [
54
- edges.map((edge) => {
55
- const source = layout.get(edge.source);
56
- const target = layout.get(edge.target);
57
- if (!source || !target) return null;
58
- return /* @__PURE__ */ jsx(
59
- "line",
60
- {
61
- class: "rr-local-graph__edge",
62
- "data-direction": edge.source === props.graph.currentSlug ? "outgoing" : "backlink",
63
- x1: source.x,
64
- y1: source.y,
65
- x2: target.x,
66
- y2: target.y
67
- },
68
- `${edge.source}-${edge.target}`
69
- );
70
- }),
71
- props.graph.nodes.map((node) => {
72
- const point = layout.get(node.slug);
73
- if (!point) return null;
74
- const isCurrent = node.slug === props.graph.currentSlug;
75
- return /* @__PURE__ */ jsx(
76
- "g",
24
+ return /* @__PURE__ */ jsxs("section", { class: "rr-local-graph", "aria-labelledby": "local-graph-title", children: [
25
+ /* @__PURE__ */ jsxs("div", { class: "rr-local-graph__header", children: [
26
+ /* @__PURE__ */ jsxs("div", { children: [
27
+ /* @__PURE__ */ jsx("p", { class: "rr-local-graph__eyebrow", children: "Local Graph" }),
28
+ /* @__PURE__ */ jsx("h2", { id: "local-graph-title", children: "Nearby Notes" })
29
+ ] }),
30
+ /* @__PURE__ */ jsx(
31
+ "a",
32
+ {
33
+ class: "rr-local-graph__explorer-link",
34
+ href: `/explore?note=${encodeURIComponent(props.graph.currentSlug)}`,
35
+ children: "Open in Explorer →"
36
+ }
37
+ )
38
+ ] }),
39
+ /* @__PURE__ */ jsxs(
40
+ "svg",
41
+ {
42
+ class: "rr-local-graph__canvas",
43
+ viewBox: `0 0 ${GRAPH_WIDTH} ${GRAPH_HEIGHT}`,
44
+ role: "img",
45
+ "aria-label": "Local graph of outgoing links and backlinks",
46
+ children: [
47
+ edges.map((edge) => {
48
+ const source = layout.get(edge.source);
49
+ const target = layout.get(edge.target);
50
+ if (!source || !target) return null;
51
+ return /* @__PURE__ */ jsx(
52
+ "line",
53
+ {
54
+ class: "rr-local-graph__edge",
55
+ "data-direction": edge.source === props.graph.currentSlug ? "outgoing" : "backlink",
56
+ x1: source.x,
57
+ y1: source.y,
58
+ x2: target.x,
59
+ y2: target.y
60
+ },
61
+ `${edge.source}-${edge.target}`
62
+ );
63
+ }),
64
+ props.graph.nodes.map((node) => {
65
+ const point = layout.get(node.slug);
66
+ if (!point) return null;
67
+ const isCurrent = node.slug === props.graph.currentSlug;
68
+ return /* @__PURE__ */ jsx(
69
+ "g",
70
+ {
71
+ class: "rr-local-graph__node",
72
+ "data-relation": node.relation,
73
+ children: /* @__PURE__ */ jsxs(
74
+ "a",
77
75
  {
78
- class: "rr-local-graph__node",
79
- "data-relation": node.relation,
80
- children: /* @__PURE__ */ jsxs(
81
- "a",
82
- {
83
- href: node.permalink,
84
- "aria-label": isCurrent ? `Current note: ${node.title}` : `Open ${node.title}`,
85
- children: [
86
- /* @__PURE__ */ jsx(
87
- "circle",
88
- {
89
- cx: point.x,
90
- cy: point.y,
91
- r: isCurrent ? 16 : point.radius
92
- }
93
- ),
94
- /* @__PURE__ */ jsx(
95
- "text",
96
- {
97
- x: point.x + (isCurrent ? 20 : 16),
98
- y: point.y + 5,
99
- "text-anchor": point.x > GRAPH_WIDTH * 0.78 ? "end" : "start",
100
- dx: point.x > GRAPH_WIDTH * 0.78 ? -32 : 0,
101
- children: node.title
102
- }
103
- )
104
- ]
105
- }
106
- )
107
- },
108
- node.slug
109
- );
110
- })
111
- ]
112
- }
113
- ),
114
- /* @__PURE__ */ jsxs("div", { class: "rr-local-graph__legend", children: [
115
- /* @__PURE__ */ jsxs("span", { children: [
116
- /* @__PURE__ */ jsx("i", { "data-kind": "current" }),
117
- "Current"
118
- ] }),
119
- /* @__PURE__ */ jsxs("span", { children: [
120
- /* @__PURE__ */ jsx("i", { "data-kind": "outgoing" }),
121
- "Outgoing"
122
- ] }),
123
- /* @__PURE__ */ jsxs("span", { children: [
124
- /* @__PURE__ */ jsx("i", { "data-kind": "backlink" }),
125
- "Backlink"
126
- ] })
127
- ] })
128
- ]
129
- }
130
- );
131
- }
76
+ href: node.permalink,
77
+ "aria-label": isCurrent ? `Current note: ${node.title}` : `Open ${node.title}`,
78
+ children: [
79
+ /* @__PURE__ */ jsx(
80
+ "circle",
81
+ {
82
+ cx: point.x,
83
+ cy: point.y,
84
+ r: isCurrent ? 16 : point.radius
85
+ }
86
+ ),
87
+ /* @__PURE__ */ jsx(
88
+ "text",
89
+ {
90
+ x: point.x + (isCurrent ? 20 : 16),
91
+ y: point.y + 5,
92
+ "text-anchor": point.x > GRAPH_WIDTH * 0.78 ? "end" : "start",
93
+ dx: point.x > GRAPH_WIDTH * 0.78 ? -32 : 0,
94
+ children: node.title
95
+ }
96
+ )
97
+ ]
98
+ }
99
+ )
100
+ },
101
+ node.slug
102
+ );
103
+ })
104
+ ]
105
+ }
106
+ ),
107
+ /* @__PURE__ */ jsxs("div", { class: "rr-local-graph__legend", children: [
108
+ /* @__PURE__ */ jsxs("span", { children: [
109
+ /* @__PURE__ */ jsx("i", { "data-kind": "current" }),
110
+ "Current"
111
+ ] }),
112
+ /* @__PURE__ */ jsxs("span", { children: [
113
+ /* @__PURE__ */ jsx("i", { "data-kind": "outgoing" }),
114
+ "Outgoing"
115
+ ] }),
116
+ /* @__PURE__ */ jsxs("span", { children: [
117
+ /* @__PURE__ */ jsx("i", { "data-kind": "backlink" }),
118
+ "Backlink"
119
+ ] })
120
+ ] })
121
+ ] });
122
+ });
123
+ var local_graph_default = LocalGraph;
132
124
 
133
125
  // src/local-graph.server.ts
134
126
  var MAX_NEIGHBORS_PER_DIRECTION = 10;
135
- function getLocalGraph(args) {
127
+ function buildLocalGraph(args) {
136
128
  const graph = args.manifest.graph;
137
129
  const current = graph.get(args.slug);
138
130
  const discoverableSlugs = new Set(
@@ -176,6 +168,28 @@ function getLocalGraph(args) {
176
168
  };
177
169
  }
178
170
  }
171
+ var getLocalGraph = ({ view, slug }) => {
172
+ const current = view.findDiscoverableBySlug(slug);
173
+ if (!current) return null;
174
+ const outgoing = view.getDiscoverableOutgoing(slug).slice(0, MAX_NEIGHBORS_PER_DIRECTION);
175
+ const incoming = view.getDiscoverableIncoming(slug).slice(0, MAX_NEIGHBORS_PER_DIRECTION);
176
+ const outgoingSlugs = outgoing.map((entry) => entry.slug);
177
+ const incomingSlugs = incoming.map((entry) => entry.slug);
178
+ const entries = [current, ...outgoing, ...incoming].filter(
179
+ (entry, index, all) => all.findIndex((candidate) => candidate.slug === entry.slug) === index
180
+ );
181
+ return {
182
+ currentSlug: slug,
183
+ nodes: entries.map((entry) => ({
184
+ slug: entry.slug,
185
+ permalink: entry.permalink,
186
+ title: entry.title || entry.slug,
187
+ relation: getRelation(entry.slug, slug, outgoingSlugs, incomingSlugs),
188
+ outgoing: entry.slug === slug ? outgoingSlugs : incomingSlugs.includes(entry.slug) ? [slug] : [],
189
+ backlinks: entry.slug === slug ? incomingSlugs : outgoingSlugs.includes(entry.slug) ? [slug] : []
190
+ }))
191
+ };
192
+ };
179
193
  function getRelation(slug, currentSlug, outgoing, backlinks) {
180
194
  if (slug === currentSlug) return "current";
181
195
  const isOutgoing = outgoing.includes(slug);
@@ -190,25 +204,6 @@ function localGraphPlugin(options = {}) {
190
204
  name: "local-graph",
191
205
  order: 400,
192
206
  options,
193
- validateOptions: validateLocalGraphOptions,
194
- onManifestCreated: ({ config, manifest }) => {
195
- if (options.render === false) return;
196
- if (!config) return;
197
- for (const entry of manifest.discoverableEntries) {
198
- const graph = getLocalGraph({
199
- manifest,
200
- config,
201
- slug: entry.slug,
202
- resolveTitle
203
- });
204
- if (!graph || graph.nodes.length <= 1) continue;
205
- appendContentBodySlot(
206
- entry,
207
- "article.footer",
208
- renderToString(LocalGraph({ graph }))
209
- );
210
- }
211
- },
212
207
  assets: [
213
208
  {
214
209
  pluginName: "local-graph",
@@ -218,19 +213,10 @@ function localGraphPlugin(options = {}) {
218
213
  ]
219
214
  });
220
215
  }
221
- function validateLocalGraphOptions(options) {
222
- if (!options || options.render === void 0 || typeof options.render === "boolean") {
223
- return [];
224
- }
225
- return [{ path: "render", message: "Expected a boolean." }];
226
- }
227
- function resolveTitle(slug, title) {
228
- if (typeof title === "string" && title.trim()) return title;
229
- return slug.split("/").at(-1) ?? slug;
230
- }
231
216
  export {
232
- LocalGraph,
217
+ local_graph_default as LocalGraph,
233
218
  buildGraphEdges2 as buildGraphEdges,
219
+ buildLocalGraph,
234
220
  getLocalGraph,
235
221
  layoutRadialGraph2 as layoutRadialGraph,
236
222
  localGraphPlugin
@@ -1,10 +1,14 @@
1
- import type { ContentManifest, ResolvedRiebeckiteConfig } from "@riebeckite/core";
1
+ import type { ContentManifest, PluginDataHelper, PublicContentView, ResolvedRiebeckiteConfig } from "@riebeckite/core";
2
2
  import type { LocalGraphData } from "./local-graph.js";
3
3
  type TitleResolver = (slug: string, title: unknown) => string;
4
- export declare function getLocalGraph(args: {
4
+ export declare function buildLocalGraph(args: {
5
5
  manifest: ContentManifest;
6
6
  config: ResolvedRiebeckiteConfig;
7
7
  slug: string;
8
8
  resolveTitle: TitleResolver;
9
9
  }): LocalGraphData | null;
10
+ export declare const getLocalGraph: PluginDataHelper<{
11
+ view: PublicContentView;
12
+ slug: string;
13
+ }, LocalGraphData | null>;
10
14
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riebeckite/plugin-local-graph",
3
- "version": "0.0.22",
3
+ "version": "0.0.23",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -22,11 +22,11 @@
22
22
  },
23
23
  "dependencies": {
24
24
  "hono": "^4.12.25",
25
- "@riebeckite/core": "0.0.22"
25
+ "@riebeckite/core": "0.0.23"
26
26
  },
27
27
  "devDependencies": {
28
28
  "tsx": "^4.22.4",
29
- "@riebeckite/test": "0.0.22"
29
+ "@riebeckite/test": "0.0.23"
30
30
  },
31
31
  "publishConfig": {
32
32
  "access": "public"