tosijs-ui 1.17.3 → 1.17.4
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/CHANGELOG.md +33 -0
- package/dist/doc-browser.d.ts +3 -1
- package/dist/doc-browser.js +16 -1
- package/dist/doc-system/example-policy.d.ts +9 -0
- package/dist/doc-system/example-policy.js +10 -0
- package/dist/doc-system/site/docs.d.ts +5 -0
- package/dist/doc-system/site/docs.js +7 -0
- package/dist/doc-system/site/page-globals.d.ts +3 -1
- package/dist/doc-system/site/page-globals.js +7 -2
- package/dist/doc-system/site/site-config.d.ts +9 -1
- package/dist/iife.js +100 -100
- package/dist/iife.js.map +9 -9
- package/dist/live-example/component.d.ts +8 -0
- package/dist/live-example/component.js +53 -9
- package/dist/live-example/index.d.ts +2 -2
- package/dist/live-example/index.js +1 -1
- package/dist/live-example/insert-examples.d.ts +4 -1
- package/dist/live-example/insert-examples.js +20 -1
- package/dist/live-example/styles.d.ts +6 -0
- package/dist/live-example/styles.js +11 -0
- package/dist/tab-selector.d.ts +10 -0
- package/dist/tab-selector.js +63 -4
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/llms.txt +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.17.4
|
|
4
|
+
|
|
5
|
+
> Live examples' inline views keep their controls in the code panel's tab bar, and a site or
|
|
6
|
+
> page can set the view its examples open in. Nothing to change on upgrade. Asked by tjs-lang
|
|
7
|
+
> for its learn-to-program book (#252). `dist/iife.js` grows 0.6 kB (508.7 kB gzip).
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- `SiteConfig.exampleView` (`'preview'` | `'code'` | `'console'`) sets the view every live
|
|
12
|
+
example opens in, and `exampleView` in a page's metadata or frontmatter sets it for one page.
|
|
13
|
+
The nearest setting wins (fence, then page, then site), and `"preview"` opts out of a default
|
|
14
|
+
above it, so a big example on a code-first page takes `{"view": "preview"}`. A misspelt value
|
|
15
|
+
fails the build in the site config and is reported in page metadata. `setExampleView` (from
|
|
16
|
+
`tosijs-ui/live-example`) sets it from code.
|
|
17
|
+
- A refresh button in the code panel's tab bar, beside ⋮, in every view. Editing does not re-run
|
|
18
|
+
an example, and ⌘S / ⌘R were undiscoverable.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- In the inline views (`{"view": "code"}`, `{"view": "console"}`) the toolbar column beside the
|
|
23
|
+
preview is gone: it stood between the preview and its code. Maximize and the new-window editor
|
|
24
|
+
are in the code panel's tab bar. "view/edit code" (the code is already open) and the tests
|
|
25
|
+
check (inline tests always run) are not shown there. Maximized and plain examples are
|
|
26
|
+
unchanged.
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
|
|
30
|
+
- `<tosi-tabs>` with more tabs than fit pushed its `after-tabs` controls past its clipped edge:
|
|
31
|
+
at phone width a live example's close button was pushed past the panel's clipped edge. The tab names now
|
|
32
|
+
scroll (swipe, trackpad, or the mouse wheel over them) and the controls stay where they are.
|
|
33
|
+
Selecting a tab scrolls it into view, and the underline follows the scroll, clipped to the
|
|
34
|
+
strip.
|
|
35
|
+
|
|
3
36
|
## 1.17.3
|
|
4
37
|
|
|
5
38
|
> A doc site answers `/slug` as well as `/slug/`, and a missing page gets a real 404 page.
|
package/dist/doc-browser.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type AccessibilityMode } from './doc-system/render.js';
|
|
2
2
|
import { TestResults } from './live-example/test-harness.js';
|
|
3
|
-
import { type ExamplePolicy } from './doc-system/example-policy.js';
|
|
3
|
+
import { type ExamplePolicy, type ExampleView } from './doc-system/example-policy.js';
|
|
4
4
|
export declare const hasTestBlock: (text: string | undefined, policy?: ExamplePolicy) => boolean;
|
|
5
5
|
export interface PageTestResults {
|
|
6
6
|
passed: boolean;
|
|
@@ -45,6 +45,8 @@ export interface Doc {
|
|
|
45
45
|
header?: boolean;
|
|
46
46
|
/** `'full-width'` drops the reading measure; `'full-screen'` also puts the nav away. */
|
|
47
47
|
layout?: 'full-width' | 'full-screen';
|
|
48
|
+
/** the view this page's live examples open in (see the site `Doc.exampleView`) */
|
|
49
|
+
exampleView?: ExampleView;
|
|
48
50
|
testStatus?: 'passed' | 'failed' | 'pending';
|
|
49
51
|
bakes?: Array<[string, {
|
|
50
52
|
dialect: string;
|
package/dist/doc-browser.js
CHANGED
|
@@ -110,7 +110,7 @@ import { LiveExample, testManager, pageTestCount, enableTests, disableTests, } f
|
|
|
110
110
|
import { highlightBlocks } from './doc-system/highlight.js';
|
|
111
111
|
import { examplePolicy } from './live-example/insert-examples.js';
|
|
112
112
|
import { collectCodeTokens } from './doc-system/code-fences.js';
|
|
113
|
-
import { isLiveFence } from './doc-system/example-policy.js';
|
|
113
|
+
import { isExampleView, isLiveFence, } from './doc-system/example-policy.js';
|
|
114
114
|
import { tosiSidenav, TosiSidenav } from './side-nav.js';
|
|
115
115
|
import { icons } from './icons.js';
|
|
116
116
|
import { tosiPalette } from './palette.js';
|
|
@@ -957,6 +957,19 @@ export function createDocBrowser(options) {
|
|
|
957
957
|
// render from doc text. Every navigation funnels through navigateTo() -> showDoc().
|
|
958
958
|
const docContent = contentElement || div();
|
|
959
959
|
docContent.classList.add('doc-content');
|
|
960
|
+
/*
|
|
961
|
+
A page's `exampleView` (#252), where its examples look for it: on the content they sit in. A
|
|
962
|
+
value the metadata block got wrong is reported, not ignored, as frontmatter's is.
|
|
963
|
+
*/
|
|
964
|
+
const stampExampleView = (doc) => {
|
|
965
|
+
const view = doc.exampleView;
|
|
966
|
+
if (view !== undefined && !isExampleView(view))
|
|
967
|
+
console.error(`${doc.path || doc.filename}: unknown exampleView ${JSON.stringify(view)}`);
|
|
968
|
+
if (isExampleView(view))
|
|
969
|
+
docContent.setAttribute('data-example-view', view);
|
|
970
|
+
else
|
|
971
|
+
docContent.removeAttribute('data-example-view');
|
|
972
|
+
};
|
|
960
973
|
Object.assign(docContent.style, {
|
|
961
974
|
display: 'block',
|
|
962
975
|
// Same var the pre-hydration `:not(:defined)` layout uses (doc-system-styles.ts).
|
|
@@ -1132,6 +1145,7 @@ export function createDocBrowser(options) {
|
|
|
1132
1145
|
rewriteContentLinks();
|
|
1133
1146
|
// Stamp each example with its source file (for the source↔doc map). doc.path
|
|
1134
1147
|
// is the extracted file (.md, or a source file with doc comments).
|
|
1148
|
+
stampExampleView(doc);
|
|
1135
1149
|
LiveExample.insertExamples(docContent, context, doc.path || undefined);
|
|
1136
1150
|
focusableCodeBlocks(docContent);
|
|
1137
1151
|
/*
|
|
@@ -1370,6 +1384,7 @@ export function createDocBrowser(options) {
|
|
|
1370
1384
|
if (view === 'preview') {
|
|
1371
1385
|
docContent.innerHTML = renderDocMarkdown(docMarkdownFromSource(editUI.editor.value, editUI.doc.path), { wikilinks, accessible: !!accessibility, title: editUI.doc.title });
|
|
1372
1386
|
rewriteContentLinks();
|
|
1387
|
+
stampExampleView(editUI.doc);
|
|
1373
1388
|
LiveExample.insertExamples(docContent, context, editUI.doc.path || undefined);
|
|
1374
1389
|
focusableCodeBlocks(docContent);
|
|
1375
1390
|
}
|
|
@@ -71,6 +71,15 @@ export declare const EXAMPLE_TABS: readonly ["js", "html", "css", "test", "conso
|
|
|
71
71
|
export type ExampleTab = (typeof EXAMPLE_TABS)[number];
|
|
72
72
|
/** Why `value` is not a list of example tabs, or undefined when it is one. */
|
|
73
73
|
export declare function exampleTabsProblem(value: unknown): string | undefined;
|
|
74
|
+
/**
|
|
75
|
+
* The view a live example opens in (#252): `preview` (the default), `code` (the preview beside
|
|
76
|
+
* its code) or `console` (the console beside the code). Set per fence (`{"view": "code"}`), per
|
|
77
|
+
* page (`exampleView` in its metadata) or per site (`SiteConfig.exampleView`); the nearest wins,
|
|
78
|
+
* so `preview` opts one example or page out of a default.
|
|
79
|
+
*/
|
|
80
|
+
export declare const EXAMPLE_VIEWS: readonly ["preview", "code", "console"];
|
|
81
|
+
export type ExampleView = (typeof EXAMPLE_VIEWS)[number];
|
|
82
|
+
export declare function isExampleView(value: unknown): value is ExampleView;
|
|
74
83
|
/**
|
|
75
84
|
* Will this fence become a live example?
|
|
76
85
|
*
|
|
@@ -118,6 +118,16 @@ export function exampleTabsProblem(value) {
|
|
|
118
118
|
.join(', ')} (the tabs are ${EXAMPLE_TABS.join(', ')})`
|
|
119
119
|
: undefined;
|
|
120
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* The view a live example opens in (#252): `preview` (the default), `code` (the preview beside
|
|
123
|
+
* its code) or `console` (the console beside the code). Set per fence (`{"view": "code"}`), per
|
|
124
|
+
* page (`exampleView` in its metadata) or per site (`SiteConfig.exampleView`); the nearest wins,
|
|
125
|
+
* so `preview` opts one example or page out of a default.
|
|
126
|
+
*/
|
|
127
|
+
export const EXAMPLE_VIEWS = ['preview', 'code', 'console'];
|
|
128
|
+
export function isExampleView(value) {
|
|
129
|
+
return EXAMPLE_VIEWS.includes(value);
|
|
130
|
+
}
|
|
121
131
|
/**
|
|
122
132
|
* Will this fence become a live example?
|
|
123
133
|
*
|
|
@@ -76,6 +76,11 @@ export interface Doc {
|
|
|
76
76
|
* reach them from out here.
|
|
77
77
|
*/
|
|
78
78
|
layout?: 'full-width' | 'full-screen';
|
|
79
|
+
/**
|
|
80
|
+
* The view this page's live examples open in (1.17.4, #252): `'code'`, `'console'`, or
|
|
81
|
+
* `'preview'` to opt out of the site's `exampleView`. A fence's `{"view": …}` still wins.
|
|
82
|
+
*/
|
|
83
|
+
exampleView?: 'preview' | 'code' | 'console';
|
|
79
84
|
headTitle?: string;
|
|
80
85
|
description?: string;
|
|
81
86
|
keywords?: string | string[];
|
|
@@ -160,6 +160,13 @@ export function parseFrontmatter(content) {
|
|
|
160
160
|
else if (val)
|
|
161
161
|
console.error(`unknown layout ${JSON.stringify(val)} in frontmatter`);
|
|
162
162
|
}
|
|
163
|
+
else if (key === 'exampleview') {
|
|
164
|
+
// Same reasoning as layout: a misspelt view would silently do nothing.
|
|
165
|
+
if (val === 'preview' || val === 'code' || val === 'console')
|
|
166
|
+
data.exampleView = val;
|
|
167
|
+
else if (val)
|
|
168
|
+
console.error(`unknown exampleView ${JSON.stringify(val)} in frontmatter`);
|
|
169
|
+
}
|
|
163
170
|
else if (key === 'header') {
|
|
164
171
|
if (/^(false|no|0)$/i.test(val))
|
|
165
172
|
data.header = false;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import type { ExampleTab } from '../example-policy.js';
|
|
1
|
+
import type { ExampleTab, ExampleView } from '../example-policy.js';
|
|
2
2
|
export interface PageGlobalsConfig {
|
|
3
3
|
liveExamples?: 'auto' | 'opt-in' | 'no-code';
|
|
4
4
|
exampleConsole?: boolean;
|
|
5
5
|
exampleTabs?: ExampleTab[];
|
|
6
|
+
exampleView?: ExampleView;
|
|
6
7
|
dialects?: string[];
|
|
7
8
|
}
|
|
8
9
|
/**
|
|
@@ -13,5 +14,6 @@ export interface PageGlobalsConfig {
|
|
|
13
14
|
export declare function siteSwitchProblem(config: {
|
|
14
15
|
liveExamples?: string;
|
|
15
16
|
kind?: string;
|
|
17
|
+
exampleView?: string;
|
|
16
18
|
}): string | null;
|
|
17
19
|
export declare function pageGlobalsHead(config: PageGlobalsConfig): string;
|
|
@@ -6,7 +6,7 @@ bundle reads when it runs (so they must come BEFORE the bundle script — genera
|
|
|
6
6
|
Each is emitted only when it differs from the default, so a default site's HTML is unchanged
|
|
7
7
|
byte-for-byte when a new switch is added.
|
|
8
8
|
*/
|
|
9
|
-
import { exampleTabsProblem, normalizeDialectNames } from '../example-policy.js';
|
|
9
|
+
import { EXAMPLE_VIEWS, exampleTabsProblem, normalizeDialectNames, } from '../example-policy.js';
|
|
10
10
|
const LIVE_EXAMPLE_POLICIES = ['auto', 'opt-in', 'no-code'];
|
|
11
11
|
const SITE_KINDS = ['documentation', 'book'];
|
|
12
12
|
/**
|
|
@@ -19,7 +19,8 @@ export function siteSwitchProblem(config) {
|
|
|
19
19
|
? `SiteConfig.${name} is ${JSON.stringify(value)}; it must be one of ${allowed.map((a) => `'${a}'`).join(', ')}`
|
|
20
20
|
: null;
|
|
21
21
|
return (wrong('liveExamples', config.liveExamples, LIVE_EXAMPLE_POLICIES) ??
|
|
22
|
-
wrong('kind', config.kind, SITE_KINDS)
|
|
22
|
+
wrong('kind', config.kind, SITE_KINDS) ??
|
|
23
|
+
wrong('exampleView', config.exampleView, [...EXAMPLE_VIEWS]));
|
|
23
24
|
}
|
|
24
25
|
export function pageGlobalsHead(config) {
|
|
25
26
|
// A misspelt tab would hide a tab on every example with nothing to say why.
|
|
@@ -35,6 +36,10 @@ export function pageGlobalsHead(config) {
|
|
|
35
36
|
config.exampleTabs
|
|
36
37
|
? `<script>globalThis.__TOSI_EXAMPLE_TABS=${JSON.stringify(config.exampleTabs)}</script>`
|
|
37
38
|
: '',
|
|
39
|
+
// #252: the view examples open in
|
|
40
|
+
config.exampleView && config.exampleView !== 'preview'
|
|
41
|
+
? `<script>globalThis.__TOSI_EXAMPLE_VIEW="${config.exampleView}"</script>`
|
|
42
|
+
: '',
|
|
38
43
|
// 1.16.2: the example console
|
|
39
44
|
config.exampleConsole === false
|
|
40
45
|
? `<script>globalThis.__TOSI_EXAMPLE_CONSOLE=false</script>`
|
|
@@ -8,7 +8,7 @@ import type { EditableDataOptions } from './data-store.js';
|
|
|
8
8
|
import type { BookManifest } from '../book-manifest.js';
|
|
9
9
|
import type { AccessibilityMode } from '../render.js';
|
|
10
10
|
import type { AltTextHook } from './alt-text.js';
|
|
11
|
-
import type { ExampleTab } from '../example-policy.js';
|
|
11
|
+
import type { ExampleTab, ExampleView } from '../example-policy.js';
|
|
12
12
|
export type SiteHost = 'github-pages' | 'firebase' | 'static';
|
|
13
13
|
/** Resolved paths handed to a `libraryBuild` override (see SiteConfig). */
|
|
14
14
|
export interface LibraryBuildContext {
|
|
@@ -200,6 +200,14 @@ export interface SiteConfig {
|
|
|
200
200
|
* `{"tabs": ["html"]}`. A hidden tab's block still runs; it just can't be edited.
|
|
201
201
|
*/
|
|
202
202
|
exampleTabs?: ExampleTab[];
|
|
203
|
+
/**
|
|
204
|
+
* The view every live example opens in (1.17.4, #252): `'code'` puts the preview beside its
|
|
205
|
+
* code, `'console'` the console beside the code. Default `'preview'`, the example alone. For
|
|
206
|
+
* a book whose small examples should show their code: set it once here instead of
|
|
207
|
+
* `{"view": "code"}` on every fence. A page overrides it with `exampleView` in its metadata,
|
|
208
|
+
* and one example with the fence option `{"view": "preview"}`.
|
|
209
|
+
*/
|
|
210
|
+
exampleView?: ExampleView;
|
|
203
211
|
/**
|
|
204
212
|
* Run script examples from same-origin modules (1.17.0, #245), for a site served under a
|
|
205
213
|
* Content Security Policy without `'unsafe-eval'` (`script-src 'self'`).
|