shelving 1.222.1 → 1.222.2

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.
@@ -2,9 +2,11 @@ import { type FileElementProps } from "../util/element.js";
2
2
  import { FileExtractor } from "./FileExtractor.js";
3
3
  /**
4
4
  * File extractor for Markdown files.
5
- * - Stores the raw markdown text as `content`; rendering happens at output time via `<Markup>`.
5
+ * - Stores the markdown text as `content`; rendering happens at output time via `<Markup>`.
6
6
  * - Sets `title` from the first `# h1` heading if one is present — otherwise leaves it undefined
7
7
  * (a confident title only).
8
+ * - When a `title` is found, strips the leading `# h1` from `content` so renderers (which show
9
+ * `title` separately) don't display the heading twice.
8
10
  * - Sets `description` to the first prose paragraph as a plain-text summary (used for card listings and `<meta>`).
9
11
  */
10
12
  export declare class MarkupExtractor extends FileExtractor {
@@ -3,9 +3,11 @@ import { getElementText, walkElements } from "../util/element.js";
3
3
  import { FileExtractor } from "./FileExtractor.js";
4
4
  /**
5
5
  * File extractor for Markdown files.
6
- * - Stores the raw markdown text as `content`; rendering happens at output time via `<Markup>`.
6
+ * - Stores the markdown text as `content`; rendering happens at output time via `<Markup>`.
7
7
  * - Sets `title` from the first `# h1` heading if one is present — otherwise leaves it undefined
8
8
  * (a confident title only).
9
+ * - When a `title` is found, strips the leading `# h1` from `content` so renderers (which show
10
+ * `title` separately) don't display the heading twice.
9
11
  * - Sets `description` to the first prose paragraph as a plain-text summary (used for card listings and `<meta>`).
10
12
  */
11
13
  export class MarkupExtractor extends FileExtractor {
@@ -13,7 +15,8 @@ export class MarkupExtractor extends FileExtractor {
13
15
  priority = 10;
14
16
  extractProps(name, text) {
15
17
  const { title, description } = extractMarkdownProps(text);
16
- return { name, title, description, content: text };
18
+ // The title `# h1` is surfaced separately as `title`, so strip it from the body to avoid rendering it twice.
19
+ return { name, title, description, content: title ? _stripTitle(text) : text };
17
20
  }
18
21
  }
19
22
  /**
@@ -43,3 +46,7 @@ export function extractMarkdownProps(text) {
43
46
  function _plain(element) {
44
47
  return getElementText(element).replace(/\s+/g, " ").trim() || undefined;
45
48
  }
49
+ /** Strip a leading `# h1` heading (and any blank lines after it) from markdown text. */
50
+ function _stripTitle(text) {
51
+ return text.replace(/^\s*#[^\n\S]+\S[^\n]*(?:\n+|$)/, "");
52
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shelving",
3
- "version": "1.222.1",
3
+ "version": "1.222.2",
4
4
  "author": "Dave Houlbrooke <dave@shax.com>",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Prose } from "../block/Prose.js";
3
+ import { Title } from "../block/Title.js";
3
4
  import { Markup } from "../misc/Markup.js";
4
5
  import { requireMeta } from "../misc/MetaContext.js";
5
6
  import { Page } from "../page/Page.js";
@@ -8,5 +9,5 @@ import { TreeCards } from "../tree/TreeCards.js";
8
9
  export function DirectoryPage({ title, name, description, content, children }) {
9
10
  const { url } = requireMeta();
10
11
  const path = url?.pathname ?? "/";
11
- return (_jsxs(Page, { title: title ?? name, description: description, children: [content && (_jsx(Prose, { children: _jsx(Markup, { children: content }) })), _jsx(TreeCards, { path: path, children: children })] }));
12
+ return (_jsxs(Page, { title: title ?? name, description: description, children: [_jsx(Title, { children: title ?? name }), content && (_jsx(Prose, { children: _jsx(Markup, { children: content }) })), _jsx(TreeCards, { path: path, children: children })] }));
12
13
  }
@@ -1,6 +1,7 @@
1
1
  import type { ReactNode } from "react";
2
2
  import type { DirectoryElementProps } from "../../util/element.js";
3
3
  import { Prose } from "../block/Prose.js";
4
+ import { Title } from "../block/Title.js";
4
5
  import { Markup } from "../misc/Markup.js";
5
6
  import { requireMeta } from "../misc/MetaContext.js";
6
7
  import { Page } from "../page/Page.js";
@@ -12,6 +13,7 @@ export function DirectoryPage({ title, name, description, content, children }: D
12
13
  const path = url?.pathname ?? "/";
13
14
  return (
14
15
  <Page title={title ?? name} description={description}>
16
+ <Title>{title ?? name}</Title>
15
17
  {content && (
16
18
  <Prose>
17
19
  <Markup>{content}</Markup>
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Prose } from "../block/Prose.js";
3
+ import { Title } from "../block/Title.js";
3
4
  import { Markup } from "../misc/Markup.js";
4
5
  import { requireMeta } from "../misc/MetaContext.js";
5
6
  import { Page } from "../page/Page.js";
@@ -8,5 +9,5 @@ import { TreeCards } from "../tree/TreeCards.js";
8
9
  export function FilePage({ title, name, description, content, children }) {
9
10
  const { url } = requireMeta();
10
11
  const path = url?.pathname ?? "/";
11
- return (_jsxs(Page, { title: title ?? name, description: description, children: [content && (_jsx(Prose, { children: _jsx(Markup, { children: content }) })), _jsx(TreeCards, { path: path, children: children })] }));
12
+ return (_jsxs(Page, { title: title ?? name, description: description, children: [_jsx(Title, { children: title ?? name }), content && (_jsx(Prose, { children: _jsx(Markup, { children: content }) })), _jsx(TreeCards, { path: path, children: children })] }));
12
13
  }
@@ -1,6 +1,7 @@
1
1
  import type { ReactNode } from "react";
2
2
  import type { FileElementProps } from "../../util/element.js";
3
3
  import { Prose } from "../block/Prose.js";
4
+ import { Title } from "../block/Title.js";
4
5
  import { Markup } from "../misc/Markup.js";
5
6
  import { requireMeta } from "../misc/MetaContext.js";
6
7
  import { Page } from "../page/Page.js";
@@ -12,6 +13,7 @@ export function FilePage({ title, name, description, content, children }: FileEl
12
13
  const path = url?.pathname ?? "/";
13
14
  return (
14
15
  <Page title={title ?? name} description={description}>
16
+ <Title>{title ?? name}</Title>
15
17
  {content && (
16
18
  <Prose>
17
19
  <Markup>{content}</Markup>
package/util/element.d.ts CHANGED
@@ -41,7 +41,7 @@ export interface TreeElementProps extends ElementProps {
41
41
  /**
42
42
  * Markup source string that should be rendered as the element's visible body content.
43
43
  * - Rendered via the `<Markup>` component (typically inside a `<Prose>` wrapper).
44
- * - For Markdown files this is the file's text; for TypeScript symbols this is the JSDoc description.
44
+ * - For Markdown files this is the file's body (the title `# h1` is lifted into `title`); for TypeScript symbols this is the JSDoc description.
45
45
  */
46
46
  readonly content?: string | undefined;
47
47
  /** Children of a tree element must be other tree elements. */