tutuca 0.9.21 → 0.9.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/tutuca-cli.js +291 -283
- package/dist/tutuca-dev.js +649 -569
- package/dist/tutuca-dev.min.js +2 -2
- package/dist/tutuca-extra.js +4 -0
- package/dist/tutuca-extra.min.js +1 -1
- package/dist/tutuca.js +4 -0
- package/dist/tutuca.min.js +1 -1
- package/package.json +1 -1
package/dist/tutuca-cli.js
CHANGED
|
@@ -67,13 +67,10 @@ MODULE CONVENTION
|
|
|
67
67
|
-> Component[] // results of tutuca's component()
|
|
68
68
|
|
|
69
69
|
export function getExamples() // required for render/doctor
|
|
70
|
-
->
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
items: Example[] // at least one of items/groups
|
|
75
|
-
}
|
|
76
|
-
where Example = { title, description?, value, view? }
|
|
70
|
+
-> Section | Section[] // single section or an array
|
|
71
|
+
where Section = { title: string, description?: string,
|
|
72
|
+
items: Example[] }
|
|
73
|
+
and Example = { title, description?, value, view? }
|
|
77
74
|
and value = an instance returned by <Component>.make(...)
|
|
78
75
|
and view = a view name (defaults to "main")
|
|
79
76
|
|
|
@@ -85,21 +82,20 @@ MODULE CONVENTION
|
|
|
85
82
|
|
|
86
83
|
export function getRoot() // optional; returned by info
|
|
87
84
|
|
|
88
|
-
The legacy
|
|
89
|
-
|
|
85
|
+
The legacy \`getStoryBookSection()\` name fails fast with
|
|
86
|
+
EXAMPLES_SHAPE_MISMATCH — rename it to \`getExamples\`.
|
|
90
87
|
|
|
91
88
|
COMMANDS (require <module-path>)
|
|
92
89
|
info
|
|
93
90
|
Summarize which getX() exports are present and count components,
|
|
94
|
-
macros, request handlers, examples, and
|
|
91
|
+
macros, request handlers, examples, and sections. Good first step.
|
|
95
92
|
|
|
96
93
|
list
|
|
97
94
|
List each component with its declared views and fields (name, type).
|
|
98
95
|
|
|
99
96
|
examples
|
|
100
|
-
Print the module's example
|
|
101
|
-
|
|
102
|
-
and view.
|
|
97
|
+
Print the module's example sections: title, description, items.
|
|
98
|
+
Each item shows its resolved component name and view.
|
|
103
99
|
|
|
104
100
|
docs [name]
|
|
105
101
|
Generate API docs (methods, input handlers, fields with their
|
|
@@ -219,8 +215,8 @@ class ComponentList {
|
|
|
219
215
|
}
|
|
220
216
|
|
|
221
217
|
class ExampleIndex {
|
|
222
|
-
constructor({
|
|
223
|
-
this.
|
|
218
|
+
constructor({ sections }) {
|
|
219
|
+
this.sections = sections;
|
|
224
220
|
}
|
|
225
221
|
}
|
|
226
222
|
|
|
@@ -231,10 +227,11 @@ class ComponentDocs {
|
|
|
231
227
|
}
|
|
232
228
|
|
|
233
229
|
class LintFinding {
|
|
234
|
-
constructor({ id, level, info }) {
|
|
230
|
+
constructor({ id, level, info, context = {} }) {
|
|
235
231
|
this.id = id;
|
|
236
232
|
this.level = level;
|
|
237
233
|
this.info = info;
|
|
234
|
+
this.context = context;
|
|
238
235
|
}
|
|
239
236
|
}
|
|
240
237
|
|
|
@@ -268,7 +265,6 @@ class LintReport {
|
|
|
268
265
|
|
|
269
266
|
class RenderedExample {
|
|
270
267
|
constructor({
|
|
271
|
-
groupTitle = null,
|
|
272
268
|
title,
|
|
273
269
|
description = null,
|
|
274
270
|
componentName,
|
|
@@ -276,7 +272,6 @@ class RenderedExample {
|
|
|
276
272
|
html,
|
|
277
273
|
error = null
|
|
278
274
|
}) {
|
|
279
|
-
this.groupTitle = groupTitle;
|
|
280
275
|
this.title = title;
|
|
281
276
|
this.description = description;
|
|
282
277
|
this.componentName = componentName;
|
|
@@ -286,13 +281,20 @@ class RenderedExample {
|
|
|
286
281
|
}
|
|
287
282
|
}
|
|
288
283
|
|
|
289
|
-
class
|
|
290
|
-
constructor({
|
|
291
|
-
this.
|
|
284
|
+
class RenderedSection {
|
|
285
|
+
constructor({ title, description = null, items }) {
|
|
286
|
+
this.title = title;
|
|
287
|
+
this.description = description;
|
|
292
288
|
this.items = items;
|
|
293
289
|
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
class RenderBatch {
|
|
293
|
+
constructor({ sections }) {
|
|
294
|
+
this.sections = sections;
|
|
295
|
+
}
|
|
294
296
|
get hasErrors() {
|
|
295
|
-
return this.items.some((i) => i.error !== null);
|
|
297
|
+
return this.sections.some((s) => s.items.some((i) => i.error !== null));
|
|
296
298
|
}
|
|
297
299
|
}
|
|
298
300
|
|
|
@@ -326,59 +328,41 @@ function resolveComponentName(value, components) {
|
|
|
326
328
|
return null;
|
|
327
329
|
}
|
|
328
330
|
|
|
329
|
-
class ExampleGroup {
|
|
330
|
-
constructor({ title, description = null, items }) {
|
|
331
|
-
this.title = title;
|
|
332
|
-
this.description = description;
|
|
333
|
-
this.items = items;
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
|
|
337
331
|
class ExampleSection {
|
|
338
|
-
constructor({ title, description = null,
|
|
332
|
+
constructor({ title, description = null, items = [] }) {
|
|
339
333
|
this.title = title;
|
|
340
334
|
this.description = description;
|
|
341
|
-
this.groups = groups;
|
|
342
335
|
this.items = items;
|
|
343
336
|
}
|
|
344
|
-
*flatten() {
|
|
345
|
-
for (const item of this.items) {
|
|
346
|
-
yield { groupTitle: null, example: item };
|
|
347
|
-
}
|
|
348
|
-
for (const group of this.groups) {
|
|
349
|
-
for (const item of group.items) {
|
|
350
|
-
yield { groupTitle: group.title, example: item };
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
337
|
}
|
|
355
338
|
|
|
356
339
|
class NormalizedModule {
|
|
357
|
-
constructor({ mod, path = null, components, macros, requestHandlers,
|
|
340
|
+
constructor({ mod, path = null, components, macros, requestHandlers, sections, root }) {
|
|
358
341
|
this.mod = mod;
|
|
359
342
|
this.path = path;
|
|
360
343
|
this.components = components;
|
|
361
344
|
this.macros = macros;
|
|
362
345
|
this.requestHandlers = requestHandlers;
|
|
363
|
-
this.
|
|
346
|
+
this.sections = sections;
|
|
364
347
|
this.root = root;
|
|
365
348
|
}
|
|
366
349
|
}
|
|
367
|
-
function
|
|
350
|
+
function shapeError(message, where) {
|
|
351
|
+
const err = new Error(`${EXAMPLES_SHAPE_MISMATCH}: ${message}`);
|
|
352
|
+
err.code = EXAMPLES_SHAPE_MISMATCH;
|
|
353
|
+
err.where = where;
|
|
354
|
+
return err;
|
|
355
|
+
}
|
|
356
|
+
function parseExample(raw, index, components, parentPath) {
|
|
357
|
+
const where = `${parentPath}.items[${index}]`;
|
|
368
358
|
if (!raw || typeof raw !== "object") {
|
|
369
|
-
|
|
370
|
-
err.code = EXAMPLES_SHAPE_MISMATCH;
|
|
371
|
-
throw err;
|
|
359
|
+
throw shapeError(`example at ${where} is not an object`, where);
|
|
372
360
|
}
|
|
373
361
|
if (raw.value === undefined && raw.item !== undefined) {
|
|
374
|
-
|
|
375
|
-
err.code = EXAMPLES_SHAPE_MISMATCH;
|
|
376
|
-
throw err;
|
|
362
|
+
throw shapeError(`example at ${where} uses legacy "item" key; rename to "value"`, where);
|
|
377
363
|
}
|
|
378
364
|
if (raw.value === undefined) {
|
|
379
|
-
|
|
380
|
-
err.code = EXAMPLES_SHAPE_MISMATCH;
|
|
381
|
-
throw err;
|
|
365
|
+
throw shapeError(`example at ${where} missing "value"`, where);
|
|
382
366
|
}
|
|
383
367
|
return new Example({
|
|
384
368
|
title: raw.title ?? `Example ${index + 1}`,
|
|
@@ -388,42 +372,29 @@ function parseExample(raw, index, components) {
|
|
|
388
372
|
componentName: resolveComponentName(raw.value, components)
|
|
389
373
|
});
|
|
390
374
|
}
|
|
391
|
-
function
|
|
392
|
-
if (!raw || typeof raw !== "object" ||
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
375
|
+
function parseSection(raw, components, where) {
|
|
376
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
377
|
+
throw shapeError(`section at ${where} must be an object { title, description?, items }`, where);
|
|
378
|
+
}
|
|
379
|
+
const items = Array.isArray(raw.items) ? raw.items.map((e, i) => parseExample(e, i, components, where)) : [];
|
|
380
|
+
if (items.length === 0) {
|
|
381
|
+
throw shapeError(`section at ${where} has no items`, where);
|
|
396
382
|
}
|
|
397
|
-
return new
|
|
398
|
-
title: raw.title ??
|
|
383
|
+
return new ExampleSection({
|
|
384
|
+
title: raw.title ?? "Examples",
|
|
399
385
|
description: raw.description ?? null,
|
|
400
|
-
items
|
|
386
|
+
items
|
|
401
387
|
});
|
|
402
388
|
}
|
|
403
|
-
function
|
|
389
|
+
function parseSections(raw, components) {
|
|
390
|
+
const where = "examples";
|
|
404
391
|
if (Array.isArray(raw)) {
|
|
405
|
-
|
|
406
|
-
err.code = EXAMPLES_SHAPE_MISMATCH;
|
|
407
|
-
throw err;
|
|
392
|
+
return raw.map((r, i) => parseSection(r, components, `${where}[${i}]`));
|
|
408
393
|
}
|
|
409
394
|
if (!raw || typeof raw !== "object") {
|
|
410
|
-
|
|
411
|
-
err.code = EXAMPLES_SHAPE_MISMATCH;
|
|
412
|
-
throw err;
|
|
413
|
-
}
|
|
414
|
-
const items = Array.isArray(raw.items) ? raw.items.map((e, i) => parseExample(e, i, components)) : [];
|
|
415
|
-
const groups = Array.isArray(raw.groups) ? raw.groups.map((g, i) => parseGroup(g, i, components)) : [];
|
|
416
|
-
if (items.length === 0 && groups.length === 0) {
|
|
417
|
-
const err = new Error(`${EXAMPLES_SHAPE_MISMATCH}: getExamples() returned a section with no items or groups`);
|
|
418
|
-
err.code = EXAMPLES_SHAPE_MISMATCH;
|
|
419
|
-
throw err;
|
|
395
|
+
throw shapeError("getExamples() must return a section object or an array of section objects", where);
|
|
420
396
|
}
|
|
421
|
-
return
|
|
422
|
-
title: raw.title ?? "Examples",
|
|
423
|
-
description: raw.description ?? null,
|
|
424
|
-
groups,
|
|
425
|
-
items
|
|
426
|
-
});
|
|
397
|
+
return [parseSection(raw, components, where)];
|
|
427
398
|
}
|
|
428
399
|
function normalizeModule(mod, { path = null } = {}) {
|
|
429
400
|
const present = new Set;
|
|
@@ -439,15 +410,13 @@ function normalizeModule(mod, { path = null } = {}) {
|
|
|
439
410
|
present.add(key);
|
|
440
411
|
}
|
|
441
412
|
if (present.has("getStoryBookSection") && !present.has("getExamples")) {
|
|
442
|
-
|
|
443
|
-
err.code = EXAMPLES_SHAPE_MISMATCH;
|
|
444
|
-
throw err;
|
|
413
|
+
throw shapeError("module exports getStoryBookSection; rename it to getExamples.", "module");
|
|
445
414
|
}
|
|
446
415
|
const components = present.has("getComponents") ? mod.getComponents() : [];
|
|
447
416
|
const macros = present.has("getMacros") ? mod.getMacros() : null;
|
|
448
417
|
const requestHandlers = present.has("getRequestHandlers") ? mod.getRequestHandlers() : null;
|
|
449
418
|
const root = present.has("getRoot") ? mod.getRoot() : null;
|
|
450
|
-
const
|
|
419
|
+
const sections = present.has("getExamples") ? parseSections(mod.getExamples(), components) : [];
|
|
451
420
|
return {
|
|
452
421
|
normalized: new NormalizedModule({
|
|
453
422
|
mod,
|
|
@@ -455,7 +424,7 @@ function normalizeModule(mod, { path = null } = {}) {
|
|
|
455
424
|
components,
|
|
456
425
|
macros,
|
|
457
426
|
requestHandlers,
|
|
458
|
-
|
|
427
|
+
sections,
|
|
459
428
|
root
|
|
460
429
|
}),
|
|
461
430
|
present
|
|
@@ -469,14 +438,17 @@ function describeModule(mod, { path = null } = {}) {
|
|
|
469
438
|
components: normalized.components.length,
|
|
470
439
|
macros: normalized.macros ? Object.keys(normalized.macros).length : 0,
|
|
471
440
|
requestHandlers: normalized.requestHandlers ? Object.keys(normalized.requestHandlers).length : 0,
|
|
472
|
-
examples: normalized.
|
|
473
|
-
|
|
441
|
+
examples: normalized.sections.reduce((n, s) => n + s.items.length, 0),
|
|
442
|
+
sections: normalized.sections.length
|
|
474
443
|
};
|
|
475
444
|
const warnings = [];
|
|
476
445
|
if (!normalized.components.length)
|
|
477
446
|
warnings.push("module exports no components");
|
|
478
|
-
if (!
|
|
447
|
+
if (!present.has("getExamples")) {
|
|
479
448
|
warnings.push("module exports no getExamples()");
|
|
449
|
+
} else if (normalized.sections.length === 0) {
|
|
450
|
+
warnings.push("getExamples() returned no sections");
|
|
451
|
+
}
|
|
480
452
|
return new ModuleInfo({ path, present, counts, warnings });
|
|
481
453
|
}
|
|
482
454
|
|
|
@@ -517,7 +489,7 @@ function fmtModuleInfo(info) {
|
|
|
517
489
|
lines.push(`Components: ${info.counts.components}`);
|
|
518
490
|
lines.push(`Macros: ${info.counts.macros}`);
|
|
519
491
|
lines.push(`Request handlers: ${info.counts.requestHandlers}`);
|
|
520
|
-
lines.push(`Examples: ${info.counts.examples} (
|
|
492
|
+
lines.push(`Examples: ${info.counts.examples} (sections: ${info.counts.sections})`);
|
|
521
493
|
if (info.warnings.length) {
|
|
522
494
|
lines.push("");
|
|
523
495
|
lines.push("Warnings:");
|
|
@@ -541,18 +513,13 @@ function fmtComponentList(list) {
|
|
|
541
513
|
`);
|
|
542
514
|
}
|
|
543
515
|
function fmtExampleIndex(idx) {
|
|
544
|
-
if (
|
|
516
|
+
if (idx.sections.length === 0)
|
|
545
517
|
return "(no examples)";
|
|
546
518
|
const lines = [];
|
|
547
|
-
const s
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
}
|
|
552
|
-
for (const group of s.groups) {
|
|
553
|
-
lines.push(` [${group.title}]${group.description ? ` — ${group.description}` : ""}`);
|
|
554
|
-
for (const item of group.items) {
|
|
555
|
-
lines.push(` - ${item.title}${item.description ? ` — ${item.description}` : ""} [${item.componentName}${item.view !== "main" ? `/${item.view}` : ""}]`);
|
|
519
|
+
for (const s of idx.sections) {
|
|
520
|
+
lines.push(`${s.title}${s.description ? ` — ${s.description}` : ""}`);
|
|
521
|
+
for (const item of s.items) {
|
|
522
|
+
lines.push(` - ${item.title}${item.description ? ` — ${item.description}` : ""} [${item.componentName}${item.view !== "main" ? `/${item.view}` : ""}]`);
|
|
556
523
|
}
|
|
557
524
|
}
|
|
558
525
|
return lines.join(`
|
|
@@ -604,8 +571,9 @@ function fmtLintReport(rep) {
|
|
|
604
571
|
lines.push(`${c.componentName}:`);
|
|
605
572
|
for (const f of c.findings) {
|
|
606
573
|
const tag = f.level.toUpperCase();
|
|
574
|
+
const view = f.context?.viewName ? ` view=${f.context.viewName}` : "";
|
|
607
575
|
const extra = fmtFindingInfo(f.info);
|
|
608
|
-
lines.push(` [${tag}] ${f.id}${extra ? ` (${extra})` : ""}`);
|
|
576
|
+
lines.push(` [${tag}] ${f.id}${view}${extra ? ` (${extra})` : ""}`);
|
|
609
577
|
}
|
|
610
578
|
}
|
|
611
579
|
lines.push("");
|
|
@@ -614,21 +582,16 @@ function fmtLintReport(rep) {
|
|
|
614
582
|
`);
|
|
615
583
|
}
|
|
616
584
|
function fmtRenderBatch(batch) {
|
|
617
|
-
|
|
585
|
+
const totalItems = batch.sections.reduce((n, s) => n + s.items.length, 0);
|
|
586
|
+
if (totalItems === 0)
|
|
618
587
|
return "(no examples rendered)";
|
|
619
588
|
const lines = [];
|
|
620
|
-
|
|
621
|
-
lines.push(`${
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
if (item.groupTitle !== currentGroup) {
|
|
626
|
-
currentGroup = item.groupTitle;
|
|
627
|
-
if (currentGroup)
|
|
628
|
-
lines.push(` [${currentGroup}]`);
|
|
589
|
+
for (const section of batch.sections) {
|
|
590
|
+
lines.push(`${section.title}${section.description ? ` — ${section.description}` : ""}`);
|
|
591
|
+
for (const item of section.items) {
|
|
592
|
+
const status = item.error ? `ERROR: ${item.error.message}` : `${item.html.length} bytes`;
|
|
593
|
+
lines.push(` ${item.title} [${item.componentName}] — ${status}`);
|
|
629
594
|
}
|
|
630
|
-
const status = item.error ? `ERROR: ${item.error.message}` : `${item.html.length} bytes`;
|
|
631
|
-
lines.push(` ${item.title} [${item.componentName}] — ${status}`);
|
|
632
595
|
}
|
|
633
596
|
return lines.join(`
|
|
634
597
|
`);
|
|
@@ -711,67 +674,53 @@ function fmtComponentDocs2(docs) {
|
|
|
711
674
|
async function fmtRenderBatch2(batch, { pretty = false } = {}) {
|
|
712
675
|
const prettify = pretty ? (await import("prettier")).format : null;
|
|
713
676
|
const lines = [];
|
|
714
|
-
|
|
715
|
-
lines.push(`# ${
|
|
716
|
-
if (
|
|
677
|
+
for (const section of batch.sections) {
|
|
678
|
+
lines.push(`# ${section.title}`);
|
|
679
|
+
if (section.description)
|
|
717
680
|
lines.push(`
|
|
718
|
-
${
|
|
681
|
+
${section.description}`);
|
|
719
682
|
lines.push("");
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
for (const item of batch.items) {
|
|
723
|
-
if (item.groupTitle !== currentGroup) {
|
|
724
|
-
currentGroup = item.groupTitle;
|
|
725
|
-
if (currentGroup)
|
|
726
|
-
lines.push(`## ${currentGroup}
|
|
727
|
-
`);
|
|
728
|
-
}
|
|
729
|
-
const depth = currentGroup ? "###" : "##";
|
|
730
|
-
lines.push(`${depth} ${item.title}
|
|
683
|
+
for (const item of section.items) {
|
|
684
|
+
lines.push(`## ${item.title}
|
|
731
685
|
`);
|
|
732
|
-
|
|
733
|
-
|
|
686
|
+
if (item.description)
|
|
687
|
+
lines.push(`${item.description}
|
|
734
688
|
`);
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
689
|
+
if (item.error) {
|
|
690
|
+
lines.push("```");
|
|
691
|
+
lines.push(`ERROR: ${item.error.message}`);
|
|
692
|
+
lines.push("```\n");
|
|
693
|
+
continue;
|
|
694
|
+
}
|
|
695
|
+
let html = item.html;
|
|
696
|
+
if (prettify) {
|
|
697
|
+
try {
|
|
698
|
+
html = (await prettify(html, { parser: "html" })).trimEnd();
|
|
699
|
+
} catch {}
|
|
700
|
+
}
|
|
701
|
+
lines.push("```html");
|
|
702
|
+
lines.push(html);
|
|
738
703
|
lines.push("```\n");
|
|
739
|
-
continue;
|
|
740
|
-
}
|
|
741
|
-
let html = item.html;
|
|
742
|
-
if (prettify) {
|
|
743
|
-
try {
|
|
744
|
-
html = (await prettify(html, { parser: "html" })).trimEnd();
|
|
745
|
-
} catch {}
|
|
746
704
|
}
|
|
747
|
-
lines.push("```html");
|
|
748
|
-
lines.push(html);
|
|
749
|
-
lines.push("```\n");
|
|
750
705
|
}
|
|
751
706
|
return lines.join(`
|
|
752
707
|
`);
|
|
753
708
|
}
|
|
754
709
|
function fmtExampleIndex2(idx) {
|
|
755
|
-
if (
|
|
710
|
+
if (idx.sections.length === 0)
|
|
756
711
|
return "_(no examples)_";
|
|
757
|
-
const
|
|
758
|
-
const
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
712
|
+
const lines = [];
|
|
713
|
+
for (const s of idx.sections) {
|
|
714
|
+
lines.push(`# ${s.title}`);
|
|
715
|
+
if (s.description)
|
|
716
|
+
lines.push("", s.description);
|
|
717
|
+
if (s.items.length) {
|
|
718
|
+
lines.push("");
|
|
719
|
+
for (const item of s.items) {
|
|
720
|
+
lines.push(`- **${item.title}** — \`${item.componentName}\`${item.description ? ` — ${item.description}` : ""}`);
|
|
721
|
+
}
|
|
765
722
|
}
|
|
766
|
-
}
|
|
767
|
-
for (const group of s.groups) {
|
|
768
|
-
lines.push("", `## ${group.title}`);
|
|
769
|
-
if (group.description)
|
|
770
|
-
lines.push("", group.description);
|
|
771
723
|
lines.push("");
|
|
772
|
-
for (const item of group.items) {
|
|
773
|
-
lines.push(`- **${item.title}** — \`${item.componentName}\`${item.description ? ` — ${item.description}` : ""}`);
|
|
774
|
-
}
|
|
775
724
|
}
|
|
776
725
|
return lines.join(`
|
|
777
726
|
`);
|
|
@@ -785,7 +734,8 @@ function fmtLintReport2(rep) {
|
|
|
785
734
|
continue;
|
|
786
735
|
}
|
|
787
736
|
for (const f of c.findings) {
|
|
788
|
-
|
|
737
|
+
const view = f.context?.viewName ? ` — view: \`${f.context.viewName}\`` : "";
|
|
738
|
+
lines.push(`- **${f.level.toUpperCase()}** \`${f.id}\`${view}`);
|
|
789
739
|
}
|
|
790
740
|
lines.push("");
|
|
791
741
|
}
|
|
@@ -799,7 +749,7 @@ function fmtModuleInfo2(info) {
|
|
|
799
749
|
lines.push(`- Components: ${info.counts.components}`);
|
|
800
750
|
lines.push(`- Macros: ${info.counts.macros}`);
|
|
801
751
|
lines.push(`- Request handlers: ${info.counts.requestHandlers}`);
|
|
802
|
-
lines.push(`- Examples: ${info.counts.examples} (
|
|
752
|
+
lines.push(`- Examples: ${info.counts.examples} (sections: ${info.counts.sections})`);
|
|
803
753
|
if (info.warnings.length) {
|
|
804
754
|
lines.push("", "## Warnings", "");
|
|
805
755
|
for (const w of info.warnings)
|
|
@@ -875,19 +825,22 @@ var supports4 = new Set(["RenderBatch"]);
|
|
|
875
825
|
async function format4(result, { pretty = false } = {}) {
|
|
876
826
|
const prettify = pretty ? (await import("prettier")).format : null;
|
|
877
827
|
const parts = [];
|
|
878
|
-
for (const
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
828
|
+
for (const section of result.sections) {
|
|
829
|
+
parts.push(`<!-- === ${section.title} === -->`);
|
|
830
|
+
for (const item of section.items) {
|
|
831
|
+
if (item.error) {
|
|
832
|
+
parts.push(`<!-- ERROR ${item.title}: ${item.error.message} -->`);
|
|
833
|
+
continue;
|
|
834
|
+
}
|
|
835
|
+
let html = item.html;
|
|
836
|
+
if (prettify) {
|
|
837
|
+
try {
|
|
838
|
+
html = (await prettify(html, { parser: "html" })).trimEnd();
|
|
839
|
+
} catch {}
|
|
840
|
+
}
|
|
841
|
+
parts.push(`<!-- ${item.title} -->`);
|
|
842
|
+
parts.push(html);
|
|
888
843
|
}
|
|
889
|
-
parts.push(`<!-- ${item.title} -->`);
|
|
890
|
-
parts.push(html);
|
|
891
844
|
}
|
|
892
845
|
return parts.join(`
|
|
893
846
|
`);
|
|
@@ -1000,10 +953,7 @@ __export(exports_examples, {
|
|
|
1000
953
|
|
|
1001
954
|
// tools/core/list-examples.js
|
|
1002
955
|
function listExamples(normalized) {
|
|
1003
|
-
|
|
1004
|
-
return new ExampleIndex({ section: null });
|
|
1005
|
-
}
|
|
1006
|
-
return new ExampleIndex({ section: normalized.section });
|
|
956
|
+
return new ExampleIndex({ sections: normalized.sections });
|
|
1007
957
|
}
|
|
1008
958
|
|
|
1009
959
|
// tools/cli/commands/examples.js
|
|
@@ -2895,18 +2845,20 @@ var LEVEL_WARN = "warn";
|
|
|
2895
2845
|
var LEVEL_ERROR = "error";
|
|
2896
2846
|
var LEVEL_HINT = "hint";
|
|
2897
2847
|
function checkComponent(Comp, lx = new LintContext) {
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2848
|
+
return lx.push({ componentName: Comp.name }, () => {
|
|
2849
|
+
const referencedAlters = new Set;
|
|
2850
|
+
const referencedInputs = new Set;
|
|
2851
|
+
const referencedComputed = new Set;
|
|
2852
|
+
checkEventHandlersHaveImpls(lx, Comp, referencedInputs);
|
|
2853
|
+
checkConsistentAttrs(lx, Comp, referencedAlters, referencedComputed);
|
|
2854
|
+
for (const name in Comp.views) {
|
|
2855
|
+
lx.push({ viewName: name }, () => checkView(lx, Comp.views[name], Comp, referencedAlters, referencedComputed));
|
|
2856
|
+
}
|
|
2857
|
+
checkUnreferencedAlterHandlers(lx, Comp, referencedAlters);
|
|
2858
|
+
checkUnreferencedInputHandlers(lx, Comp, referencedInputs);
|
|
2859
|
+
checkUnreferencedComputed(lx, Comp, referencedComputed);
|
|
2860
|
+
return lx;
|
|
2861
|
+
});
|
|
2910
2862
|
}
|
|
2911
2863
|
function checkView(lx, view, Comp, referencedAlters, referencedComputed) {
|
|
2912
2864
|
checkRenderItInLoop(lx, view);
|
|
@@ -2914,17 +2866,45 @@ function checkView(lx, view, Comp, referencedAlters, referencedComputed) {
|
|
|
2914
2866
|
checkKnownHandlerNames(lx, view, Comp, referencedAlters, referencedComputed);
|
|
2915
2867
|
}
|
|
2916
2868
|
function checkRenderItInLoop(lx, view) {
|
|
2917
|
-
|
|
2918
|
-
for (
|
|
2919
|
-
const node = nodes[i];
|
|
2869
|
+
let hasRenderIt = false;
|
|
2870
|
+
for (const node of view.ctx.nodes) {
|
|
2920
2871
|
if (node.constructor.name === "RenderItNode") {
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
if (nextName !== "EachNode" && nextName !== "RenderEachNode") {
|
|
2924
|
-
lx.error(RENDER_IT_OUTSIDE_OF_LOOP, { node });
|
|
2925
|
-
}
|
|
2872
|
+
hasRenderIt = true;
|
|
2873
|
+
break;
|
|
2926
2874
|
}
|
|
2927
2875
|
}
|
|
2876
|
+
if (!hasRenderIt)
|
|
2877
|
+
return;
|
|
2878
|
+
walkForRenderIt(lx, view.anode, 0);
|
|
2879
|
+
}
|
|
2880
|
+
function walkForRenderIt(lx, node, loopDepth) {
|
|
2881
|
+
if (node === null || node === undefined)
|
|
2882
|
+
return;
|
|
2883
|
+
switch (node.constructor.name) {
|
|
2884
|
+
case "RenderItNode":
|
|
2885
|
+
if (loopDepth === 0)
|
|
2886
|
+
lx.error(RENDER_IT_OUTSIDE_OF_LOOP, { node });
|
|
2887
|
+
return;
|
|
2888
|
+
case "EachNode":
|
|
2889
|
+
walkForRenderIt(lx, node.node, loopDepth + 1);
|
|
2890
|
+
return;
|
|
2891
|
+
case "ShowNode":
|
|
2892
|
+
case "HideNode":
|
|
2893
|
+
case "ScopeNode":
|
|
2894
|
+
case "SlotNode":
|
|
2895
|
+
case "PushViewNameNode":
|
|
2896
|
+
case "MacroNode":
|
|
2897
|
+
case "RenderOnceNode":
|
|
2898
|
+
walkForRenderIt(lx, node.node, loopDepth);
|
|
2899
|
+
return;
|
|
2900
|
+
case "DomNode":
|
|
2901
|
+
case "FragmentNode":
|
|
2902
|
+
for (const child of node.childs)
|
|
2903
|
+
walkForRenderIt(lx, child, loopDepth);
|
|
2904
|
+
return;
|
|
2905
|
+
default:
|
|
2906
|
+
return;
|
|
2907
|
+
}
|
|
2928
2908
|
}
|
|
2929
2909
|
var NO_WRAPPERS = {};
|
|
2930
2910
|
function checkEventModifiers(lx, view) {
|
|
@@ -2981,46 +2961,48 @@ function checkEventHandlersHaveImpls(lx, Comp, referencedInputs) {
|
|
|
2981
2961
|
const { input, views, Class } = Comp;
|
|
2982
2962
|
const { prototype: proto } = Class;
|
|
2983
2963
|
for (const viewName in views) {
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
for (const
|
|
2987
|
-
const
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
handler,
|
|
2995
|
-
event
|
|
2996
|
-
});
|
|
2997
|
-
if (proto[handlerVal.name] !== undefined) {
|
|
2998
|
-
lx.hint(INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER, {
|
|
2964
|
+
lx.push({ viewName }, () => {
|
|
2965
|
+
const view = views[viewName];
|
|
2966
|
+
for (const event of view.ctx.events) {
|
|
2967
|
+
for (const handler of event.handlers) {
|
|
2968
|
+
const { handlerVal } = handler.handlerCall;
|
|
2969
|
+
const hvName = handlerVal?.constructor.name;
|
|
2970
|
+
if (hvName === "InputHandlerNameVal") {
|
|
2971
|
+
referencedInputs?.add(handlerVal.name);
|
|
2972
|
+
if (input[handlerVal.name] === undefined) {
|
|
2973
|
+
lx.warn(INPUT_HANDLER_NOT_IMPLEMENTED, {
|
|
2999
2974
|
name: handlerVal.name,
|
|
3000
2975
|
handler,
|
|
3001
2976
|
event
|
|
3002
2977
|
});
|
|
2978
|
+
if (proto[handlerVal.name] !== undefined) {
|
|
2979
|
+
lx.hint(INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER, {
|
|
2980
|
+
name: handlerVal.name,
|
|
2981
|
+
handler,
|
|
2982
|
+
event
|
|
2983
|
+
});
|
|
2984
|
+
}
|
|
3003
2985
|
}
|
|
3004
|
-
}
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
lx.warn(INPUT_HANDLER_METHOD_NOT_IMPLEMENTED, {
|
|
3009
|
-
name: handlerVal.name,
|
|
3010
|
-
handler,
|
|
3011
|
-
event
|
|
3012
|
-
});
|
|
3013
|
-
if (input[handlerVal.name] !== undefined) {
|
|
3014
|
-
lx.hint(INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD, {
|
|
2986
|
+
} else if (hvName === "RawFieldVal") {
|
|
2987
|
+
referencedInputs?.add(handlerVal.name);
|
|
2988
|
+
if (proto[handlerVal.name] === undefined) {
|
|
2989
|
+
lx.warn(INPUT_HANDLER_METHOD_NOT_IMPLEMENTED, {
|
|
3015
2990
|
name: handlerVal.name,
|
|
3016
2991
|
handler,
|
|
3017
2992
|
event
|
|
3018
2993
|
});
|
|
2994
|
+
if (input[handlerVal.name] !== undefined) {
|
|
2995
|
+
lx.hint(INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD, {
|
|
2996
|
+
name: handlerVal.name,
|
|
2997
|
+
handler,
|
|
2998
|
+
event
|
|
2999
|
+
});
|
|
3000
|
+
}
|
|
3019
3001
|
}
|
|
3020
3002
|
}
|
|
3021
3003
|
}
|
|
3022
3004
|
}
|
|
3023
|
-
}
|
|
3005
|
+
});
|
|
3024
3006
|
}
|
|
3025
3007
|
}
|
|
3026
3008
|
function checkConsistentAttrVal(lx, val, fields, proto, computed, scope, alter, referencedAlters, referencedComputed) {
|
|
@@ -3069,39 +3051,41 @@ function checkConsistentAttrs(lx, Comp, referencedAlters, referencedComputed) {
|
|
|
3069
3051
|
const { prototype: proto } = Class;
|
|
3070
3052
|
const { fields } = Class.getMetaClass();
|
|
3071
3053
|
for (const viewName in views) {
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
const
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3054
|
+
lx.push({ viewName }, () => {
|
|
3055
|
+
const view = views[viewName];
|
|
3056
|
+
for (const attr of view.ctx.attrs) {
|
|
3057
|
+
const { attrs, wrapperAttrs, textChild } = attr;
|
|
3058
|
+
if (attrs?.constructor.name === "DynAttrs") {
|
|
3059
|
+
for (const attr2 of attrs.items) {
|
|
3060
|
+
if (attr2?.constructor.name === "Attr") {
|
|
3061
|
+
checkConsistentAttrVal(lx, attr2.val, fields, proto, computed, scope, alter, referencedAlters, referencedComputed);
|
|
3062
|
+
}
|
|
3079
3063
|
}
|
|
3080
3064
|
}
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3065
|
+
if (wrapperAttrs !== null) {
|
|
3066
|
+
for (const w of wrapperAttrs) {
|
|
3067
|
+
if (w.name === "each") {
|
|
3068
|
+
if (w.whenVal)
|
|
3069
|
+
checkConsistentAttrVal(lx, w.whenVal, fields, proto, computed, scope, alter, referencedAlters, referencedComputed);
|
|
3070
|
+
if (w.enrichWithVal)
|
|
3071
|
+
checkConsistentAttrVal(lx, w.enrichWithVal, fields, proto, computed, scope, alter, referencedAlters, referencedComputed);
|
|
3072
|
+
if (w.loopWithVal)
|
|
3073
|
+
checkConsistentAttrVal(lx, w.loopWithVal, fields, proto, computed, scope, alter, referencedAlters, referencedComputed);
|
|
3074
|
+
} else if (w.name !== "scope") {
|
|
3075
|
+
checkConsistentAttrVal(lx, w.val, fields, proto, computed, scope, alter, referencedAlters, referencedComputed);
|
|
3076
|
+
}
|
|
3093
3077
|
}
|
|
3094
3078
|
}
|
|
3079
|
+
if (textChild) {
|
|
3080
|
+
checkConsistentAttrVal(lx, textChild, fields, proto, computed, scope, alter, referencedAlters, referencedComputed);
|
|
3081
|
+
}
|
|
3095
3082
|
}
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
for (const node of view.ctx.nodes) {
|
|
3101
|
-
if (node.val) {
|
|
3102
|
-
checkConsistentAttrVal(lx, node.val, fields, proto, computed, scope, alter, referencedAlters, referencedComputed);
|
|
3083
|
+
for (const node of view.ctx.nodes) {
|
|
3084
|
+
if (node.val) {
|
|
3085
|
+
checkConsistentAttrVal(lx, node.val, fields, proto, computed, scope, alter, referencedAlters, referencedComputed);
|
|
3086
|
+
}
|
|
3103
3087
|
}
|
|
3104
|
-
}
|
|
3088
|
+
});
|
|
3105
3089
|
}
|
|
3106
3090
|
}
|
|
3107
3091
|
function checkUnreferencedAlterHandlers(lx, Comp, referencedAlters) {
|
|
@@ -3129,6 +3113,16 @@ function checkUnreferencedComputed(lx, Comp, referencedComputed) {
|
|
|
3129
3113
|
class LintContext {
|
|
3130
3114
|
constructor() {
|
|
3131
3115
|
this.reports = [];
|
|
3116
|
+
this.frame = {};
|
|
3117
|
+
}
|
|
3118
|
+
push(patch, fn) {
|
|
3119
|
+
const prev = this.frame;
|
|
3120
|
+
this.frame = { ...prev, ...patch };
|
|
3121
|
+
try {
|
|
3122
|
+
return fn();
|
|
3123
|
+
} finally {
|
|
3124
|
+
this.frame = prev;
|
|
3125
|
+
}
|
|
3132
3126
|
}
|
|
3133
3127
|
error(id, info) {
|
|
3134
3128
|
this.report(id, info, LEVEL_ERROR);
|
|
@@ -3140,7 +3134,7 @@ class LintContext {
|
|
|
3140
3134
|
this.report(id, info, LEVEL_HINT);
|
|
3141
3135
|
}
|
|
3142
3136
|
report(id, info = {}, level = LEVEL_ERROR) {
|
|
3143
|
-
this.reports.push({ id, info, level });
|
|
3137
|
+
this.reports.push({ id, info, level, context: { ...this.frame } });
|
|
3144
3138
|
}
|
|
3145
3139
|
}
|
|
3146
3140
|
|
|
@@ -8810,36 +8804,39 @@ function renderToHTML(document2, components, macros, rootState, ParseContext2) {
|
|
|
8810
8804
|
|
|
8811
8805
|
// tools/core/render.js
|
|
8812
8806
|
function renderExamples(normalized, env, { name = null, title = null, view = null } = {}) {
|
|
8813
|
-
const
|
|
8814
|
-
|
|
8815
|
-
|
|
8816
|
-
|
|
8817
|
-
|
|
8818
|
-
|
|
8819
|
-
|
|
8820
|
-
|
|
8821
|
-
|
|
8822
|
-
|
|
8823
|
-
|
|
8824
|
-
|
|
8825
|
-
|
|
8826
|
-
|
|
8827
|
-
|
|
8828
|
-
|
|
8829
|
-
|
|
8830
|
-
|
|
8831
|
-
|
|
8832
|
-
|
|
8833
|
-
|
|
8834
|
-
|
|
8835
|
-
|
|
8836
|
-
|
|
8837
|
-
|
|
8838
|
-
|
|
8839
|
-
|
|
8807
|
+
const sections = [];
|
|
8808
|
+
for (const section of normalized.sections) {
|
|
8809
|
+
const items = [];
|
|
8810
|
+
for (const example of section.items) {
|
|
8811
|
+
const componentName = example.componentName;
|
|
8812
|
+
if (name !== null && componentName !== name)
|
|
8813
|
+
continue;
|
|
8814
|
+
if (title !== null && example.title !== title)
|
|
8815
|
+
continue;
|
|
8816
|
+
const viewName = view ?? example.view ?? "main";
|
|
8817
|
+
let html = "";
|
|
8818
|
+
let error = null;
|
|
8819
|
+
try {
|
|
8820
|
+
html = renderToHTML(env.document, normalized.components, normalized.macros, example.value, env.ParseContext);
|
|
8821
|
+
} catch (e) {
|
|
8822
|
+
error = { message: e.message, stack: e.stack };
|
|
8823
|
+
}
|
|
8824
|
+
items.push(new RenderedExample({
|
|
8825
|
+
title: example.title,
|
|
8826
|
+
description: example.description,
|
|
8827
|
+
componentName,
|
|
8828
|
+
view: viewName,
|
|
8829
|
+
html,
|
|
8830
|
+
error
|
|
8831
|
+
}));
|
|
8832
|
+
}
|
|
8833
|
+
sections.push(new RenderedSection({
|
|
8834
|
+
title: section.title,
|
|
8835
|
+
description: section.description,
|
|
8836
|
+
items
|
|
8840
8837
|
}));
|
|
8841
8838
|
}
|
|
8842
|
-
return new RenderBatch({
|
|
8839
|
+
return new RenderBatch({ sections });
|
|
8843
8840
|
}
|
|
8844
8841
|
|
|
8845
8842
|
// tools/cli/commands/render.js
|
|
@@ -8965,7 +8962,18 @@ async function main() {
|
|
|
8965
8962
|
try {
|
|
8966
8963
|
await cmd.run(commandArgs, opts);
|
|
8967
8964
|
} catch (e) {
|
|
8968
|
-
if (e?.code === "EXAMPLES_SHAPE_MISMATCH"
|
|
8965
|
+
if (e?.code === "EXAMPLES_SHAPE_MISMATCH") {
|
|
8966
|
+
const parts = [];
|
|
8967
|
+
if (opts.module)
|
|
8968
|
+
parts.push(opts.module);
|
|
8969
|
+
if (e.where)
|
|
8970
|
+
parts.push(`@ ${e.where}`);
|
|
8971
|
+
const prefix = parts.length ? `[${parts.join(" ")}] ` : "";
|
|
8972
|
+
process.stderr.write(`tutuca: ${prefix}${e.message}
|
|
8973
|
+
`);
|
|
8974
|
+
process.exit(1);
|
|
8975
|
+
}
|
|
8976
|
+
if (e?.code?.startsWith?.("ERR_PARSE_ARGS_")) {
|
|
8969
8977
|
process.stderr.write(`tutuca: ${e.message}
|
|
8970
8978
|
`);
|
|
8971
8979
|
process.exit(1);
|