@moldea.ai/website-ui 1.2.2 → 1.6.0
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 +163 -2
- package/dist/markdown/index.d.ts +7 -0
- package/dist/markdown/index.d.ts.map +1 -1
- package/dist/markdown.js +33 -6
- package/dist/markdown.js.map +1 -1
- package/package.json +22 -1
- package/src/components/accordion/accordion.component.astro +103 -0
- package/src/components/action-link/action-link.component.astro +6 -1
- package/src/components/breadcrumbs/breadcrumbs.component.astro +1 -1
- package/src/components/code-block/code-block.component.astro +22 -0
- package/src/components/connection-label/connection-label.component.astro +26 -0
- package/src/components/dialog/dialog.component.astro +266 -0
- package/src/components/documentation-shell/documentation-outline.component.astro +1 -4
- package/src/components/documentation-shell/documentation-shell.component.astro +2 -12
- package/src/components/evaluation-replay/evaluation-replay-markdown.component.astro +1 -1
- package/src/components/file-preview/file-preview.component.astro +55 -0
- package/src/components/hero-backdrop/hero-backdrop.component.astro +9 -0
- package/src/components/inline-brand-text/inline-brand-text.component.astro +1 -1
- package/src/components/local-search/local-search.component.astro +37 -17
- package/src/components/result-summary/result-summary.component.astro +64 -0
- package/src/components/site-header/site-header.component.astro +39 -32
- package/src/components/status-badge/status-badge.component.astro +8 -2
- package/src/styles.css +52 -6
- package/src/tokens.css +2 -2
package/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# `@moldea.ai/website-ui`
|
|
2
2
|
|
|
3
|
-
Shared Astro foundations for moldea public websites.
|
|
3
|
+
Shared Astro foundations for `moldea` public websites.
|
|
4
4
|
|
|
5
5
|
The package owns the reusable design tokens, global website primitives, interaction states, base-path and theme utilities, and small accessible Astro components used by the package and skill websites. Each website continues to own its page composition, navigation copy, content generation, SEO identity, public assets, site URL, and theme storage key.
|
|
6
6
|
|
|
7
7
|
## Install after release
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
pnpm add @moldea.ai/website-ui@1.
|
|
10
|
+
pnpm add @moldea.ai/website-ui@1.6.0
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
The package currently supports Astro `7.2.2` and Tailwind CSS `4.3.3` exactly. Import the shared stylesheet once from the website's global stylesheet:
|
|
@@ -18,10 +18,38 @@ The package currently supports Astro `7.2.2` and Tailwind CSS `4.3.3` exactly. I
|
|
|
18
18
|
|
|
19
19
|
Tailwind scans the shipped Astro components through the package stylesheet's explicit source declaration.
|
|
20
20
|
|
|
21
|
+
## Composition guidelines
|
|
22
|
+
|
|
23
|
+
- Keep reusable presentation, interaction behavior, tokens, and design guidance in this package. Websites own routes, content, fixtures, domain status mappings, result selection, and page composition. Compose public exports instead of copying their markup, querying their private DOM, or overriding their state styles.
|
|
24
|
+
- Use `page-shell`, `section-title`, and `eyebrow` for the shared width and type hierarchy. For a two-column hero, keep badges inside the text column, followed by a `mb-7` gap, then the eyebrow with `mb-4` before the heading. Use `py-14 sm:py-18 lg:py-20` for hero insets, and align the example with the complete text column. Badge content and column proportions remain site-owned.
|
|
25
|
+
- Use `HeroBackdrop` inside a `relative overflow-hidden` section, with foreground content positioned `relative`. It owns the static, theme-aware radial/grid background shared with the Skill website. Do not duplicate its gradients in page markup.
|
|
26
|
+
- Section introductions may place the title on the left and a concise explanation on the right at `lg`, stacking on mobile. Alternate this with compact stacked introductions when the content warrants it; do not force every section into the same composition.
|
|
27
|
+
- Demonstrations should show recognizable files, one visible connection or mismatch, and a concise outcome. Compose `FilePreview`, `ConnectionLabel`, `ResultSummary`, `StatusBadge`, `CodeBlock`, and `Dialog`. Keep the essential result visible without interaction; dialogs contain optional evidence. Use `Accordion` when several examples share a section.
|
|
28
|
+
- Preserve semantic inline code for filenames, variables, operations, and package names using `inline-code`; use `InlineBrandText` for prose containing the product name. Keep code wrapping and interaction feedback in the shared policies below.
|
|
29
|
+
- Verify compositions at 320px through desktop, in both themes, with keyboard focus and reduced motion. Flatten unnecessary mobile panels and preserve legible filenames, labels, and status text. Use icons and explicit text together rather than relying on color alone.
|
|
30
|
+
|
|
21
31
|
## Surface-aware selection
|
|
22
32
|
|
|
23
33
|
Add `dark-surface-selection` to an intentionally dark surface and `light-surface-selection` to an intentionally light surface when it differs from the active theme. Use `theme-surface-selection` when a nested surface returns to the active website theme. These utilities keep ordinary and inline-code text selection legible across nested light and dark surfaces.
|
|
24
34
|
|
|
35
|
+
## Link states
|
|
36
|
+
|
|
37
|
+
Interaction roles follow the platform's `TextLink`, footer, navigation, button, and linked package-card patterns. Shared branding does not mean every anchor has the same feedback:
|
|
38
|
+
|
|
39
|
+
- `text-link` uses the platform's primary text colors, a persistent underline, 70% hover opacity, 60% pressed opacity, and a current-color focus ring. Markdown links inherit this treatment.
|
|
40
|
+
- `ActionLink` with `variant="link"` is a standalone text action: the same opacity feedback, no underline or pressed translation. `link-feedback` is available for high-contrast text compositions, not muted text or whole cards.
|
|
41
|
+
- `plain-link` keeps footer, breadcrumb, and outline links muted at rest and uses foreground on hover and press, without fading or underlining them.
|
|
42
|
+
- `navigation-link` uses secondary hover/pressed fills and a separate `aria-current="page"` selected treatment.
|
|
43
|
+
- `surface-link` adds secondary hover/pressed fills to compact linked surfaces. `surface-link-warning` and `surface-link-danger` retain semantic tints throughout interaction.
|
|
44
|
+
- `interactive-card` uses the platform's small lift, pressed translation, and border feedback without fading its contents. Reduced motion removes all movement.
|
|
45
|
+
- Button-style `ActionLink` variants and `ActionButton` retain button interaction states. The button's `link` variant retains its hover underline and pressed translation.
|
|
46
|
+
|
|
47
|
+
The global stylesheet keeps keyboard focus visible; text-only links use their role-specific focus treatment. Both themes and reduced-motion preferences are supported. The Astro package remains independent of the platform's React package.
|
|
48
|
+
|
|
49
|
+
Dark prose keeps its primary foreground opaque before the 70%/60% opacity feedback. Compounding the platform's additional 80% dark hover text alpha with pressed opacity falls below 4.5:1 contrast on the shared dark background. This accessibility correction preserves the interaction scale without fading muted navigation or entire cards.
|
|
50
|
+
|
|
51
|
+
`BrandLogo` stays background-free in its resting, hover, and pressed states while retaining the global keyboard focus ring.
|
|
52
|
+
|
|
25
53
|
## Utilities
|
|
26
54
|
|
|
27
55
|
```typescript
|
|
@@ -33,21 +61,32 @@ import { isDarkTheme } from '@moldea.ai/website-ui/theme';
|
|
|
33
61
|
|
|
34
62
|
`parseSearchDocuments` accepts only complete search records with safe root-relative result URLs. Base-path failures and invalid generated search indexes throw `WebsiteUiConfigurationException` with stable error codes.
|
|
35
63
|
|
|
64
|
+
`LocalSearch` loads its index on the first non-empty submitted query and shares that request across overlapping searches. Only the latest submission can update results or status, including when a query is cleared. Failed or malformed index responses produce the consumer's failure message; a later submission retries the load. Successful indexes remain cached for that component instance.
|
|
65
|
+
|
|
66
|
+
Set `shouldFocusOnLoad` on a dedicated search page to focus its input without scrolling on direct loads and Astro client navigation. It defaults to `false` for embedded searches. Opt in at most one search per page; consumers do not need a separate focus script.
|
|
67
|
+
|
|
36
68
|
## Components
|
|
37
69
|
|
|
38
70
|
Every component has a dedicated public subpath:
|
|
39
71
|
|
|
72
|
+
- `@moldea.ai/website-ui/accordion`
|
|
40
73
|
- `@moldea.ai/website-ui/action-button`
|
|
41
74
|
- `@moldea.ai/website-ui/action-link`
|
|
42
75
|
- `@moldea.ai/website-ui/brand-logo`
|
|
43
76
|
- `@moldea.ai/website-ui/breadcrumbs`
|
|
77
|
+
- `@moldea.ai/website-ui/code-block`
|
|
78
|
+
- `@moldea.ai/website-ui/connection-label`
|
|
44
79
|
- `@moldea.ai/website-ui/documentation-shell`
|
|
80
|
+
- `@moldea.ai/website-ui/dialog`
|
|
45
81
|
- `@moldea.ai/website-ui/evaluation-replay`
|
|
46
82
|
- `@moldea.ai/website-ui/evaluation-replay-model`
|
|
83
|
+
- `@moldea.ai/website-ui/file-preview`
|
|
84
|
+
- `@moldea.ai/website-ui/hero-backdrop`
|
|
47
85
|
- `@moldea.ai/website-ui/inline-brand-text`
|
|
48
86
|
- `@moldea.ai/website-ui/local-search`
|
|
49
87
|
- `@moldea.ai/website-ui/markdown`
|
|
50
88
|
- `@moldea.ai/website-ui/navigation-progress`
|
|
89
|
+
- `@moldea.ai/website-ui/result-summary`
|
|
51
90
|
- `@moldea.ai/website-ui/site-footer`
|
|
52
91
|
- `@moldea.ai/website-ui/site-header`
|
|
53
92
|
- `@moldea.ai/website-ui/status-badge`
|
|
@@ -59,8 +98,130 @@ Every component has a dedicated public subpath:
|
|
|
59
98
|
|
|
60
99
|
`SiteHeader`, `SiteFooter`, and `DocumentationShell` own responsive structure while consumers retain navigation data, accessible labels, copy, branding, actions, and page content. `TabbedPanels` keeps every panel readable without JavaScript and adds WAI-ARIA tab behavior, including Arrow Left, Arrow Right, Home, and End, after enhancement. `StatusBadge` exposes semantic tones and border treatments without defining domain status mappings.
|
|
61
100
|
|
|
101
|
+
Each `SiteHeader` navigation item accepts `href`, `isActive`, `label`, and optional `compactLabel`. The desktop navigation shows the compact label below `xl` (1280px) when supplied. Wider desktop navigation and the mobile menu show the full label. Accessible names always identify the full destination. The header's existing `md` or `lg` desktop breakpoint remains independent of label selection.
|
|
102
|
+
|
|
103
|
+
### Accordions
|
|
104
|
+
|
|
105
|
+
`Accordion` is one native disclosure item. Keep related items together in a section, give each a document-unique `id`, and use the same document-unique `group` for mutually exclusive items. At most one item in a group can be open; users can also close every item. Pass `isOpen` to the first item to show an example immediately. Do not mark multiple items in one group initially open.
|
|
106
|
+
|
|
107
|
+
```astro
|
|
108
|
+
---
|
|
109
|
+
import Accordion from '@moldea.ai/website-ui/accordion';
|
|
110
|
+
import StatusBadge from '@moldea.ai/website-ui/status-badge';
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
<section aria-labelledby="checks-heading">
|
|
114
|
+
<h2 id="checks-heading">Repository checks</h2>
|
|
115
|
+
<div class="grid gap-3">
|
|
116
|
+
<Accordion
|
|
117
|
+
id="file-check"
|
|
118
|
+
group="repository-checks"
|
|
119
|
+
title="Check file connections"
|
|
120
|
+
description="One referenced file is missing."
|
|
121
|
+
isOpen
|
|
122
|
+
>
|
|
123
|
+
<StatusBadge
|
|
124
|
+
slot="status"
|
|
125
|
+
label="Invalid"
|
|
126
|
+
tone="danger"
|
|
127
|
+
size="sm"
|
|
128
|
+
/>
|
|
129
|
+
<p>A consumer-owned visual goes here.</p>
|
|
130
|
+
</Accordion>
|
|
131
|
+
<Accordion
|
|
132
|
+
id="variable-check"
|
|
133
|
+
group="repository-checks"
|
|
134
|
+
title="Check variable declarations"
|
|
135
|
+
>
|
|
136
|
+
<p>Another consumer-owned visual goes here.</p>
|
|
137
|
+
</Accordion>
|
|
138
|
+
</div>
|
|
139
|
+
</section>
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Required props are `id`, `group`, and `title`. Optional `description` stays visible when closed and supplies the control's accessible description; `isOpen` defaults to `false`. The default slot accepts arbitrary content, including files and dialogs. The optional `status` slot accepts a compact non-interactive status, not another button or link. Consumers can derive props using `ComponentProps<typeof Accordion>` through the public subpath.
|
|
143
|
+
|
|
144
|
+
Native disclosure and group exclusivity work without JavaScript. JavaScript reveals hash-linked items on initial load, hash changes, and Astro client navigation without adding history entries or taking focus. Variable-height panels use a short fade; reduced motion removes it and the chevron transition. Mobile items use a flat surface, while desktop items retain the shared border, radius, colors, and interaction states. The package owns no example content or domain status mapping.
|
|
145
|
+
|
|
146
|
+
### Files and result summaries
|
|
147
|
+
|
|
148
|
+
`ConnectionLabel` places a short relationship label between visual examples. Its default slot accepts text and inline markup; the optional `icon` slot takes a decorative 16px icon. `tone` is `neutral` by default or `danger` for a broken connection. It owns spacing, icon alignment, and narrow-screen wrapping, not the meaning of a connection.
|
|
149
|
+
|
|
150
|
+
`FilePreview` receives `path`, optional `label`, and optional `tone`. Its header preserves an identifiable filename while truncating the directory prefix; the complete path remains selectable and readable by assistive technology without hover. Long filenames can wrap within the header. The default slot owns the body, `icon` replaces the default file icon, and `status` accepts a consumer-owned badge. This component does not parse files, choose excerpts, or define result semantics.
|
|
151
|
+
|
|
152
|
+
`ResultSummary` receives `title`, `description`, optional `tone`, `headingId`, `as` (`p`, `h2`, or `h3`), `hideIconOnMobile`, and `ariaLabel`. Defaults are a paragraph heading, neutral tone, visible icon, and “Result” group label. The optional `icon` slot renders inside a 40px badge; supply a 20px decorative icon. The `status` slot sits beside the heading, outside its accessible name. Titles use 14px type and descriptions 12px, both with 20px line height. Both components use the `danger`, `info`, `neutral`, `success`, and `warning` semantic tones.
|
|
153
|
+
|
|
154
|
+
For a dialog heading, compose `ResultSummary` in Dialog's `heading` slot, set `as="h2"` and `headingId` to `${id}-title`, keep `title` equal to Dialog's title, and use `hideIconOnMobile`. Consumer-owned status badges can use `size="sm"`. Neither component depends on Core, runs checks, or maps domain statuses. Derive their props with Astro's `ComponentProps` through the documented public subpaths.
|
|
155
|
+
|
|
156
|
+
`StatusBadge` defaults to `size="md"`. Use `size="sm"` for secondary status beside compact headings: a 20px minimum height, tighter padding, and lighter 10px lettering. Both sizes retain the same semantic colors and wrapping behavior.
|
|
157
|
+
|
|
158
|
+
`InlineBrandText` renders standalone product names as semantic inline code. Its default `badge` variant includes the code background and padding; `compact` omits them. Both variants scale with surrounding text and use normal letter spacing so display headings do not compress the monospace token.
|
|
159
|
+
|
|
160
|
+
For other hand-authored inline tokens, use `<code class="inline-code">`. This shared class matches rendered Markdown's code background, padding, monospace weight, and theme colors. `FilePreview` uses it for paths while retaining filename-preserving truncation. It does not parse text or add code semantics to plain strings; consumers must mark filenames and variable tokens explicitly.
|
|
161
|
+
|
|
62
162
|
The compiled `markdown` entry renders sanitized documents and fragments with stable headings, syntax highlighting, safe external links, base-aware internal links, and keyboard-scrollable tables. Raw HTML is disabled. The replay component accepts only the normalized contracts from `evaluation-replay-model`; semantic and qualification evidence conversion remains application-owned.
|
|
63
163
|
|
|
164
|
+
### Code and text wrapping
|
|
165
|
+
|
|
166
|
+
`CodeBlock` receives literal `source`, optional `language`, and `variant="panel"` (default) or `variant="plain"` for use inside another surface. It owns compact typography, syntax highlighting, keyboard scrolling, and light/dark presentation. Pass raw code rather than constructing a Markdown fence; embedded fences and HTML remain literal source. `renderCodeBlock` from the public `markdown` subpath exposes the same rendering for non-component consumers.
|
|
167
|
+
|
|
168
|
+
```astro
|
|
169
|
+
---
|
|
170
|
+
import CodeBlock from '@moldea.ai/website-ui/code-block';
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
<CodeBlock
|
|
174
|
+
source={JSON.stringify({ valid: false }, null, 2)}
|
|
175
|
+
language="json"
|
|
176
|
+
/>
|
|
177
|
+
<CodeBlock
|
|
178
|
+
source="pnpm test"
|
|
179
|
+
language="sh"
|
|
180
|
+
variant="plain"
|
|
181
|
+
/>
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Code preserves its source line breaks and scrolls horizontally when needed. This includes JSON, YAML, shell commands, diffs, and Markdown source. Unlabelled fences also preserve lines, since they may contain code or aligned file trees. Only fences explicitly labelled `text`, `txt`, or `plaintext` wrap long lines while retaining their original line breaks. Use these labels for prose, not as a shortcut to force code to fit.
|
|
185
|
+
|
|
186
|
+
Markdown and literal code renderers apply this policy through `styles.css`. Rendered code blocks are named, keyboard-focusable regions with visible focus indicators. Hand-authored `<pre>` elements use the shared `code-block` class, `tabindex="0"`, `role="region"`, and a descriptive `aria-label`; add `data-code-language="text"` only for plain text. Do not add page-wide wrapping overrides to code, diagnostics, or replay content.
|
|
187
|
+
|
|
188
|
+
### Optional detail dialogs
|
|
189
|
+
|
|
190
|
+
`Dialog` defaults to a compact outline trigger, a named native modal, and a slotted scrolling body. It follows the platform's medium dialog: a bordered desktop surface, full-screen mobile layout, fixed header, 28px desktop close control, and 36px mobile back control. Opening takes 300ms with a fade and small slide, plus a subtle desktop scale. Closing takes 200ms on desktop and 300ms on mobile; native modality and background scroll locking remain active through the exit. Reduced motion skips animations. Escape and the close control dismiss it and return focus to the trigger. Set `isOverlayCloseEnabled` for read-only content to also dismiss on backdrop clicks; dragging between the panel and backdrop does not dismiss it. Astro client navigation dismisses immediately and initializes new triggers.
|
|
191
|
+
|
|
192
|
+
```astro
|
|
193
|
+
---
|
|
194
|
+
import Dialog from '@moldea.ai/website-ui/dialog';
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
<Dialog
|
|
198
|
+
id="check-result"
|
|
199
|
+
title="Check passed"
|
|
200
|
+
triggerLabel="View result"
|
|
201
|
+
triggerAriaLabel="View repository check result"
|
|
202
|
+
closeLabel="Close check result"
|
|
203
|
+
isOverlayCloseEnabled
|
|
204
|
+
>
|
|
205
|
+
<p>No broken references were found.</p>
|
|
206
|
+
</Dialog>
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Supply a unique document `id`, `title`, and `triggerLabel`. `description` and `triggerAriaLabel` are optional; `closeLabel` defaults to “Close dialog” and `isOverlayCloseEnabled` defaults to `false`, matching the platform. Consumers own content, status mapping, and any result transformation. The package does not depend on Core or execute checks. Triggers remain hidden without JavaScript, so keep essential information visible outside the dialog.
|
|
210
|
+
|
|
211
|
+
The optional `heading` slot replaces the default heading with an application-owned summary, such as an icon, outcome, description, and status badge. Supply an `h2` whose ID is `${id}-title` and whose text matches `title`; that heading alone provides the dialog's accessible name. Keep supplemental copy and badges outside the `h2`, and preserve readable wrapping on narrow screens. The dialog continues to own the close control and header layout.
|
|
212
|
+
|
|
213
|
+
Use these typed props to customize presentation without replacing the shared controls:
|
|
214
|
+
|
|
215
|
+
- `triggerVariant`: `outline` (default), `primary`, `secondary`, `ghost`, or `link`, using the corresponding `ActionButton` variant.
|
|
216
|
+
- `triggerSize`: `compact` (default) preserves the existing result-card button; `sm`, `md`, and `lg` use standard `ActionButton` text-button sizes. The trigger remains a labelled text button.
|
|
217
|
+
- `size`: `medium` (default) caps desktop width at 42rem; `large` uses the platform's 64rem cap for wider evidence. Both retain the viewport gutter, full-screen mobile layout, fixed header, scrolling body, and the same focus and dismissal behavior.
|
|
218
|
+
|
|
219
|
+
For example, add `size="large" triggerVariant="primary" triggerSize="lg"` to the example above. Import the component through `@moldea.ai/website-ui/dialog`; consumers can derive its props with Astro's `ComponentProps<typeof Dialog>`.
|
|
220
|
+
|
|
221
|
+
### Website composition
|
|
222
|
+
|
|
223
|
+
Each website owns its dependency and lockfile. Use the documented public component subpaths, shared code-wrapping policy, semantic tones, and supported slots. Verify long code, replay content, keyboard scrolling, and both themes at mobile and desktop widths. Website UI does not modify consumer source files or lockfiles.
|
|
224
|
+
|
|
64
225
|
## Development
|
|
65
226
|
|
|
66
227
|
From the monorepo root:
|
package/dist/markdown/index.d.ts
CHANGED
|
@@ -43,4 +43,11 @@ export declare const renderMarkdownDocument: (markdown: string, options?: IMarkd
|
|
|
43
43
|
* - If the strong-label badge configuration is invalid
|
|
44
44
|
*/
|
|
45
45
|
export declare const renderMarkdownFragment: (markdown: string, options?: IMarkdownRenderOptions) => Promise<string>;
|
|
46
|
+
/**
|
|
47
|
+
* Renders literal source without interpreting its contents as Markdown or HTML.
|
|
48
|
+
* @param source Code or plain text to display verbatim.
|
|
49
|
+
* @param language Syntax language; omitted languages remain unhighlighted and do not wrap.
|
|
50
|
+
* @returns Sanitized, highlighted HTML with a keyboard-accessible code region.
|
|
51
|
+
*/
|
|
52
|
+
export declare const renderCodeBlock: (source: string, language?: string) => Promise<string>;
|
|
46
53
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/markdown/index.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAGD,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,QAAQ,EAAE,SAAS,wBAAwB,EAAE,CAAC;IACvD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAGD,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAGvF,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;CACnC;AAGD,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC1C,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAChD,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,yBAAyB,EAAE,CAAC;CACnE;AAGD,MAAM,WAAW,8BAA+B,SAAQ,sBAAsB;IAC5E,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;CACrC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/markdown/index.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAGD,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,QAAQ,EAAE,SAAS,wBAAwB,EAAE,CAAC;IACvD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAGD,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAGvF,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;CACnC;AAGD,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC1C,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAChD,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,yBAAyB,EAAE,CAAC;CACnE;AAGD,MAAM,WAAW,8BAA+B,SAAQ,sBAAsB;IAC5E,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;CACrC;AAsID;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,GACjC,UAAU,MAAM,EAChB,UAAS,8BAAmC,KAC3C,OAAO,CAAC,yBAAyB,CAMnC,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,GACjC,UAAU,MAAM,EAChB,UAAS,sBAA2B,KACnC,OAAO,CAAC,MAAM,CAIhB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,eAAe,GAAU,QAAQ,MAAM,EAAE,iBAAa,KAAG,OAAO,CAAC,MAAM,CAQnF,CAAC"}
|
package/dist/markdown.js
CHANGED
|
@@ -31254,6 +31254,10 @@ var markExternalLinks = (html) => {
|
|
|
31254
31254
|
var wrapTables = (html) => {
|
|
31255
31255
|
return html.replaceAll(/<table>([\s\S]*?)<\/table>/g, "<div class=\"table-scroll\" tabindex=\"0\" role=\"region\" aria-label=\"Scrollable table\"><table>$1</table></div>");
|
|
31256
31256
|
};
|
|
31257
|
+
/** Names code regions and makes their horizontal overflow keyboard-accessible. */
|
|
31258
|
+
var markCodeBlocks = (html) => html.replaceAll(/<pre\b([^>]*)>/gu, (_match, attributes) => {
|
|
31259
|
+
return `<pre${attributes}${/\btabindex=/u.test(attributes) ? "" : " tabindex=\"0\""} role="region" aria-label="Code block">`;
|
|
31260
|
+
});
|
|
31257
31261
|
/** Applies the public product-name treatment outside existing code elements. */
|
|
31258
31262
|
var renderProductNamesAsCode = (html) => {
|
|
31259
31263
|
let codeDepth = 0;
|
|
@@ -31273,14 +31277,15 @@ var renderStrongLabelBadges = (html, badges) => {
|
|
|
31273
31277
|
return renderedHtml.replaceAll(`<strong>${badge.label}</strong>`, `<span class="markdown-badge ${BADGE_TONE_CLASSES[badge.tone]}" data-markdown-badge="${badge.id}">${badge.label}</span>`);
|
|
31274
31278
|
}, html);
|
|
31275
31279
|
};
|
|
31276
|
-
/**
|
|
31277
|
-
var
|
|
31280
|
+
/** Shares sanitization and highlighting between authored Markdown and literal code. */
|
|
31281
|
+
var createMarkdownProcessor = (shouldSlugHeadings) => {
|
|
31278
31282
|
const processor = unified().use(remarkParse).use(remarkGfm).use(remarkRehype);
|
|
31279
31283
|
if (shouldSlugHeadings) processor.use(rehypeSlug);
|
|
31280
|
-
|
|
31284
|
+
return processor.use(rehypeSanitize, {
|
|
31281
31285
|
...defaultSchema,
|
|
31282
31286
|
clobberPrefix: ""
|
|
31283
31287
|
}).use(rehypeShiki, {
|
|
31288
|
+
addLanguageClass: true,
|
|
31284
31289
|
defaultColor: false,
|
|
31285
31290
|
langs: [],
|
|
31286
31291
|
lazy: true,
|
|
@@ -31288,14 +31293,18 @@ var processMarkdown = async (source, shouldSlugHeadings) => {
|
|
|
31288
31293
|
dark: "github-dark-default",
|
|
31289
31294
|
light: "github-light-default"
|
|
31290
31295
|
}
|
|
31291
|
-
}).use(rehypeStringify)
|
|
31296
|
+
}).use(rehypeStringify);
|
|
31297
|
+
};
|
|
31298
|
+
/** Processes Markdown with optional stable heading IDs. */
|
|
31299
|
+
var processMarkdown = async (source, shouldSlugHeadings) => {
|
|
31300
|
+
const file = await createMarkdownProcessor(shouldSlugHeadings).process(source);
|
|
31292
31301
|
return String(file);
|
|
31293
31302
|
};
|
|
31294
31303
|
/** Applies deterministic link, table, badge, and product-name presentation. */
|
|
31295
31304
|
var applyPresentation = (html, options) => {
|
|
31296
31305
|
const basePath = options.basePath ?? "/";
|
|
31297
31306
|
const badgedHtml = renderStrongLabelBadges((options.localLinks ?? "prefix") === "unwrap" ? unwrapLocalLinks(html) : prefixInternalLinks(html, basePath), options.strongLabelBadges ?? []);
|
|
31298
|
-
return wrapTables(markExternalLinks(options.productNameTreatment === "code" ? renderProductNamesAsCode(badgedHtml) : badgedHtml));
|
|
31307
|
+
return markCodeBlocks(wrapTables(markExternalLinks(options.productNameTreatment === "code" ? renderProductNamesAsCode(badgedHtml) : badgedHtml)));
|
|
31299
31308
|
};
|
|
31300
31309
|
/** Extracts stable second- and third-level headings from sanitized document HTML. */
|
|
31301
31310
|
var getHeadings = (html) => {
|
|
@@ -31334,7 +31343,25 @@ var renderMarkdownDocument = async (markdown, options = {}) => {
|
|
|
31334
31343
|
var renderMarkdownFragment = async (markdown, options = {}) => {
|
|
31335
31344
|
return applyPresentation(await processMarkdown(markdown, false), options);
|
|
31336
31345
|
};
|
|
31346
|
+
/**
|
|
31347
|
+
* Renders literal source without interpreting its contents as Markdown or HTML.
|
|
31348
|
+
* @param source Code or plain text to display verbatim.
|
|
31349
|
+
* @param language Syntax language; omitted languages remain unhighlighted and do not wrap.
|
|
31350
|
+
* @returns Sanitized, highlighted HTML with a keyboard-accessible code region.
|
|
31351
|
+
*/
|
|
31352
|
+
var renderCodeBlock = async (source, language = "") => {
|
|
31353
|
+
const processor = createMarkdownProcessor(false);
|
|
31354
|
+
const rendered = await processor.run({
|
|
31355
|
+
type: "root",
|
|
31356
|
+
children: [{
|
|
31357
|
+
type: "code",
|
|
31358
|
+
lang: language || null,
|
|
31359
|
+
value: source
|
|
31360
|
+
}]
|
|
31361
|
+
});
|
|
31362
|
+
return markCodeBlocks(processor.stringify(rendered));
|
|
31363
|
+
};
|
|
31337
31364
|
//#endregion
|
|
31338
|
-
export { renderMarkdownDocument, renderMarkdownFragment };
|
|
31365
|
+
export { renderCodeBlock, renderMarkdownDocument, renderMarkdownFragment };
|
|
31339
31366
|
|
|
31340
31367
|
//# sourceMappingURL=markdown.js.map
|