slotdeck 0.1.2 → 0.2.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 +86 -6
- package/dist/deck/alternatives.d.ts +34 -0
- package/dist/deck/alternatives.js +370 -0
- package/dist/deck/alternatives.js.map +1 -0
- package/dist/deck/design.d.ts +40 -0
- package/dist/deck/design.js +112 -0
- package/dist/deck/design.js.map +1 -0
- package/dist/deck/validate.d.ts +18 -0
- package/dist/deck/validate.js +38 -2
- package/dist/deck/validate.js.map +1 -1
- package/dist/index.d.ts +22 -1
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -1
- package/dist/node.d.ts +7 -0
- package/dist/node.js +29 -0
- package/dist/node.js.map +1 -1
- package/dist/plan/catalog.js +3 -1
- package/dist/plan/catalog.js.map +1 -1
- package/dist/plan/edit.js +6 -2
- package/dist/plan/edit.js.map +1 -1
- package/dist/plan/plan.d.ts +10 -0
- package/dist/plan/plan.js +8 -0
- package/dist/plan/plan.js.map +1 -1
- package/dist/plan/review.d.ts +43 -0
- package/dist/plan/review.js +141 -0
- package/dist/plan/review.js.map +1 -0
- package/dist/plan/write.d.ts +5 -0
- package/dist/plan/write.js +11 -4
- package/dist/plan/write.js.map +1 -1
- package/dist/preview/pagus.d.ts +30 -0
- package/dist/preview/pagus.js +45 -0
- package/dist/preview/pagus.js.map +1 -0
- package/dist/preview/patterns.d.ts +27 -0
- package/dist/preview/patterns.js +35 -0
- package/dist/preview/patterns.js.map +1 -0
- package/dist/preview/provider.d.ts +30 -0
- package/dist/preview/provider.js +11 -0
- package/dist/preview/provider.js.map +1 -0
- package/dist/render/render.d.ts +18 -1
- package/dist/render/render.js +28 -8
- package/dist/render/render.js.map +1 -1
- package/dist/render/repeat.d.ts +17 -2
- package/dist/render/repeat.js +150 -4
- package/dist/render/repeat.js.map +1 -1
- package/dist/render/text.d.ts +6 -0
- package/dist/render/text.js +24 -0
- package/dist/render/text.js.map +1 -1
- package/dist/template/budgets.d.ts +33 -0
- package/dist/template/budgets.js +38 -0
- package/dist/template/budgets.js.map +1 -0
- package/dist/template/change.d.ts +18 -1
- package/dist/template/change.js +33 -3
- package/dist/template/change.js.map +1 -1
- package/dist/template/check.d.ts +3 -0
- package/dist/template/check.js +53 -3
- package/dist/template/check.js.map +1 -1
- package/dist/template/derive.d.ts +54 -0
- package/dist/template/derive.js +402 -0
- package/dist/template/derive.js.map +1 -0
- package/dist/template/draft.d.ts +7 -0
- package/dist/template/draft.js +17 -1
- package/dist/template/draft.js.map +1 -1
- package/dist/template/instruct.js +11 -5
- package/dist/template/instruct.js.map +1 -1
- package/dist/template/manifest.d.ts +22 -0
- package/dist/template/manifest.js +17 -1
- package/dist/template/manifest.js.map +1 -1
- package/dist/template/sample.d.ts +17 -0
- package/dist/template/sample.js +27 -2
- package/dist/template/sample.js.map +1 -1
- package/dist/text/fontkit.d.ts +18 -0
- package/dist/text/fontkit.js +91 -0
- package/dist/text/fontkit.js.map +1 -0
- package/dist/text/fonts.d.ts +45 -0
- package/dist/text/fonts.js +59 -0
- package/dist/text/fonts.js.map +1 -0
- package/dist/text/layout.d.ts +12 -0
- package/dist/text/layout.js +104 -0
- package/dist/text/layout.js.map +1 -0
- package/dist/text/measure.d.ts +85 -0
- package/dist/text/measure.js +369 -0
- package/dist/text/measure.js.map +1 -0
- package/dist/text/styles.d.ts +123 -0
- package/dist/text/styles.js +417 -0
- package/dist/text/styles.js.map +1 -0
- package/dist/tools.d.ts +12 -0
- package/dist/tools.js +32 -6
- package/dist/tools.js.map +1 -1
- package/docs/README.md +15 -5
- package/docs/api-reference.md +278 -8
- package/docs/changelog.md +135 -0
- package/docs/chat-tools.md +22 -5
- package/docs/deck-format.md +6 -0
- package/docs/design-checks.md +216 -0
- package/docs/generating.md +4 -1
- package/docs/layout-freedom.md +255 -3
- package/docs/manifest-format.md +19 -3
- package/docs/preview.md +217 -0
- package/docs/providers.md +1 -1
- package/docs/rendering.md +8 -0
- package/docs/template-studio.md +110 -11
- package/docs/text-fit.md +456 -0
- package/docs/troubleshooting.md +13 -2
- package/package.json +7 -1
package/README.md
CHANGED
|
@@ -218,7 +218,9 @@ data reaches a model, and a pptx can be rebuilt from the JSON and the pictures a
|
|
|
218
218
|
new plan or deck under a new id; earlier versions stay.
|
|
219
219
|
|
|
220
220
|
To show a plan as layout thumbnails, render the template once and name the pictures after the patterns
|
|
221
|
-
(`scripts/pattern-thumbnails.ts`).
|
|
221
|
+
(`scripts/pattern-thumbnails.ts`). A derived pattern, such as a mirror image, looks different from the slide it
|
|
222
|
+
comes from: `scripts/template-deck.ts` writes a deck with one slide per pattern, filled with the template's own
|
|
223
|
+
sample content, to take those pictures from. `examples/plan-preview.ts` turns a plan into a self-contained page.
|
|
222
224
|
|
|
223
225
|
### Other models
|
|
224
226
|
|
|
@@ -285,6 +287,10 @@ manifest allows and the code moves the shapes; the model never positions anythin
|
|
|
285
287
|
accepts (in the demo template `icon-cards` takes 2 to 4 and `stat-cards` 2 to 6). A slide says how many with
|
|
286
288
|
`items`. Surplus cards are removed, extra ones are copies of the last, and the row is spaced out again around
|
|
287
289
|
its centre. A copied card has its own slots (`card5Icon`, `card5Heading`, ...).
|
|
290
|
+
- **Rows that fill their line.** With `widen` on the `repeat`, fewer cards than drawn grow wider instead of
|
|
291
|
+
standing in the middle of the row: backgrounds and text boxes widen, icons and pictures keep their size
|
|
292
|
+
and their side, and the text budgets grow with the cards. The number of cards decides, never the length of
|
|
293
|
+
the text.
|
|
288
294
|
- **Grids.** With `columns`, the items form a grid. They take as few rows as they need and spread evenly: four
|
|
289
295
|
figures in a three-column grid make two rows of two, five make three and two, three make one row.
|
|
290
296
|
- **Larger text.** `textScale` on a deck (or `textSize: 'large' | 'x-large'` on a brief) enlarges body text:
|
|
@@ -295,6 +301,77 @@ manifest allows and the code moves the shapes; the model never positions anythin
|
|
|
295
301
|
given a font size (`fontSize`) and paragraph spacing, and any shape can be dropped. In the demo template
|
|
296
302
|
`text-only` is the photo slide with its photo dropped and its text widened, and `chart-native` is the chart
|
|
297
303
|
slide with a native chart in place of the picture.
|
|
304
|
+
- **Variants the code works out.** For three common variants nobody types a box: the mirror image of a slide
|
|
305
|
+
with a picture, the same slide without its picture, and a slide without one of its optional lines. One
|
|
306
|
+
operation (`derivePattern`) makes each, moving the shapes and measuring the budgets again; the header, logo
|
|
307
|
+
and page number stay where they are. In the demo template `text-and-photo-mirrored`, `photo-stat-mirrored`
|
|
308
|
+
and `list-with-photo-mirrored` were made this way.
|
|
309
|
+
|
|
310
|
+
### Another layout for a slide
|
|
311
|
+
|
|
312
|
+
`slideAlternatives(manifest, deck, slideNumber)` takes a slide that already has its content and lists the
|
|
313
|
+
other patterns that can hold the same content, with the slide written for each: three cards as a list of three
|
|
314
|
+
points, two cards as two columns, a photo slide as its mirror image. It is code only. No model is asked and no
|
|
315
|
+
word is changed, so a pattern that would need a subtitle, a number or an icon the slide does not have is not
|
|
316
|
+
offered. What does not fit a new slot's budget is reported, not cut.
|
|
317
|
+
|
|
318
|
+
```ts
|
|
319
|
+
import { slideAlternatives } from 'slotdeck';
|
|
320
|
+
|
|
321
|
+
const [first] = slideAlternatives(manifest, deck, 5, { layout: 'adaptive' });
|
|
322
|
+
// first.pattern, first.slide, first.changes, first.dropped, first.warnings
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### Text that fits
|
|
326
|
+
|
|
327
|
+
By default a slot's limit is a character budget, which cannot see where lines break. Give the template its font
|
|
328
|
+
files and text is measured the way PowerPoint sets it: broken into lines at the slot's typeface and size and
|
|
329
|
+
compared with the room in its box.
|
|
330
|
+
|
|
331
|
+
```ts
|
|
332
|
+
import * as fontkit from 'fontkit'; // installed by you; slotdeck does not depend on it
|
|
333
|
+
import { fontkitMetrics, loadTemplate, renderDeck } from 'slotdeck';
|
|
334
|
+
|
|
335
|
+
const fonts = fontkitMetrics(fontkit, { Calibri: [calibri, calibriBold], Cambria: [cambria, cambriaBold] });
|
|
336
|
+
const template = loadTemplate(pptx, manifest, { fonts });
|
|
337
|
+
|
|
338
|
+
renderDeck(template, deck, { assets }).warnings;
|
|
339
|
+
// text takes 7 lines at 18 pt; the box holds 5 (2 lines too many). Text of about 290 characters fits.
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
The planner repairs drafts by the same measurement, `shrinkText` on the manifest lets text that does not fit be
|
|
343
|
+
set a little smaller, and `measuredBudgets` works out budgets from what the boxes hold. On the demo template
|
|
344
|
+
every line broke at the same word as in PowerPoint in all 1,153 text slots checked, in English and Hebrew. See
|
|
345
|
+
[`docs/text-fit.md`](docs/text-fit.md).
|
|
346
|
+
|
|
347
|
+
### Design checks
|
|
348
|
+
|
|
349
|
+
A deck can fit its boxes and still look wrong. With fonts loaded, `checkDesign(template, deck)` finds what
|
|
350
|
+
measurement can see: a box left almost empty, a card far shorter than its neighbours, a heading that ends with
|
|
351
|
+
one word on a line of its own. Each finding says what length of text would put it right, and
|
|
352
|
+
`review: designReview(template)` sends the findings back to the writing model while a deck is planned. On the
|
|
353
|
+
example deck it reports the two orphan words that PowerPoint's own picture shows. See
|
|
354
|
+
[`docs/design-checks.md`](docs/design-checks.md).
|
|
355
|
+
|
|
356
|
+
### Previews
|
|
357
|
+
|
|
358
|
+
slotdeck draws nothing itself, but it has a hook for a renderer that does: a `PreviewProvider` turns a pptx into
|
|
359
|
+
one picture for each slide. An adapter for the Pagus library comes with the package (you install Pagus), and
|
|
360
|
+
any other renderer or service can be plugged in.
|
|
361
|
+
|
|
362
|
+
```ts
|
|
363
|
+
import * as pagusCore from '@pagus-kit/core';
|
|
364
|
+
import * as pagusRenderer from '@pagus-kit/renderer';
|
|
365
|
+
import { pagusPreviews, patternPreviews, previewDeck } from 'slotdeck';
|
|
366
|
+
|
|
367
|
+
const preview = pagusPreviews(pagusCore, pagusRenderer);
|
|
368
|
+
const { pptx, previews } = await previewDeck(template, deck, preview, { assets }); // SVG, one for each slide
|
|
369
|
+
const thumbnails = await patternPreviews(template, preview); // one for each pattern
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
The chat tools take the same provider and keep a picture of every slide they make. A preview shows what a deck
|
|
373
|
+
looks like; it is not PowerPoint. What three renderers got right and wrong, in English and in Hebrew, is in
|
|
374
|
+
[`docs/preview.md`](docs/preview.md).
|
|
298
375
|
|
|
299
376
|
## Template studio
|
|
300
377
|
|
|
@@ -372,8 +449,9 @@ const view = studioView(template);
|
|
|
372
449
|
| `setSlot` | A slot's budget, whether it is required, optional, kept or always removed (`empty`), font size, area (`box`), name, deck field, picture kind, and the settings of a table or chart. |
|
|
373
450
|
| `addSlot` | Makes a shape a slot in a role (`title`, `text`, `list`, `number`, `caption`, `photo`, `icon`, `graphic`, `chart`, `table`, `decoration`), with limits measured from the shape. On a shape that is already a slot it changes the role. |
|
|
374
451
|
| `removeSlot` | The shape goes back to being part of the design. |
|
|
375
|
-
| `setRepeat`, `removeRepeat` | How many items a row or grid takes. Finds the row from numbered slot names when the pattern has none. |
|
|
452
|
+
| `setRepeat`, `removeRepeat` | How many items a row or grid takes, and whether fewer items grow wider to fill the row (`widen`). Finds the row from numbered slot names when the pattern has none. |
|
|
376
453
|
| `addPattern`, `copyPattern`, `setPattern`, `removePattern` | Which slides are patterns, their ids and descriptions, and variants of a pattern from the same slide. |
|
|
454
|
+
| `derivePattern` | A variant of a pattern that the code lays out by itself: `mirror`, `text-only`, or `without` an optional text. Refused with the reason when the slide does not allow it. |
|
|
377
455
|
| `setManifest` | The template's name, language, direction and alignment policy. |
|
|
378
456
|
|
|
379
457
|
What the code adds to each change:
|
|
@@ -387,7 +465,8 @@ What the code adds to each change:
|
|
|
387
465
|
is refused, and the rest of the list is still applied.
|
|
388
466
|
|
|
389
467
|
`editManifest` makes one model call, and a second when some of its operations were refused, so the model can
|
|
390
|
-
correct them. The model never sets a position: `box` and `span` exist only for changes made by hand
|
|
468
|
+
correct them. The model never sets a position: `box` and `span` exist only for changes made by hand, and a
|
|
469
|
+
variant it asks for by name is laid out by the code.
|
|
391
470
|
`describeManifest(template)` returns the text the model reads, for an app that wants to show the manifest to its
|
|
392
471
|
own chat model.
|
|
393
472
|
|
|
@@ -402,6 +481,7 @@ own chat model.
|
|
|
402
481
|
native-chart variant. It also asked for five cards in a row; that was refused, because four fit.
|
|
403
482
|
3. A few changes by hand with `changeManifest`: the text-only variant, chart colours, mirrored alignment for
|
|
404
483
|
right-to-left decks, and tighter budgets for figures and one-line captions.
|
|
484
|
+
4. Three `derivePattern` operations for the mirror images of the slides with a photo.
|
|
405
485
|
|
|
406
486
|
A draft is a starting point. What it does not contain, and a person adds while reviewing: budgets tuned by eye,
|
|
407
487
|
derived patterns, wider rows, picture areas and chart colours. On a 36-slide corporate template (not included
|
|
@@ -480,15 +560,15 @@ powershell -File scripts/render-pptx.ps1 -Path out/patterns-en.pptx -OutDir out/
|
|
|
480
560
|
as empty, so its budget is only as long as its sample text. Decks exported from Google Slides and decks built
|
|
481
561
|
from free-standing text boxes work as they are.
|
|
482
562
|
- **Budgets are estimates.** A character budget cannot see lines lost to wrapping. Budgets for slots with several
|
|
483
|
-
paragraphs should be set with room to spare, and a sample deck is the way to see them.
|
|
563
|
+
paragraphs should be set with room to spare, and a sample deck is the way to see them. A template loaded with
|
|
564
|
+
its fonts measures text slots in lines instead (see Text that fits); tables and charts keep their budgets.
|
|
484
565
|
- **Models invent details.** In the showcase deck the model made up an email address and a phone number for the
|
|
485
566
|
closing slide, which were replaced by hand. Figures are guarded (see How planning works); contact details and
|
|
486
567
|
names are not.
|
|
487
568
|
- **What has been run.** The whole path was run against the Gemini Developer API with `gemini-3.8-flash` for
|
|
488
569
|
text and `gemini-3.1-flash-image` for photos, in English and Hebrew. Vertex AI is supported by the adapter but
|
|
489
570
|
has not been run live. Output was checked by rendering in PowerPoint on Windows; other viewers were not tested.
|
|
490
|
-
- **Not built:**
|
|
491
|
-
made in PowerPoint.
|
|
571
|
+
- **Not built:** stacked or combined charts, speaker notes, and reading back changes made in PowerPoint.
|
|
492
572
|
|
|
493
573
|
## The demo template and pictures
|
|
494
574
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { TemplateManifest } from '../template/manifest.ts';
|
|
2
|
+
import type { DeckSpec, SlideSpec } from './spec.ts';
|
|
3
|
+
import type { Issue, LayoutMode } from './validate.ts';
|
|
4
|
+
export interface SlideAlternative {
|
|
5
|
+
/** Id of a pattern that has a place for everything the slide says. */
|
|
6
|
+
pattern: string;
|
|
7
|
+
/** What that pattern is for, from the manifest. */
|
|
8
|
+
description: string;
|
|
9
|
+
/** The slide written for that pattern. Put it in the deck in place of the original. */
|
|
10
|
+
slide: SlideSpec;
|
|
11
|
+
/** What was done to the content where it was not copied slot for slot, a sentence each. */
|
|
12
|
+
changes: string[];
|
|
13
|
+
/** Slots of the original slide whose photo or icon the pattern has no place for. */
|
|
14
|
+
dropped: string[];
|
|
15
|
+
/** What `validateDeck` says about the new slide, such as a text over its budget. Empty when everything fits. */
|
|
16
|
+
warnings: Issue[];
|
|
17
|
+
}
|
|
18
|
+
export interface AlternativesOptions {
|
|
19
|
+
/** `strict` (default): every slot of the new pattern must be filled. `adaptive`: its optional slots may stay empty. */
|
|
20
|
+
layout?: LayoutMode;
|
|
21
|
+
/** Consider only these patterns. */
|
|
22
|
+
patterns?: string[];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Lists the other patterns that can hold what one slide of a deck says, with the slide written
|
|
26
|
+
* for each. `slide` is the slide's number in the deck, from 1. No model is asked and no text is
|
|
27
|
+
* rewritten: a title stays a title, and a row of items becomes other items or a list of points.
|
|
28
|
+
*
|
|
29
|
+
* A pattern is an alternative when every text, table, chart and supplied graphic of the slide
|
|
30
|
+
* has a place in it and every slot it requires can be filled. A photo or an icon may be left
|
|
31
|
+
* out, which `dropped` reports. A text that is longer than its new slot holds is reported in
|
|
32
|
+
* `warnings`, as `validateDeck` would. Alternatives that fit without a warning come first.
|
|
33
|
+
*/
|
|
34
|
+
export declare function slideAlternatives(manifest: TemplateManifest, deck: DeckSpec, slide: number, options?: AlternativesOptions): SlideAlternative[];
|
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
// Other layouts for a slide that already has its content. The content is read out of the slide
|
|
2
|
+
// by what each slot is for (a title, a body, items with a heading and a text) and put into every
|
|
3
|
+
// other pattern that has a place for all of it. Code only: no model is asked and nothing is
|
|
4
|
+
// rewritten, so an alternative says exactly what the slide said.
|
|
5
|
+
import { effectiveSlots, itemRange } from '../template/manifest.js';
|
|
6
|
+
import { isImageRef, toParagraphs } from './spec.js';
|
|
7
|
+
import { validateDeck } from './validate.js';
|
|
8
|
+
const fillable = (slot) => slot.empty !== 'keep' && slot.empty !== 'drop' && !(slot.kind === 'text' && slot.deckField);
|
|
9
|
+
const sizeOf = (slot) => slot.fontSize ?? slot.size ?? 0;
|
|
10
|
+
/** A big, short text is a figure: "87%", "3.5x". */
|
|
11
|
+
const isFigure = (slot) => (slot.maxChars ?? Infinity) <= 10 && sizeOf(slot) >= 24;
|
|
12
|
+
const largest = (slots) => slots.slice().sort((a, b) => (b.maxChars ?? 0) - (a.maxChars ?? 0))[0];
|
|
13
|
+
const plural = (count, word) => `${count} ${word}${count === 1 ? '' : 's'}`;
|
|
14
|
+
const empty = (value) => value === null || value === undefined || (typeof value === 'string' && value.trim() === '');
|
|
15
|
+
/** A photo or an icon illustrates and may be left out; a supplied graphic is something the slide says. */
|
|
16
|
+
const illustrates = (kind) => kind !== 'graphic';
|
|
17
|
+
const asValue = (text) => (text.length === 1 ? text[0] : text);
|
|
18
|
+
const isList = (slot) => (slot?.maxParagraphs ?? 1) > 1;
|
|
19
|
+
function textOf(value) {
|
|
20
|
+
if (typeof value !== 'string' && !Array.isArray(value))
|
|
21
|
+
return undefined;
|
|
22
|
+
const paragraphs = toParagraphs(value).filter((paragraph) => paragraph !== '');
|
|
23
|
+
return paragraphs.length > 0 ? paragraphs : undefined;
|
|
24
|
+
}
|
|
25
|
+
function anatomy(pattern) {
|
|
26
|
+
const repeat = pattern.repeat;
|
|
27
|
+
const inRow = new Set(repeat ? repeat.shapes.flatMap((_, index) => repeat.slots.map((name) => name.replace('{n}', String(index + 1)))) : []);
|
|
28
|
+
const own = pattern.slots.filter((slot) => fillable(slot) && !inRow.has(slot.name));
|
|
29
|
+
const texts = own.filter((slot) => slot.kind === 'text');
|
|
30
|
+
const take = (slot) => {
|
|
31
|
+
if (slot)
|
|
32
|
+
texts.splice(texts.indexOf(slot), 1);
|
|
33
|
+
return slot;
|
|
34
|
+
};
|
|
35
|
+
const shape = { others: [] };
|
|
36
|
+
const title = take(texts.find((slot) => /title$/i.test(slot.name) && !/sub/i.test(slot.name)));
|
|
37
|
+
const subtitle = take(texts.find((slot) => /sub(title|heading)$/i.test(slot.name)));
|
|
38
|
+
const figure = take(texts.find(isFigure));
|
|
39
|
+
// Of what is left, the text with the most room is the body.
|
|
40
|
+
const body = take(largest(texts));
|
|
41
|
+
if (title)
|
|
42
|
+
shape.title = title;
|
|
43
|
+
if (subtitle)
|
|
44
|
+
shape.subtitle = subtitle;
|
|
45
|
+
if (figure)
|
|
46
|
+
shape.figure = figure;
|
|
47
|
+
if (body)
|
|
48
|
+
shape.body = body;
|
|
49
|
+
const pictures = own.filter((slot) => slot.kind === 'image' && slot.imageKind !== 'icon');
|
|
50
|
+
if (pictures.length === 1 && pictures[0])
|
|
51
|
+
shape.picture = pictures[0];
|
|
52
|
+
shape.others = [...texts, ...own.filter((slot) => slot.kind !== 'text' && slot !== shape.picture)];
|
|
53
|
+
if (repeat) {
|
|
54
|
+
const parts = new Map();
|
|
55
|
+
let clear = true;
|
|
56
|
+
const itemTexts = [];
|
|
57
|
+
for (const template of repeat.slots) {
|
|
58
|
+
const slot = pattern.slots.find((candidate) => candidate.name === template.replace('{n}', '1'));
|
|
59
|
+
if (!slot || !fillable(slot))
|
|
60
|
+
continue;
|
|
61
|
+
if (slot.kind === 'text')
|
|
62
|
+
itemTexts.push({ template, slot });
|
|
63
|
+
else if (slot.kind === 'image') {
|
|
64
|
+
const part = slot.imageKind === 'icon' ? 'icon' : 'picture';
|
|
65
|
+
if (parts.has(part))
|
|
66
|
+
clear = false;
|
|
67
|
+
parts.set(part, { template, slot });
|
|
68
|
+
}
|
|
69
|
+
else
|
|
70
|
+
clear = false;
|
|
71
|
+
}
|
|
72
|
+
const number = itemTexts.length > 1 ? itemTexts.find((entry) => isFigure(entry.slot)) : undefined;
|
|
73
|
+
if (number)
|
|
74
|
+
parts.set('figure', number);
|
|
75
|
+
const rest = itemTexts.filter((entry) => entry !== number).sort((a, b) => (a.slot.maxChars ?? 0) - (b.slot.maxChars ?? 0));
|
|
76
|
+
// Of two texts, the one with less room is the heading. More than two cannot be told apart.
|
|
77
|
+
if (rest.length > 2)
|
|
78
|
+
clear = false;
|
|
79
|
+
if (rest.length === 2 && rest[0])
|
|
80
|
+
parts.set('heading', rest[0]);
|
|
81
|
+
const main = rest.at(-1);
|
|
82
|
+
if (main)
|
|
83
|
+
parts.set('text', main);
|
|
84
|
+
shape.row = { parts, clear };
|
|
85
|
+
}
|
|
86
|
+
return shape;
|
|
87
|
+
}
|
|
88
|
+
function contentOf(pattern, shape, slide) {
|
|
89
|
+
const content = { others: new Map(), items: [], itemName: pattern.repeat?.item ?? 'item', itemPictures: [], bodyIsList: isList(shape.body) };
|
|
90
|
+
const read = (slot) => (slot ? textOf(slide.slots[slot.name]) : undefined);
|
|
91
|
+
const title = read(shape.title);
|
|
92
|
+
const subtitle = read(shape.subtitle);
|
|
93
|
+
const figure = read(shape.figure);
|
|
94
|
+
const body = read(shape.body);
|
|
95
|
+
if (title)
|
|
96
|
+
content.title = title;
|
|
97
|
+
if (subtitle)
|
|
98
|
+
content.subtitle = subtitle;
|
|
99
|
+
if (figure)
|
|
100
|
+
content.figure = figure;
|
|
101
|
+
if (body)
|
|
102
|
+
content.body = body;
|
|
103
|
+
const picture = shape.picture && slide.slots[shape.picture.name];
|
|
104
|
+
if (shape.picture && isImageRef(picture))
|
|
105
|
+
content.picture = { ref: picture, kind: shape.picture.imageKind, from: shape.picture.name };
|
|
106
|
+
for (const slot of shape.others) {
|
|
107
|
+
const value = slide.slots[slot.name];
|
|
108
|
+
if (!empty(value))
|
|
109
|
+
content.others.set(slot.name, { value, slot });
|
|
110
|
+
}
|
|
111
|
+
const range = itemRange(pattern);
|
|
112
|
+
if (shape.row && range) {
|
|
113
|
+
for (let n = 1; n <= (slide.items ?? range.drawn); n++) {
|
|
114
|
+
const item = {};
|
|
115
|
+
for (const [part, { template, slot }] of shape.row.parts) {
|
|
116
|
+
const name = template.replace('{n}', String(n));
|
|
117
|
+
const value = slide.slots[name];
|
|
118
|
+
if (part === 'icon' || part === 'picture') {
|
|
119
|
+
if (isImageRef(value) && slot.kind === 'image') {
|
|
120
|
+
item[part] = value;
|
|
121
|
+
content.itemPictures.push({ from: name, part, kind: slot.imageKind });
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
const text = textOf(value);
|
|
126
|
+
if (text)
|
|
127
|
+
item[part] = text;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
content.items.push(item);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return content;
|
|
134
|
+
}
|
|
135
|
+
class NoPlace extends Error {
|
|
136
|
+
}
|
|
137
|
+
const no = () => {
|
|
138
|
+
throw new NoPlace();
|
|
139
|
+
};
|
|
140
|
+
/** A heading and a text as one line: "Heading: text". */
|
|
141
|
+
function joined(lead, text) {
|
|
142
|
+
const head = (lead ?? []).join(' ');
|
|
143
|
+
const rest = (text ?? []).join(' ');
|
|
144
|
+
if (!head || !rest)
|
|
145
|
+
return head || rest;
|
|
146
|
+
return /[:.!?…]$/.test(head) ? `${head} ${rest}` : `${head}: ${rest}`;
|
|
147
|
+
}
|
|
148
|
+
/** The two halves of "Heading: text", or nothing when the line is not written that way. */
|
|
149
|
+
function split(line) {
|
|
150
|
+
const match = /^(.{1,80}?)(?::\s+|\s+[–—-]\s+)(\S.*)$/.exec(line);
|
|
151
|
+
return match ? [match[1], match[2]] : undefined;
|
|
152
|
+
}
|
|
153
|
+
/** Copies every value to the slot of the same name: the way between variants of one slide. */
|
|
154
|
+
function byName(source, target, slide) {
|
|
155
|
+
const range = itemRange(target);
|
|
156
|
+
const items = range ? (slide.items ?? itemRange(source)?.drawn ?? range.drawn) : undefined;
|
|
157
|
+
if (range && items !== undefined && (items < range.min || items > range.max))
|
|
158
|
+
no();
|
|
159
|
+
const places = new Map(effectiveSlots(target, items).filter(fillable).map((slot) => [slot.name, slot]));
|
|
160
|
+
const draft = { slots: {}, changes: [], dropped: [] };
|
|
161
|
+
if (items !== undefined)
|
|
162
|
+
draft.items = items;
|
|
163
|
+
for (const slot of effectiveSlots(source, slide.items).filter(fillable)) {
|
|
164
|
+
const value = slide.slots[slot.name];
|
|
165
|
+
if (empty(value))
|
|
166
|
+
continue;
|
|
167
|
+
const place = places.get(slot.name);
|
|
168
|
+
const same = place && place.kind === slot.kind && (place.kind !== 'image' || slot.kind !== 'image' || place.imageKind === slot.imageKind);
|
|
169
|
+
if (same)
|
|
170
|
+
draft.slots[slot.name] = value;
|
|
171
|
+
else if (slot.kind === 'image' && illustrates(slot.imageKind))
|
|
172
|
+
draft.dropped.push(slot.name);
|
|
173
|
+
else
|
|
174
|
+
no();
|
|
175
|
+
}
|
|
176
|
+
return draft;
|
|
177
|
+
}
|
|
178
|
+
/** Puts the content into the target by what each slot is for. */
|
|
179
|
+
function byParts(content, target, shape) {
|
|
180
|
+
const draft = { slots: {}, changes: [], dropped: [] };
|
|
181
|
+
const put = (slot, text) => {
|
|
182
|
+
if (!text)
|
|
183
|
+
return;
|
|
184
|
+
if (!slot)
|
|
185
|
+
return no();
|
|
186
|
+
draft.slots[slot.name] = asValue(text);
|
|
187
|
+
};
|
|
188
|
+
put(shape.title, content.title);
|
|
189
|
+
put(shape.subtitle, content.subtitle);
|
|
190
|
+
put(shape.figure, content.figure);
|
|
191
|
+
for (const [name, { value, slot }] of content.others) {
|
|
192
|
+
if (!shape.others.some((candidate) => candidate.name === name && candidate.kind === slot.kind))
|
|
193
|
+
no();
|
|
194
|
+
draft.slots[name] = value;
|
|
195
|
+
}
|
|
196
|
+
if (content.picture) {
|
|
197
|
+
if (shape.picture && shape.picture.imageKind === content.picture.kind)
|
|
198
|
+
draft.slots[shape.picture.name] = content.picture.ref;
|
|
199
|
+
else if (illustrates(content.picture.kind))
|
|
200
|
+
draft.dropped.push(content.picture.from);
|
|
201
|
+
else
|
|
202
|
+
no();
|
|
203
|
+
}
|
|
204
|
+
const row = shape.row;
|
|
205
|
+
const range = itemRange(target);
|
|
206
|
+
const count = content.items.length;
|
|
207
|
+
const itemWord = target.repeat?.item ?? 'item';
|
|
208
|
+
const nameOf = (part, n) => (row?.parts.get(part)?.template ?? '').replace('{n}', String(n));
|
|
209
|
+
const oneLine = (item) => [item.heading, item.text, item.figure].every((part) => (part?.length ?? 0) <= 1);
|
|
210
|
+
if (count > 0 && row && range) {
|
|
211
|
+
// Items into items: cards into columns, a row into a grid.
|
|
212
|
+
if (!row.clear || count < range.min || count > range.max)
|
|
213
|
+
no();
|
|
214
|
+
put(shape.body, content.body);
|
|
215
|
+
draft.items = count;
|
|
216
|
+
// A row of single texts written "heading: text" can fill items that want the two apart.
|
|
217
|
+
const halves = row.parts.has('heading') && row.parts.has('text') ? content.items.map((item) => (!item.heading && !item.figure && item.text?.length === 1 ? split(item.text[0]) : undefined)) : [];
|
|
218
|
+
const apart = halves.length > 0 && halves.every((half) => half !== undefined);
|
|
219
|
+
let merged = false;
|
|
220
|
+
content.items.forEach((item, index) => {
|
|
221
|
+
const n = index + 1;
|
|
222
|
+
if (item.figure && item.heading)
|
|
223
|
+
no();
|
|
224
|
+
const leadPart = item.figure ? 'figure' : item.heading ? 'heading' : undefined;
|
|
225
|
+
const lead = item.figure ?? item.heading;
|
|
226
|
+
if (apart) {
|
|
227
|
+
const [heading, text] = halves[index];
|
|
228
|
+
draft.slots[nameOf('heading', n)] = heading;
|
|
229
|
+
draft.slots[nameOf('text', n)] = text;
|
|
230
|
+
}
|
|
231
|
+
else if (leadPart && row.parts.has(leadPart)) {
|
|
232
|
+
draft.slots[nameOf(leadPart, n)] = lead.join(' ');
|
|
233
|
+
if (item.text) {
|
|
234
|
+
if (!row.parts.has('text'))
|
|
235
|
+
no();
|
|
236
|
+
draft.slots[nameOf('text', n)] = asValue(item.text);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
else if (leadPart) {
|
|
240
|
+
// The target's items have one text: the heading leads it.
|
|
241
|
+
if (!row.parts.has('text') || row.parts.has('heading') || row.parts.has('figure') || !oneLine(item))
|
|
242
|
+
no();
|
|
243
|
+
draft.slots[nameOf('text', n)] = joined(lead, item.text);
|
|
244
|
+
merged = true;
|
|
245
|
+
}
|
|
246
|
+
else if (item.text) {
|
|
247
|
+
if (!row.parts.has('text'))
|
|
248
|
+
no();
|
|
249
|
+
draft.slots[nameOf('text', n)] = asValue(item.text);
|
|
250
|
+
}
|
|
251
|
+
for (const part of ['icon', 'picture']) {
|
|
252
|
+
const place = row.parts.get(part)?.slot;
|
|
253
|
+
const kind = content.itemPictures.find((picture) => picture.part === part)?.kind;
|
|
254
|
+
if (item[part] && place?.kind === 'image' && place.imageKind === kind)
|
|
255
|
+
draft.slots[nameOf(part, n)] = item[part];
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
for (const picture of content.itemPictures) {
|
|
259
|
+
const place = row.parts.get(picture.part)?.slot;
|
|
260
|
+
if (place?.kind === 'image' && place.imageKind === picture.kind)
|
|
261
|
+
continue;
|
|
262
|
+
if (!illustrates(picture.kind))
|
|
263
|
+
no();
|
|
264
|
+
draft.dropped.push(picture.from);
|
|
265
|
+
}
|
|
266
|
+
if (content.itemName !== itemWord)
|
|
267
|
+
draft.changes.push(`The ${plural(count, content.itemName)} became ${plural(count, itemWord)}.`);
|
|
268
|
+
if (merged)
|
|
269
|
+
draft.changes.push(`Each ${itemWord} is written as one text, "heading: text".`);
|
|
270
|
+
if (apart)
|
|
271
|
+
draft.changes.push(`Each ${itemWord} was split at the colon into a heading and a text.`);
|
|
272
|
+
}
|
|
273
|
+
else if (count > 0) {
|
|
274
|
+
// Items into a list: one point for each item.
|
|
275
|
+
const body = shape.body;
|
|
276
|
+
if (!body || content.body || !isList(body) || !content.items.every(oneLine))
|
|
277
|
+
return no();
|
|
278
|
+
if (content.itemPictures.some((picture) => !illustrates(picture.kind)))
|
|
279
|
+
no();
|
|
280
|
+
draft.slots[body.name] = content.items.map((item) => joined(item.figure ?? item.heading, item.text));
|
|
281
|
+
draft.dropped.push(...content.itemPictures.map((picture) => picture.from));
|
|
282
|
+
const lead = content.items.some((item) => item.figure) ? 'figure' : 'heading';
|
|
283
|
+
const written = content.items.some((item) => (item.figure ?? item.heading) && item.text) ? `, each written as "${lead}: text"` : '';
|
|
284
|
+
draft.changes.push(`The ${plural(count, content.itemName)} became a list of ${plural(count, 'point')}${written}.`);
|
|
285
|
+
}
|
|
286
|
+
else if (row && range) {
|
|
287
|
+
// A list into items: one item for each point.
|
|
288
|
+
const points = content.body;
|
|
289
|
+
if (!points || !row.clear || points.length < 2 || points.length < range.min || points.length > range.max || row.parts.has('figure') || !row.parts.has('text'))
|
|
290
|
+
return no();
|
|
291
|
+
draft.items = points.length;
|
|
292
|
+
if (row.parts.has('heading')) {
|
|
293
|
+
// The items want a heading and a text each: only a list written "heading: text" gives both.
|
|
294
|
+
const halves = points.map(split);
|
|
295
|
+
if (!halves.every((half) => half !== undefined))
|
|
296
|
+
no();
|
|
297
|
+
halves.forEach((half, index) => {
|
|
298
|
+
draft.slots[nameOf('heading', index + 1)] = half[0];
|
|
299
|
+
draft.slots[nameOf('text', index + 1)] = half[1];
|
|
300
|
+
});
|
|
301
|
+
draft.changes.push(`The ${plural(points.length, 'point')} became ${plural(points.length, itemWord)}, each split at the colon into a heading and a text.`);
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
points.forEach((point, index) => (draft.slots[nameOf('text', index + 1)] = point));
|
|
305
|
+
draft.changes.push(`The ${plural(points.length, 'point')} became ${plural(points.length, itemWord)}.`);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
put(shape.body, content.body);
|
|
310
|
+
// The words are the same; whether they show as points or as paragraphs is the new slot's own formatting.
|
|
311
|
+
const lines = content.body?.length ?? 0;
|
|
312
|
+
if (lines > 1 && content.bodyIsList !== isList(shape.body)) {
|
|
313
|
+
draft.changes.push(content.bodyIsList ? `The ${plural(lines, 'point')} of the list are written as ${plural(lines, 'paragraph')}.` : `The ${plural(lines, 'paragraph')} became a list of ${plural(lines, 'point')}.`);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return draft;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Lists the other patterns that can hold what one slide of a deck says, with the slide written
|
|
320
|
+
* for each. `slide` is the slide's number in the deck, from 1. No model is asked and no text is
|
|
321
|
+
* rewritten: a title stays a title, and a row of items becomes other items or a list of points.
|
|
322
|
+
*
|
|
323
|
+
* A pattern is an alternative when every text, table, chart and supplied graphic of the slide
|
|
324
|
+
* has a place in it and every slot it requires can be filled. A photo or an icon may be left
|
|
325
|
+
* out, which `dropped` reports. A text that is longer than its new slot holds is reported in
|
|
326
|
+
* `warnings`, as `validateDeck` would. Alternatives that fit without a warning come first.
|
|
327
|
+
*/
|
|
328
|
+
export function slideAlternatives(manifest, deck, slide, options = {}) {
|
|
329
|
+
const original = deck.slides[slide - 1];
|
|
330
|
+
if (!original)
|
|
331
|
+
throw new RangeError(`the deck has ${deck.slides.length} slides; there is no slide ${slide}`);
|
|
332
|
+
const source = manifest.patterns.find((pattern) => pattern.id === original.pattern);
|
|
333
|
+
if (!source)
|
|
334
|
+
throw new Error(`slide ${slide} uses the pattern "${original.pattern}", which the manifest does not have`);
|
|
335
|
+
const layout = options.layout ?? 'strict';
|
|
336
|
+
const filled = { ...original, slots: original.slots ?? {} };
|
|
337
|
+
const content = contentOf(source, anatomy(source), filled);
|
|
338
|
+
const found = [];
|
|
339
|
+
for (const target of manifest.patterns) {
|
|
340
|
+
if (target === source || (options.patterns && !options.patterns.includes(target.id)))
|
|
341
|
+
continue;
|
|
342
|
+
// Slot for slot where the names agree, which is exact; by what the slots are for where they do not.
|
|
343
|
+
for (const attempt of [() => byName(source, target, filled), () => byParts(content, target, anatomy(target))]) {
|
|
344
|
+
let draft;
|
|
345
|
+
try {
|
|
346
|
+
draft = attempt();
|
|
347
|
+
}
|
|
348
|
+
catch (error) {
|
|
349
|
+
if (!(error instanceof NoPlace))
|
|
350
|
+
throw error;
|
|
351
|
+
continue;
|
|
352
|
+
}
|
|
353
|
+
const written = { pattern: target.id, slots: draft.slots };
|
|
354
|
+
if (draft.items !== undefined)
|
|
355
|
+
written.items = draft.items;
|
|
356
|
+
// The renderer's own rules decide whether the slide can be made: a required slot left empty is an error.
|
|
357
|
+
const issues = validateDeck(manifest, { ...deck, slides: [written] }, { layout });
|
|
358
|
+
if (issues.some((issue) => issue.severity === 'error'))
|
|
359
|
+
continue;
|
|
360
|
+
found.push({ pattern: target.id, description: target.description, slide: written, changes: draft.changes, dropped: draft.dropped, warnings: issues.map((issue) => ({ ...issue, slide })) });
|
|
361
|
+
break;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
const rank = (alternative) => (alternative.warnings.length > 0 ? 2 : alternative.dropped.length > 0 ? 1 : 0);
|
|
365
|
+
return found
|
|
366
|
+
.map((alternative, index) => ({ alternative, index }))
|
|
367
|
+
.sort((a, b) => rank(a.alternative) - rank(b.alternative) || a.index - b.index)
|
|
368
|
+
.map((entry) => entry.alternative);
|
|
369
|
+
}
|
|
370
|
+
//# sourceMappingURL=alternatives.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alternatives.js","sourceRoot":"","sources":["../../src/deck/alternatives.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,iGAAiG;AACjG,4FAA4F;AAC5F,iEAAiE;AACjE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAErD,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAqE7C,MAAM,QAAQ,GAAG,CAAC,IAAa,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,KAAK,MAAM,IAAI,IAAI,CAAC,KAAK,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC;AAChI,MAAM,MAAM,GAAG,CAAC,IAAiB,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC;AACtE,oDAAoD;AACpD,MAAM,QAAQ,GAAG,CAAC,IAAiB,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,IAAI,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;AAChG,MAAM,OAAO,GAAG,CAAC,KAAoB,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjH,MAAM,MAAM,GAAG,CAAC,KAAa,EAAE,IAAY,EAAE,EAAE,CAAC,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;AAC5F,MAAM,KAAK,GAAG,CAAC,KAA4B,EAA6B,EAAE,CAAC,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AACvK,0GAA0G;AAC1G,MAAM,WAAW,GAAG,CAAC,IAAe,EAAE,EAAE,CAAC,IAAI,KAAK,SAAS,CAAC;AAC5D,MAAM,OAAO,GAAG,CAAC,IAAc,EAAa,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAE,IAAI,CAAC,CAAC,CAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AAChG,MAAM,MAAM,GAAG,CAAC,IAA6B,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,aAAa,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;AAEjF,SAAS,MAAM,CAAC,KAA4B;IAC1C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACzE,MAAM,UAAU,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,KAAK,EAAE,CAAC,CAAC;IAC/E,OAAO,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;AACxD,CAAC;AAED,SAAS,OAAO,CAAC,OAAmB;IAClC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAC9B,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC7I,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACpF,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,EAAuB,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;IAC9E,MAAM,IAAI,GAAG,CAAC,IAA6B,EAA2B,EAAE;QACtE,IAAI,IAAI;YAAE,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAC/C,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IACF,MAAM,KAAK,GAAY,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACtC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC/F,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpF,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC1C,4DAA4D;IAC5D,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IAClC,IAAI,KAAK;QAAE,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;IAC/B,IAAI,QAAQ;QAAE,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAC;IACxC,IAAI,MAAM;QAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;IAClC,IAAI,IAAI;QAAE,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;IAC5B,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,EAAwB,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,IAAI,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC;IAChH,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC;QAAE,KAAK,CAAC,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IACtE,KAAK,CAAC,MAAM,GAAG,CAAC,GAAG,KAAK,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;IAEnG,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,KAAK,GAAG,IAAI,GAAG,EAA6C,CAAC;QACnE,IAAI,KAAK,GAAG,IAAI,CAAC;QACjB,MAAM,SAAS,GAAmD,EAAE,CAAC;QACrE,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACpC,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;YAChG,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAAE,SAAS;YACvC,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;gBAAE,SAAS,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;iBACxD,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC/B,MAAM,IAAI,GAAgB,IAAI,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;gBACzE,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;oBAAE,KAAK,GAAG,KAAK,CAAC;gBACnC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;YACtC,CAAC;;gBAAM,KAAK,GAAG,KAAK,CAAC;QACvB,CAAC;QACD,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAClG,IAAI,MAAM;YAAE,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACxC,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC;QAC3H,2FAA2F;QAC3F,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;YAAE,KAAK,GAAG,KAAK,CAAC;QACnC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;YAAE,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAChE,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACzB,IAAI,IAAI;YAAE,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAClC,KAAK,CAAC,GAAG,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAC/B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,SAAS,CAAC,OAAmB,EAAE,KAAc,EAAE,KAAgB;IACtE,MAAM,OAAO,GAAY,EAAE,MAAM,EAAE,IAAI,GAAG,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,MAAM,EAAE,IAAI,IAAI,MAAM,EAAE,YAAY,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;IACtJ,MAAM,IAAI,GAAG,CAAC,IAA6B,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACpG,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAChC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC9B,IAAI,KAAK;QAAE,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC;IACjC,IAAI,QAAQ;QAAE,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC1C,IAAI,MAAM;QAAE,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;IACpC,IAAI,IAAI;QAAE,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAC9B,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,IAAI,KAAK,CAAC,OAAO,IAAI,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,CAAC,OAAO,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IACtI,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QAChC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;YAAE,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACpE,CAAC;IACD,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IACjC,IAAI,KAAK,CAAC,GAAG,IAAI,KAAK,EAAE,CAAC;QACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YACvD,MAAM,IAAI,GAAS,EAAE,CAAC;YACtB,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;gBACzD,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;gBAChD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAChC,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;oBAC1C,IAAI,UAAU,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;wBAC/C,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;wBACnB,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;oBACxE,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;oBAC3B,IAAI,IAAI;wBAAE,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;gBAC9B,CAAC;YACH,CAAC;YACD,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,OAAQ,SAAQ,KAAK;CAAG;AAC9B,MAAM,EAAE,GAAG,GAAU,EAAE;IACrB,MAAM,IAAI,OAAO,EAAE,CAAC;AACtB,CAAC,CAAC;AAEF,yDAAyD;AACzD,SAAS,MAAM,CAAC,IAA0B,EAAE,IAA0B;IACpE,MAAM,IAAI,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACpC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,IAAI,IAAI,CAAC;IACxC,OAAO,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,IAAI,EAAE,CAAC;AACxE,CAAC;AAED,2FAA2F;AAC3F,SAAS,KAAK,CAAC,IAAY;IACzB,MAAM,KAAK,GAAG,wCAAwC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClE,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAW,EAAE,KAAK,CAAC,CAAC,CAAW,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACtE,CAAC;AASD,8FAA8F;AAC9F,SAAS,MAAM,CAAC,MAAkB,EAAE,MAAkB,EAAE,KAAgB;IACtE,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IAChC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,IAAI,SAAS,CAAC,MAAM,CAAC,EAAE,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3F,IAAI,KAAK,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,IAAI,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC;QAAE,EAAE,EAAE,CAAC;IACnF,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;IACxG,MAAM,KAAK,GAAU,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAC7D,IAAI,KAAK,KAAK,SAAS;QAAE,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;IAC7C,KAAK,MAAM,IAAI,IAAI,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxE,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,KAAK,CAAC,KAAK,CAAC;YAAE,SAAS;QAC3B,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,IAAI,GAAG,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC;QAC1I,IAAI,IAAI;YAAE,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;aACpC,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC;YAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;;YACxF,EAAE,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,iEAAiE;AACjE,SAAS,OAAO,CAAC,OAAgB,EAAE,MAAkB,EAAE,KAAc;IACnE,MAAM,KAAK,GAAU,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAC7D,MAAM,GAAG,GAAG,CAAC,IAA6B,EAAE,IAA0B,EAAQ,EAAE;QAC9E,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,IAAI,CAAC,IAAI;YAAE,OAAO,EAAE,EAAE,CAAC;QACvB,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,CAAC,CAAC;IACF,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAChC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IACtC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAClC,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACrD,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,IAAI,IAAI,SAAS,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC;YAAE,EAAE,EAAE,CAAC;QACrG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;IAC5B,CAAC;IACD,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACpB,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,KAAK,OAAO,CAAC,OAAO,CAAC,IAAI;YAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC;aACxH,IAAI,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;YAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;;YAChF,EAAE,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;IACtB,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IAChC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC;IACnC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,IAAI,IAAI,MAAM,CAAC;IAC/C,MAAM,MAAM,GAAG,CAAC,IAAU,EAAE,CAAS,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,QAAQ,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3G,MAAM,OAAO,GAAG,CAAC,IAAU,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAEjH,IAAI,KAAK,GAAG,CAAC,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;QAC9B,2DAA2D;QAC3D,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,KAAK,GAAG,KAAK,CAAC,GAAG,IAAI,KAAK,GAAG,KAAK,CAAC,GAAG;YAAE,EAAE,EAAE,CAAC;QAC/D,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAC9B,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;QACpB,wFAAwF;QACxF,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,IAAI,EAAE,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAW,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5M,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;QAC9E,IAAI,MAAM,GAAG,KAAK,CAAC;QACnB,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;YACpC,MAAM,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;YACpB,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,OAAO;gBAAE,EAAE,EAAE,CAAC;YACtC,MAAM,QAAQ,GAAyB,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;YACrG,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC;YACzC,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,CAAqB,CAAC;gBAC1D,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;gBAC5C,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;YACxC,CAAC;iBAAM,IAAI,QAAQ,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC/C,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,GAAI,IAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAChE,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;oBACd,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC;wBAAE,EAAE,EAAE,CAAC;oBACjC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACtD,CAAC;YACH,CAAC;iBAAM,IAAI,QAAQ,EAAE,CAAC;gBACpB,0DAA0D;gBAC1D,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;oBAAE,EAAE,EAAE,CAAC;gBAC1G,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;gBACzD,MAAM,GAAG,IAAI,CAAC;YAChB,CAAC;iBAAM,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACrB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC;oBAAE,EAAE,EAAE,CAAC;gBACjC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtD,CAAC;YACD,KAAK,MAAM,IAAI,IAAI,CAAC,MAAM,EAAE,SAAS,CAAU,EAAE,CAAC;gBAChD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC;gBACxC,MAAM,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,IAAI,CAAC;gBACjF,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,EAAE,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,SAAS,KAAK,IAAI;oBAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAa,CAAC;YAC/H,CAAC;QACH,CAAC,CAAC,CAAC;QACH,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;YAC3C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC;YAChD,IAAI,KAAK,EAAE,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,SAAS,KAAK,OAAO,CAAC,IAAI;gBAAE,SAAS;YAC1E,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC;gBAAE,EAAE,EAAE,CAAC;YACrC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACnC,CAAC;QACD,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ;YAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,WAAW,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC;QACnI,IAAI,MAAM;YAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,QAAQ,2CAA2C,CAAC,CAAC;QAC5F,IAAI,KAAK;YAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,QAAQ,oDAAoD,CAAC,CAAC;IACtG,CAAC;SAAM,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACrB,8CAA8C;QAC9C,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QACxB,IAAI,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC;YAAE,OAAO,EAAE,EAAE,CAAC;QACzF,IAAI,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAAE,EAAE,EAAE,CAAC;QAC7E,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACrG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAC3E,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;QAC9E,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,sBAAsB,IAAI,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;QACpI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,qBAAqB,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,OAAO,GAAG,CAAC,CAAC;IACrH,CAAC;SAAM,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,8CAA8C;QAC9C,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;QAC5B,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC,GAAG,IAAI,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,OAAO,EAAE,EAAE,CAAC;QAC3K,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7B,4FAA4F;YAC5F,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACjC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,SAAS,CAAC;gBAAE,EAAE,EAAE,CAAC;YACtD,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;gBAC7B,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,GAAI,IAAyB,CAAC,CAAC,CAAC,CAAC;gBAC1E,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,GAAI,IAAyB,CAAC,CAAC,CAAC,CAAC;YACzE,CAAC,CAAC,CAAC;YACH,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,sDAAsD,CAAC,CAAC;QAC5J,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;YACnF,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC;QACzG,CAAC;IACH,CAAC;SAAM,CAAC;QACN,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAC9B,yGAAyG;QACzG,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC,CAAC;QACxC,IAAI,KAAK,GAAG,CAAC,IAAI,OAAO,CAAC,UAAU,KAAK,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3D,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,+BAA+B,MAAM,CAAC,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,MAAM,CAAC,KAAK,EAAE,WAAW,CAAC,qBAAqB,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;QACvN,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAA0B,EAAE,IAAc,EAAE,KAAa,EAAE,OAAO,GAAwB,EAAE;IAC5H,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IACxC,IAAI,CAAC,QAAQ;QAAE,MAAM,IAAI,UAAU,CAAC,gBAAgB,IAAI,CAAC,MAAM,CAAC,MAAM,8BAA8B,KAAK,EAAE,CAAC,CAAC;IAC7G,MAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,KAAK,QAAQ,CAAC,OAAO,CAAC,CAAC;IACpF,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,SAAS,KAAK,sBAAsB,QAAQ,CAAC,OAAO,qCAAqC,CAAC,CAAC;IACxH,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,QAAQ,CAAC;IAC1C,MAAM,MAAM,GAAc,EAAE,GAAG,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;IACvE,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;IAE3D,MAAM,KAAK,GAAuB,EAAE,CAAC;IACrC,KAAK,MAAM,MAAM,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;QACvC,IAAI,MAAM,KAAK,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAAE,SAAS;QAC/F,oGAAoG;QACpG,KAAK,MAAM,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9G,IAAI,KAAY,CAAC;YACjB,IAAI,CAAC;gBACH,KAAK,GAAG,OAAO,EAAE,CAAC;YACpB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,CAAC,KAAK,YAAY,OAAO,CAAC;oBAAE,MAAM,KAAK,CAAC;gBAC7C,SAAS;YACX,CAAC;YACD,MAAM,OAAO,GAAc,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;YACtE,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;gBAAE,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;YAC3D,yGAAyG;YACzG,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,EAAE,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;YAClF,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,KAAK,OAAO,CAAC;gBAAE,SAAS;YACjE,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;YAC5L,MAAM;QACR,CAAC;IACH,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,WAA6B,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/H,OAAO,KAAK;SACT,GAAG,CAAC,CAAC,WAAW,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC;SACrD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;SAC9E,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;AACvC,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Template } from '../render/render.ts';
|
|
2
|
+
import type { DeckSpec } from './spec.ts';
|
|
3
|
+
import type { Issue, LayoutMode } from './validate.ts';
|
|
4
|
+
/**
|
|
5
|
+
* - `overflow`: the text runs over its box.
|
|
6
|
+
* - `empty`: the text takes far less room than the template's own text does, so its box looks empty.
|
|
7
|
+
* - `uneven`: one item of a row of cards holds far less text than another.
|
|
8
|
+
* - `orphan`: a heading ends with a single word on a line of its own.
|
|
9
|
+
*/
|
|
10
|
+
export type DesignKind = 'overflow' | 'empty' | 'uneven' | 'orphan';
|
|
11
|
+
/** A design problem on one slot of one slide. Its message is written so that it can be sent to the model that wrote the text. */
|
|
12
|
+
export interface DesignIssue extends Issue {
|
|
13
|
+
severity: 'warning';
|
|
14
|
+
slide: number;
|
|
15
|
+
slot: string;
|
|
16
|
+
kind: DesignKind;
|
|
17
|
+
}
|
|
18
|
+
export interface DesignOptions {
|
|
19
|
+
/** As for `renderDeck`. Defaults to `strict`. */
|
|
20
|
+
layout?: LayoutMode;
|
|
21
|
+
/** Which problems to look for. Defaults to all of them. */
|
|
22
|
+
kinds?: DesignKind[];
|
|
23
|
+
/**
|
|
24
|
+
* A text leaves its box empty when it takes this share, or less, of the lines the template's own
|
|
25
|
+
* text takes there; a card is uneven when it takes this share or less of its fullest neighbour.
|
|
26
|
+
* Defaults to a third.
|
|
27
|
+
*/
|
|
28
|
+
emptyBelow?: number;
|
|
29
|
+
/** The font size in points from which a single paragraph counts as a heading. Defaults to 20. */
|
|
30
|
+
headingSize?: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Lists the design problems of a deck that follow from measurement alone: text that runs over its
|
|
34
|
+
* box, boxes and cards left mostly empty, and headings that end in a lone word. The template must
|
|
35
|
+
* be loaded with fonts. No picture is made and no model is called.
|
|
36
|
+
*
|
|
37
|
+
* A slot that cannot be measured (its typeface was not supplied) is passed over, as is a slide
|
|
38
|
+
* that cannot be rendered: `validateDeck` reports those.
|
|
39
|
+
*/
|
|
40
|
+
export declare function checkDesign(template: Template, deck: DeckSpec, options?: DesignOptions): DesignIssue[];
|