@riebeckite/plugin-local-graph 0.0.24 → 0.0.25

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.
@@ -1,6 +1,6 @@
1
1
  import type { LocalGraphData } from "../src/local-graph.js";
2
2
  export type LocalGraphProps = {
3
- graph: LocalGraphData;
3
+ graph?: LocalGraphData | null;
4
4
  };
5
- declare const LocalGraph: (props: Readonly<LocalGraphProps>) => import("hono/jsx/jsx-dev-runtime").JSX.Element;
5
+ declare const LocalGraph: (props: Readonly<LocalGraphProps>) => Promise<import("hono/utils/html").HtmlEscapedString>;
6
6
  export default LocalGraph;
@@ -1,15 +1,54 @@
1
1
  // components/local-graph.tsx
2
2
  import { buildGraphEdges, layoutRadialGraph } from "@riebeckite/core";
3
+ import { useArticleContext, useSiteContext } from "@riebeckite/ui";
4
+ import { html } from "hono/html";
5
+
6
+ // src/local-graph.server.ts
7
+ var MAX_NEIGHBORS_PER_DIRECTION = 10;
8
+ var getLocalGraph = ({ view, slug }) => {
9
+ const current = view.findDiscoverableBySlug(slug);
10
+ if (!current) return null;
11
+ const outgoing = view.getDiscoverableOutgoing(slug).slice(0, MAX_NEIGHBORS_PER_DIRECTION);
12
+ const incoming = view.getDiscoverableIncoming(slug).slice(0, MAX_NEIGHBORS_PER_DIRECTION);
13
+ const outgoingSlugs = outgoing.map((entry) => entry.slug);
14
+ const incomingSlugs = incoming.map((entry) => entry.slug);
15
+ const entries = [current, ...outgoing, ...incoming].filter(
16
+ (entry, index, all) => all.findIndex((candidate) => candidate.slug === entry.slug) === index
17
+ );
18
+ return {
19
+ currentSlug: slug,
20
+ nodes: entries.map((entry) => ({
21
+ slug: entry.slug,
22
+ permalink: entry.permalink,
23
+ title: entry.title || entry.slug,
24
+ relation: getRelation(entry.slug, slug, outgoingSlugs, incomingSlugs),
25
+ outgoing: entry.slug === slug ? outgoingSlugs : incomingSlugs.includes(entry.slug) ? [slug] : [],
26
+ backlinks: entry.slug === slug ? incomingSlugs : outgoingSlugs.includes(entry.slug) ? [slug] : []
27
+ }))
28
+ };
29
+ };
30
+ function getRelation(slug, currentSlug, outgoing, backlinks) {
31
+ if (slug === currentSlug) return "current";
32
+ const isOutgoing = outgoing.includes(slug);
33
+ const isBacklink = backlinks.includes(slug);
34
+ if (isOutgoing && isBacklink) return "both";
35
+ return isOutgoing ? "outgoing" : "backlink";
36
+ }
37
+
38
+ // components/local-graph.tsx
3
39
  import { jsx, jsxs } from "hono/jsx/jsx-runtime";
4
40
  var GRAPH_WIDTH = 640;
5
41
  var GRAPH_HEIGHT = 320;
6
- var LocalGraph = ((props) => {
7
- if (props.graph.nodes.length <= 1) return null;
8
- const edges = buildGraphEdges(props.graph.nodes);
9
- const layout = layoutRadialGraph(props.graph.nodes, {
42
+ var LocalGraph = (async (props) => {
43
+ const site = useSiteContext();
44
+ const article = useArticleContext();
45
+ const graph = props.graph ?? (site && article?.entry ? await getLocalGraph({ view: site.view, slug: article.entry.slug }) : null);
46
+ if (!graph || graph.nodes.length <= 1) return html``;
47
+ const edges = buildGraphEdges(graph.nodes);
48
+ const layout = layoutRadialGraph(graph.nodes, {
10
49
  width: GRAPH_WIDTH,
11
50
  height: GRAPH_HEIGHT,
12
- centerSlug: props.graph.currentSlug,
51
+ centerSlug: graph.currentSlug,
13
52
  radiusRatio: 0.34,
14
53
  minNodeRadius: 7,
15
54
  maxNodeRadius: 12
@@ -24,7 +63,7 @@ var LocalGraph = ((props) => {
24
63
  "a",
25
64
  {
26
65
  class: "rr-local-graph__explorer-link",
27
- href: `/explore?note=${encodeURIComponent(props.graph.currentSlug)}`,
66
+ href: `/explore?note=${encodeURIComponent(graph.currentSlug)}`,
28
67
  children: "Open in Explorer →"
29
68
  }
30
69
  )
@@ -45,7 +84,7 @@ var LocalGraph = ((props) => {
45
84
  "line",
46
85
  {
47
86
  class: "rr-local-graph__edge",
48
- "data-direction": edge.source === props.graph.currentSlug ? "outgoing" : "backlink",
87
+ "data-direction": edge.source === graph.currentSlug ? "outgoing" : "backlink",
49
88
  x1: source.x,
50
89
  y1: source.y,
51
90
  x2: target.x,
@@ -54,10 +93,10 @@ var LocalGraph = ((props) => {
54
93
  `${edge.source}-${edge.target}`
55
94
  );
56
95
  }),
57
- props.graph.nodes.map((node) => {
96
+ graph.nodes.map((node) => {
58
97
  const point = layout.get(node.slug);
59
98
  if (!point) return null;
60
- const isCurrent = node.slug === props.graph.currentSlug;
99
+ const isCurrent = node.slug === graph.currentSlug;
61
100
  return /* @__PURE__ */ jsx(
62
101
  "g",
63
102
  {
package/dist/index.js CHANGED
@@ -7,16 +7,99 @@ import {
7
7
 
8
8
  // components/local-graph.tsx
9
9
  import { buildGraphEdges, layoutRadialGraph } from "@riebeckite/core";
10
+ import { useArticleContext, useSiteContext } from "@riebeckite/ui";
11
+ import { html } from "hono/html";
12
+
13
+ // src/local-graph.server.ts
14
+ var MAX_NEIGHBORS_PER_DIRECTION = 10;
15
+ function buildLocalGraph(args) {
16
+ const graph = args.manifest.graph;
17
+ const current = graph.get(args.slug);
18
+ const discoverableSlugs = new Set(
19
+ args.manifest.discoverableEntries.map((entry) => entry.slug)
20
+ );
21
+ if (!current || !discoverableSlugs.has(current.slug)) return null;
22
+ const { outgoingSlugs, incomingSlugs } = graph.filterNeighbors(
23
+ args.slug,
24
+ isPublishedSlug
25
+ );
26
+ const visibleOutgoing = outgoingSlugs.slice(0, MAX_NEIGHBORS_PER_DIRECTION);
27
+ const visibleBacklinks = incomingSlugs.slice(0, MAX_NEIGHBORS_PER_DIRECTION);
28
+ const visibleSlugs = /* @__PURE__ */ new Set([
29
+ args.slug,
30
+ ...visibleOutgoing,
31
+ ...visibleBacklinks
32
+ ]);
33
+ const nodes = Array.from(visibleSlugs).map(
34
+ (nodeSlug) => toLocalGraphNode(nodeSlug, args.slug, visibleOutgoing, visibleBacklinks)
35
+ ).filter((node) => node !== null);
36
+ return { currentSlug: args.slug, nodes };
37
+ function isPublishedSlug(nodeSlug) {
38
+ const entry = graph.get(nodeSlug);
39
+ return entry !== null && discoverableSlugs.has(entry.slug);
40
+ }
41
+ function toLocalGraphNode(nodeSlug, currentSlug, outgoingSlugs2, backlinkSlugs) {
42
+ const entry = graph.get(nodeSlug);
43
+ if (!entry) return null;
44
+ return {
45
+ slug: entry.slug,
46
+ permalink: entry.permalink,
47
+ title: args.resolveTitle(entry.slug, entry.frontmatter.title),
48
+ relation: getRelation(
49
+ nodeSlug,
50
+ currentSlug,
51
+ outgoingSlugs2,
52
+ backlinkSlugs
53
+ ),
54
+ outgoing: nodeSlug === currentSlug ? outgoingSlugs2 : backlinkSlugs.includes(nodeSlug) ? [currentSlug] : [],
55
+ backlinks: nodeSlug === currentSlug ? backlinkSlugs : outgoingSlugs2.includes(nodeSlug) ? [currentSlug] : []
56
+ };
57
+ }
58
+ }
59
+ var getLocalGraph = ({ view, slug }) => {
60
+ const current = view.findDiscoverableBySlug(slug);
61
+ if (!current) return null;
62
+ const outgoing = view.getDiscoverableOutgoing(slug).slice(0, MAX_NEIGHBORS_PER_DIRECTION);
63
+ const incoming = view.getDiscoverableIncoming(slug).slice(0, MAX_NEIGHBORS_PER_DIRECTION);
64
+ const outgoingSlugs = outgoing.map((entry) => entry.slug);
65
+ const incomingSlugs = incoming.map((entry) => entry.slug);
66
+ const entries = [current, ...outgoing, ...incoming].filter(
67
+ (entry, index, all) => all.findIndex((candidate) => candidate.slug === entry.slug) === index
68
+ );
69
+ return {
70
+ currentSlug: slug,
71
+ nodes: entries.map((entry) => ({
72
+ slug: entry.slug,
73
+ permalink: entry.permalink,
74
+ title: entry.title || entry.slug,
75
+ relation: getRelation(entry.slug, slug, outgoingSlugs, incomingSlugs),
76
+ outgoing: entry.slug === slug ? outgoingSlugs : incomingSlugs.includes(entry.slug) ? [slug] : [],
77
+ backlinks: entry.slug === slug ? incomingSlugs : outgoingSlugs.includes(entry.slug) ? [slug] : []
78
+ }))
79
+ };
80
+ };
81
+ function getRelation(slug, currentSlug, outgoing, backlinks) {
82
+ if (slug === currentSlug) return "current";
83
+ const isOutgoing = outgoing.includes(slug);
84
+ const isBacklink = backlinks.includes(slug);
85
+ if (isOutgoing && isBacklink) return "both";
86
+ return isOutgoing ? "outgoing" : "backlink";
87
+ }
88
+
89
+ // components/local-graph.tsx
10
90
  import { jsx, jsxs } from "hono/jsx/jsx-runtime";
11
91
  var GRAPH_WIDTH = 640;
12
92
  var GRAPH_HEIGHT = 320;
13
- var LocalGraph = ((props) => {
14
- if (props.graph.nodes.length <= 1) return null;
15
- const edges = buildGraphEdges(props.graph.nodes);
16
- const layout = layoutRadialGraph(props.graph.nodes, {
93
+ var LocalGraph = (async (props) => {
94
+ const site = useSiteContext();
95
+ const article = useArticleContext();
96
+ const graph = props.graph ?? (site && article?.entry ? await getLocalGraph({ view: site.view, slug: article.entry.slug }) : null);
97
+ if (!graph || graph.nodes.length <= 1) return html``;
98
+ const edges = buildGraphEdges(graph.nodes);
99
+ const layout = layoutRadialGraph(graph.nodes, {
17
100
  width: GRAPH_WIDTH,
18
101
  height: GRAPH_HEIGHT,
19
- centerSlug: props.graph.currentSlug,
102
+ centerSlug: graph.currentSlug,
20
103
  radiusRatio: 0.34,
21
104
  minNodeRadius: 7,
22
105
  maxNodeRadius: 12
@@ -31,7 +114,7 @@ var LocalGraph = ((props) => {
31
114
  "a",
32
115
  {
33
116
  class: "rr-local-graph__explorer-link",
34
- href: `/explore?note=${encodeURIComponent(props.graph.currentSlug)}`,
117
+ href: `/explore?note=${encodeURIComponent(graph.currentSlug)}`,
35
118
  children: "Open in Explorer →"
36
119
  }
37
120
  )
@@ -52,7 +135,7 @@ var LocalGraph = ((props) => {
52
135
  "line",
53
136
  {
54
137
  class: "rr-local-graph__edge",
55
- "data-direction": edge.source === props.graph.currentSlug ? "outgoing" : "backlink",
138
+ "data-direction": edge.source === graph.currentSlug ? "outgoing" : "backlink",
56
139
  x1: source.x,
57
140
  y1: source.y,
58
141
  x2: target.x,
@@ -61,10 +144,10 @@ var LocalGraph = ((props) => {
61
144
  `${edge.source}-${edge.target}`
62
145
  );
63
146
  }),
64
- props.graph.nodes.map((node) => {
147
+ graph.nodes.map((node) => {
65
148
  const point = layout.get(node.slug);
66
149
  if (!point) return null;
67
- const isCurrent = node.slug === props.graph.currentSlug;
150
+ const isCurrent = node.slug === graph.currentSlug;
68
151
  return /* @__PURE__ */ jsx(
69
152
  "g",
70
153
  {
@@ -122,82 +205,6 @@ var LocalGraph = ((props) => {
122
205
  });
123
206
  var local_graph_default = LocalGraph;
124
207
 
125
- // src/local-graph.server.ts
126
- var MAX_NEIGHBORS_PER_DIRECTION = 10;
127
- function buildLocalGraph(args) {
128
- const graph = args.manifest.graph;
129
- const current = graph.get(args.slug);
130
- const discoverableSlugs = new Set(
131
- args.manifest.discoverableEntries.map((entry) => entry.slug)
132
- );
133
- if (!current || !discoverableSlugs.has(current.slug)) return null;
134
- const { outgoingSlugs, incomingSlugs } = graph.filterNeighbors(
135
- args.slug,
136
- isPublishedSlug
137
- );
138
- const visibleOutgoing = outgoingSlugs.slice(0, MAX_NEIGHBORS_PER_DIRECTION);
139
- const visibleBacklinks = incomingSlugs.slice(0, MAX_NEIGHBORS_PER_DIRECTION);
140
- const visibleSlugs = /* @__PURE__ */ new Set([
141
- args.slug,
142
- ...visibleOutgoing,
143
- ...visibleBacklinks
144
- ]);
145
- const nodes = Array.from(visibleSlugs).map(
146
- (nodeSlug) => toLocalGraphNode(nodeSlug, args.slug, visibleOutgoing, visibleBacklinks)
147
- ).filter((node) => node !== null);
148
- return { currentSlug: args.slug, nodes };
149
- function isPublishedSlug(nodeSlug) {
150
- const entry = graph.get(nodeSlug);
151
- return entry !== null && discoverableSlugs.has(entry.slug);
152
- }
153
- function toLocalGraphNode(nodeSlug, currentSlug, outgoingSlugs2, backlinkSlugs) {
154
- const entry = graph.get(nodeSlug);
155
- if (!entry) return null;
156
- return {
157
- slug: entry.slug,
158
- permalink: entry.permalink,
159
- title: args.resolveTitle(entry.slug, entry.frontmatter.title),
160
- relation: getRelation(
161
- nodeSlug,
162
- currentSlug,
163
- outgoingSlugs2,
164
- backlinkSlugs
165
- ),
166
- outgoing: nodeSlug === currentSlug ? outgoingSlugs2 : backlinkSlugs.includes(nodeSlug) ? [currentSlug] : [],
167
- backlinks: nodeSlug === currentSlug ? backlinkSlugs : outgoingSlugs2.includes(nodeSlug) ? [currentSlug] : []
168
- };
169
- }
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
- };
193
- function getRelation(slug, currentSlug, outgoing, backlinks) {
194
- if (slug === currentSlug) return "current";
195
- const isOutgoing = outgoing.includes(slug);
196
- const isBacklink = backlinks.includes(slug);
197
- if (isOutgoing && isBacklink) return "both";
198
- return isOutgoing ? "outgoing" : "backlink";
199
- }
200
-
201
208
  // index.ts
202
209
  function localGraphPlugin(options = {}) {
203
210
  return definePlugin({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riebeckite/plugin-local-graph",
3
- "version": "0.0.24",
3
+ "version": "0.0.25",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -22,11 +22,12 @@
22
22
  },
23
23
  "dependencies": {
24
24
  "hono": "^4.12.25",
25
- "@riebeckite/core": "0.0.24"
25
+ "@riebeckite/core": "0.0.25",
26
+ "@riebeckite/ui": "0.0.25"
26
27
  },
27
28
  "devDependencies": {
28
29
  "tsx": "^4.22.4",
29
- "@riebeckite/test": "0.0.24"
30
+ "@riebeckite/test": "0.0.25"
30
31
  },
31
32
  "publishConfig": {
32
33
  "access": "public"