@nanisoft/prism-llms 0.5.0 → 0.5.1
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/dist/data.json +64 -22
- package/dist/extractor.js +42 -15
- package/dist/llms-full.txt +306 -26
- package/dist/llms.txt +4 -3
- package/dist/md/blocks/note-grid-01.md +0 -4
- package/dist/md/blocks/product-grid-01.md +0 -6
- package/dist/md/blocks/settings-panel-01.md +0 -2
- package/dist/md/blocks/site-header.md +0 -4
- package/dist/md/changelogs/prism-llms.md +38 -0
- package/dist/md/changelogs/prism-mcp-server.md +7 -0
- package/dist/md/changelogs/prism-ui.md +38 -0
- package/dist/md/components/product-mark.md +0 -9
- package/dist/md/components/select.md +1 -1
- package/dist/md/pages/docs-shell.md +218 -0
- package/dist/prism-skill.md +1 -1
- package/package.json +3 -3
package/dist/extractor.js
CHANGED
|
@@ -36,13 +36,13 @@ export function extractProps(source) {
|
|
|
36
36
|
if (!(match[1] ?? '').endsWith('Props'))
|
|
37
37
|
continue;
|
|
38
38
|
const openBrace = pattern.lastIndex - 1;
|
|
39
|
-
const
|
|
40
|
-
if (
|
|
39
|
+
const found = readBalancedBody(source, openBrace);
|
|
40
|
+
if (found === undefined)
|
|
41
41
|
continue;
|
|
42
42
|
results.push({
|
|
43
43
|
typeName: match[1] ?? '',
|
|
44
44
|
...(match[2] ? { extendsType: match[2].trim() } : {}),
|
|
45
|
-
props: parseMembers(body).map(toProp),
|
|
45
|
+
props: parseMembers(found.body).map(toProp),
|
|
46
46
|
});
|
|
47
47
|
}
|
|
48
48
|
return results;
|
|
@@ -64,7 +64,15 @@ export function extractExports(source, exportNames) {
|
|
|
64
64
|
};
|
|
65
65
|
});
|
|
66
66
|
}
|
|
67
|
-
/**
|
|
67
|
+
/**
|
|
68
|
+
* The `{...}` body of the declaration whose brace sits at `openBrace`, and the
|
|
69
|
+
* index of the brace that closed it.
|
|
70
|
+
*
|
|
71
|
+
* The index is returned as well as the text because `findTypeBodies` has to
|
|
72
|
+
* resume scanning after the body, and re-walking it with a second depth counter
|
|
73
|
+
* is how the two came to disagree. `undefined` for the text means the body never
|
|
74
|
+
* closed, and the caller stops rather than guessing where it ended.
|
|
75
|
+
*/
|
|
68
76
|
function readBalancedBody(source, openBrace) {
|
|
69
77
|
let depth = 0;
|
|
70
78
|
let i = openBrace;
|
|
@@ -94,7 +102,7 @@ function readBalancedBody(source, openBrace) {
|
|
|
94
102
|
if (ch === '}') {
|
|
95
103
|
depth -= 1;
|
|
96
104
|
if (depth === 0)
|
|
97
|
-
return source.slice(openBrace + 1, i);
|
|
105
|
+
return { body: source.slice(openBrace + 1, i), end: i };
|
|
98
106
|
}
|
|
99
107
|
i += 1;
|
|
100
108
|
}
|
|
@@ -131,6 +139,24 @@ function skipString(source, start, quote) {
|
|
|
131
139
|
* the declaration at `variant?: 'icon';` and never reach the second arm, which
|
|
132
140
|
* is the defect this function exists to remove. Angle brackets are tracked
|
|
133
141
|
* because a generic argument can carry its own braces.
|
|
142
|
+
*
|
|
143
|
+
* **A body is consumed once and skipped, not re-walked.** `readBalancedBody`
|
|
144
|
+
* returns a body's text, and the scan used to leave `i` on the opening brace and
|
|
145
|
+
* walk the body a second time with its own depth counter. The second walk counts
|
|
146
|
+
* every `{` the balanced read had already accounted for, so the two disagreed and
|
|
147
|
+
* `depth` could not be trusted to reach 0 at the brace that closed the body. The
|
|
148
|
+
* scan therefore depended on finding a terminator it was no longer counting
|
|
149
|
+
* correctly, and the caller concatenates the emitted JavaScript of the same
|
|
150
|
+
* module beside the declaration, so a scan that ran long published every object
|
|
151
|
+
* literal in that implementation as another arm of the type. Advancing `i` to the
|
|
152
|
+
* brace `readBalancedBody` reported removes the second walk rather than trying to
|
|
153
|
+
* correct for it, and one walk cannot disagree with itself.
|
|
154
|
+
*
|
|
155
|
+
* The honest limit on that claim: a declaration whose body closes and is followed
|
|
156
|
+
* immediately by a terminator terminated the scan correctly even before this
|
|
157
|
+
* change, which is why every Page in the package was published correctly and only
|
|
158
|
+
* the first Page with a two-line barrel was not. The defect was a miscount, not a
|
|
159
|
+
* missing terminator, and a miscount is only visible where a miscount is.
|
|
134
160
|
*/
|
|
135
161
|
function findTypeBodies(source, name) {
|
|
136
162
|
const pattern = new RegExp(`(?:export\\s+)?(?:type|interface)\\s+${name}\\b`);
|
|
@@ -154,16 +180,17 @@ function findTypeBodies(source, name) {
|
|
|
154
180
|
continue;
|
|
155
181
|
}
|
|
156
182
|
if (ch === '{') {
|
|
157
|
-
const
|
|
158
|
-
if (
|
|
183
|
+
const found = readBalancedBody(source, i);
|
|
184
|
+
if (found === undefined)
|
|
159
185
|
return bodies;
|
|
160
|
-
bodies.push(body);
|
|
161
|
-
|
|
186
|
+
bodies.push(found.body);
|
|
187
|
+
// Resume AFTER the brace that closed the body. The re-walk this replaces
|
|
188
|
+
// counted every `{` in the body a second time and only the closing `}`
|
|
189
|
+
// once, so `depth` never returned to 0 and the scan never terminated.
|
|
190
|
+
i = found.end;
|
|
162
191
|
continue;
|
|
163
192
|
}
|
|
164
|
-
if (ch === '
|
|
165
|
-
depth -= 1;
|
|
166
|
-
else if (ch === '(')
|
|
193
|
+
if (ch === '(')
|
|
167
194
|
depth += 1;
|
|
168
195
|
else if (ch === ')')
|
|
169
196
|
depth -= 1;
|
|
@@ -247,9 +274,9 @@ function resolveAnnotation(annotation, source) {
|
|
|
247
274
|
return { props: named.flatMap((body) => parseMembers(body)).map(toProp), inherited: [] };
|
|
248
275
|
}
|
|
249
276
|
if (annotation.startsWith('{')) {
|
|
250
|
-
const
|
|
251
|
-
if (
|
|
252
|
-
return { props: parseMembers(body).map(toProp), inherited: [] };
|
|
277
|
+
const found = readBalancedBody(annotation, 0);
|
|
278
|
+
if (found !== undefined)
|
|
279
|
+
return { props: parseMembers(found.body).map(toProp), inherited: [] };
|
|
253
280
|
}
|
|
254
281
|
const props = [];
|
|
255
282
|
const inherited = [];
|
package/dist/llms-full.txt
CHANGED
|
@@ -6,6 +6,44 @@
|
|
|
6
6
|
|
|
7
7
|
# @nanisoft/prism-llms
|
|
8
8
|
|
|
9
|
+
## 0.5.1
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 5c43520: Add `DocsShell`, a documentation page that takes a site's navigation as data
|
|
14
|
+
|
|
15
|
+
`DocsShell` is a documentation screen: a navigation rail, the document, a
|
|
16
|
+
contents rail, and a pager to the neighbouring pages. It replaces the unstyled
|
|
17
|
+
`docs-shell` the retired line published, and it is the Page the three NaniSoft
|
|
18
|
+
product sites already import by that name.
|
|
19
|
+
|
|
20
|
+
The navigation is data. A tree of one page and a tree of twenty-seven render the
|
|
21
|
+
same way, at any depth, and the frame is sized by what the caller passed rather
|
|
22
|
+
than by a fixed arrangement, so three sites whose documentation sets differ in
|
|
23
|
+
shape share one Page with no per-site fork.
|
|
24
|
+
|
|
25
|
+
- `nav` and `toc` are closed unions of `page`, `group` and `divider`. Both are
|
|
26
|
+
read in the order given: nothing is sorted or alphabetised, so a site that
|
|
27
|
+
files its rail as a pipeline and its contents as a reference has both in one
|
|
28
|
+
render.
|
|
29
|
+
- The pager is derived from `nav` and `currentHref`. There is no `neighbours`
|
|
30
|
+
prop, so a neighbour that is not in the tree cannot be expressed, and each
|
|
31
|
+
consumer loses one derivation of its own.
|
|
32
|
+
- A group with no `href` renders a `span` rather than an anchor with no
|
|
33
|
+
destination. The three sites spell that case today as an empty string, and two
|
|
34
|
+
of them carry a stylesheet rule that styles the result back into a label; those
|
|
35
|
+
rules are now deletable.
|
|
36
|
+
- A section carries no status, no badge, no count, no collapse and no sort. A
|
|
37
|
+
status written into a title stays in the title as words.
|
|
38
|
+
- Both rails are bounded against the viewport, because one site's tree is half
|
|
39
|
+
again as tall as another's.
|
|
40
|
+
|
|
41
|
+
The corpus fix that shipped with it: the props extractor read each declaration
|
|
42
|
+
body twice with two depth counters that disagreed, so a Page whose `index.tsx`
|
|
43
|
+
re-exported a value and a type from one sibling published every prop twice and
|
|
44
|
+
swept the members of its navigation union into its own prop list. It now reads
|
|
45
|
+
each body once.
|
|
46
|
+
|
|
9
47
|
## 0.5.0
|
|
10
48
|
|
|
11
49
|
### Minor Changes
|
|
@@ -216,6 +254,13 @@ Changesets are appended above this entry for every published change.
|
|
|
216
254
|
|
|
217
255
|
# @nanisoft/prism-mcp-server
|
|
218
256
|
|
|
257
|
+
## 0.4.1
|
|
258
|
+
|
|
259
|
+
### Patch Changes
|
|
260
|
+
|
|
261
|
+
- Updated dependencies [5c43520]
|
|
262
|
+
- @nanisoft/prism-llms@0.5.1
|
|
263
|
+
|
|
219
264
|
## 0.4.0
|
|
220
265
|
|
|
221
266
|
### Patch Changes
|
|
@@ -438,6 +483,44 @@ Changesets are appended above this entry for every published change.
|
|
|
438
483
|
|
|
439
484
|
# @nanisoft/prism-ui
|
|
440
485
|
|
|
486
|
+
## 0.7.0
|
|
487
|
+
|
|
488
|
+
### Minor Changes
|
|
489
|
+
|
|
490
|
+
- 5c43520: Add `DocsShell`, a documentation page that takes a site's navigation as data
|
|
491
|
+
|
|
492
|
+
`DocsShell` is a documentation screen: a navigation rail, the document, a
|
|
493
|
+
contents rail, and a pager to the neighbouring pages. It replaces the unstyled
|
|
494
|
+
`docs-shell` the retired line published, and it is the Page the three NaniSoft
|
|
495
|
+
product sites already import by that name.
|
|
496
|
+
|
|
497
|
+
The navigation is data. A tree of one page and a tree of twenty-seven render the
|
|
498
|
+
same way, at any depth, and the frame is sized by what the caller passed rather
|
|
499
|
+
than by a fixed arrangement, so three sites whose documentation sets differ in
|
|
500
|
+
shape share one Page with no per-site fork.
|
|
501
|
+
|
|
502
|
+
- `nav` and `toc` are closed unions of `page`, `group` and `divider`. Both are
|
|
503
|
+
read in the order given: nothing is sorted or alphabetised, so a site that
|
|
504
|
+
files its rail as a pipeline and its contents as a reference has both in one
|
|
505
|
+
render.
|
|
506
|
+
- The pager is derived from `nav` and `currentHref`. There is no `neighbours`
|
|
507
|
+
prop, so a neighbour that is not in the tree cannot be expressed, and each
|
|
508
|
+
consumer loses one derivation of its own.
|
|
509
|
+
- A group with no `href` renders a `span` rather than an anchor with no
|
|
510
|
+
destination. The three sites spell that case today as an empty string, and two
|
|
511
|
+
of them carry a stylesheet rule that styles the result back into a label; those
|
|
512
|
+
rules are now deletable.
|
|
513
|
+
- A section carries no status, no badge, no count, no collapse and no sort. A
|
|
514
|
+
status written into a title stays in the title as words.
|
|
515
|
+
- Both rails are bounded against the viewport, because one site's tree is half
|
|
516
|
+
again as tall as another's.
|
|
517
|
+
|
|
518
|
+
The corpus fix that shipped with it: the props extractor read each declaration
|
|
519
|
+
body twice with two depth counters that disagreed, so a Page whose `index.tsx`
|
|
520
|
+
re-exported a value and a type from one sibling published every prop twice and
|
|
521
|
+
swept the members of its navigation union into its own prop list. It now reads
|
|
522
|
+
each body once.
|
|
523
|
+
|
|
441
524
|
## 0.6.0
|
|
442
525
|
|
|
443
526
|
### Minor Changes
|
|
@@ -3812,15 +3895,6 @@ export default function ProductMarkDemo() {
|
|
|
3812
3895
|
**`pack`** `PackId | null` · optional · default: — — The product's pack, which is the mark's hue. Omit it, or pass `null`, for the one entry in a set that has no pack of its own: that entry is drawn as the full spectrum rather than as a colourless mark. See `SPECTRUM` above. `default` is a real answer and not the same as the empty one. The base pack is a pack a product can wear, and it is the absence of a `data-pack` attribute, so a product whose pack is `default` carries no attribute and its core resolves the base pack's `primary` from the page.
|
|
3813
3896
|
**`size`** `ProductMarkSize` · optional · default: `'md'` — Which of the three drawn sizes to use.
|
|
3814
3897
|
**`className`** `string` · optional · default: — — Layout only, exactly as on every Component. Changing a Prism-owned visual property from here is prohibited, and this Component spreads no other prop, so there is no second route to its ink.
|
|
3815
|
-
**`stored`** `string | null` · required · default: — — Raw contents of the key this line writes, or `null` when it is absent.
|
|
3816
|
-
**`legacy`** `string | null` · required · default: — — Raw contents of one key this line no longer writes, or `null`.
|
|
3817
|
-
**`documentPack`** `string | null` · required · default: — — `data-pack` on the root element as rendered, valid or not.
|
|
3818
|
-
**`documentDark`** `boolean` · required · default: — — Whether the root element carries `.dark` as rendered.
|
|
3819
|
-
**`defaultPack`** `PackId` · required · default: —
|
|
3820
|
-
**`defaultMode`** `Mode` · required · default: —
|
|
3821
|
-
**`mode`** `Mode` · required · default: —
|
|
3822
|
-
**`origin`** `ThemeOrigin` · required · default: — — Which source named the pair, for `THEME_ORIGIN_ATTRIBUTE`.
|
|
3823
|
-
**`key`** `string` · required · default: —
|
|
3824
3898
|
|
|
3825
3899
|
|
|
3826
3900
|
---
|
|
@@ -4465,12 +4539,12 @@ export default function SelectDemo() {
|
|
|
4465
4539
|
**`items`** `Record<string, React.ReactNode> | ReadonlyArray<{ label: React.ReactNode; value: string; }>` · optional · default: — — The options, keyed by value, so the trigger can render a label before any item has mounted. Without it, `SelectValue` shows the raw value.
|
|
4466
4540
|
**`itemToStringLabel`** `(value: string) => string` · optional · default: — — Converts an item value to the label shown in the trigger.
|
|
4467
4541
|
**`children`** `React.ReactNode` · optional · default: — — The trigger and the popup content.
|
|
4468
|
-
**`label`** `React.ReactNode` · required · default: —
|
|
4469
4542
|
**`size`** `'sm' | 'default'` · optional · default: `default` — The trigger's height.
|
|
4470
4543
|
**`placeholder`** `React.ReactNode` · optional · default: — — Shown when no value is selected.
|
|
4471
4544
|
**`side`** `'top' | 'right' | 'bottom' | 'left'` · optional · default: `bottom` — Which side of the trigger the list is placed on.
|
|
4472
4545
|
**`align`** `'start' | 'center' | 'end'` · optional · default: `center` — How the list aligns against the trigger.
|
|
4473
4546
|
**`sideOffset`** `number` · optional · default: `4` — The distance in pixels between the trigger and the list.
|
|
4547
|
+
**`label`** `string` · optional · default: — — A text label used for keyboard typeahead when the option text differs.
|
|
4474
4548
|
|
|
4475
4549
|
|
|
4476
4550
|
---
|
|
@@ -6455,10 +6529,6 @@ export default function NoteGrid01Demo() {
|
|
|
6455
6529
|
**`notes`** `readonly NoteGrid01Note[]` · required · default: — — The notes, in the order a reader should meet them. Order is the caller's because it is a claim about which point matters first.
|
|
6456
6530
|
**`caption`** `string` · optional · default: — — The line under the grid, for the sentence that qualifies it: what the points do not cover, or where to read more.
|
|
6457
6531
|
**`headingLevel`** `HeadingLevel` · optional · default: — — Heading level for the section title. See `HeadingLevel`.
|
|
6458
|
-
**`body`** `string` · required · default: — — One or two sentences about the point.
|
|
6459
|
-
**`children`** `[title ? (_jsx(SectionHeading, { as: headingLevel, align: "left", eyebrow: eyebrow, title: title, description: description, className: "mb-12" })) : null, _jsx("dl", { "data-slot": "note-grid", className: "grid gap-8 sm:grid-cols-2 lg:grid-cols-3", children: notes.map((note) => (_jsxs("div", { "data-slot": "note-grid-note", className: "border-border flex flex-col gap-2 border-t pt-4", children: [_jsx("dt", { className: "text-sm font-semibold", children: note.title }), _jsx("dd", { className: "text-muted-foreground text-pretty text-sm", children: note.body })] }, note.title))) }), caption ? _jsx("p", { className: "text-muted-foreground mt-6 text-pretty text-sm", children: caption }) : null]` · required · default: —
|
|
6460
|
-
**`as`** `headingLevel, align: "left", eyebrow: eyebrow, title: title, description: description, className: "mb-12"` · required · default: —
|
|
6461
|
-
**`className`** `"text-sm font-semibold", children: note.title` · required · default: —
|
|
6462
6532
|
|
|
6463
6533
|
## Composition
|
|
6464
6534
|
|
|
@@ -6876,12 +6946,6 @@ export default function ProductGrid01Demo() {
|
|
|
6876
6946
|
**`products`** `readonly ProductGrid01Product[]` · required · default: — — The products, in the order a reader should meet them. Order is the caller's because it is a claim about which product matters first.
|
|
6877
6947
|
**`caption`** `string` · optional · default: — — The line under the grid, for the sentence that qualifies it: what the set does not include, or where to read more.
|
|
6878
6948
|
**`headingLevel`** `HeadingLevel` · optional · default: — — Heading level for the section title. See `HeadingLevel`.
|
|
6879
|
-
**`id`** `string` · required · default: — — The product's key within the set. Carried on the markup as `data-product` through `ProductMark`, so a test can name one product rather than the first one, and two products in one document are individually addressable.
|
|
6880
|
-
**`name`** `string` · required · default: — — The product's own name, which is the second part of its mark. It is the anchor of the row and the first thing a reader reads.
|
|
6881
|
-
**`pack`** `ProductMarkProps['pack']` · optional · default: — — The product's pack, which is the hue of the mark's core. Omit it, or pass `null`, for the one member of a set that has no pack of its own: that member wears the full spectrum rather than a colourless mark.
|
|
6882
|
-
**`tagline`** `string` · required · default: — — One line about what the product is.
|
|
6883
|
-
**`href`** `string` · required · default: — — Where the row goes. Rendered as a native anchor's `href`, so the row is a link with the browser's own affordances rather than a click handler.
|
|
6884
|
-
**`newTab`** `boolean` · optional · default: — — Opens the destination in a new browsing context, which defaults the link relationship to `noopener noreferrer`. Prism does not decide what counts as external, so the caller declares it.
|
|
6885
6949
|
|
|
6886
6950
|
## Composition
|
|
6887
6951
|
|
|
@@ -7032,8 +7096,6 @@ export default function SettingsPanel01Demo() {
|
|
|
7032
7096
|
**`onSubmit`** `(event: FormEvent<HTMLFormElement>) => void` · optional · default: —
|
|
7033
7097
|
**`secondaryAction`** `{ label: string; onClick?: () => void; }` · optional · default: — — A secondary control, such as Cancel.
|
|
7034
7098
|
**`footer`** `ReactNode` · optional · default: — — Extra content in the footer, e.g. a status note.
|
|
7035
|
-
**`label`** `string` · required · default: —
|
|
7036
|
-
**`onClick`** `() => void` · optional · default: —
|
|
7037
7099
|
|
|
7038
7100
|
## Composition
|
|
7039
7101
|
|
|
@@ -7268,10 +7330,6 @@ export default function SiteHeaderDemo() {
|
|
|
7268
7330
|
**`actions`** `ReactNode` · optional · default: — — A slot for the controls a product owns on the right: an account menu, a sign in link, a mode toggle, a theme picker. A slot rather than a prop, because every one of those is application state and none of them is a fact a header can be told.
|
|
7269
7331
|
**`sticky`** `boolean` · optional · default: — — Keeps the header at the top of the viewport as the page scrolls. Off by default, because a sticky header is a decision about a page rather than about a header, and a header that is sticky on a page with no scroll costs the reader a strip of their viewport.
|
|
7270
7332
|
**`className`** `string` · optional · default: — — Layout only, exactly as on every Component. Changing a Prism-owned visual property from here is prohibited.
|
|
7271
|
-
**`label`** `string` · required · default: — — The text of the link.
|
|
7272
|
-
**`href`** `string` · required · default: — — Where the link goes.
|
|
7273
|
-
**`current`** `boolean` · optional · default: — — Marks this link as the page the reader is on. Set it on the one link whose destination is the current route; leave it off every other link.
|
|
7274
|
-
**`newTab`** `boolean` · optional · default: — — Opens the destination in a new browsing context, which defaults the link relationship to `noopener noreferrer`. Prism does not decide what counts as external: a cross-origin destination is not by itself a reason to open a tab.
|
|
7275
7333
|
|
|
7276
7334
|
## Composition
|
|
7277
7335
|
|
|
@@ -8148,6 +8206,228 @@ export default function DashboardPageDemo() {
|
|
|
8148
8206
|
- [Stats01](https://prism.nanisoft.com/blocks/stats-01.md)
|
|
8149
8207
|
|
|
8150
8208
|
|
|
8209
|
+
---
|
|
8210
|
+
|
|
8211
|
+
# DocsShell
|
|
8212
|
+
|
|
8213
|
+
A documentation screen: a navigation rail whose shape arrives as data, the document at the measure, a contents rail, and a pager derived from the navigation rather than passed.
|
|
8214
|
+
|
|
8215
|
+
```tsx
|
|
8216
|
+
import { DocsShell } from '@nanisoft/prism-ui/pages/docs-shell'
|
|
8217
|
+
```
|
|
8218
|
+
|
|
8219
|
+
## Overview
|
|
8220
|
+
|
|
8221
|
+
DocsShell is a documentation screen: a navigation rail, the document, a contents
|
|
8222
|
+
rail, and the pager to the neighbouring pages.
|
|
8223
|
+
|
|
8224
|
+
**It is the Page the other three NaniSoft sites import, and the name is theirs.**
|
|
8225
|
+
All three already read `import { DocsShell, type DocsNavEntry } from
|
|
8226
|
+
'@nanisoft/prism-ui/pages'` in their own document template, and all three map
|
|
8227
|
+
their page tree into that shape in their own `lib/to-prism-tree`. A published
|
|
8228
|
+
name cannot be cheaply changed and there is no redirect lane for item routes, so
|
|
8229
|
+
the name follows those three import lines rather than this file's shape. It was
|
|
8230
|
+
`docs-shell` in the retired line too, where it was an empty `div` and a class
|
|
8231
|
+
name each site then had to style from scratch.
|
|
8232
|
+
|
|
8233
|
+
**The shape arrives as data.** The three sites publish full documentation sets
|
|
8234
|
+
and none of them agrees on the shape:
|
|
8235
|
+
|
|
8236
|
+
- Nexus files six sections of five pages, each named for a documentation genre,
|
|
8237
|
+
each with an index.
|
|
8238
|
+
- Atlas files four sections, one of which holds nine pages under a single
|
|
8239
|
+
heading, and not one of them has an index.
|
|
8240
|
+
- AlphaLens files six sections separated by rules, named for subject matter
|
|
8241
|
+
rather than for a genre, with a status inside three of the titles.
|
|
8242
|
+
|
|
8243
|
+
The tree is a prop and the Page renders it, so none of the three had to be told
|
|
8244
|
+
which of the others it looks like.
|
|
8245
|
+
|
|
8246
|
+
## Guidelines
|
|
8247
|
+
|
|
8248
|
+
### When to use
|
|
8249
|
+
|
|
8250
|
+
Use DocsShell as the body of the route that renders one documentation page,
|
|
8251
|
+
handed the page tree, the document's own outline, and the address being rendered.
|
|
8252
|
+
|
|
8253
|
+
Use it for every page of a documentation set. A documentation site whose pages
|
|
8254
|
+
each carry their own rail is a site whose rail drifts.
|
|
8255
|
+
|
|
8256
|
+
### When not to use
|
|
8257
|
+
|
|
8258
|
+
Do not use it for a single-page site. It is a whole screen around a tree, and a
|
|
8259
|
+
site with one page has no tree.
|
|
8260
|
+
|
|
8261
|
+
Do not use it for a blog. A post is a dated argument about one thing, and
|
|
8262
|
+
`BlogPostPage` is that screen.
|
|
8263
|
+
|
|
8264
|
+
Do not hand it a `nav` you built by parsing a folder tree at render time. Map
|
|
8265
|
+
the tree once, in your own adapter, and pass the result: a Page that walked a
|
|
8266
|
+
filesystem would be a Page that fetches, and a Page imports no router and no data
|
|
8267
|
+
client.
|
|
8268
|
+
|
|
8269
|
+
### Best practices
|
|
8270
|
+
|
|
8271
|
+
- **A section is a label, not a control.** It carries no status, no badge, no
|
|
8272
|
+
count, no collapse and no sort, and that is the whole of its interface. AlphaLens
|
|
8273
|
+
files its documentation as a pipeline, where "Unified data contract (approved)"
|
|
8274
|
+
is a stage of the work and not a topic a reader may visit in any order, and
|
|
8275
|
+
every structural affordance says the opposite. A status in the title is part of
|
|
8276
|
+
the title and stays there as words: the Page reads no parentheses, matches no
|
|
8277
|
+
vocabulary, and renders no pill beside a heading that has one.
|
|
8278
|
+
- **Omit `href` on a group that has no index.** That absence is what makes the
|
|
8279
|
+
heading a label rather than a route, and it is the same thing all three sites
|
|
8280
|
+
already spell as `url: node.index?.url ?? ''`, which two of them then restyle
|
|
8281
|
+
back into a label in their own stylesheets. Naming the case in the type makes
|
|
8282
|
+
those rules dead rather than load-bearing, and the type is the only thing that
|
|
8283
|
+
had to change.
|
|
8284
|
+
- **Do not pass a previous and a next.** The pager is derived from `nav` and
|
|
8285
|
+
`currentHref`, which removes one derivation from every consumer. It is derived
|
|
8286
|
+
rather than passed for a second reason: a caller who passes neighbours can pass
|
|
8287
|
+
a neighbour that is not in the tree, and this is the one arrangement where a
|
|
8288
|
+
reader would notice.
|
|
8289
|
+
- **Give the rail and the contents their own orders, and let both stand.** `nav`
|
|
8290
|
+
is in the order the rail shows and `toc` is in the order the contents rail
|
|
8291
|
+
shows. Nothing is sorted, deduplicated or alphabetised. A site that files its
|
|
8292
|
+
rail as a pipeline and its contents as a reference has both in one render.
|
|
8293
|
+
- Pass `toc` whole or not at all. A partial outline is a contents list that lies
|
|
8294
|
+
about the page.
|
|
8295
|
+
- Omit `title` when your document owns its own heading. The Page renders no empty
|
|
8296
|
+
`h1` to fill the gap, so a document with no title keeps exactly the outline its
|
|
8297
|
+
own content declares.
|
|
8298
|
+
- Name the three regions. `navLabel`, `tocLabel` and `pagerLabel` are required
|
|
8299
|
+
because they are words a reader hears, and a Page that ships no copy ships no
|
|
8300
|
+
reader-facing copy either. A site that files its pages as a pipeline and its
|
|
8301
|
+
contents as a reference names the three regions three different ways.
|
|
8302
|
+
|
|
8303
|
+
### Content guidelines
|
|
8304
|
+
|
|
8305
|
+
- Put a section's stage in its title, as AlphaLens does, and let it stay a
|
|
8306
|
+
sentence. The Page will not pull it out into a badge for you, and a badge is a
|
|
8307
|
+
state the reader can act on, which a stage of a pipeline is not.
|
|
8308
|
+
- Keep a rule's title short or leave it empty. A rule with words is a label a
|
|
8309
|
+
reader reads twice: once in the rule and once on the section beneath it.
|
|
8310
|
+
- Keep a section index page's title the same as its section's title, so a reader
|
|
8311
|
+
who arrives at the index and a reader who is already inside the section are
|
|
8312
|
+
reading the same words.
|
|
8313
|
+
|
|
8314
|
+
**A documentation screen: the rail, the document, the contents and the pager.**
|
|
8315
|
+
|
|
8316
|
+
```tsx
|
|
8317
|
+
import { DocsShell, type DocsNavEntry } from '@nanisoft/prism-ui/pages/docs-shell'
|
|
8318
|
+
|
|
8319
|
+
/**
|
|
8320
|
+
* The shape the three consumer sites actually publish, taken from AlphaLens
|
|
8321
|
+
* because it is the one that exercises every part of the interface at once: a
|
|
8322
|
+
* status inside a section title, a rule between sections, and a section whose
|
|
8323
|
+
* own index is a page a reader lands on.
|
|
8324
|
+
*/
|
|
8325
|
+
const NAV: DocsNavEntry[] = [
|
|
8326
|
+
{ type: 'page', title: 'AlphaLens', href: '#alphalens' },
|
|
8327
|
+
{ type: 'divider', title: 'Data platform (live)' },
|
|
8328
|
+
{
|
|
8329
|
+
type: 'group',
|
|
8330
|
+
title: 'Data platform (live)',
|
|
8331
|
+
href: '#data-platform',
|
|
8332
|
+
items: [
|
|
8333
|
+
{ type: 'page', title: 'Capture', href: '#capture' },
|
|
8334
|
+
{ type: 'page', title: 'Storage', href: '#storage' },
|
|
8335
|
+
{ type: 'page', title: 'Operations', href: '#platform-operations' },
|
|
8336
|
+
],
|
|
8337
|
+
},
|
|
8338
|
+
{ type: 'divider', title: 'Unified data contract (approved)' },
|
|
8339
|
+
{
|
|
8340
|
+
type: 'group',
|
|
8341
|
+
title: 'Unified data contract (approved)',
|
|
8342
|
+
href: '#data-contract',
|
|
8343
|
+
items: [
|
|
8344
|
+
{ type: 'page', title: 'Data feed view', href: '#feed-view' },
|
|
8345
|
+
{ type: 'page', title: 'Timestamps and symbols', href: '#timestamps' },
|
|
8346
|
+
],
|
|
8347
|
+
},
|
|
8348
|
+
{ type: 'divider', title: 'Research pipeline (designed)' },
|
|
8349
|
+
{
|
|
8350
|
+
// No `href`: this group is a label, because its folder holds no index page.
|
|
8351
|
+
type: 'group',
|
|
8352
|
+
title: 'Research pipeline (designed)',
|
|
8353
|
+
items: [
|
|
8354
|
+
{ type: 'page', title: 'Anatomy', href: '#anatomy' },
|
|
8355
|
+
{ type: 'page', title: 'NSE portability', href: '#nse-portability' },
|
|
8356
|
+
],
|
|
8357
|
+
},
|
|
8358
|
+
]
|
|
8359
|
+
|
|
8360
|
+
/** The headings inside this page. Your own pipeline knows them; Prism does not. */
|
|
8361
|
+
const TOC: DocsNavEntry[] = [
|
|
8362
|
+
{ type: 'page', title: 'The capture path', href: '#the-capture-path' },
|
|
8363
|
+
{ type: 'page', title: 'What the store holds', href: '#what-the-store-holds' },
|
|
8364
|
+
{ type: 'page', title: 'Where this is heading', href: '#where-this-is-heading' },
|
|
8365
|
+
]
|
|
8366
|
+
|
|
8367
|
+
/** A documentation screen: the rail, the document, the contents and the pager. */
|
|
8368
|
+
export default function DocsShellDemo() {
|
|
8369
|
+
return (
|
|
8370
|
+
<DocsShell
|
|
8371
|
+
title="Storage"
|
|
8372
|
+
description="Where a full chain of bars lands, and how it is partitioned."
|
|
8373
|
+
nav={NAV}
|
|
8374
|
+
toc={TOC}
|
|
8375
|
+
currentHref="#storage"
|
|
8376
|
+
navLabel="AlphaLens documentation"
|
|
8377
|
+
tocLabel="On this page"
|
|
8378
|
+
pagerLabel="AlphaLens pages"
|
|
8379
|
+
pagerLabels={{ previous: 'Previous', next: 'Next' }}
|
|
8380
|
+
>
|
|
8381
|
+
<p>
|
|
8382
|
+
The chain is written in columnar blocks, one per session per symbol, and
|
|
8383
|
+
nothing is rewritten to correct it. What lands is what the exchange sent.
|
|
8384
|
+
</p>
|
|
8385
|
+
<h2 id="the-capture-path">The capture path</h2>
|
|
8386
|
+
<p>
|
|
8387
|
+
A capture is a session and a symbol, never a whole day. A day is a
|
|
8388
|
+
partition over sessions, which is what makes a backtest cheap to repeat
|
|
8389
|
+
and expensive to store twice.
|
|
8390
|
+
</p>
|
|
8391
|
+
<h2 id="what-the-store-holds">What the store holds</h2>
|
|
8392
|
+
<ul>
|
|
8393
|
+
<li>Every strike, call and put, at the exchange clock.</li>
|
|
8394
|
+
<li>Open interest and the implied volatility of each strike.</li>
|
|
8395
|
+
<li>The index future and the spot it settled against.</li>
|
|
8396
|
+
</ul>
|
|
8397
|
+
<h2 id="where-this-is-heading">Where this is heading</h2>
|
|
8398
|
+
<p>
|
|
8399
|
+
The same path, ported to .NET, is designed rather than built. The stage it
|
|
8400
|
+
is at is in its title, because a stage of a pipeline is not a topic a
|
|
8401
|
+
reader may visit in any order.
|
|
8402
|
+
</p>
|
|
8403
|
+
</DocsShell>
|
|
8404
|
+
)
|
|
8405
|
+
}
|
|
8406
|
+
```
|
|
8407
|
+
|
|
8408
|
+
## Props
|
|
8409
|
+
|
|
8410
|
+
**`title`** `string` · optional · default: — — The page's title, and the document's `h1`. It is optional because the three consumer sites do not agree about whether a documentation page has one: two render the frontmatter title as the page heading, and one lets the document's own Markdown own it. When it is absent the Page renders no heading at all rather than an empty one, so the document keeps exactly the outline its own content declares.
|
|
8411
|
+
**`description`** `ReactNode` · optional · default: — — One or two sentences under the title: what this part of the documentation covers. A `ReactNode` because a site that files a page for a pipeline states the pipeline's stage as markup rather than as a sentence.
|
|
8412
|
+
**`nav`** `readonly DocsNavEntry[]` · optional · default: — — The documentation tree, in the order a reader should meet it. The whole shape arrives here, so the Page holds no opinion about how many sections a site has, how deep they nest, or what a section is called.
|
|
8413
|
+
**`toc`** `readonly DocsNavEntry[]` · optional · default: — — The headings inside this page, in document order, for the contents rail. It is the consumer's document that knows its own outline, because Prism does not parse Markdown and a Page that guessed at it would guess wrong on every document rather than on some. Pass the whole outline or none: a partial one is a contents list that lies about the page.
|
|
8414
|
+
**`currentHref`** `string` · optional · default: — — The address of the page being rendered. The rail marks it with `aria-current="page"` and the pager derives its two neighbours from it, so the same navigation renders a different pager for every page without the caller deriving anything.
|
|
8415
|
+
**`navLabel`** `string` · required · default: — — The accessible name of the rail. Required whenever `nav` is passed, because it is a word a reader hears and a Page that ships no copy ships no reader-facing copy either.
|
|
8416
|
+
**`tocLabel`** `string` · required · default: — — The accessible name of the contents rail. Required whenever `toc` is passed, for the same reason `navLabel` is.
|
|
8417
|
+
**`pagerLabel`** `string` · required · default: — — The accessible name of the pager. Required whenever there is a neighbour to reach, for the same reason `navLabel` is.
|
|
8418
|
+
**`pagerLabels`** `DocsPagerLabels` · required · default: — — The two words the pager renders above the neighbouring pages' titles. Required whenever either neighbour exists, for the same reason `navLabel` is.
|
|
8419
|
+
**`children`** `ReactNode` · required · default: — — The document's own body. Any flow content: paragraphs, headings, lists, code, images, tables. `Prose` holds it to the reading measure and to the block rhythm, and it is passed `fullWidth` so the document fills the column the frame gives it rather than sitting in a second measure inside one.
|
|
8420
|
+
**`header`** `ReactNode` · optional · default: — — A slot above the frame, inside the container: a breadcrumb trail, a version picker, a search field. A slot rather than a prop because each of those is a Block, and a Page that took one per prop would be a Page whose interface lists the whole catalogue.
|
|
8421
|
+
**`footer`** `ReactNode` · optional · default: — — A slot below the frame, inside the container: a feedback prompt, a link back to the section index, a support address.
|
|
8422
|
+
**`className`** `string` · optional · default: — — Layout only, exactly as on every Component. Changing a Prism-owned visual property from here is prohibited.
|
|
8423
|
+
|
|
8424
|
+
## Composition
|
|
8425
|
+
|
|
8426
|
+
**`exports`** `DocsShell` — the public runtime names this Page promises
|
|
8427
|
+
**`source`** `packages/ui/src/pages/docs-shell/index.tsx` — the file this Page is defined in
|
|
8428
|
+
**`dependencies`** `Prose` — the public Prism exports this item composes
|
|
8429
|
+
|
|
8430
|
+
|
|
8151
8431
|
---
|
|
8152
8432
|
|
|
8153
8433
|
# MarketingPage
|
package/dist/llms.txt
CHANGED
|
@@ -98,13 +98,14 @@
|
|
|
98
98
|
- [AuthPage](https://prism.nanisoft.com/pages/auth-page.md): A full authentication screen composing a sign-in form with an optional supporting card.
|
|
99
99
|
- [BlogPostPage](https://prism.nanisoft.com/pages/blog-post-page.md): A complete blog post screen: title, standfirst, byline with both the display and the machine date, the body at the measure and the trail to the neighbouring posts.
|
|
100
100
|
- [DashboardPage](https://prism.nanisoft.com/pages/dashboard-page.md): A full dashboard screen composing the app shell, a page header, a KPI row and a data table.
|
|
101
|
+
- [DocsShell](https://prism.nanisoft.com/pages/docs-shell.md): A documentation screen: a navigation rail whose shape arrives as data, the document at the measure, a contents rail, and a pager derived from the navigation rather than passed.
|
|
101
102
|
- [MarketingPage](https://prism.nanisoft.com/pages/marketing-page.md): A complete marketing page composing a hero, a feature grid, a KPI row, a plan comparison and a closing call to action.
|
|
102
103
|
- [NotFoundPage](https://prism.nanisoft.com/pages/not-found-page.md): A complete not-found screen: the status code as the heading of the page, one sentence about what happened, and the ways out.
|
|
103
104
|
- [SettingsPage](https://prism.nanisoft.com/pages/settings-page.md): A full settings screen composing the app shell, a page header and tabs of grouped settings forms.
|
|
104
105
|
|
|
105
106
|
## Changelogs
|
|
106
107
|
|
|
107
|
-
- [@nanisoft/prism-llms](https://prism.nanisoft.com/changelogs/prism-llms.md): 0.5.0, 0.2.0, 0.1.0
|
|
108
|
-
- [@nanisoft/prism-mcp-server](https://prism.nanisoft.com/changelogs/prism-mcp-server.md): 0.4.0, 0.2.0, 0.1.0
|
|
108
|
+
- [@nanisoft/prism-llms](https://prism.nanisoft.com/changelogs/prism-llms.md): 0.5.1, 0.5.0, 0.2.0, 0.1.0
|
|
109
|
+
- [@nanisoft/prism-mcp-server](https://prism.nanisoft.com/changelogs/prism-mcp-server.md): 0.4.1, 0.4.0, 0.2.0, 0.1.0
|
|
109
110
|
- [@nanisoft/prism-tokens](https://prism.nanisoft.com/changelogs/prism-tokens.md): 0.6.0, 0.5.1, 0.5.0
|
|
110
|
-
- [@nanisoft/prism-ui](https://prism.nanisoft.com/changelogs/prism-ui.md): 0.6.0, 0.5.1, 0.5.0
|
|
111
|
+
- [@nanisoft/prism-ui](https://prism.nanisoft.com/changelogs/prism-ui.md): 0.7.0, 0.6.0, 0.5.1, 0.5.0
|
|
@@ -90,10 +90,6 @@ export default function NoteGrid01Demo() {
|
|
|
90
90
|
**`notes`** `readonly NoteGrid01Note[]` · required · default: — — The notes, in the order a reader should meet them. Order is the caller's because it is a claim about which point matters first.
|
|
91
91
|
**`caption`** `string` · optional · default: — — The line under the grid, for the sentence that qualifies it: what the points do not cover, or where to read more.
|
|
92
92
|
**`headingLevel`** `HeadingLevel` · optional · default: — — Heading level for the section title. See `HeadingLevel`.
|
|
93
|
-
**`body`** `string` · required · default: — — One or two sentences about the point.
|
|
94
|
-
**`children`** `[title ? (_jsx(SectionHeading, { as: headingLevel, align: "left", eyebrow: eyebrow, title: title, description: description, className: "mb-12" })) : null, _jsx("dl", { "data-slot": "note-grid", className: "grid gap-8 sm:grid-cols-2 lg:grid-cols-3", children: notes.map((note) => (_jsxs("div", { "data-slot": "note-grid-note", className: "border-border flex flex-col gap-2 border-t pt-4", children: [_jsx("dt", { className: "text-sm font-semibold", children: note.title }), _jsx("dd", { className: "text-muted-foreground text-pretty text-sm", children: note.body })] }, note.title))) }), caption ? _jsx("p", { className: "text-muted-foreground mt-6 text-pretty text-sm", children: caption }) : null]` · required · default: —
|
|
95
|
-
**`as`** `headingLevel, align: "left", eyebrow: eyebrow, title: title, description: description, className: "mb-12"` · required · default: —
|
|
96
|
-
**`className`** `"text-sm font-semibold", children: note.title` · required · default: —
|
|
97
93
|
|
|
98
94
|
## Composition
|
|
99
95
|
|
|
@@ -99,12 +99,6 @@ export default function ProductGrid01Demo() {
|
|
|
99
99
|
**`products`** `readonly ProductGrid01Product[]` · required · default: — — The products, in the order a reader should meet them. Order is the caller's because it is a claim about which product matters first.
|
|
100
100
|
**`caption`** `string` · optional · default: — — The line under the grid, for the sentence that qualifies it: what the set does not include, or where to read more.
|
|
101
101
|
**`headingLevel`** `HeadingLevel` · optional · default: — — Heading level for the section title. See `HeadingLevel`.
|
|
102
|
-
**`id`** `string` · required · default: — — The product's key within the set. Carried on the markup as `data-product` through `ProductMark`, so a test can name one product rather than the first one, and two products in one document are individually addressable.
|
|
103
|
-
**`name`** `string` · required · default: — — The product's own name, which is the second part of its mark. It is the anchor of the row and the first thing a reader reads.
|
|
104
|
-
**`pack`** `ProductMarkProps['pack']` · optional · default: — — The product's pack, which is the hue of the mark's core. Omit it, or pass `null`, for the one member of a set that has no pack of its own: that member wears the full spectrum rather than a colourless mark.
|
|
105
|
-
**`tagline`** `string` · required · default: — — One line about what the product is.
|
|
106
|
-
**`href`** `string` · required · default: — — Where the row goes. Rendered as a native anchor's `href`, so the row is a link with the browser's own affordances rather than a click handler.
|
|
107
|
-
**`newTab`** `boolean` · optional · default: — — Opens the destination in a new browsing context, which defaults the link relationship to `noopener noreferrer`. Prism does not decide what counts as external, so the caller declares it.
|
|
108
102
|
|
|
109
103
|
## Composition
|
|
110
104
|
|
|
@@ -138,8 +138,6 @@ export default function SettingsPanel01Demo() {
|
|
|
138
138
|
**`onSubmit`** `(event: FormEvent<HTMLFormElement>) => void` · optional · default: —
|
|
139
139
|
**`secondaryAction`** `{ label: string; onClick?: () => void; }` · optional · default: — — A secondary control, such as Cancel.
|
|
140
140
|
**`footer`** `ReactNode` · optional · default: — — Extra content in the footer, e.g. a status note.
|
|
141
|
-
**`label`** `string` · required · default: —
|
|
142
|
-
**`onClick`** `() => void` · optional · default: —
|
|
143
141
|
|
|
144
142
|
## Composition
|
|
145
143
|
|
|
@@ -107,10 +107,6 @@ export default function SiteHeaderDemo() {
|
|
|
107
107
|
**`actions`** `ReactNode` · optional · default: — — A slot for the controls a product owns on the right: an account menu, a sign in link, a mode toggle, a theme picker. A slot rather than a prop, because every one of those is application state and none of them is a fact a header can be told.
|
|
108
108
|
**`sticky`** `boolean` · optional · default: — — Keeps the header at the top of the viewport as the page scrolls. Off by default, because a sticky header is a decision about a page rather than about a header, and a header that is sticky on a page with no scroll costs the reader a strip of their viewport.
|
|
109
109
|
**`className`** `string` · optional · default: — — Layout only, exactly as on every Component. Changing a Prism-owned visual property from here is prohibited.
|
|
110
|
-
**`label`** `string` · required · default: — — The text of the link.
|
|
111
|
-
**`href`** `string` · required · default: — — Where the link goes.
|
|
112
|
-
**`current`** `boolean` · optional · default: — — Marks this link as the page the reader is on. Set it on the one link whose destination is the current route; leave it off every other link.
|
|
113
|
-
**`newTab`** `boolean` · optional · default: — — Opens the destination in a new browsing context, which defaults the link relationship to `noopener noreferrer`. Prism does not decide what counts as external: a cross-origin destination is not by itself a reason to open a tab.
|
|
114
110
|
|
|
115
111
|
## Composition
|
|
116
112
|
|
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# @nanisoft/prism-llms
|
|
2
2
|
|
|
3
|
+
## 0.5.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 5c43520: Add `DocsShell`, a documentation page that takes a site's navigation as data
|
|
8
|
+
|
|
9
|
+
`DocsShell` is a documentation screen: a navigation rail, the document, a
|
|
10
|
+
contents rail, and a pager to the neighbouring pages. It replaces the unstyled
|
|
11
|
+
`docs-shell` the retired line published, and it is the Page the three NaniSoft
|
|
12
|
+
product sites already import by that name.
|
|
13
|
+
|
|
14
|
+
The navigation is data. A tree of one page and a tree of twenty-seven render the
|
|
15
|
+
same way, at any depth, and the frame is sized by what the caller passed rather
|
|
16
|
+
than by a fixed arrangement, so three sites whose documentation sets differ in
|
|
17
|
+
shape share one Page with no per-site fork.
|
|
18
|
+
|
|
19
|
+
- `nav` and `toc` are closed unions of `page`, `group` and `divider`. Both are
|
|
20
|
+
read in the order given: nothing is sorted or alphabetised, so a site that
|
|
21
|
+
files its rail as a pipeline and its contents as a reference has both in one
|
|
22
|
+
render.
|
|
23
|
+
- The pager is derived from `nav` and `currentHref`. There is no `neighbours`
|
|
24
|
+
prop, so a neighbour that is not in the tree cannot be expressed, and each
|
|
25
|
+
consumer loses one derivation of its own.
|
|
26
|
+
- A group with no `href` renders a `span` rather than an anchor with no
|
|
27
|
+
destination. The three sites spell that case today as an empty string, and two
|
|
28
|
+
of them carry a stylesheet rule that styles the result back into a label; those
|
|
29
|
+
rules are now deletable.
|
|
30
|
+
- A section carries no status, no badge, no count, no collapse and no sort. A
|
|
31
|
+
status written into a title stays in the title as words.
|
|
32
|
+
- Both rails are bounded against the viewport, because one site's tree is half
|
|
33
|
+
again as tall as another's.
|
|
34
|
+
|
|
35
|
+
The corpus fix that shipped with it: the props extractor read each declaration
|
|
36
|
+
body twice with two depth counters that disagreed, so a Page whose `index.tsx`
|
|
37
|
+
re-exported a value and a type from one sibling published every prop twice and
|
|
38
|
+
swept the members of its navigation union into its own prop list. It now reads
|
|
39
|
+
each body once.
|
|
40
|
+
|
|
3
41
|
## 0.5.0
|
|
4
42
|
|
|
5
43
|
### Minor Changes
|