@riebeckite/plugin-local-graph 0.0.19 → 0.0.21

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
@@ -5,7 +5,7 @@ outgoing links and backlinks.
5
5
 
6
6
  [日本語](./README_ja.md)
7
7
 
8
- ## Overview
8
+ ## Recommended placement
9
9
 
10
10
  `localGraph()` provides a `LocalGraph` component that renders the current note
11
11
  plus its direct links as an SVG radial graph. `getLocalGraph()` collects the
@@ -22,7 +22,11 @@ Relations are tagged per node:
22
22
 
23
23
  The component renders nothing when there is no published neighbor.
24
24
 
25
- ## Usage
25
+ `localGraphPlugin()` automatically contributes this component to
26
+ `article.footer`. The Site decides where that semantic slot is rendered; the
27
+ official Starter renders it after article content.
28
+
29
+ ## Quick Start
26
30
 
27
31
  ```ts
28
32
  import { defineConfig } from "@riebeckite/core";
@@ -34,15 +38,19 @@ export default defineConfig({
34
38
  });
35
39
  ```
36
40
 
37
- `localGraphPlugin()` registers the plugin in the plugin list and bundles
38
- `style.css` into the app stylesheet.
41
+ `localGraphPlugin()` registers the plugin and bundles `style.css` into the app
42
+ stylesheet. Render `<ContentSlot slots={bodySlots} name="article.footer" />`
43
+ once in the article layout to show automatic output.
44
+
45
+ ## Advanced customization
39
46
 
40
- ### Render the component
47
+ Set `render: false` to use the public data resolver and component in a
48
+ Site-owned location without duplicating the automatic footer. This leaves graph
49
+ generation and published-neighbor filtering intact.
41
50
 
42
51
  ```tsx
43
52
  import LocalGraph, { getLocalGraph } from "@riebeckite/plugin-local-graph";
44
- import { config } from "../config";
45
- import { content } from "../content";
53
+ import { content } from "virtual:riebeckite/content";
46
54
  import { getArticleTitle } from "../lib/article-title";
47
55
 
48
56
  const manifest = await content.getManifest();
@@ -55,12 +63,22 @@ const graph = getLocalGraph({
55
63
 
56
64
  // ...in your route
57
65
  return (
58
- <Article
59
- footerContent={graph && <LocalGraph graph={graph} />}
60
- />
66
+ <aside>{graph && <LocalGraph graph={graph} />}</aside>
61
67
  );
62
68
  ```
63
69
 
70
+ ```ts
71
+ plugins: [localGraphPlugin({ render: false })];
72
+ ```
73
+
74
+ Remove the component to remove manually placed UI.
75
+
76
+ ## Configuration
77
+
78
+ | Option | Type | Default | Description |
79
+ | --- | --- | --- | --- |
80
+ | `render` | `boolean` | `true` | Append the graph to `article.footer`. Set `false` for manual placement. |
81
+
64
82
  ## Graph layout
65
83
 
66
84
  Node positions come from `layoutRadialGraph()`: the center node sits at the
@@ -81,6 +99,6 @@ internal selection key `/explore?note=<slug>`.
81
99
 
82
100
  ## See also
83
101
 
84
- - [Plugin guide](../../../docs/docs/reference/plugin-api.en.md)
102
+ - [Plugin guide](../../../docs/docs/reference/plugin-api.md)
85
103
  - [`@riebeckite/plugin-backlinks`](../backlinks/README.md)
86
104
  - [`@riebeckite/plugin-garden-explorer`](../garden-explorer/README.md)
package/README_ja.md CHANGED
@@ -4,13 +4,15 @@
4
4
 
5
5
  [English](./README.md)
6
6
 
7
- ## できること
7
+ ## 推奨配置
8
8
 
9
9
  `getLocalGraph()` はマニフェストからリンク先と被リンク元を集め、公開済みノートだけを残します。各方向は最大 10 件です。`LocalGraph` はそのデータを SVG として描画し、周辺ノートがなければ何も表示しません。
10
10
 
11
+ `localGraphPlugin()` は既定で `article.footer` slot に自動追加します。物理的な位置は Site が決め、公式 Starter は記事本文の後でこの slot を描画します。
12
+
11
13
  ノードには `current`、`outgoing`、`backlink`、`both` の関係が付きます。中央が現在のノート、周囲が直接つながるノートです。
12
14
 
13
- ## 設定と配置
15
+ ## クイックスタート
14
16
 
15
17
  ```ts
16
18
  import { defineConfig } from "@riebeckite/core";
@@ -19,6 +21,12 @@ import { localGraphPlugin } from "@riebeckite/plugin-local-graph";
19
21
  export default defineConfig({ plugins: [localGraphPlugin()] });
20
22
  ```
21
23
 
24
+ 記事レイアウトで `<ContentSlot slots={bodySlots} name="article.footer" />` を一度描画します。
25
+
26
+ ## 高度なカスタマイズ
27
+
28
+ 重複させずに Site 側で配置を決めるには、`render: false` を指定します。グラフの生成と公開済み近傍だけを残すフィルタリングは維持されます。
29
+
22
30
  ```tsx
23
31
  import LocalGraph, { getLocalGraph } from "@riebeckite/plugin-local-graph";
24
32
 
@@ -26,6 +34,16 @@ const graph = getLocalGraph({ manifest: await content.getManifest(), config, slu
26
34
  return <Article footerContent={graph && <LocalGraph graph={graph} />} />;
27
35
  ```
28
36
 
37
+ ```ts
38
+ plugins: [localGraphPlugin({ render: false })];
39
+ ```
40
+
41
+ ## 設定
42
+
43
+ | オプション | 型 | 既定値 | 説明 |
44
+ | --- | --- | --- | --- |
45
+ | `render` | `boolean` | `true` | `article.footer` への自動追加。手動配置では `false`。 |
46
+
29
47
  グラフのノード位置は `layoutRadialGraph()`、辺は `buildGraphEdges()` が計算します。各ノードのリンクは解決済みの `permalink` を使い、見出しは internal selection key `/explore?note=<slug>` で Explorer を開きます。
30
48
 
31
49
  ## 公開 API
@@ -37,7 +55,6 @@ return <Article footerContent={graph && <LocalGraph graph={graph} />} />;
37
55
 
38
56
  ## 関連資料
39
57
 
40
- - [プラグインシステム](../../../docs/docs/reference/plugin-api.md)
58
+ - [プラグインシステム](../../../docs/docs/reference/plugin-api.ja.md)
41
59
  - [`@riebeckite/plugin-backlinks`](../backlinks/README_ja.md)
42
60
  - [`@riebeckite/plugin-garden-explorer`](../garden-explorer/README_ja.md)
43
-
@@ -17,18 +17,18 @@ function LocalGraph(props) {
17
17
  return /* @__PURE__ */ jsxs(
18
18
  "section",
19
19
  {
20
- class: "local-graph rr-local-graph max-w-4xl mx-auto px-4",
20
+ class: "rr-local-graph max-w-4xl mx-auto px-4",
21
21
  "aria-labelledby": "local-graph-title",
22
22
  children: [
23
- /* @__PURE__ */ jsxs("div", { class: "local-graph__header", children: [
23
+ /* @__PURE__ */ jsxs("div", { class: "rr-local-graph__header", children: [
24
24
  /* @__PURE__ */ jsxs("div", { children: [
25
- /* @__PURE__ */ jsx("p", { class: "local-graph__eyebrow", children: "Local Graph" }),
25
+ /* @__PURE__ */ jsx("p", { class: "rr-local-graph__eyebrow", children: "Local Graph" }),
26
26
  /* @__PURE__ */ jsx("h2", { id: "local-graph-title", children: "Nearby Notes" })
27
27
  ] }),
28
28
  /* @__PURE__ */ jsx(
29
29
  "a",
30
30
  {
31
- class: "local-graph__explorer-link",
31
+ class: "rr-local-graph__explorer-link",
32
32
  href: `/explore?note=${encodeURIComponent(props.graph.currentSlug)}`,
33
33
  children: "Open in Explorer →"
34
34
  }
@@ -37,7 +37,7 @@ function LocalGraph(props) {
37
37
  /* @__PURE__ */ jsxs(
38
38
  "svg",
39
39
  {
40
- class: "local-graph__canvas",
40
+ class: "rr-local-graph__canvas",
41
41
  viewBox: `0 0 ${GRAPH_WIDTH} ${GRAPH_HEIGHT}`,
42
42
  role: "img",
43
43
  "aria-label": "Local graph of outgoing links and backlinks",
@@ -49,7 +49,7 @@ function LocalGraph(props) {
49
49
  return /* @__PURE__ */ jsx(
50
50
  "line",
51
51
  {
52
- class: "local-graph__edge",
52
+ class: "rr-local-graph__edge",
53
53
  "data-direction": edge.source === props.graph.currentSlug ? "outgoing" : "backlink",
54
54
  x1: source.x,
55
55
  y1: source.y,
@@ -66,7 +66,7 @@ function LocalGraph(props) {
66
66
  return /* @__PURE__ */ jsx(
67
67
  "g",
68
68
  {
69
- class: "local-graph__node",
69
+ class: "rr-local-graph__node",
70
70
  "data-relation": node.relation,
71
71
  children: /* @__PURE__ */ jsxs(
72
72
  "a",
@@ -102,7 +102,7 @@ function LocalGraph(props) {
102
102
  ]
103
103
  }
104
104
  ),
105
- /* @__PURE__ */ jsxs("div", { class: "local-graph__legend", children: [
105
+ /* @__PURE__ */ jsxs("div", { class: "rr-local-graph__legend", children: [
106
106
  /* @__PURE__ */ jsxs("span", { children: [
107
107
  /* @__PURE__ */ jsx("i", { "data-kind": "current" }),
108
108
  "Current"
package/dist/index.d.ts CHANGED
@@ -3,4 +3,7 @@ export { default as LocalGraph } from "./components/local-graph.js";
3
3
  export type { LocalGraphData, LocalGraphNode, LocalGraphNodeRelation, } from "./src/local-graph.js";
4
4
  export { getLocalGraph } from "./src/local-graph.server.js";
5
5
  export { buildGraphEdges, layoutRadialGraph };
6
- export declare function localGraphPlugin(): import("@riebeckite/core").RiebeckitePlugin<unknown>;
6
+ export type LocalGraphOptions = {
7
+ render?: boolean;
8
+ };
9
+ export declare function localGraphPlugin(options?: LocalGraphOptions): import("@riebeckite/core").RiebeckitePlugin<LocalGraphOptions>;
package/dist/index.js CHANGED
@@ -26,18 +26,18 @@ function LocalGraph(props) {
26
26
  return /* @__PURE__ */ jsxs(
27
27
  "section",
28
28
  {
29
- class: "local-graph rr-local-graph max-w-4xl mx-auto px-4",
29
+ class: "rr-local-graph max-w-4xl mx-auto px-4",
30
30
  "aria-labelledby": "local-graph-title",
31
31
  children: [
32
- /* @__PURE__ */ jsxs("div", { class: "local-graph__header", children: [
32
+ /* @__PURE__ */ jsxs("div", { class: "rr-local-graph__header", children: [
33
33
  /* @__PURE__ */ jsxs("div", { children: [
34
- /* @__PURE__ */ jsx("p", { class: "local-graph__eyebrow", children: "Local Graph" }),
34
+ /* @__PURE__ */ jsx("p", { class: "rr-local-graph__eyebrow", children: "Local Graph" }),
35
35
  /* @__PURE__ */ jsx("h2", { id: "local-graph-title", children: "Nearby Notes" })
36
36
  ] }),
37
37
  /* @__PURE__ */ jsx(
38
38
  "a",
39
39
  {
40
- class: "local-graph__explorer-link",
40
+ class: "rr-local-graph__explorer-link",
41
41
  href: `/explore?note=${encodeURIComponent(props.graph.currentSlug)}`,
42
42
  children: "Open in Explorer →"
43
43
  }
@@ -46,7 +46,7 @@ function LocalGraph(props) {
46
46
  /* @__PURE__ */ jsxs(
47
47
  "svg",
48
48
  {
49
- class: "local-graph__canvas",
49
+ class: "rr-local-graph__canvas",
50
50
  viewBox: `0 0 ${GRAPH_WIDTH} ${GRAPH_HEIGHT}`,
51
51
  role: "img",
52
52
  "aria-label": "Local graph of outgoing links and backlinks",
@@ -58,7 +58,7 @@ function LocalGraph(props) {
58
58
  return /* @__PURE__ */ jsx(
59
59
  "line",
60
60
  {
61
- class: "local-graph__edge",
61
+ class: "rr-local-graph__edge",
62
62
  "data-direction": edge.source === props.graph.currentSlug ? "outgoing" : "backlink",
63
63
  x1: source.x,
64
64
  y1: source.y,
@@ -75,7 +75,7 @@ function LocalGraph(props) {
75
75
  return /* @__PURE__ */ jsx(
76
76
  "g",
77
77
  {
78
- class: "local-graph__node",
78
+ class: "rr-local-graph__node",
79
79
  "data-relation": node.relation,
80
80
  children: /* @__PURE__ */ jsxs(
81
81
  "a",
@@ -111,7 +111,7 @@ function LocalGraph(props) {
111
111
  ]
112
112
  }
113
113
  ),
114
- /* @__PURE__ */ jsxs("div", { class: "local-graph__legend", children: [
114
+ /* @__PURE__ */ jsxs("div", { class: "rr-local-graph__legend", children: [
115
115
  /* @__PURE__ */ jsxs("span", { children: [
116
116
  /* @__PURE__ */ jsx("i", { "data-kind": "current" }),
117
117
  "Current"
@@ -185,11 +185,14 @@ function getRelation(slug, currentSlug, outgoing, backlinks) {
185
185
  }
186
186
 
187
187
  // index.ts
188
- function localGraphPlugin() {
188
+ function localGraphPlugin(options = {}) {
189
189
  return definePlugin({
190
190
  name: "local-graph",
191
191
  order: 400,
192
+ options,
193
+ validateOptions: validateLocalGraphOptions,
192
194
  onManifestCreated: ({ config, manifest }) => {
195
+ if (options.render === false) return;
193
196
  if (!config) return;
194
197
  for (const entry of manifest.discoverableEntries) {
195
198
  const graph = getLocalGraph({
@@ -215,6 +218,12 @@ function localGraphPlugin() {
215
218
  ]
216
219
  });
217
220
  }
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
+ }
218
227
  function resolveTitle(slug, title) {
219
228
  if (typeof title === "string" && title.trim()) return title;
220
229
  return slug.split("/").at(-1) ?? slug;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riebeckite/plugin-local-graph",
3
- "version": "0.0.19",
3
+ "version": "0.0.21",
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.19"
25
+ "@riebeckite/core": "0.0.21"
26
26
  },
27
27
  "devDependencies": {
28
28
  "tsx": "^4.22.4",
29
- "@riebeckite/test": "0.0.19"
29
+ "@riebeckite/test": "0.0.21"
30
30
  },
31
31
  "publishConfig": {
32
32
  "access": "public"
package/style.css CHANGED
@@ -1,11 +1,11 @@
1
1
  @layer components {
2
- .local-graph {
2
+ .rr-local-graph {
3
3
  margin-block-start: var(--rb-space-6, 3rem);
4
4
  padding-top: 1.5rem;
5
5
  border-top: var(--rb-rule-width) solid var(--rb-color-border);
6
6
  }
7
7
 
8
- .local-graph__header {
8
+ .rr-local-graph__header {
9
9
  display: flex;
10
10
  justify-content: space-between;
11
11
  align-items: end;
@@ -13,7 +13,7 @@
13
13
  margin-bottom: var(--rb-space-1);
14
14
  }
15
15
 
16
- .local-graph__eyebrow {
16
+ .rr-local-graph__eyebrow {
17
17
  margin: 0 0 0.25rem;
18
18
  color: var(--rb-color-muted);
19
19
  font-size: 0.75rem;
@@ -22,13 +22,13 @@
22
22
  text-transform: uppercase;
23
23
  }
24
24
 
25
- .local-graph h2 {
25
+ .rr-local-graph h2 {
26
26
  margin: 0;
27
27
  font-size: clamp(1.4rem, 4vw, 2rem);
28
28
  line-height: 1.1;
29
29
  }
30
30
 
31
- .local-graph__explorer-link {
31
+ .rr-local-graph__explorer-link {
32
32
  flex: none;
33
33
  color: var(--rb-color-ink);
34
34
  font-size: 0.9rem;
@@ -37,13 +37,13 @@
37
37
  border-bottom: var(--rb-rule-width) solid currentColor;
38
38
  }
39
39
 
40
- .local-graph__explorer-link:focus-visible,
41
- .local-graph__node a:focus-visible {
40
+ .rr-local-graph__explorer-link:focus-visible,
41
+ .rr-local-graph__node a:focus-visible {
42
42
  outline: 2px solid var(--rb-color-accent);
43
43
  outline-offset: 2px;
44
44
  }
45
45
 
46
- .local-graph__canvas {
46
+ .rr-local-graph__canvas {
47
47
  display: block;
48
48
  width: 100%;
49
49
  min-height: 16rem;
@@ -54,54 +54,54 @@
54
54
  background-size: 40px 40px;
55
55
  }
56
56
 
57
- .local-graph__edge {
57
+ .rr-local-graph__edge {
58
58
  stroke: var(--rb-color-border);
59
59
  stroke-width: 1.2;
60
60
  }
61
61
 
62
- .local-graph__edge[data-direction="backlink"] {
62
+ .rr-local-graph__edge[data-direction="backlink"] {
63
63
  stroke-dasharray: 4 4;
64
64
  }
65
65
 
66
- .local-graph__node a {
66
+ .rr-local-graph__node a {
67
67
  color: var(--rb-color-ink);
68
68
  cursor: pointer;
69
69
  text-decoration: none;
70
70
  }
71
71
 
72
- .local-graph__node circle {
72
+ .rr-local-graph__node circle {
73
73
  fill: var(--rb-color-paper);
74
74
  stroke: var(--rb-color-ink);
75
75
  stroke-width: 1.5;
76
76
  }
77
77
 
78
- .local-graph__node[data-relation="current"] circle {
78
+ .rr-local-graph__node[data-relation="current"] circle {
79
79
  fill: var(--rb-color-accent);
80
80
  stroke: var(--rb-color-accent);
81
81
  }
82
82
 
83
- .local-graph__node[data-relation="backlink"] circle {
83
+ .rr-local-graph__node[data-relation="backlink"] circle {
84
84
  stroke-dasharray: 3 3;
85
85
  }
86
86
 
87
- .local-graph__node[data-relation="both"] circle {
87
+ .rr-local-graph__node[data-relation="both"] circle {
88
88
  fill: color-mix(in srgb, var(--rb-color-accent) 18%, var(--rb-color-paper));
89
89
  }
90
90
 
91
- .local-graph__node text {
91
+ .rr-local-graph__node text {
92
92
  fill: currentColor;
93
93
  font-size: 0.78rem;
94
94
  font-weight: 600;
95
95
  pointer-events: none;
96
96
  }
97
97
 
98
- .local-graph__explorer-link:hover,
99
- .local-graph__node a:hover text {
98
+ .rr-local-graph__explorer-link:hover,
99
+ .rr-local-graph__node a:hover text {
100
100
  color: var(--rb-color-accent);
101
101
  fill: var(--rb-color-accent);
102
102
  }
103
103
 
104
- .local-graph__legend {
104
+ .rr-local-graph__legend {
105
105
  display: flex;
106
106
  flex-wrap: wrap;
107
107
  gap: var(--rb-space-1);
@@ -110,39 +110,39 @@
110
110
  font-size: 0.8rem;
111
111
  }
112
112
 
113
- .local-graph__legend span {
113
+ .rr-local-graph__legend span {
114
114
  display: inline-flex;
115
115
  align-items: center;
116
116
  gap: 0.4rem;
117
117
  }
118
118
 
119
- .local-graph__legend i {
119
+ .rr-local-graph__legend i {
120
120
  width: 0.75rem;
121
121
  height: 0.75rem;
122
122
  border: var(--rb-rule-width) solid var(--rb-color-ink);
123
123
  border-radius: 999px;
124
124
  }
125
125
 
126
- .local-graph__legend i[data-kind="current"] {
126
+ .rr-local-graph__legend i[data-kind="current"] {
127
127
  background: var(--rb-color-accent);
128
128
  border-color: var(--rb-color-accent);
129
129
  }
130
130
 
131
- .local-graph__legend i[data-kind="backlink"] {
131
+ .rr-local-graph__legend i[data-kind="backlink"] {
132
132
  border-style: dashed;
133
133
  }
134
134
 
135
135
  @media (max-width: 640px) {
136
- .local-graph__header {
136
+ .rr-local-graph__header {
137
137
  display: grid;
138
138
  align-items: start;
139
139
  }
140
140
 
141
- .local-graph__canvas {
141
+ .rr-local-graph__canvas {
142
142
  min-height: 13rem;
143
143
  }
144
144
 
145
- .local-graph__node text {
145
+ .rr-local-graph__node text {
146
146
  font-size: 0.68rem;
147
147
  }
148
148
  }