@riebeckite/plugin-backlinks 0.0.22 → 0.0.24

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
@@ -8,13 +8,13 @@ current note.
8
8
  [日本語](./README_ja.md)
9
9
 
10
10
  ## Recommended placement
11
-
12
- `backlinksPlugin()` automatically appends a footer list of incoming links to
13
- the `article.footer` semantic body slot. The Site owns physical placement: it
14
- displays the list only where it renders that slot, normally once after article
15
- content. `getPublishedBacklinks()` resolves the incoming links of a note from
16
- the content manifest, keeps only publicly discoverable notes, and returns them
17
- sorted in manifest order.
11
+ `backlinksPlugin()` provides a `getBacklinks({ view, slug })` helper that returns
12
+ `readonly ArticleBacklink[]` (`{ slug, permalink, title }`) and a `<Backlinks
13
+ backlinks={...} />` component that renders a `<footer class="rr-backlinks">` with
14
+ an eyebrow label and a list of links. The Site places the `<Backlinks />`
15
+ component itself, normally once after article content. `getBacklinks()` resolves
16
+ the incoming links of a note from the content manifest, keeps only publicly
17
+ discoverable notes, and returns them sorted in manifest order.
18
18
 
19
19
  Without incoming links (or when none of them are published), the component
20
20
  renders nothing.
@@ -33,47 +33,33 @@ export default defineConfig({
33
33
 
34
34
  `backlinksPlugin()` adds backlinks for every public entry with published
35
35
  incoming links and bundles `style.css` into the app stylesheet. Render
36
- `<ContentSlot slots={bodySlots} name="article.footer" />` once in the article
37
- layout to display it. The official Starter already renders this slot.
36
+ `<Backlinks backlinks={getBacklinks({ view, slug })} />` once in the article
37
+ layout to display it. The official Starter already renders this component.
38
38
 
39
39
  ## Advanced customization
40
40
 
41
- To choose a different location, prevent the automatic slot contribution with
42
- `render: false`; this does not change backlink data or its publication
43
- filtering. Resolve the data in the Site route and render the public component
44
- exactly once:
41
+ To place the component in a custom location, call `getBacklinks({ view, slug })`
42
+ in the Site route and render the `<Backlinks backlinks={...} />` component exactly
43
+ once. The data resolver does not change backlink data or its publication
44
+ filtering.
45
45
 
46
46
  ```tsx
47
- import Backlinks, { getPublishedBacklinks } from "@riebeckite/plugin-backlinks";
47
+ import Backlinks, { getBacklinks } from "@riebeckite/plugin-backlinks";
48
48
  import { content } from "virtual:riebeckite/content";
49
49
  import { getArticleTitle } from "../lib/article-title";
50
50
 
51
51
  const manifest = await content.getManifest();
52
- const backlinks = getPublishedBacklinks({
53
- manifest,
54
- config,
55
- slug,
56
- resolveTitle: getArticleTitle,
57
- });
52
+ const backlinks = getBacklinks({ view, slug, resolveTitle: getArticleTitle });
58
53
 
59
54
  return (
60
55
  <aside><Backlinks backlinks={backlinks} /></aside>
61
56
  );
62
57
  ```
63
58
 
64
- ```ts
65
- plugins: [backlinksPlugin({ render: false })];
66
- ```
67
-
68
- Remove the component to remove manually placed UI. Do not render both this
69
- component and `article.footer` with automatic rendering enabled, or it will
70
- appear twice.
71
-
72
59
  ## Configuration
73
60
 
74
- | Option | Type | Default | Description |
75
- | --- | --- | --- | --- |
76
- | `render` | `boolean` | `true` | Append the generated list to `article.footer`. Set `false` for manual placement. |
61
+ There are no plugin options for `backlinksPlugin`. The `Backlinks` component
62
+ accepts `backlinks` as a required prop.
77
63
 
78
64
  ## Component
79
65
 
@@ -84,8 +70,8 @@ an eyebrow label and a list of links to each backlink's resolved `permalink`.
84
70
 
85
71
  - `backlinksPlugin()` — plugin factory
86
72
  - `Backlinks` — list component (default export of `components/backlinks.tsx`)
87
- - `getPublishedBacklinks({ manifest, config, slug, resolveTitle })` — resolves
88
- published backlinks for a slug
73
+ - `getBacklinks({ view, slug })` — resolves published backlinks for a slug
74
+ (`{ slug, permalink, title }` each)
89
75
  - Type: `ArticleBacklink` (`{ slug, permalink, title }`)
90
76
 
91
77
  ## See also
package/README_ja.md CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  ## 推奨配置
10
10
 
11
- `backlinksPlugin()` はコンテンツマニフェストから被リンクを集め、公開対象のノートだけをマニフェスト順で `article.footer` body slot に自動追加します。物理的な配置は Site が所有し、通常は記事本文の後でこの slot を一度描画します。`Backlinks` コンポーネントはその結果をリンク一覧として描画します。表示対象がなければ何も出力しません。
11
+ `backlinksPlugin()` はコンテンツマニフェストから被リンクを集め、公開対象のノートだけをマニフェスト順で `<Backlinks backlinks={getBacklinks({ view, slug })} />` へ渡します。物理的な配置は Site が所有し、通常は記事本文の後でこのコンポーネントを一度描画します。`Backlinks` コンポーネントはその結果をリンク一覧として描画します。表示対象がなければ何も出力しません。
12
12
 
13
13
  ## クイックスタート
14
14
 
@@ -22,38 +22,32 @@ export default defineConfig({
22
22
  });
23
23
  ```
24
24
 
25
- プラグインは公開済みの被リンクがある記事へ自動的に出力を追加します。記事レイアウトで `<ContentSlot slots={bodySlots} name="article.footer" />` を一度描画してください。公式 Starter はこの slot をすでに描画しています。
25
+ プラグインは公開済みの被リンクがある記事へ自動的に出力を追加します。記事レイアウトで `<Backlinks backlinks={getBacklinks({ view, slug })} />` を一度描画してください。公式 Starter はこのコンポーネントをすでに描画しています。
26
26
 
27
27
  ## 高度なカスタマイズ
28
28
 
29
- アプリ側で表示位置を決める場合は、`render: false` で自動 slot 追加を止めます。データの生成と公開境界のフィルタリングは維持されます。記事ルートなどでマニフェストを取得し、現在の `slug` に対する被リンクを渡してください。
29
+ アプリ側で表示位置を決める場合は、`getBacklinks({ view, slug })` を呼び出してデータを取得し、 `<Backlinks backlinks={...} />` コンポーネントを一度だけ描画してください。データの生成と公開境界のフィルタリングは維持されます。
30
30
 
31
31
  ```tsx
32
- import Backlinks, { getPublishedBacklinks } from "@riebeckite/plugin-backlinks";
32
+ import Backlinks, { getBacklinks } from "@riebeckite/plugin-backlinks";
33
33
 
34
34
  const manifest = await content.getManifest();
35
- const items = getPublishedBacklinks({ manifest, config, slug, resolveTitle });
35
+ const items = getBacklinks({ manifest, config, slug, resolveTitle });
36
36
 
37
37
  return <Article footerContent={<Backlinks backlinks={items} />} />;
38
38
  ```
39
39
 
40
- ```ts
41
- plugins: [backlinksPlugin({ render: false })];
42
- ```
43
-
44
40
  手動配置を消すにはコンポーネントを消します。自動描画を有効にしたまま同じコンポーネントを描画すると重複します。
45
41
 
46
42
  ## 設定
47
43
 
48
- | オプション | 型 | 既定値 | 説明 |
49
- | --- | --- | --- | --- |
50
- | `render` | `boolean` | `true` | `article.footer` への自動追加。手動配置では `false`。 |
44
+ `backlinksPlugin()` にはプラグイン用のオプションがありません。`Backlinks` コンポーネントは `backlinks` 必須プロップを受け取ります。
51
45
 
52
46
  ## 公開 API
53
47
 
54
48
  - `backlinksPlugin()` — プラグインファクトリ
55
49
  - `Backlinks` — 被リンク一覧コンポーネント
56
- - `getPublishedBacklinks({ manifest, config, slug, resolveTitle })` — 公開済みの被リンクを解決する関数
50
+ - `getBacklinks({ view, slug })` — 公開済みの被リンクを解決する関数
57
51
  - `ArticleBacklink` — `{ slug, permalink, title }` の型。`permalink` は解決済みの canonical URL
58
52
 
59
53
  ## 関連資料
@@ -1,6 +1,6 @@
1
1
  import type { ArticleBacklink } from "../src/backlinks.js";
2
- type Props = {
3
- backlinks: ArticleBacklink[];
2
+ export type BacklinksProps = {
3
+ backlinks: readonly ArticleBacklink[];
4
4
  };
5
- export default function Backlinks(props: Props): import("hono/jsx/jsx-dev-runtime").JSX.Element;
6
- export {};
5
+ declare const Backlinks: (props: Readonly<BacklinksProps>) => import("hono/jsx/jsx-dev-runtime").JSX.Element;
6
+ export default Backlinks;
@@ -1,12 +1,13 @@
1
1
  // components/backlinks.tsx
2
2
  import { jsx, jsxs } from "hono/jsx/jsx-runtime";
3
- function Backlinks(props) {
3
+ var Backlinks = ((props) => {
4
4
  if (props.backlinks.length === 0) return null;
5
5
  return /* @__PURE__ */ jsxs("footer", { class: "rr-backlinks", children: [
6
6
  /* @__PURE__ */ jsx("p", { class: "rr-backlinks__eyebrow", children: "Backlinks" }),
7
7
  /* @__PURE__ */ jsx("ul", { class: "rr-backlinks__list", children: props.backlinks.map((backlink) => /* @__PURE__ */ jsx("li", { class: "rr-backlinks__item", children: /* @__PURE__ */ jsx("a", { class: "rr-backlinks__link", href: backlink.permalink, children: backlink.title }) }, backlink.slug)) })
8
8
  ] });
9
- }
9
+ });
10
+ var backlinks_default = Backlinks;
10
11
  export {
11
- Backlinks as default
12
+ backlinks_default as default
12
13
  };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,6 @@
1
+ export type { BacklinksProps } from "./components/backlinks.js";
1
2
  export { default as Backlinks } from "./components/backlinks.js";
2
3
  export type { ArticleBacklink } from "./src/backlinks.js";
3
- export { getPublishedBacklinks } from "./src/backlinks.server.js";
4
- export type BacklinksOptions = {
5
- render?: boolean;
6
- };
4
+ export { getBacklinks, getPublishedBacklinks } from "./src/backlinks.server.js";
5
+ export type BacklinksOptions = Record<never, never>;
7
6
  export declare function backlinksPlugin(options?: BacklinksOptions): import("@riebeckite/core").RiebeckitePlugin<BacklinksOptions>;
package/dist/index.js CHANGED
@@ -1,19 +1,16 @@
1
1
  // index.ts
2
- import {
3
- appendContentBodySlot,
4
- definePlugin
5
- } from "@riebeckite/core";
6
- import { renderToString } from "hono/jsx/dom/server";
2
+ import { definePlugin } from "@riebeckite/core";
7
3
 
8
4
  // components/backlinks.tsx
9
5
  import { jsx, jsxs } from "hono/jsx/jsx-runtime";
10
- function Backlinks(props) {
6
+ var Backlinks = ((props) => {
11
7
  if (props.backlinks.length === 0) return null;
12
8
  return /* @__PURE__ */ jsxs("footer", { class: "rr-backlinks", children: [
13
9
  /* @__PURE__ */ jsx("p", { class: "rr-backlinks__eyebrow", children: "Backlinks" }),
14
10
  /* @__PURE__ */ jsx("ul", { class: "rr-backlinks__list", children: props.backlinks.map((backlink) => /* @__PURE__ */ jsx("li", { class: "rr-backlinks__item", children: /* @__PURE__ */ jsx("a", { class: "rr-backlinks__link", href: backlink.permalink, children: backlink.title }) }, backlink.slug)) })
15
11
  ] });
16
- }
12
+ });
13
+ var backlinks_default = Backlinks;
17
14
 
18
15
  // src/backlinks.server.ts
19
16
  function getPublishedBacklinks(args) {
@@ -32,6 +29,11 @@ function getPublishedBacklinks(args) {
32
29
  (backlink) => backlink !== null
33
30
  );
34
31
  }
32
+ var getBacklinks = ({ view, slug }) => view.getDiscoverableIncoming(slug).map((entry) => ({
33
+ slug: entry.slug,
34
+ permalink: entry.permalink,
35
+ title: entry.title || entry.slug
36
+ }));
35
37
 
36
38
  // index.ts
37
39
  function backlinksPlugin(options = {}) {
@@ -39,25 +41,6 @@ function backlinksPlugin(options = {}) {
39
41
  name: "backlinks",
40
42
  order: 500,
41
43
  options,
42
- validateOptions: validateBacklinksOptions,
43
- onManifestCreated: ({ config, manifest }) => {
44
- if (options.render === false) return;
45
- if (!config) return;
46
- for (const entry of manifest.discoverableEntries) {
47
- const backlinks = getPublishedBacklinks({
48
- manifest,
49
- config,
50
- slug: entry.slug,
51
- resolveTitle
52
- });
53
- if (backlinks.length === 0) continue;
54
- appendContentBodySlot(
55
- entry,
56
- "article.footer",
57
- renderToString(Backlinks({ backlinks }))
58
- );
59
- }
60
- },
61
44
  assets: [
62
45
  {
63
46
  pluginName: "backlinks",
@@ -67,18 +50,9 @@ function backlinksPlugin(options = {}) {
67
50
  ]
68
51
  });
69
52
  }
70
- function validateBacklinksOptions(options) {
71
- if (!options || options.render === void 0 || typeof options.render === "boolean") {
72
- return [];
73
- }
74
- return [{ path: "render", message: "Expected a boolean." }];
75
- }
76
- function resolveTitle(slug, title) {
77
- if (typeof title === "string" && title.trim()) return title;
78
- return slug.split("/").at(-1) ?? slug;
79
- }
80
53
  export {
81
- Backlinks,
54
+ backlinks_default as Backlinks,
82
55
  backlinksPlugin,
56
+ getBacklinks,
83
57
  getPublishedBacklinks
84
58
  };
@@ -1,4 +1,4 @@
1
- import type { ContentManifest, ResolvedRiebeckiteConfig } from "@riebeckite/core";
1
+ import type { ContentManifest, PluginDataHelper, PublicContentView, ResolvedRiebeckiteConfig } from "@riebeckite/core";
2
2
  import type { ArticleBacklink } from "./backlinks.js";
3
3
  type TitleResolver = (slug: string, title: unknown) => string;
4
4
  export declare function getPublishedBacklinks(args: {
@@ -7,4 +7,8 @@ export declare function getPublishedBacklinks(args: {
7
7
  slug: string;
8
8
  resolveTitle: TitleResolver;
9
9
  }): ArticleBacklink[];
10
+ export declare const getBacklinks: PluginDataHelper<{
11
+ view: PublicContentView;
12
+ slug: string;
13
+ }, readonly ArticleBacklink[]>;
10
14
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riebeckite/plugin-backlinks",
3
- "version": "0.0.22",
3
+ "version": "0.0.24",
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.24"
26
26
  },
27
27
  "devDependencies": {
28
28
  "tsx": "^4.22.4",
29
- "@riebeckite/test": "0.0.22"
29
+ "@riebeckite/test": "0.0.24"
30
30
  },
31
31
  "publishConfig": {
32
32
  "access": "public"