@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 +11 -26
- package/README_ja.md +7 -18
- package/dist/components/local-graph.d.ts +3 -3
- package/dist/components/local-graph.js +101 -107
- package/dist/index.d.ts +3 -4
- package/dist/index.js +125 -139
- package/dist/src/local-graph.server.d.ts +6 -2
- package/package.json +3 -3
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
|
|
15
|
-
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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.
|
|
45
|
-
|
|
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
|
|
50
|
-
Site-owned location without duplicating the automatic
|
|
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
|
-
|
|
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
|
-
記事レイアウトで `<
|
|
22
|
+
記事レイアウトで `<LocalGraph />` コンポーネントを一度描画します。
|
|
23
|
+
|
|
24
|
+
## 設定
|
|
25
|
+
|
|
26
|
+
`localGraphPlugin()` にはプラグイン用のオプションがありません。`LocalGraph` コンポーネントは `graph` 必須プロップを受け取ります。
|
|
27
27
|
|
|
28
28
|
## 高度なカスタマイズ
|
|
29
29
|
|
|
30
|
-
|
|
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
|
|
2
|
+
export type LocalGraphProps = {
|
|
3
3
|
graph: LocalGraphData;
|
|
4
4
|
};
|
|
5
|
-
|
|
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
|
-
|
|
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
|
-
"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
-
|
|
53
|
-
"
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
"
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
"
|
|
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
|
-
|
|
79
|
-
"
|
|
80
|
-
children:
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
25
|
+
"@riebeckite/core": "0.0.23"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"tsx": "^4.22.4",
|
|
29
|
-
"@riebeckite/test": "0.0.
|
|
29
|
+
"@riebeckite/test": "0.0.23"
|
|
30
30
|
},
|
|
31
31
|
"publishConfig": {
|
|
32
32
|
"access": "public"
|