@riebeckite/plugin-series 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.
@@ -0,0 +1,9 @@
1
+ import type { ResolvedSeriesOptions, SeriesIndex } from "../src/types.js";
2
+ export type SeriesNavigationProps = {
3
+ index: SeriesIndex | null;
4
+ currentSlug: string;
5
+ className?: string;
6
+ options?: Pick<ResolvedSeriesOptions, "heading" | "positionLabel">;
7
+ };
8
+ declare const SeriesNavigation: ({ index, currentSlug, className, options, }: Readonly<SeriesNavigationProps>) => import("hono/jsx/jsx-dev-runtime").JSX.Element;
9
+ export default SeriesNavigation;
@@ -0,0 +1,54 @@
1
+ // components/series-navigation.tsx
2
+ import { jsx, jsxs } from "hono/jsx/jsx-runtime";
3
+ var SeriesNavigation = (({
4
+ index,
5
+ currentSlug,
6
+ className = "rb-series",
7
+ options
8
+ }) => {
9
+ if (!index || index.members.length === 0) return null;
10
+ const position = index.members.findIndex(
11
+ (member) => member.slug === currentSlug
12
+ );
13
+ const previous = position > 0 ? index.members[position - 1] : void 0;
14
+ const next = position >= 0 && position < index.members.length - 1 ? index.members[position + 1] : void 0;
15
+ const heading = options?.heading ?? true;
16
+ const positionLabel = options?.positionLabel ?? false;
17
+ return /* @__PURE__ */ jsxs(
18
+ "nav",
19
+ {
20
+ class: className,
21
+ "data-series": index.name,
22
+ "aria-label": "Series navigation",
23
+ children: [
24
+ heading ? /* @__PURE__ */ jsxs("p", { class: `${className}__title`, children: [
25
+ /* @__PURE__ */ jsx("a", { class: `${className}__link`, href: index.members[0].permalink, children: index.title }),
26
+ positionLabel && position >= 0 ? /* @__PURE__ */ jsx("span", { class: `${className}__position`, children: ` Part ${position + 1} of ${index.members.length}` }) : null
27
+ ] }) : null,
28
+ /* @__PURE__ */ jsx("ol", { class: `${className}__list`, children: index.members.map((member) => /* @__PURE__ */ jsx("li", { class: `${className}__item`, children: /* @__PURE__ */ jsx(
29
+ "a",
30
+ {
31
+ class: `${className}__link`,
32
+ href: member.permalink,
33
+ "aria-current": member.slug === currentSlug ? "page" : void 0,
34
+ children: member.title
35
+ }
36
+ ) }, member.slug)) }),
37
+ /* @__PURE__ */ jsxs("div", { class: `${className}__nav`, children: [
38
+ previous ? /* @__PURE__ */ jsxs("a", { class: `${className}__prev`, href: previous.permalink, rel: "prev", children: [
39
+ "← ",
40
+ previous.title
41
+ ] }) : null,
42
+ next ? /* @__PURE__ */ jsxs("a", { class: `${className}__next`, href: next.permalink, rel: "next", children: [
43
+ next.title,
44
+ " →"
45
+ ] }) : null
46
+ ] })
47
+ ]
48
+ }
49
+ );
50
+ });
51
+ var series_navigation_default = SeriesNavigation;
52
+ export {
53
+ series_navigation_default as default
54
+ };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import { resolveSeriesOptions } from "./src/series.js";
2
2
  import type { SeriesOptions } from "./src/types.js";
3
- export { buildSeriesIndex, collectSeriesIndexes, DEFAULT_SERIES_BASE_PATH, renderSeriesIndex, renderSeriesList, renderSeriesNavigation, seriesLandingPath, seriesSlug, } from "./src/series.js";
3
+ export type { SeriesNavigationProps } from "./components/series-navigation.js";
4
+ export { default as SeriesNavigation } from "./components/series-navigation.js";
5
+ export { buildSeriesIndex, collectSeriesIndexes, DEFAULT_SERIES_BASE_PATH, getSeriesNavigation, renderSeriesIndex, renderSeriesList, renderSeriesNavigation, seriesLandingPath, seriesSlug, } from "./src/series.js";
4
6
  export type { ResolvedSeriesOptions, SeriesIndex, SeriesMember, SeriesOptions, } from "./src/types.js";
5
7
  /**
6
8
  * Series (ordered multi-part posts) for Riebeckite.
package/dist/index.js CHANGED
@@ -1,6 +1,5 @@
1
1
  // index.ts
2
2
  import {
3
- appendContentBodySlot,
4
3
  createStyleAsset,
5
4
  definePlugin
6
5
  } from "@riebeckite/core";
@@ -50,6 +49,13 @@ function buildSeriesIndex(manifest, name, options = {}) {
50
49
  (index) => index.name === name
51
50
  ) ?? null;
52
51
  }
52
+ var getSeriesNavigation = ({ view, entry, index }) => {
53
+ if (!index || !view.findDiscoverableBySlug(entry.slug)) return null;
54
+ const members = index.members.filter(
55
+ (member) => view.findDiscoverableBySlug(member.slug)
56
+ );
57
+ return members.some((member) => member.slug === entry.slug) ? { ...index, members } : null;
58
+ };
53
59
  function seriesSlug(name) {
54
60
  return name.split("/").map((segment) => {
55
61
  const normalized = segment.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
@@ -284,6 +290,58 @@ function normalizeBasePath(value) {
284
290
  return prefixed.length > 1 ? prefixed.replace(/\/+$/, "") : prefixed;
285
291
  }
286
292
 
293
+ // components/series-navigation.tsx
294
+ import { jsx, jsxs } from "hono/jsx/jsx-runtime";
295
+ var SeriesNavigation = (({
296
+ index,
297
+ currentSlug,
298
+ className = "rb-series",
299
+ options
300
+ }) => {
301
+ if (!index || index.members.length === 0) return null;
302
+ const position = index.members.findIndex(
303
+ (member) => member.slug === currentSlug
304
+ );
305
+ const previous = position > 0 ? index.members[position - 1] : void 0;
306
+ const next = position >= 0 && position < index.members.length - 1 ? index.members[position + 1] : void 0;
307
+ const heading = options?.heading ?? true;
308
+ const positionLabel = options?.positionLabel ?? false;
309
+ return /* @__PURE__ */ jsxs(
310
+ "nav",
311
+ {
312
+ class: className,
313
+ "data-series": index.name,
314
+ "aria-label": "Series navigation",
315
+ children: [
316
+ heading ? /* @__PURE__ */ jsxs("p", { class: `${className}__title`, children: [
317
+ /* @__PURE__ */ jsx("a", { class: `${className}__link`, href: index.members[0].permalink, children: index.title }),
318
+ positionLabel && position >= 0 ? /* @__PURE__ */ jsx("span", { class: `${className}__position`, children: ` Part ${position + 1} of ${index.members.length}` }) : null
319
+ ] }) : null,
320
+ /* @__PURE__ */ jsx("ol", { class: `${className}__list`, children: index.members.map((member) => /* @__PURE__ */ jsx("li", { class: `${className}__item`, children: /* @__PURE__ */ jsx(
321
+ "a",
322
+ {
323
+ class: `${className}__link`,
324
+ href: member.permalink,
325
+ "aria-current": member.slug === currentSlug ? "page" : void 0,
326
+ children: member.title
327
+ }
328
+ ) }, member.slug)) }),
329
+ /* @__PURE__ */ jsxs("div", { class: `${className}__nav`, children: [
330
+ previous ? /* @__PURE__ */ jsxs("a", { class: `${className}__prev`, href: previous.permalink, rel: "prev", children: [
331
+ "← ",
332
+ previous.title
333
+ ] }) : null,
334
+ next ? /* @__PURE__ */ jsxs("a", { class: `${className}__next`, href: next.permalink, rel: "next", children: [
335
+ next.title,
336
+ " →"
337
+ ] }) : null
338
+ ] })
339
+ ]
340
+ }
341
+ );
342
+ });
343
+ var series_navigation_default = SeriesNavigation;
344
+
287
345
  // index.ts
288
346
  function series(options = {}) {
289
347
  const models = /* @__PURE__ */ new WeakMap();
@@ -321,30 +379,11 @@ function series(options = {}) {
321
379
  version: "series-v1",
322
380
  dependencyMode: "none"
323
381
  },
324
- outputDependencies: [{ type: "global" }],
382
+ contentOutputDependencies: [{ type: "global" }],
325
383
  options,
326
384
  validateOptions: validateSeriesOptions,
327
385
  onManifestCreated: ({ manifest, diagnostics }) => {
328
386
  diagnostics.push(...collectSeriesDiagnostics(manifest, options));
329
- const view = modelFor(manifest).view;
330
- const injected = /* @__PURE__ */ new Set();
331
- for (const index of collectSeriesIndexes(view, options)) {
332
- if (index.members.length < 2) continue;
333
- for (const member of index.members) {
334
- if (injected.has(member.slug)) continue;
335
- const entry = view.bySlug.get(member.slug);
336
- if (!entry) continue;
337
- injected.add(member.slug);
338
- const navigation = renderSeriesNavigation(
339
- index,
340
- member.slug,
341
- options
342
- );
343
- if (!hasSlotFragment(entry.bodySlots?.["article.footer"], navigation)) {
344
- appendContentBodySlot(entry, "article.footer", navigation);
345
- }
346
- }
347
- }
348
387
  },
349
388
  pageTypes: [
350
389
  {
@@ -386,17 +425,10 @@ function series(options = {}) {
386
425
  }
387
426
  }
388
427
  ],
389
- assets: [createStyleAsset("series")]
428
+ assets: [createStyleAsset("series", "@riebeckite/plugin-series/style.css")]
390
429
  });
391
430
  }
392
431
  var seriesPlugin = series;
393
- function hasSlotFragment(slot, fragment) {
394
- return slot === fragment || slot?.startsWith(`${fragment}
395
- `) || slot?.endsWith(`
396
- ${fragment}`) || slot?.includes(`
397
- ${fragment}
398
- `) || false;
399
- }
400
432
  function validateSeriesOptions(options) {
401
433
  if (!options) return [];
402
434
  const issues = [];
@@ -423,8 +455,10 @@ var DEFAULT_CLASS_NAME = resolveSeriesOptions({}).className;
423
455
  export {
424
456
  DEFAULT_CLASS_NAME,
425
457
  DEFAULT_SERIES_BASE_PATH,
458
+ series_navigation_default as SeriesNavigation,
426
459
  buildSeriesIndex,
427
460
  collectSeriesIndexes,
461
+ getSeriesNavigation,
428
462
  renderSeriesIndex,
429
463
  renderSeriesList,
430
464
  renderSeriesNavigation,
@@ -1,4 +1,4 @@
1
- import { type ContentManifest, type Diagnostic } from "@riebeckite/core";
1
+ import { type ContentManifest, type Diagnostic, type PluginDataHelper, type PublicContentEntry, type PublicContentView } from "@riebeckite/core";
2
2
  import type { ResolvedSeriesOptions, SeriesIndex, SeriesOptions } from "./types.js";
3
3
  /** Base class applied when `options.className` is not set. */
4
4
  export declare const DEFAULT_SERIES_CLASS_NAME = "rb-series";
@@ -14,6 +14,11 @@ export declare function resolveSeriesOptions(options?: SeriesOptions): ResolvedS
14
14
  export declare function collectSeriesIndexes(manifest: ContentManifest, options?: SeriesOptions): SeriesIndex[];
15
15
  /** Returns a single series index, or `null` when no note declares `name`. */
16
16
  export declare function buildSeriesIndex(manifest: ContentManifest, name: string, options?: SeriesOptions): SeriesIndex | null;
17
+ export declare const getSeriesNavigation: PluginDataHelper<{
18
+ view: PublicContentView;
19
+ entry: PublicContentEntry;
20
+ index: SeriesIndex | null;
21
+ }, SeriesIndex | null>;
17
22
  export declare function seriesSlug(name: string): string;
18
23
  export declare function seriesLandingPath(name: string, options?: SeriesOptions): string;
19
24
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riebeckite/plugin-series",
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",
@@ -12,14 +12,21 @@
12
12
  "source": "./index.ts",
13
13
  "default": "./dist/index.js"
14
14
  },
15
+ "./components": {
16
+ "types": "./dist/components/series-navigation.d.ts",
17
+ "import": "./dist/components/series-navigation.js",
18
+ "source": "./components/series-navigation.tsx",
19
+ "default": "./dist/components/series-navigation.js"
20
+ },
15
21
  "./style.css": "./style.css"
16
22
  },
17
23
  "dependencies": {
18
- "@riebeckite/core": "0.0.22"
24
+ "hono": "^4.12.25",
25
+ "@riebeckite/core": "0.0.24"
19
26
  },
20
27
  "devDependencies": {
21
28
  "tsx": "^4.22.4",
22
- "@riebeckite/test": "0.0.22"
29
+ "@riebeckite/test": "0.0.24"
23
30
  },
24
31
  "publishConfig": {
25
32
  "access": "public"