fleuron 0.1.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 +132 -0
- package/dist/client.d.ts +74 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +124 -0
- package/dist/client.js.map +1 -0
- package/dist/engine.d.ts +50 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +163 -0
- package/dist/engine.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/preview.d.ts +193 -0
- package/dist/preview.d.ts.map +1 -0
- package/dist/preview.js +303 -0
- package/dist/preview.js.map +1 -0
- package/dist/protocol.d.ts +153 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +19 -0
- package/dist/protocol.js.map +1 -0
- package/dist/svg.d.ts +57 -0
- package/dist/svg.d.ts.map +1 -0
- package/dist/svg.js +210 -0
- package/dist/svg.js.map +1 -0
- package/dist/version.d.ts +8 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +8 -0
- package/dist/version.js.map +1 -0
- package/dist/wire.d.ts +179 -0
- package/dist/wire.d.ts.map +1 -0
- package/dist/wire.js +174 -0
- package/dist/wire.js.map +1 -0
- package/dist/worker.d.ts +16 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +23 -0
- package/dist/worker.js.map +1 -0
- package/package.json +45 -0
- package/wasm/fleuron.d.ts +221 -0
- package/wasm/fleuron.js +629 -0
- package/wasm/fleuron_bg.wasm +0 -0
- package/wasm/fleuron_bg.wasm.d.ts +30 -0
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A preview, mounted: markdown in, a page on screen.
|
|
3
|
+
*
|
|
4
|
+
* The worker, the module, the postcard buffer and the display structure
|
|
5
|
+
* are what this is built out of, not what it asks a caller to hold.
|
|
6
|
+
* A host that wants them keeps having them, since the client, the
|
|
7
|
+
* protocol, the reader and the painter are all still exported. A host
|
|
8
|
+
* that only wants to see the book says where to put it and hands over
|
|
9
|
+
* the manuscript.
|
|
10
|
+
*
|
|
11
|
+
* One page at a time, because that is what a page-through needs and
|
|
12
|
+
* what a scrolling preview would have to virtualise anyway.
|
|
13
|
+
*
|
|
14
|
+
* Every method that changes an input renders. Nothing here is on a
|
|
15
|
+
* timer: renders that pile up while the engine is busy collapse into
|
|
16
|
+
* one, and an engine with nothing to do repaints straight away. A
|
|
17
|
+
* host that wants a fixed delay puts one in front of these calls.
|
|
18
|
+
*/
|
|
19
|
+
import type { Metadata, Op, Source } from './protocol.js';
|
|
20
|
+
import type { Asset, LayoutOutput, Warning } from './wire.js';
|
|
21
|
+
/** How a preview is set up. */
|
|
22
|
+
export interface PreviewOptions {
|
|
23
|
+
/**
|
|
24
|
+
* The worker to run layout in. The package's own is used when
|
|
25
|
+
* there is none, which is what a host that has nothing to add to
|
|
26
|
+
* it wants.
|
|
27
|
+
*/
|
|
28
|
+
worker?: Worker;
|
|
29
|
+
/** Which markdown the sources are written in. */
|
|
30
|
+
dialect?: 'commonmark' | 'gfm' | 'obsidian';
|
|
31
|
+
/** The heading level a section begins at, or 0 for one per file. */
|
|
32
|
+
split?: number;
|
|
33
|
+
/** Points to CSS pixels. */
|
|
34
|
+
zoom?: number;
|
|
35
|
+
/** The page to show, counting from 1. */
|
|
36
|
+
page?: number;
|
|
37
|
+
/**
|
|
38
|
+
* Where the faces on screen come from.
|
|
39
|
+
*
|
|
40
|
+
* `module` asks the session for the file it shaped with and
|
|
41
|
+
* registers that, which is the only way to be certain the page on
|
|
42
|
+
* screen is set in the face the export will use.
|
|
43
|
+
*
|
|
44
|
+
* `host` registers nothing and leaves the painter's family stack
|
|
45
|
+
* to resolve against whatever the document already has. A host
|
|
46
|
+
* that already serves the same file, or a subset of it with the
|
|
47
|
+
* same metrics, uses this rather than fetch a second copy: the
|
|
48
|
+
* glyphs land where the display structure put them either way, and
|
|
49
|
+
* parsing a book face is main-thread work a page paying for it
|
|
50
|
+
* twice can see.
|
|
51
|
+
*/
|
|
52
|
+
faces?: 'module' | 'host';
|
|
53
|
+
/** What the page is printed on; `null` leaves it transparent. */
|
|
54
|
+
paper?: string | null;
|
|
55
|
+
/** What it is printed in. */
|
|
56
|
+
ink?: string;
|
|
57
|
+
/**
|
|
58
|
+
* The images the manuscript refers to, by the url it names them
|
|
59
|
+
* by. Nothing here fetches a url, so a host that wants an image on
|
|
60
|
+
* the page fetches the file itself and hands over the bytes.
|
|
61
|
+
*
|
|
62
|
+
* The same bytes both size the box and fill it: the module reads
|
|
63
|
+
* the header, and the painter draws from a blob url over the file
|
|
64
|
+
* that header came from.
|
|
65
|
+
*/
|
|
66
|
+
images?: Record<string, Uint8Array>;
|
|
67
|
+
/**
|
|
68
|
+
* Where an image's pixels come from, for a host that would rather
|
|
69
|
+
* name its own urls than hand over bytes. This outranks whatever
|
|
70
|
+
* {@link PreviewOptions.images} supplied.
|
|
71
|
+
*/
|
|
72
|
+
asset?: (asset: Asset, index: number) => string | null | undefined;
|
|
73
|
+
/** Called after every render that reached the screen. */
|
|
74
|
+
onRender?: (output: LayoutOutput) => void;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* A book on screen, and the worker behind it.
|
|
78
|
+
*
|
|
79
|
+
* Every method that changes an input renders and repaints. A render
|
|
80
|
+
* the caller has already typed past paints nothing, so calling these
|
|
81
|
+
* on a keystroke is the intended use rather than a risk.
|
|
82
|
+
*/
|
|
83
|
+
export declare class Preview {
|
|
84
|
+
private readonly element;
|
|
85
|
+
private readonly frame;
|
|
86
|
+
private readonly worker;
|
|
87
|
+
private readonly client;
|
|
88
|
+
private readonly options;
|
|
89
|
+
private readonly faces;
|
|
90
|
+
/** A blob url per image the host handed over, by its own url. */
|
|
91
|
+
private readonly pixels;
|
|
92
|
+
private output;
|
|
93
|
+
private showing;
|
|
94
|
+
private scale;
|
|
95
|
+
private constructor();
|
|
96
|
+
/**
|
|
97
|
+
* Opens a worker, loads the module into it, and takes the element
|
|
98
|
+
* over. Nothing is painted until a manuscript arrives.
|
|
99
|
+
*/
|
|
100
|
+
static mount(element: Element, options?: PreviewOptions): Promise<Preview>;
|
|
101
|
+
/** Sets the manuscript: one markdown source as the whole book. */
|
|
102
|
+
setMarkdown(text: string, name?: string): Promise<void>;
|
|
103
|
+
/**
|
|
104
|
+
* Sets the manuscript from several sources, in reading order.
|
|
105
|
+
*
|
|
106
|
+
* A book of one file takes its title and author from that file's
|
|
107
|
+
* frontmatter. A book of several has no frontmatter of its own, so
|
|
108
|
+
* it is left unnamed until {@link setMetadata} names it, rather
|
|
109
|
+
* than named after whichever chapter came first.
|
|
110
|
+
*/
|
|
111
|
+
setBook(sources: Source[]): Promise<void>;
|
|
112
|
+
/** Drops one source and leaves the rest of the book standing. */
|
|
113
|
+
remove(name: string): Promise<void>;
|
|
114
|
+
/**
|
|
115
|
+
* Names the book. Only the PDF export reads this, so it costs no
|
|
116
|
+
* layout.
|
|
117
|
+
*/
|
|
118
|
+
setMetadata(metadata: Metadata): Promise<void>;
|
|
119
|
+
/**
|
|
120
|
+
* Replaces one source and leaves the rest of the book standing.
|
|
121
|
+
* This is the keystroke path: the sections that came from this
|
|
122
|
+
* file are read again and every other file keeps the lines it
|
|
123
|
+
* already has.
|
|
124
|
+
*
|
|
125
|
+
* A name the book has not seen is appended, which is one way to
|
|
126
|
+
* add a file to a book already open.
|
|
127
|
+
*/
|
|
128
|
+
edit(name: string, text: string): Promise<void>;
|
|
129
|
+
/** Sets the author stylesheet, cascading over the built-in one. */
|
|
130
|
+
setStyle(css: string): Promise<void>;
|
|
131
|
+
/** Registers a face for the session's life. */
|
|
132
|
+
addFont(bytes: Uint8Array): Promise<void>;
|
|
133
|
+
/**
|
|
134
|
+
* Registers one image, by the url the manuscript names it by, and
|
|
135
|
+
* lays the book out again around the room it takes.
|
|
136
|
+
*
|
|
137
|
+
* A url the manuscript names and nobody supplies is a diagnostic
|
|
138
|
+
* and a page with nothing where the image was.
|
|
139
|
+
*/
|
|
140
|
+
addImage(url: string, bytes: Uint8Array): Promise<void>;
|
|
141
|
+
/** Lays the book out again and repaints. */
|
|
142
|
+
render(ops?: Op[]): Promise<void>;
|
|
143
|
+
/** How many pages the book set to. */
|
|
144
|
+
get pages(): number;
|
|
145
|
+
/** The page on screen, counting from 1. */
|
|
146
|
+
get page(): number;
|
|
147
|
+
set page(number: number);
|
|
148
|
+
/** Points to CSS pixels. */
|
|
149
|
+
get zoom(): number;
|
|
150
|
+
set zoom(scale: number);
|
|
151
|
+
/** The next page, if the book has one. */
|
|
152
|
+
next(): void;
|
|
153
|
+
/** The previous page, if there is one. */
|
|
154
|
+
previous(): void;
|
|
155
|
+
/** Everything the run had to complain about. */
|
|
156
|
+
get warnings(): Warning[];
|
|
157
|
+
/**
|
|
158
|
+
* The markup on screen, or a page that is not on screen. Empty
|
|
159
|
+
* before the first render.
|
|
160
|
+
*/
|
|
161
|
+
svg(number?: number): string;
|
|
162
|
+
/**
|
|
163
|
+
* The book as PDF bytes, from the stages the preview settled, so
|
|
164
|
+
* the export cannot contradict what is on screen.
|
|
165
|
+
*/
|
|
166
|
+
exportPdf(): Promise<Uint8Array | null>;
|
|
167
|
+
/** Closes the worker and gives the element back. */
|
|
168
|
+
destroy(): void;
|
|
169
|
+
/**
|
|
170
|
+
* Keeps a blob url over an image's bytes and hands the same bytes
|
|
171
|
+
* to the engine.
|
|
172
|
+
*
|
|
173
|
+
* The blob is made before the op is sent, because the bytes move
|
|
174
|
+
* across the wall rather than being copied and the buffer is empty
|
|
175
|
+
* on this side afterwards.
|
|
176
|
+
*/
|
|
177
|
+
private hold;
|
|
178
|
+
private paint;
|
|
179
|
+
private painting;
|
|
180
|
+
/**
|
|
181
|
+
* Loads the faces the run drew with, from the same files the
|
|
182
|
+
* engine shaped with.
|
|
183
|
+
*
|
|
184
|
+
* The bundled face is why this asks the module rather than the
|
|
185
|
+
* network: it is inside the module, and there is no URL to fetch
|
|
186
|
+
* it from. A face whose bytes do not come back is left out, and
|
|
187
|
+
* the painter's fallback stack is what the reader sees instead of
|
|
188
|
+
* a blank page. `faces: 'host'` is that stack on purpose.
|
|
189
|
+
*/
|
|
190
|
+
private load;
|
|
191
|
+
private face;
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=preview.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preview.d.ts","sourceRoot":"","sources":["../src/preview.ts"],"names":[],"mappings":"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"}
|
package/dist/preview.js
ADDED
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A preview, mounted: markdown in, a page on screen.
|
|
3
|
+
*
|
|
4
|
+
* The worker, the module, the postcard buffer and the display structure
|
|
5
|
+
* are what this is built out of, not what it asks a caller to hold.
|
|
6
|
+
* A host that wants them keeps having them, since the client, the
|
|
7
|
+
* protocol, the reader and the painter are all still exported. A host
|
|
8
|
+
* that only wants to see the book says where to put it and hands over
|
|
9
|
+
* the manuscript.
|
|
10
|
+
*
|
|
11
|
+
* One page at a time, because that is what a page-through needs and
|
|
12
|
+
* what a scrolling preview would have to virtualise anyway.
|
|
13
|
+
*
|
|
14
|
+
* Every method that changes an input renders. Nothing here is on a
|
|
15
|
+
* timer: renders that pile up while the engine is busy collapse into
|
|
16
|
+
* one, and an engine with nothing to do repaints straight away. A
|
|
17
|
+
* host that wants a fixed delay puts one in front of these calls.
|
|
18
|
+
*/
|
|
19
|
+
import { Client } from './client.js';
|
|
20
|
+
import { faceFamily, paintPage } from './svg.js';
|
|
21
|
+
/**
|
|
22
|
+
* A book on screen, and the worker behind it.
|
|
23
|
+
*
|
|
24
|
+
* Every method that changes an input renders and repaints. A render
|
|
25
|
+
* the caller has already typed past paints nothing, so calling these
|
|
26
|
+
* on a keystroke is the intended use rather than a risk.
|
|
27
|
+
*/
|
|
28
|
+
export class Preview {
|
|
29
|
+
element;
|
|
30
|
+
frame;
|
|
31
|
+
worker;
|
|
32
|
+
client;
|
|
33
|
+
options;
|
|
34
|
+
faces = new Map();
|
|
35
|
+
/** A blob url per image the host handed over, by its own url. */
|
|
36
|
+
pixels = new Map();
|
|
37
|
+
output = null;
|
|
38
|
+
showing;
|
|
39
|
+
scale;
|
|
40
|
+
constructor(element, worker, options) {
|
|
41
|
+
this.element = element;
|
|
42
|
+
this.worker = worker;
|
|
43
|
+
this.options = options;
|
|
44
|
+
this.showing = options.page ?? 1;
|
|
45
|
+
this.scale = options.zoom ?? 1;
|
|
46
|
+
this.frame = element.ownerDocument.createElement('div');
|
|
47
|
+
this.frame.setAttribute('data-fleuron', 'preview');
|
|
48
|
+
element.replaceChildren(this.frame);
|
|
49
|
+
const transport = {
|
|
50
|
+
post: (request, transfer) => worker.postMessage(request, transfer),
|
|
51
|
+
};
|
|
52
|
+
this.client = new Client(transport);
|
|
53
|
+
worker.addEventListener('message', (event) => this.client.receive(event.data));
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Opens a worker, loads the module into it, and takes the element
|
|
57
|
+
* over. Nothing is painted until a manuscript arrives.
|
|
58
|
+
*/
|
|
59
|
+
static async mount(element, options = {}) {
|
|
60
|
+
const worker = options.worker ??
|
|
61
|
+
new Worker(new URL('./worker.js', import.meta.url), { type: 'module' });
|
|
62
|
+
const preview = new Preview(element, worker, options);
|
|
63
|
+
const setup = [];
|
|
64
|
+
if (options.dialect !== undefined) {
|
|
65
|
+
setup.push({ op: 'dialect', dialect: options.dialect });
|
|
66
|
+
}
|
|
67
|
+
if (options.split !== undefined) {
|
|
68
|
+
setup.push({ op: 'split', level: options.split });
|
|
69
|
+
}
|
|
70
|
+
for (const [url, bytes] of Object.entries(options.images ?? {})) {
|
|
71
|
+
setup.push(preview.hold(url, bytes));
|
|
72
|
+
}
|
|
73
|
+
if (setup.length > 0) {
|
|
74
|
+
await preview.client.apply(setup);
|
|
75
|
+
}
|
|
76
|
+
return preview;
|
|
77
|
+
}
|
|
78
|
+
/** Sets the manuscript: one markdown source as the whole book. */
|
|
79
|
+
async setMarkdown(text, name = 'manuscript.md') {
|
|
80
|
+
await this.render([{ op: 'markdown', name, text }]);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Sets the manuscript from several sources, in reading order.
|
|
84
|
+
*
|
|
85
|
+
* A book of one file takes its title and author from that file's
|
|
86
|
+
* frontmatter. A book of several has no frontmatter of its own, so
|
|
87
|
+
* it is left unnamed until {@link setMetadata} names it, rather
|
|
88
|
+
* than named after whichever chapter came first.
|
|
89
|
+
*/
|
|
90
|
+
async setBook(sources) {
|
|
91
|
+
await this.render([{ op: 'book', sources }]);
|
|
92
|
+
}
|
|
93
|
+
/** Drops one source and leaves the rest of the book standing. */
|
|
94
|
+
async remove(name) {
|
|
95
|
+
await this.render([{ op: 'remove', name }]);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Names the book. Only the PDF export reads this, so it costs no
|
|
99
|
+
* layout.
|
|
100
|
+
*/
|
|
101
|
+
async setMetadata(metadata) {
|
|
102
|
+
await this.render([{ op: 'metadata', metadata }]);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Replaces one source and leaves the rest of the book standing.
|
|
106
|
+
* This is the keystroke path: the sections that came from this
|
|
107
|
+
* file are read again and every other file keeps the lines it
|
|
108
|
+
* already has.
|
|
109
|
+
*
|
|
110
|
+
* A name the book has not seen is appended, which is one way to
|
|
111
|
+
* add a file to a book already open.
|
|
112
|
+
*/
|
|
113
|
+
async edit(name, text) {
|
|
114
|
+
await this.render([{ op: 'edit', name, text }]);
|
|
115
|
+
}
|
|
116
|
+
/** Sets the author stylesheet, cascading over the built-in one. */
|
|
117
|
+
async setStyle(css) {
|
|
118
|
+
await this.render([{ op: 'style', css }]);
|
|
119
|
+
}
|
|
120
|
+
/** Registers a face for the session's life. */
|
|
121
|
+
async addFont(bytes) {
|
|
122
|
+
await this.render([{ op: 'font', bytes }]);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Registers one image, by the url the manuscript names it by, and
|
|
126
|
+
* lays the book out again around the room it takes.
|
|
127
|
+
*
|
|
128
|
+
* A url the manuscript names and nobody supplies is a diagnostic
|
|
129
|
+
* and a page with nothing where the image was.
|
|
130
|
+
*/
|
|
131
|
+
async addImage(url, bytes) {
|
|
132
|
+
await this.render([this.hold(url, bytes)]);
|
|
133
|
+
}
|
|
134
|
+
/** Lays the book out again and repaints. */
|
|
135
|
+
async render(ops = []) {
|
|
136
|
+
const output = await this.client.preview(ops);
|
|
137
|
+
if (output === null) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
this.output = output;
|
|
141
|
+
await this.load(output);
|
|
142
|
+
this.paint();
|
|
143
|
+
this.options.onRender?.(output);
|
|
144
|
+
}
|
|
145
|
+
/** How many pages the book set to. */
|
|
146
|
+
get pages() {
|
|
147
|
+
return this.output?.pages.length ?? 0;
|
|
148
|
+
}
|
|
149
|
+
/** The page on screen, counting from 1. */
|
|
150
|
+
get page() {
|
|
151
|
+
return this.showing;
|
|
152
|
+
}
|
|
153
|
+
set page(number) {
|
|
154
|
+
this.showing = Math.min(Math.max(Math.round(number), 1), Math.max(this.pages, 1));
|
|
155
|
+
this.paint();
|
|
156
|
+
}
|
|
157
|
+
/** Points to CSS pixels. */
|
|
158
|
+
get zoom() {
|
|
159
|
+
return this.scale;
|
|
160
|
+
}
|
|
161
|
+
set zoom(scale) {
|
|
162
|
+
this.scale = scale;
|
|
163
|
+
this.paint();
|
|
164
|
+
}
|
|
165
|
+
/** The next page, if the book has one. */
|
|
166
|
+
next() {
|
|
167
|
+
this.page = this.showing + 1;
|
|
168
|
+
}
|
|
169
|
+
/** The previous page, if there is one. */
|
|
170
|
+
previous() {
|
|
171
|
+
this.page = this.showing - 1;
|
|
172
|
+
}
|
|
173
|
+
/** Everything the run had to complain about. */
|
|
174
|
+
get warnings() {
|
|
175
|
+
return this.output?.warnings ?? [];
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* The markup on screen, or a page that is not on screen. Empty
|
|
179
|
+
* before the first render.
|
|
180
|
+
*/
|
|
181
|
+
svg(number = this.showing) {
|
|
182
|
+
const page = this.output?.pages[number - 1];
|
|
183
|
+
return page === undefined ? '' : paintPage(page, this.painting());
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* The book as PDF bytes, from the stages the preview settled, so
|
|
187
|
+
* the export cannot contradict what is on screen.
|
|
188
|
+
*/
|
|
189
|
+
async exportPdf() {
|
|
190
|
+
return this.client.exportPdf();
|
|
191
|
+
}
|
|
192
|
+
/** Closes the worker and gives the element back. */
|
|
193
|
+
destroy() {
|
|
194
|
+
for (const face of this.faces.values()) {
|
|
195
|
+
this.element.ownerDocument.fonts.delete(face);
|
|
196
|
+
}
|
|
197
|
+
this.faces.clear();
|
|
198
|
+
for (const url of this.pixels.values()) {
|
|
199
|
+
URL.revokeObjectURL(url);
|
|
200
|
+
}
|
|
201
|
+
this.pixels.clear();
|
|
202
|
+
this.element.replaceChildren();
|
|
203
|
+
this.worker.terminate();
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Keeps a blob url over an image's bytes and hands the same bytes
|
|
207
|
+
* to the engine.
|
|
208
|
+
*
|
|
209
|
+
* The blob is made before the op is sent, because the bytes move
|
|
210
|
+
* across the wall rather than being copied and the buffer is empty
|
|
211
|
+
* on this side afterwards.
|
|
212
|
+
*/
|
|
213
|
+
hold(url, bytes) {
|
|
214
|
+
const held = this.pixels.get(url);
|
|
215
|
+
if (held !== undefined) {
|
|
216
|
+
URL.revokeObjectURL(held);
|
|
217
|
+
}
|
|
218
|
+
this.pixels.set(url, URL.createObjectURL(new Blob([bytes.slice()], { type: mediaType(bytes) })));
|
|
219
|
+
return { op: 'image', url, bytes };
|
|
220
|
+
}
|
|
221
|
+
paint() {
|
|
222
|
+
this.frame.innerHTML = this.svg();
|
|
223
|
+
}
|
|
224
|
+
painting() {
|
|
225
|
+
return {
|
|
226
|
+
fonts: this.output?.fonts ?? [],
|
|
227
|
+
assets: this.output?.assets ?? [],
|
|
228
|
+
zoom: this.scale,
|
|
229
|
+
...(this.options.paper === undefined ? {} : { paper: this.options.paper }),
|
|
230
|
+
...(this.options.ink === undefined ? {} : { ink: this.options.ink }),
|
|
231
|
+
asset: this.options.asset ?? ((asset) => this.pixels.get(asset.url)),
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Loads the faces the run drew with, from the same files the
|
|
236
|
+
* engine shaped with.
|
|
237
|
+
*
|
|
238
|
+
* The bundled face is why this asks the module rather than the
|
|
239
|
+
* network: it is inside the module, and there is no URL to fetch
|
|
240
|
+
* it from. A face whose bytes do not come back is left out, and
|
|
241
|
+
* the painter's fallback stack is what the reader sees instead of
|
|
242
|
+
* a blank page. `faces: 'host'` is that stack on purpose.
|
|
243
|
+
*/
|
|
244
|
+
async load(output) {
|
|
245
|
+
if (this.options.faces === 'host') {
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
const used = new Set();
|
|
249
|
+
for (const page of output.pages) {
|
|
250
|
+
for (const item of page.items) {
|
|
251
|
+
if (item.kind === 'text') {
|
|
252
|
+
used.add(item.fontId);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
const wanted = [...used].filter((id) => !this.faces.has(id));
|
|
257
|
+
await Promise.all(wanted.map((id) => this.face(id)));
|
|
258
|
+
}
|
|
259
|
+
async face(id) {
|
|
260
|
+
try {
|
|
261
|
+
const bytes = await this.client.fontBytes(id);
|
|
262
|
+
// Registered as what it is, so that asking for it by that
|
|
263
|
+
// slope and weight is an exact match and the browser
|
|
264
|
+
// synthesises nothing over the cut the engine shaped with.
|
|
265
|
+
const attributes = this.output?.fonts[id]?.attributes;
|
|
266
|
+
const face = new FontFace(faceFamily(id), bytes.buffer, {
|
|
267
|
+
style: attributes?.italic === true ? 'italic' : 'normal',
|
|
268
|
+
weight: String(attributes?.weight ?? 400),
|
|
269
|
+
});
|
|
270
|
+
await face.load();
|
|
271
|
+
this.faces.set(id, face);
|
|
272
|
+
this.element.ownerDocument.fonts.add(face);
|
|
273
|
+
}
|
|
274
|
+
catch {
|
|
275
|
+
// A face that will not load is one the painter falls back
|
|
276
|
+
// from, which is visible on the page and needs no throw here.
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* What an image is, read off its own first bytes.
|
|
282
|
+
*
|
|
283
|
+
* A blob with no type is sniffed by the browser in some places and
|
|
284
|
+
* refused in others, and the file already says what it is in the
|
|
285
|
+
* same signature the engine probed it by.
|
|
286
|
+
*/
|
|
287
|
+
function mediaType(bytes) {
|
|
288
|
+
const starts = (...signature) => signature.every((byte, at) => bytes[at] === byte);
|
|
289
|
+
if (starts(0x89, 0x50, 0x4e, 0x47)) {
|
|
290
|
+
return 'image/png';
|
|
291
|
+
}
|
|
292
|
+
if (starts(0xff, 0xd8)) {
|
|
293
|
+
return 'image/jpeg';
|
|
294
|
+
}
|
|
295
|
+
if (starts(0x47, 0x49, 0x46, 0x38)) {
|
|
296
|
+
return 'image/gif';
|
|
297
|
+
}
|
|
298
|
+
if (starts(0x52, 0x49, 0x46, 0x46)) {
|
|
299
|
+
return 'image/webp';
|
|
300
|
+
}
|
|
301
|
+
return 'application/octet-stream';
|
|
302
|
+
}
|
|
303
|
+
//# sourceMappingURL=preview.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preview.js","sourceRoot":"","sources":["../src/preview.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,MAAM,EAAkB,MAAM,aAAa,CAAC;AAErD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AA2DjD;;;;;;GAMG;AACH,MAAM,OAAO,OAAO;IACD,OAAO,CAAU;IACjB,KAAK,CAAU;IACf,MAAM,CAAS;IACf,MAAM,CAAS;IACf,OAAO,CAAiB;IACxB,KAAK,GAAG,IAAI,GAAG,EAAoB,CAAC;IACrD,iEAAiE;IAChD,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC5C,MAAM,GAAwB,IAAI,CAAC;IACnC,OAAO,CAAS;IAChB,KAAK,CAAS;IAEtB,YAAoB,OAAgB,EAAE,MAAc,EAAE,OAAuB;QAC3E,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC;QACjC,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACxD,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;QACnD,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpC,MAAM,SAAS,GAAc;YAC3B,IAAI,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,QAAQ,CAAC;SACnE,CAAC;QACF,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC;QACpC,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE,CAC3C,IAAI,CAAC,MAAM,CAAC,OAAO,CAAE,KAAgC,CAAC,IAAI,CAAC,CAC5D,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,OAAgB,EAAE,UAA0B,EAAE;QAC/D,MAAM,MAAM,GACV,OAAO,CAAC,MAAM;YACd,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC1E,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;QACtD,MAAM,KAAK,GAAS,EAAE,CAAC;QACvB,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAClC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;QAC1D,CAAC;QACD,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAChC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QACpD,CAAC;QACD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAAC;YAChE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;QACvC,CAAC;QACD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrB,MAAM,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACpC,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,kEAAkE;IAClE,KAAK,CAAC,WAAW,CAAC,IAAY,EAAE,IAAI,GAAG,eAAe;QACpD,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACtD,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,OAAO,CAAC,OAAiB;QAC7B,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;IAC/C,CAAC;IAED,iEAAiE;IACjE,KAAK,CAAC,MAAM,CAAC,IAAY;QACvB,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC9C,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,WAAW,CAAC,QAAkB;QAClC,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;IACpD,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,IAAI,CAAC,IAAY,EAAE,IAAY;QACnC,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAClD,CAAC;IAED,mEAAmE;IACnE,KAAK,CAAC,QAAQ,CAAC,GAAW;QACxB,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED,+CAA+C;IAC/C,KAAK,CAAC,OAAO,CAAC,KAAiB;QAC7B,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,QAAQ,CAAC,GAAW,EAAE,KAAiB;QAC3C,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED,4CAA4C;IAC5C,KAAK,CAAC,MAAM,CAAC,MAAY,EAAE;QACzB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC9C,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACpB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxB,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,CAAC;IAClC,CAAC;IAED,sCAAsC;IACtC,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;IACxC,CAAC;IAED,2CAA2C;IAC3C,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,IAAI,IAAI,CAAC,MAAc;QACrB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;QAClF,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IAED,4BAA4B;IAC5B,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,IAAI,IAAI,CAAC,KAAa;QACpB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IAED,0CAA0C;IAC1C,IAAI;QACF,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;IAC/B,CAAC;IAED,0CAA0C;IAC1C,QAAQ;QACN,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;IAC/B,CAAC;IAED,gDAAgD;IAChD,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,MAAM,EAAE,QAAQ,IAAI,EAAE,CAAC;IACrC,CAAC;IAED;;;OAGG;IACH,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,OAAO;QACvB,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC5C,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IACpE,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,SAAS;QACb,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;IACjC,CAAC;IAED,oDAAoD;IACpD,OAAO;QACL,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YACvC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAChD,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACnB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;YACvC,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACpB,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC;QAC/B,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;IAC1B,CAAC;IAED;;;;;;;OAOG;IACK,IAAI,CAAC,GAAW,EAAE,KAAiB;QACzC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,eAAe,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACjG,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;IACrC,CAAC;IAEO,KAAK;QACX,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACpC,CAAC;IAEO,QAAQ;QACd,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE;YAC/B,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,IAAI,EAAE;YACjC,IAAI,EAAE,IAAI,CAAC,KAAK;YAChB,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YAC1E,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;YACpE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,KAAY,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;SAC5E,CAAC;IACJ,CAAC;IAED;;;;;;;;;OASG;IACK,KAAK,CAAC,IAAI,CAAC,MAAoB;QACrC,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,KAAK,MAAM,EAAE,CAAC;YAClC,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YAChC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBAC9B,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;oBACzB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACxB,CAAC;YACH,CAAC;QACH,CAAC;QACD,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QAC7D,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACvD,CAAC;IAEO,KAAK,CAAC,IAAI,CAAC,EAAU;QAC3B,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;YAC9C,0DAA0D;YAC1D,qDAAqD;YACrD,2DAA2D;YAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,EAAE,UAAU,CAAC;YACtD,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,MAAqB,EAAE;gBACrE,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ;gBACxD,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,IAAI,GAAG,CAAC;aAC1C,CAAC,CAAC;YACH,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;YAClB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;YACzB,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC7C,CAAC;QAAC,MAAM,CAAC;YACP,0DAA0D;YAC1D,8DAA8D;QAChE,CAAC;IACH,CAAC;CACF;AAED;;;;;;GAMG;AACH,SAAS,SAAS,CAAC,KAAiB;IAClC,MAAM,MAAM,GAAG,CAAC,GAAG,SAAmB,EAAW,EAAE,CACjD,SAAS,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC,CAAC;IACpD,IAAI,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;QACnC,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;QACvB,OAAO,YAAY,CAAC;IACtB,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;QACnC,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;QACnC,OAAO,YAAY,CAAC;IACtB,CAAC;IACD,OAAO,0BAA0B,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What crosses between a host and the worker the engine runs in.
|
|
3
|
+
*
|
|
4
|
+
* A request is an edit plus, sometimes, a render: inputs travel when
|
|
5
|
+
* they change rather than once per frame, and the module keeps every
|
|
6
|
+
* stage between them. Each request carries a generation, which the
|
|
7
|
+
* worker echoes back untouched. The host raises it whenever the
|
|
8
|
+
* input goes stale, and a reply that comes back behind the current
|
|
9
|
+
* one is dropped rather than painted.
|
|
10
|
+
*/
|
|
11
|
+
/** One markdown source: what it is called, and what is in it. */
|
|
12
|
+
export interface Source {
|
|
13
|
+
/** What the book calls this file, and what an edit replaces. */
|
|
14
|
+
name: string;
|
|
15
|
+
/** Its markdown. */
|
|
16
|
+
text: string;
|
|
17
|
+
}
|
|
18
|
+
/** What names a book: its title, its author, and whatever else. */
|
|
19
|
+
export interface Metadata {
|
|
20
|
+
/** Title, for the half-title and running heads. */
|
|
21
|
+
title?: string;
|
|
22
|
+
/** Author, for the title page. */
|
|
23
|
+
author?: string;
|
|
24
|
+
/** Anything else a frontend carries, such as `language`. */
|
|
25
|
+
extra?: Record<string, string>;
|
|
26
|
+
}
|
|
27
|
+
/** One input reaching the engine. */
|
|
28
|
+
export type Op =
|
|
29
|
+
/** Font bytes, registered once and kept for the session's life. */
|
|
30
|
+
{
|
|
31
|
+
op: 'font';
|
|
32
|
+
bytes: Uint8Array;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* One image, by the url the manuscript names it by, kept for the
|
|
36
|
+
* session's life. The engine opens nothing, so the host fetches
|
|
37
|
+
* the file and the bytes cross once rather than once per render.
|
|
38
|
+
*/
|
|
39
|
+
| {
|
|
40
|
+
op: 'image';
|
|
41
|
+
url: string;
|
|
42
|
+
bytes: Uint8Array;
|
|
43
|
+
}
|
|
44
|
+
/** Which markdown the sources are written in. */
|
|
45
|
+
| {
|
|
46
|
+
op: 'dialect';
|
|
47
|
+
dialect: 'commonmark' | 'gfm' | 'obsidian';
|
|
48
|
+
}
|
|
49
|
+
/** Where a source's sections begin: a heading level, or 0 for a file per section. */
|
|
50
|
+
| {
|
|
51
|
+
op: 'split';
|
|
52
|
+
level: number;
|
|
53
|
+
}
|
|
54
|
+
/** One markdown source as the whole book. */
|
|
55
|
+
| {
|
|
56
|
+
op: 'markdown';
|
|
57
|
+
name: string;
|
|
58
|
+
text: string;
|
|
59
|
+
}
|
|
60
|
+
/** Every markdown source of a book, in reading order. */
|
|
61
|
+
| {
|
|
62
|
+
op: 'book';
|
|
63
|
+
sources: Source[];
|
|
64
|
+
}
|
|
65
|
+
/** One source dropped, and the rest of the book left standing. */
|
|
66
|
+
| {
|
|
67
|
+
op: 'remove';
|
|
68
|
+
name: string;
|
|
69
|
+
}
|
|
70
|
+
/** What names the book, for a book whose sources cannot say. */
|
|
71
|
+
| {
|
|
72
|
+
op: 'metadata';
|
|
73
|
+
metadata: Metadata;
|
|
74
|
+
}
|
|
75
|
+
/** One source replaced: the keystroke path, where the rest of the book stands. */
|
|
76
|
+
| {
|
|
77
|
+
op: 'edit';
|
|
78
|
+
name: string;
|
|
79
|
+
text: string;
|
|
80
|
+
}
|
|
81
|
+
/** A content tree, as JSON, for a host with a structured source of its own. */
|
|
82
|
+
| {
|
|
83
|
+
op: 'content';
|
|
84
|
+
json: string;
|
|
85
|
+
}
|
|
86
|
+
/** The author stylesheet, as CSS text. */
|
|
87
|
+
| {
|
|
88
|
+
op: 'style';
|
|
89
|
+
css: string;
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* What a request wants back, if anything: a display structure, a PDF, or
|
|
93
|
+
* the file a face was registered from.
|
|
94
|
+
*
|
|
95
|
+
* The first two are renders and the last is a question, which is
|
|
96
|
+
* what decides whether a later request may overtake it.
|
|
97
|
+
*/
|
|
98
|
+
export type Want = 'preview' | 'pdf' | 'font';
|
|
99
|
+
/** An edit, a render, a question, or an edit and one of those. */
|
|
100
|
+
export interface Request {
|
|
101
|
+
/** Pairs the reply with the call. */
|
|
102
|
+
id: number;
|
|
103
|
+
/** Raised by the host whenever the input goes stale. */
|
|
104
|
+
generation: number;
|
|
105
|
+
/** The inputs that changed, applied in the order they arrive. */
|
|
106
|
+
ops: Op[];
|
|
107
|
+
/** What to send back once they have been applied. */
|
|
108
|
+
want?: Want;
|
|
109
|
+
/** Which face `want: 'font'` is asking for. */
|
|
110
|
+
font?: number;
|
|
111
|
+
}
|
|
112
|
+
/** The bytes a request produced: a display structure, a PDF, or a font file. */
|
|
113
|
+
export interface Rendered {
|
|
114
|
+
id: number;
|
|
115
|
+
generation: number;
|
|
116
|
+
kind: Want;
|
|
117
|
+
bytes: Uint8Array;
|
|
118
|
+
/**
|
|
119
|
+
* How many times each stage has run since the session opened, as
|
|
120
|
+
* `[style, lines, flow, paint]`. What the edit cost, in stage runs
|
|
121
|
+
* rather than milliseconds: a cache that served shows here, where
|
|
122
|
+
* a clock would only show a fast machine.
|
|
123
|
+
*/
|
|
124
|
+
stages: [number, number, number, number];
|
|
125
|
+
}
|
|
126
|
+
/** Inputs applied, with nothing asked for back. */
|
|
127
|
+
export interface Applied {
|
|
128
|
+
id: number;
|
|
129
|
+
generation: number;
|
|
130
|
+
applied: true;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* A render another request overtook before it ran. Its inputs were
|
|
134
|
+
* applied; only the painting was skipped.
|
|
135
|
+
*/
|
|
136
|
+
export interface Superseded {
|
|
137
|
+
id: number;
|
|
138
|
+
generation: number;
|
|
139
|
+
superseded: true;
|
|
140
|
+
}
|
|
141
|
+
/** A request the engine refused, and what it said. */
|
|
142
|
+
export interface Failed {
|
|
143
|
+
id: number;
|
|
144
|
+
generation: number;
|
|
145
|
+
error: string;
|
|
146
|
+
}
|
|
147
|
+
/** What comes back for a request. */
|
|
148
|
+
export type Response = Rendered | Applied | Superseded | Failed;
|
|
149
|
+
/** Whether a reply carries bytes. */
|
|
150
|
+
export declare function isRendered(response: Response): response is Rendered;
|
|
151
|
+
/** Whether a reply is the engine reporting trouble. */
|
|
152
|
+
export declare function isFailed(response: Response): response is Failed;
|
|
153
|
+
//# sourceMappingURL=protocol.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"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"}
|