@12ui/design 0.2.75 → 0.2.76

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.
Files changed (126) hide show
  1. package/README.md +126 -116
  2. package/SKILL.md +33 -28
  3. package/dist/cli-arguments.d.ts.map +1 -1
  4. package/dist/cli-arguments.js +21 -7
  5. package/dist/cli-arguments.js.map +1 -1
  6. package/dist/cli-capabilities.d.ts +3 -2
  7. package/dist/cli-capabilities.d.ts.map +1 -1
  8. package/dist/cli-capabilities.js +2 -1
  9. package/dist/cli-capabilities.js.map +1 -1
  10. package/dist/cli-help/design.d.ts +1 -1
  11. package/dist/cli-help/design.js +1 -1
  12. package/dist/cli-help/design.js.map +1 -1
  13. package/dist/cli-help/index.d.ts +18 -8
  14. package/dist/cli-help/index.d.ts.map +1 -1
  15. package/dist/cli-help/scene.d.ts +15 -5
  16. package/dist/cli-help/scene.d.ts.map +1 -1
  17. package/dist/cli-help/scene.js +44 -0
  18. package/dist/cli-help/scene.js.map +1 -1
  19. package/dist/cli-help/workflow.d.ts +2 -2
  20. package/dist/cli-help/workflow.d.ts.map +1 -1
  21. package/dist/cli-help/workflow.js +4 -3
  22. package/dist/cli-help/workflow.js.map +1 -1
  23. package/dist/cli-scene-command.d.ts.map +1 -1
  24. package/dist/cli-scene-command.js +39 -6
  25. package/dist/cli-scene-command.js.map +1 -1
  26. package/dist/cli-usage.d.ts.map +1 -1
  27. package/dist/cli-usage.js +8 -6
  28. package/dist/cli-usage.js.map +1 -1
  29. package/dist/legacy-skill-catalog.d.ts.map +1 -1
  30. package/dist/legacy-skill-catalog.js +26 -2
  31. package/dist/legacy-skill-catalog.js.map +1 -1
  32. package/dist/mcp-slate-command.d.ts +9 -0
  33. package/dist/mcp-slate-command.d.ts.map +1 -1
  34. package/dist/mcp-slate-command.js +19 -5
  35. package/dist/mcp-slate-command.js.map +1 -1
  36. package/dist/mcp-workflow-tools.js +3 -3
  37. package/dist/mcp-workflow-tools.js.map +1 -1
  38. package/dist/scene/camera-diagnostics.d.ts +61 -0
  39. package/dist/scene/camera-diagnostics.d.ts.map +1 -0
  40. package/dist/scene/camera-diagnostics.js +166 -0
  41. package/dist/scene/camera-diagnostics.js.map +1 -0
  42. package/dist/scene/camera-solve.d.ts +2 -0
  43. package/dist/scene/camera-solve.d.ts.map +1 -1
  44. package/dist/scene/camera-solve.js +59 -42
  45. package/dist/scene/camera-solve.js.map +1 -1
  46. package/dist/scene/capture.d.ts +24 -0
  47. package/dist/scene/capture.d.ts.map +1 -1
  48. package/dist/scene/capture.js +53 -2
  49. package/dist/scene/capture.js.map +1 -1
  50. package/dist/scene/convert-run.d.ts +30 -0
  51. package/dist/scene/convert-run.d.ts.map +1 -0
  52. package/dist/scene/convert-run.js +135 -0
  53. package/dist/scene/convert-run.js.map +1 -0
  54. package/dist/scene/media-query.d.ts +21 -0
  55. package/dist/scene/media-query.d.ts.map +1 -0
  56. package/dist/scene/media-query.js +208 -0
  57. package/dist/scene/media-query.js.map +1 -0
  58. package/dist/scene/page-css.d.ts +38 -0
  59. package/dist/scene/page-css.d.ts.map +1 -0
  60. package/dist/scene/page-css.js +210 -0
  61. package/dist/scene/page-css.js.map +1 -0
  62. package/dist/scene/page-images.d.ts +33 -0
  63. package/dist/scene/page-images.d.ts.map +1 -0
  64. package/dist/scene/page-images.js +53 -0
  65. package/dist/scene/page-images.js.map +1 -0
  66. package/dist/scene/page-merge.d.ts +41 -0
  67. package/dist/scene/page-merge.d.ts.map +1 -0
  68. package/dist/scene/page-merge.js +197 -0
  69. package/dist/scene/page-merge.js.map +1 -0
  70. package/dist/scene/responsive-bands.d.ts +19 -0
  71. package/dist/scene/responsive-bands.d.ts.map +1 -0
  72. package/dist/scene/responsive-bands.js +25 -0
  73. package/dist/scene/responsive-bands.js.map +1 -0
  74. package/dist/scene/scene-index.d.ts +10 -0
  75. package/dist/scene/scene-index.d.ts.map +1 -0
  76. package/dist/scene/scene-index.js +43 -0
  77. package/dist/scene/scene-index.js.map +1 -0
  78. package/dist/scene/scene-merge.d.ts +29 -0
  79. package/dist/scene/scene-merge.d.ts.map +1 -0
  80. package/dist/scene/scene-merge.js +130 -0
  81. package/dist/scene/scene-merge.js.map +1 -0
  82. package/dist/scene/scene-verbs.d.ts +1 -1
  83. package/dist/scene/scene-verbs.d.ts.map +1 -1
  84. package/dist/scene/scene-verbs.js +1 -1
  85. package/dist/scene/scene-verbs.js.map +1 -1
  86. package/dist/scene/serve-detach.d.ts +23 -0
  87. package/dist/scene/serve-detach.d.ts.map +1 -0
  88. package/dist/scene/serve-detach.js +92 -0
  89. package/dist/scene/serve-detach.js.map +1 -0
  90. package/dist/scene/static-server.d.ts +2 -0
  91. package/dist/scene/static-server.d.ts.map +1 -1
  92. package/dist/scene/static-server.js +3 -0
  93. package/dist/scene/static-server.js.map +1 -1
  94. package/dist/scene/symmetric-eigen.d.ts +12 -0
  95. package/dist/scene/symmetric-eigen.d.ts.map +1 -0
  96. package/dist/scene/symmetric-eigen.js +43 -0
  97. package/dist/scene/symmetric-eigen.js.map +1 -0
  98. package/dist/workflow/adapter-12ui.d.ts.map +1 -1
  99. package/dist/workflow/adapter-12ui.js +3 -5
  100. package/dist/workflow/adapter-12ui.js.map +1 -1
  101. package/dist/workflow/providers.d.ts.map +1 -1
  102. package/dist/workflow/providers.js +5 -2
  103. package/dist/workflow/providers.js.map +1 -1
  104. package/dist/workflow/recipes.d.ts +1 -2
  105. package/dist/workflow/recipes.d.ts.map +1 -1
  106. package/dist/workflow/recipes.js +6 -18
  107. package/dist/workflow/recipes.js.map +1 -1
  108. package/dist/workflow/routing.d.ts.map +1 -1
  109. package/dist/workflow/routing.js +3 -1
  110. package/dist/workflow/routing.js.map +1 -1
  111. package/dist/workflow/types.d.ts +7 -0
  112. package/dist/workflow/types.d.ts.map +1 -1
  113. package/dist/workflow/types.js +7 -0
  114. package/dist/workflow/types.js.map +1 -1
  115. package/dist/workspace-draw-messages.d.ts.map +1 -1
  116. package/dist/workspace-draw-messages.js +1 -2
  117. package/dist/workspace-draw-messages.js.map +1 -1
  118. package/open-design.json +2 -2
  119. package/package.json +2 -2
  120. package/skills/12ui-design/SKILL.md +79 -19
  121. package/skills/12ui-design/agents/openai.yaml +2 -0
  122. package/skills/12ui-design/improve.md +1 -5
  123. package/skills/12ui-design/inspire.md +5 -8
  124. package/skills/12ui-design/outputs.md +2 -23
  125. package/skills/12ui-design/scene.md +27 -156
  126. package/skills/12ui-design/session.md +0 -161
@@ -0,0 +1,197 @@
1
+ import { parseHTML } from 'linkedom';
2
+ import { mediaQueryMatchesFrame } from './media-query.js';
3
+ import { SceneArgumentError } from './numbers.js';
4
+ import { emptyMediaDecisions, resolveMediaAtFrame, viewportUnitsToPx } from './page-css.js';
5
+ import { classifyRef, cssImageRefs, cssImageRefsInRules, dropCssImages, isImageRef, srcsetUrls, } from './page-images.js';
6
+ import { bandsShownAtFrame } from './responsive-bands.js';
7
+ const GOOGLE_FONTS_STYLESHEET = /^https:\/\/fonts\.googleapis\.com\//iu;
8
+ const REMOTE_URL = /^(?:[a-z][a-z0-9+.-]*:)?\/\//iu;
9
+ /** Attributes that load a resource, per element; `srcset` lists several. */
10
+ const RESOURCE_ATTRIBUTES = [
11
+ ['img[src]', 'src'], ['img[srcset]', 'srcset'], ['source[src]', 'src'], ['source[srcset]', 'srcset'],
12
+ ['video[poster]', 'poster'], ['input[src]', 'src'], ['image[href]', 'href'], ['use[href]', 'href'],
13
+ ];
14
+ const isStylesheetLink = (element) => (element.tagName.toLowerCase() === 'link'
15
+ && (element.getAttribute('rel') ?? '').toLowerCase().split(/\s+/u).includes('stylesheet'));
16
+ const describe = (element) => {
17
+ const tag = element.tagName.toLowerCase();
18
+ const id = element.getAttribute('id');
19
+ const className = (element.getAttribute('class') ?? '').trim().split(/\s+/u)[0];
20
+ const alt = element.getAttribute('alt')?.trim();
21
+ const name = id ? `<${tag}#${id}>` : className ? `<${tag}.${className}>` : `<${tag}>`;
22
+ return alt ? `${name} "${alt.length > 48 ? `${alt.slice(0, 47)}…` : alt}"` : name;
23
+ };
24
+ const elementRefs = (element, attribute) => {
25
+ const value = element.getAttribute(attribute) ?? '';
26
+ const values = attribute === 'srcset' ? srcsetUrls(value) : [value];
27
+ return values.map(classifyRef).filter((ref) => ref !== undefined);
28
+ };
29
+ /** Decides a `media` attribute at the frame: false removes the element, true drops the attribute. */
30
+ const decideMediaAttribute = (element, frame, media) => {
31
+ const query = element.getAttribute('media');
32
+ if (query === null)
33
+ return;
34
+ const label = `<${element.tagName.toLowerCase()} media="${query}">`;
35
+ const applies = mediaQueryMatchesFrame(query, frame);
36
+ if (applies === true) {
37
+ media.applied.push(label);
38
+ element.removeAttribute('media');
39
+ }
40
+ else if (applies === false) {
41
+ media.removed.push(label);
42
+ element.remove();
43
+ }
44
+ else {
45
+ media.undecided.push(label);
46
+ }
47
+ };
48
+ export const mergePage = (input) => {
49
+ const { document } = parseHTML(input.html);
50
+ const all = (selector) => Array.from(document.querySelectorAll(selector));
51
+ const media = emptyMediaDecisions();
52
+ for (const element of all('style[media], link[media], picture > source[media]')) {
53
+ decideMediaAttribute(element, input.frame, media);
54
+ }
55
+ for (const style of all('style')) {
56
+ style.textContent = viewportUnitsToPx(resolveMediaAtFrame(style.textContent ?? '', input.frame, media), input.frame);
57
+ }
58
+ for (const element of all('[style]')) {
59
+ element.setAttribute('style', viewportUnitsToPx(element.getAttribute('style') ?? '', input.frame));
60
+ }
61
+ let bands;
62
+ if (input.engine === 'api') {
63
+ const decision = bandsShownAtFrame(all('style').map((style) => style.textContent ?? ''));
64
+ if (decision) {
65
+ const removed = [];
66
+ for (const band of all('.ly-band[data-ly-band]')) {
67
+ const name = band.getAttribute('data-ly-band') ?? '';
68
+ if (decision.removable(name)) {
69
+ removed.push(name);
70
+ band.remove();
71
+ }
72
+ }
73
+ bands = { shown: decision.shown, removed };
74
+ }
75
+ }
76
+ const removedScripts = [];
77
+ for (const script of all('body script[src]')) {
78
+ const source = script.getAttribute('src') ?? '';
79
+ if (REMOTE_URL.test(source.trim())) {
80
+ removedScripts.push(source);
81
+ script.remove();
82
+ }
83
+ }
84
+ const collectImages = () => {
85
+ const images = new Map();
86
+ const note = (ref, usedBy) => {
87
+ if (!isImageRef(ref))
88
+ return;
89
+ const entry = images.get(ref.ref) ?? {
90
+ ref: ref.ref, kind: ref.kind, value: ref.value, usedBy: [],
91
+ ...(input.boxes.has(ref.ref) ? { box: input.boxes.get(ref.ref) } : {}),
92
+ };
93
+ if (!entry.usedBy.includes(usedBy))
94
+ entry.usedBy.push(usedBy);
95
+ images.set(ref.ref, entry);
96
+ };
97
+ for (const [selector, attribute] of RESOURCE_ATTRIBUTES) {
98
+ for (const element of all(selector))
99
+ for (const ref of elementRefs(element, attribute))
100
+ note(ref, describe(element));
101
+ }
102
+ for (const style of all('style')) {
103
+ for (const ref of cssImageRefsInRules(style.textContent ?? ''))
104
+ note(ref, ref.rule ? `css ${ref.rule}` : 'css');
105
+ }
106
+ for (const element of all('[style]')) {
107
+ for (const ref of cssImageRefs(element.getAttribute('style') ?? ''))
108
+ note(ref, `style of ${describe(element)}`);
109
+ }
110
+ return [...images.values()];
111
+ };
112
+ const before = collectImages();
113
+ const known = new Set(before.map((image) => image.ref));
114
+ const unknown = input.drop.filter((ref) => !known.has(ref));
115
+ if (unknown.length) {
116
+ throw new SceneArgumentError(`--drop names ${unknown.join(', ')}, which ${unknown.length === 1 ? 'is' : 'are'} not`
117
+ + ` an image of this page. Its images are: ${before.map((image) => image.ref).join(', ') || 'none'}.`);
118
+ }
119
+ const dropped = new Set(input.drop);
120
+ if (dropped.size) {
121
+ for (const [selector, attribute] of RESOURCE_ATTRIBUTES) {
122
+ for (const element of all(selector)) {
123
+ if (elementRefs(element, attribute).some((ref) => dropped.has(ref.ref)))
124
+ element.remove();
125
+ }
126
+ }
127
+ for (const style of all('style'))
128
+ style.textContent = dropCssImages(style.textContent ?? '', dropped);
129
+ for (const element of all('[style]'))
130
+ element.setAttribute('style', dropCssImages(element.getAttribute('style') ?? '', dropped));
131
+ }
132
+ const images = collectImages();
133
+ const fonts = [];
134
+ const remote = new Set();
135
+ const files = new Set();
136
+ const headParts = [];
137
+ const notCarried = [];
138
+ for (const element of Array.from(document.head.children)) {
139
+ const tag = element.tagName.toLowerCase();
140
+ if (tag === 'style' || isStylesheetLink(element)) {
141
+ headParts.push(element.outerHTML);
142
+ continue;
143
+ }
144
+ if (tag === 'meta' || tag === 'title')
145
+ continue;
146
+ if (tag === 'link' && /preconnect|dns-prefetch/iu.test(element.getAttribute('rel') ?? ''))
147
+ continue;
148
+ notCarried.push(element.outerHTML.length > 120 ? `${element.outerHTML.slice(0, 119)}…` : element.outerHTML);
149
+ }
150
+ for (const link of all('link[href]').filter(isStylesheetLink)) {
151
+ const ref = classifyRef(link.getAttribute('href') ?? '');
152
+ if (ref?.kind === 'file')
153
+ files.add(ref.ref);
154
+ else if (ref?.kind === 'remote')
155
+ (GOOGLE_FONTS_STYLESHEET.test(ref.value) ? fonts.push(ref.value) : remote.add(ref.value));
156
+ }
157
+ for (const script of all('body script[src]')) {
158
+ const ref = classifyRef(script.getAttribute('src') ?? '');
159
+ if (ref?.kind === 'file')
160
+ files.add(ref.ref);
161
+ }
162
+ for (const [selector, attribute] of RESOURCE_ATTRIBUTES) {
163
+ for (const element of all(selector)) {
164
+ for (const ref of elementRefs(element, attribute)) {
165
+ if (ref.kind === 'file')
166
+ files.add(ref.ref);
167
+ if (ref.kind === 'remote')
168
+ remote.add(ref.value);
169
+ }
170
+ }
171
+ }
172
+ const cssTexts = [...all('style').map((style) => style.textContent ?? ''), ...all('[style]').map((element) => element.getAttribute('style') ?? '')];
173
+ for (const ref of cssTexts.flatMap(cssImageRefs)) {
174
+ if (ref.kind === 'file')
175
+ files.add(ref.ref);
176
+ if (ref.kind === 'remote')
177
+ remote.add(ref.value);
178
+ }
179
+ const bodyAttributes = Array.from(document.body.attributes);
180
+ if (bodyAttributes.length) {
181
+ notCarried.push(`<body ${bodyAttributes.map((attribute) => `${attribute.name}="${attribute.value}"`).join(' ')}>`);
182
+ }
183
+ return {
184
+ head: headParts.join('\n'),
185
+ body: document.body.innerHTML,
186
+ images,
187
+ dropped: [...dropped],
188
+ files: [...files],
189
+ fonts,
190
+ remote: [...remote],
191
+ removedScripts,
192
+ media,
193
+ ...(bands ? { bands } : {}),
194
+ notCarried,
195
+ };
196
+ };
197
+ //# sourceMappingURL=page-merge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-merge.js","sourceRoot":"","sources":["../../src/scene/page-merge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAGrC,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,iBAAiB,EAAuB,MAAM,eAAe,CAAC;AACjH,OAAO,EACL,WAAW,EAAE,YAAY,EAAE,mBAAmB,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,GAEtF,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAkC1D,MAAM,uBAAuB,GAAG,uCAAuC,CAAC;AACxE,MAAM,UAAU,GAAG,gCAAgC,CAAC;AAEpD,4EAA4E;AAC5E,MAAM,mBAAmB,GAAkE;IACzF,CAAC,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,EAAE,QAAQ,CAAC,EAAE,CAAC,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,EAAE,QAAQ,CAAC;IACpG,CAAC,eAAe,EAAE,QAAQ,CAAC,EAAE,CAAC,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,CAAC;CACnG,CAAC;AAEF,MAAM,gBAAgB,GAAG,CAAC,OAAgB,EAAW,EAAE,CAAC,CACtD,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,MAAM;OACrC,CAAC,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,CAC1F,CAAC;AAEF,MAAM,QAAQ,GAAG,CAAC,OAAgB,EAAU,EAAE;IAC5C,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;IAC1C,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,SAAS,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAChF,MAAM,GAAG,GAAG,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IAChD,MAAM,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,SAAS,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,GAAG,CAAC;IACtF,OAAO,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AACpF,CAAC,CAAC;AAEF,MAAM,WAAW,GAAG,CAAC,OAAgB,EAAE,SAAiB,EAAc,EAAE;IACtE,MAAM,KAAK,GAAG,OAAO,CAAC,YAAY,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;IACpD,MAAM,MAAM,GAAG,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IACpE,OAAO,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAmB,EAAE,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC;AACrF,CAAC,CAAC;AAEF,qGAAqG;AACrG,MAAM,oBAAoB,GAAG,CAAC,OAAgB,EAAE,KAAY,EAAE,KAAqB,EAAQ,EAAE;IAC3F,MAAM,KAAK,GAAG,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IAC5C,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO;IAC3B,MAAM,KAAK,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,WAAW,KAAK,IAAI,CAAC;IACpE,MAAM,OAAO,GAAG,sBAAsB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACrD,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1B,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;IACnC,CAAC;SAAM,IAAI,OAAO,KAAK,KAAK,EAAE,CAAC;QAC7B,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1B,OAAO,CAAC,MAAM,EAAE,CAAC;IACnB,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAMzB,EAAc,EAAE;IACf,MAAM,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC3C,MAAM,GAAG,GAAG,CAAC,QAAgB,EAAa,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAc,CAAC;IAC1G,MAAM,KAAK,GAAG,mBAAmB,EAAE,CAAC;IAEpC,KAAK,MAAM,OAAO,IAAI,GAAG,CAAC,oDAAoD,CAAC,EAAE,CAAC;QAChF,oBAAoB,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACpD,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QACjC,KAAK,CAAC,WAAW,GAAG,iBAAiB,CAAC,mBAAmB,CAAC,KAAK,CAAC,WAAW,IAAI,EAAE,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IACvH,CAAC;IACD,KAAK,MAAM,OAAO,IAAI,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;QACrC,OAAO,CAAC,YAAY,CAAC,OAAO,EAAE,iBAAiB,CAAC,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IACrG,CAAC;IAED,IAAI,KAA0B,CAAC;IAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,CAAC;QACzF,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,OAAO,GAAa,EAAE,CAAC;YAC7B,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,wBAAwB,CAAC,EAAE,CAAC;gBACjD,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;gBACrD,IAAI,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC7B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBACnB,IAAI,CAAC,MAAM,EAAE,CAAC;gBAChB,CAAC;YACH,CAAC;YACD,KAAK,GAAG,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC;QAC7C,CAAC;IACH,CAAC;IAED,MAAM,cAAc,GAAa,EAAE,CAAC;IACpC,KAAK,MAAM,MAAM,IAAI,GAAG,CAAC,kBAAkB,CAAC,EAAE,CAAC;QAC7C,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAChD,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YACnC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC5B,MAAM,CAAC,MAAM,EAAE,CAAC;QAClB,CAAC;IACH,CAAC;IAED,MAAM,aAAa,GAAG,GAAgB,EAAE;QACtC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAqB,CAAC;QAC5C,MAAM,IAAI,GAAG,CAAC,GAAa,EAAE,MAAc,EAAQ,EAAE;YACnD,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;gBAAE,OAAO;YAC7B,MAAM,KAAK,GAAc,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI;gBAC9C,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;gBAC1D,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACxE,CAAC;YACF,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC9D,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC7B,CAAC,CAAC;QACF,KAAK,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,mBAAmB,EAAE,CAAC;YACxD,KAAK,MAAM,OAAO,IAAI,GAAG,CAAC,QAAQ,CAAC;gBAAE,KAAK,MAAM,GAAG,IAAI,WAAW,CAAC,OAAO,EAAE,SAAS,CAAC;oBAAE,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;QACvH,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YACjC,KAAK,MAAM,GAAG,IAAI,mBAAmB,CAAC,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC;gBAAE,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAClH,CAAC;QACD,KAAK,MAAM,OAAO,IAAI,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YACrC,KAAK,MAAM,GAAG,IAAI,YAAY,CAAC,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;gBAAE,IAAI,CAAC,GAAG,EAAE,YAAY,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAClH,CAAC;QACD,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9B,CAAC,CAAC;IAEF,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IACxD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5D,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,MAAM,IAAI,kBAAkB,CAAC,gBAAgB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM;cAC/G,2CAA2C,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC;IAC3G,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,KAAK,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,mBAAmB,EAAE,CAAC;YACxD,KAAK,MAAM,OAAO,IAAI,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACpC,IAAI,WAAW,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;oBAAE,OAAO,CAAC,MAAM,EAAE,CAAC;YAC5F,CAAC;QACH,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC;YAAE,KAAK,CAAC,WAAW,GAAG,aAAa,CAAC,KAAK,CAAC,WAAW,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC;QACtG,KAAK,MAAM,OAAO,IAAI,GAAG,CAAC,SAAS,CAAC;YAAE,OAAO,CAAC,YAAY,CAAC,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;IACnI,CAAC;IACD,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAE/B,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAC;IACjC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAc,EAAE,CAAC;QACtE,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;QAC1C,IAAI,GAAG,KAAK,OAAO,IAAI,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC;YACjD,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAClC,SAAS;QACX,CAAC;QACD,IAAI,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,OAAO;YAAE,SAAS;QAChD,IAAI,GAAG,KAAK,MAAM,IAAI,2BAA2B,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YAAE,SAAS;QACpG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAC9G,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAC9D,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QACzD,IAAI,GAAG,EAAE,IAAI,KAAK,MAAM;YAAE,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;aACxC,IAAI,GAAG,EAAE,IAAI,KAAK,QAAQ;YAAE,CAAC,uBAAuB,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7H,CAAC;IACD,KAAK,MAAM,MAAM,IAAI,GAAG,CAAC,kBAAkB,CAAC,EAAE,CAAC;QAC7C,MAAM,GAAG,GAAG,WAAW,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QAC1D,IAAI,GAAG,EAAE,IAAI,KAAK,MAAM;YAAE,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC/C,CAAC;IACD,KAAK,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,mBAAmB,EAAE,CAAC;QACxD,KAAK,MAAM,OAAO,IAAI,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YACpC,KAAK,MAAM,GAAG,IAAI,WAAW,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,CAAC;gBAClD,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM;oBAAE,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBAC5C,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ;oBAAE,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;IACH,CAAC;IACD,MAAM,QAAQ,GAAG,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC,EAAE,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACpJ,KAAK,MAAM,GAAG,IAAI,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;QACjD,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM;YAAE,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5C,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ;YAAE,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACnD,CAAC;IACD,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAmE,CAAC,CAAC;IACrH,IAAI,cAAc,CAAC,MAAM,EAAE,CAAC;QAC1B,UAAU,CAAC,IAAI,CAAC,SAAS,cAAc,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,GAAG,SAAS,CAAC,IAAI,KAAK,SAAS,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACrH,CAAC;IAED,OAAO;QACL,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;QAC1B,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,SAAS;QAC7B,MAAM;QACN,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC;QACrB,KAAK,EAAE,CAAC,GAAG,KAAK,CAAC;QACjB,KAAK;QACL,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC;QACnB,cAAc;QACd,KAAK;QACL,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3B,UAAU;KACX,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * The API engine's responsive page (`<meta name="responsive-band-assembly">`)
3
+ * carries one complete layout per band, `<div class="ly-band" data-ly-band=NAME>`.
4
+ * Its CSS hides every band (`.ly-band{display:none}`) and shows one per
5
+ * `@media` block (`.ly-band[data-ly-band="NAME"]{display:block}`). Once those
6
+ * blocks are decided at the source frame, the show rules that survive name the
7
+ * bands that paint at that frame; the rest can never paint in the scene.
8
+ *
9
+ * Removing a band needs both declared facts: the hide rule, and at least one
10
+ * surviving show rule. Without them every band stays (a band that is kept but
11
+ * hidden costs bytes; a band removed in error is a hole).
12
+ */
13
+ export type BandDecision = {
14
+ shown: string[];
15
+ removable: (band: string) => boolean;
16
+ };
17
+ /** The bands the frame-decided CSS shows, or null when it does not prove which bands are hidden. */
18
+ export declare const bandsShownAtFrame: (resolvedCss: readonly string[]) => BandDecision | null;
19
+ //# sourceMappingURL=responsive-bands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responsive-bands.d.ts","sourceRoot":"","sources":["../../src/scene/responsive-bands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,MAAM,MAAM,YAAY,GAAG;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAA;CAAE,CAAC;AAErF,oGAAoG;AACpG,eAAO,MAAM,iBAAiB,GAAI,aAAa,SAAS,MAAM,EAAE,KAAG,YAAY,GAAG,IAMjF,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * The API engine's responsive page (`<meta name="responsive-band-assembly">`)
3
+ * carries one complete layout per band, `<div class="ly-band" data-ly-band=NAME>`.
4
+ * Its CSS hides every band (`.ly-band{display:none}`) and shows one per
5
+ * `@media` block (`.ly-band[data-ly-band="NAME"]{display:block}`). Once those
6
+ * blocks are decided at the source frame, the show rules that survive name the
7
+ * bands that paint at that frame; the rest can never paint in the scene.
8
+ *
9
+ * Removing a band needs both declared facts: the hide rule, and at least one
10
+ * surviving show rule. Without them every band stays (a band that is kept but
11
+ * hidden costs bytes; a band removed in error is a hole).
12
+ */
13
+ const HIDE_RULE = /\.ly-band\s*\{\s*display\s*:\s*none\b/iu;
14
+ const SHOW_RULE = /\.ly-band\[data-ly-band\s*=\s*(["']?)([^"'\]\s]+)\1\s*\]\s*\{\s*display\s*:\s*(?!none\b)[a-z-]+/giu;
15
+ /** The bands the frame-decided CSS shows, or null when it does not prove which bands are hidden. */
16
+ export const bandsShownAtFrame = (resolvedCss) => {
17
+ const css = resolvedCss.join('\n');
18
+ if (!HIDE_RULE.test(css))
19
+ return null;
20
+ const shown = [...new Set([...css.matchAll(SHOW_RULE)].map((match) => match[2]))];
21
+ if (shown.length === 0)
22
+ return null;
23
+ return { shown, removable: (band) => !shown.includes(band) };
24
+ };
25
+ //# sourceMappingURL=responsive-bands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responsive-bands.js","sourceRoot":"","sources":["../../src/scene/responsive-bands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,SAAS,GAAG,yCAAyC,CAAC;AAC5D,MAAM,SAAS,GAAG,oGAAoG,CAAC;AAIvH,oGAAoG;AACpG,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,WAA8B,EAAuB,EAAE;IACvF,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC;IACnF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;AAC/D,CAAC,CAAC"}
@@ -0,0 +1,10 @@
1
+ export type StarterInsertion = {
2
+ html: string;
3
+ replaced: boolean;
4
+ };
5
+ export declare const insertIntoStarter: (starter: string, page: {
6
+ head: string;
7
+ body: string;
8
+ label: string;
9
+ }, file: string) => StarterInsertion;
10
+ //# sourceMappingURL=scene-index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scene-index.d.ts","sourceRoot":"","sources":["../../src/scene/scene-index.ts"],"names":[],"mappings":"AAqBA,MAAM,MAAM,gBAAgB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC;AAEnE,eAAO,MAAM,iBAAiB,GAAI,SAAS,MAAM,EAAE,MAAM;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,MAAM,MAAM,KAAG,gBAyBtH,CAAC"}
@@ -0,0 +1,43 @@
1
+ import { SceneArgumentError } from './numbers.js';
2
+ /**
3
+ * Puts a merged page into the scene's index.html as text, so nothing else in
4
+ * the starter is re-serialized: the page's styles go into <head> just before
5
+ * the starter's first <style> (so the starter's rules win where they overlap),
6
+ * and its body goes inside the empty `#stage`. Both are fenced with comments,
7
+ * and a later merge replaces exactly what an earlier one wrote.
8
+ */
9
+ const HEAD_BEGIN = '<!-- 12ui scene merge: page head';
10
+ const BODY_BEGIN = '<!-- 12ui scene merge: page body';
11
+ const END = '<!-- 12ui scene merge: end -->';
12
+ const escapeRegExp = (text) => text.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&');
13
+ const fenced = (begin) => new RegExp(`${escapeRegExp(begin)}[^>]*-->[\\s\\S]*?${escapeRegExp(END)}`, 'u');
14
+ const STAGE = new RegExp(`(<div\\b[^>]*\\bid\\s*=\\s*(["']?)stage\\2(?=[\\s>/])[^>]*>)(\\s*(?:${escapeRegExp(BODY_BEGIN)}[^>]*-->[\\s\\S]*?${escapeRegExp(END)})?\\s*)</div>`, 'u');
15
+ export const insertIntoStarter = (starter, page, file) => {
16
+ const stage = STAGE.exec(starter);
17
+ if (!stage) {
18
+ const hasStage = /\bid\s*=\s*["']?stage\b/u.test(starter);
19
+ throw new SceneArgumentError(hasStage
20
+ ? `#stage in ${file} already holds content that 12ui scene merge did not write. Merge into a fresh starter`
21
+ + ' (12ui scene init <new-dir>), or move that content out of #stage first.'
22
+ : `${file} has no <div id="stage">: merge needs the starter index.html from 12ui scene init.`);
23
+ }
24
+ const replaced = stage[3].includes(BODY_BEGIN);
25
+ const bodyBlock = `${BODY_BEGIN} from ${page.label} -->\n${page.body}\n${END}`;
26
+ const headBlock = `${HEAD_BEGIN} from ${page.label} -->\n${page.head}\n${END}\n`;
27
+ let html = `${starter.slice(0, stage.index)}${stage[1]}${bodyBlock}</div>${starter.slice(stage.index + stage[0].length)}`;
28
+ const previousHead = fenced(HEAD_BEGIN).exec(html);
29
+ if (previousHead) {
30
+ html = `${html.slice(0, previousHead.index)}${headBlock.trimEnd()}${html.slice(previousHead.index + previousHead[0].length)}`;
31
+ }
32
+ else {
33
+ const headEnd = html.search(/<\/head\s*>/iu);
34
+ const headStart = html.search(/<head\b[^>]*>/iu);
35
+ if (headEnd < 0 || headStart < 0)
36
+ throw new SceneArgumentError(`${file} has no <head>: merge needs the starter index.html from 12ui scene init.`);
37
+ const style = html.slice(headStart, headEnd).search(/<style\b/iu);
38
+ const at = style >= 0 ? headStart + style : headEnd;
39
+ html = `${html.slice(0, at)}${headBlock}${html.slice(at)}`;
40
+ }
41
+ return { html, replaced };
42
+ };
43
+ //# sourceMappingURL=scene-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scene-index.js","sourceRoot":"","sources":["../../src/scene/scene-index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { type ConvertRunPage } from './convert-run.js';
2
+ import { type MergedPage } from './page-merge.js';
3
+ /**
4
+ * `12ui scene merge <convert-run> <scene-dir>`: joins the page a `12ui convert`
5
+ * run built to the scene. It reads the run by its recorded engine
6
+ * (convert-run.ts), makes the page ready for `#stage` (page-merge.ts), writes
7
+ * it into the scene's index.html (scene-index.ts) and copies the files the page
8
+ * loads beside it, keeping their paths. Every check runs before the first write.
9
+ */
10
+ export type MergeReport = {
11
+ run: ConvertRunPage;
12
+ merged: MergedPage;
13
+ indexFile: string;
14
+ replaced: boolean;
15
+ copied: string[];
16
+ alreadyThere: string[];
17
+ missing: string[];
18
+ };
19
+ export declare const mergeConvertRun: (args: {
20
+ runDir: string;
21
+ sceneDir: string;
22
+ drop: readonly string[];
23
+ }) => Promise<MergeReport>;
24
+ /** The report printed by the verb: what was merged, the images to choose from, what is left to do. */
25
+ export declare const formatMergeReport: (report: MergeReport, shown: {
26
+ run: string;
27
+ scene: string;
28
+ }) => string[];
29
+ //# sourceMappingURL=scene-merge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scene-merge.d.ts","sourceRoot":"","sources":["../../src/scene/scene-merge.ts"],"names":[],"mappings":"AAGA,OAAO,EAAkB,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGvE,OAAO,EAAa,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7D;;;;;;GAMG;AAEH,MAAM,MAAM,WAAW,GAAG;IACxB,GAAG,EAAE,cAAc,CAAC;IACpB,MAAM,EAAE,UAAU,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AA8BF,eAAO,MAAM,eAAe,GAAU,MAAM;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,KAAG,OAAO,CAAC,WAAW,CAoD9H,CAAC;AAIF,sGAAsG;AACtG,eAAO,MAAM,iBAAiB,GAAI,QAAQ,WAAW,EAAE,OAAO;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,KAAG,MAAM,EA6BpG,CAAC"}
@@ -0,0 +1,130 @@
1
+ import { copyFile, mkdir, readFile, writeFile } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { readConvertRun } from './convert-run.js';
4
+ import { SceneArgumentError } from './numbers.js';
5
+ import { cssImageRefs, formatBox } from './page-images.js';
6
+ import { mergePage } from './page-merge.js';
7
+ import { insertIntoStarter } from './scene-index.js';
8
+ const readBytes = async (file) => {
9
+ try {
10
+ return await readFile(file);
11
+ }
12
+ catch (error) {
13
+ if (['ENOENT', 'ENOTDIR', 'EISDIR'].includes(error.code ?? ''))
14
+ return undefined;
15
+ throw error;
16
+ }
17
+ };
18
+ const inside = (root, relative) => {
19
+ const resolved = path.resolve(root, relative);
20
+ return resolved.startsWith(`${path.resolve(root)}${path.sep}`) ? resolved : undefined;
21
+ };
22
+ /** The page's local files plus the files its local stylesheets load, as page-relative paths. */
23
+ const filesToCopy = async (pageDir, files) => {
24
+ const all = new Set(files);
25
+ for (const file of files.filter((name) => name.toLowerCase().endsWith('.css'))) {
26
+ const source = inside(pageDir, file);
27
+ const css = source ? await readBytes(source) : undefined;
28
+ if (!css)
29
+ continue;
30
+ for (const ref of cssImageRefs(css.toString('utf8'))) {
31
+ if (ref.kind === 'file')
32
+ all.add(path.posix.normalize(path.posix.join(path.posix.dirname(file), ref.ref)));
33
+ }
34
+ }
35
+ return [...all];
36
+ };
37
+ export const mergeConvertRun = async (args) => {
38
+ const run = await readConvertRun(args.runDir);
39
+ const indexFile = path.join(path.resolve(args.sceneDir), 'index.html');
40
+ const starter = await readBytes(indexFile);
41
+ if (!starter)
42
+ throw new SceneArgumentError(`${indexFile} is missing: run 12ui scene init ${args.sceneDir} first.`);
43
+ const merged = mergePage({
44
+ html: await readFile(run.page, 'utf8'),
45
+ frame: run.frame,
46
+ engine: run.engine,
47
+ boxes: run.boxes,
48
+ drop: args.drop,
49
+ });
50
+ const label = `${path.relative(path.dirname(indexFile), run.page) || run.page} (${run.engine} engine)`;
51
+ const inserted = insertIntoStarter(starter.toString('utf8'), { head: merged.head, body: merged.body, label }, indexFile);
52
+ const pageDir = path.dirname(run.page);
53
+ const plan = [];
54
+ const alreadyThere = [];
55
+ const missing = [];
56
+ for (const relative of await filesToCopy(pageDir, merged.files)) {
57
+ const source = inside(pageDir, relative);
58
+ const target = inside(path.dirname(indexFile), relative);
59
+ const bytes = source ? await readBytes(source) : undefined;
60
+ if (!source || !target || !bytes) {
61
+ missing.push(relative);
62
+ continue;
63
+ }
64
+ const existing = await readBytes(target);
65
+ if (existing?.equals(bytes)) {
66
+ alreadyThere.push(relative);
67
+ continue;
68
+ }
69
+ if (existing) {
70
+ throw new SceneArgumentError(`The page loads ${relative}, and ${target} already exists with different content.`
71
+ + ' Merge writes nothing over a scene file: rename or move that file, then merge again.');
72
+ }
73
+ plan.push({ relative, source, target, bytes });
74
+ }
75
+ for (const file of plan) {
76
+ await mkdir(path.dirname(file.target), { recursive: true });
77
+ await copyFile(file.source, file.target);
78
+ }
79
+ await writeFile(indexFile, inserted.html);
80
+ return {
81
+ run,
82
+ merged,
83
+ indexFile,
84
+ replaced: inserted.replaced,
85
+ copied: plan.map((file) => file.relative),
86
+ alreadyThere,
87
+ missing,
88
+ };
89
+ };
90
+ const list = (values) => values.join(', ');
91
+ /** The report printed by the verb: what was merged, the images to choose from, what is left to do. */
92
+ export const formatMergeReport = (report, shown) => {
93
+ const { run, merged } = report;
94
+ const lines = [
95
+ `merged ${path.join(shown.run, path.relative(run.runDir, run.page))} (${run.engine} engine, ${run.frame.width}x${run.frame.height}`
96
+ + ` source frame) into ${path.join(shown.scene, 'index.html')}${report.replaced ? ', replacing the earlier merge' : ''}`,
97
+ ];
98
+ const { applied, removed, undecided } = merged.media;
99
+ if (applied.length || removed.length || undecided.length) {
100
+ lines.push(` @media at ${run.frame.width}x${run.frame.height}: ${applied.length} apply (rules kept), ${removed.length} do not (removed)`
101
+ + `${undecided.length ? `, ${undecided.length} depend on the viewer (kept as written: ${list(undecided)})` : ''}`);
102
+ }
103
+ if (merged.bands) {
104
+ lines.push(` responsive bands: kept ${list(merged.bands.shown)}${merged.bands.removed.length ? `, removed ${list(merged.bands.removed)}` : ''}`);
105
+ }
106
+ for (const script of merged.removedScripts)
107
+ lines.push(` removed remote script ${script}`);
108
+ if (report.copied.length)
109
+ lines.push(` copied beside index.html: ${list(report.copied)}`);
110
+ if (report.alreadyThere.length)
111
+ lines.push(` already beside index.html: ${list(report.alreadyThere)}`);
112
+ if (report.missing.length)
113
+ lines.push(` warning: the page loads files that are not in the run: ${list(report.missing)}`);
114
+ for (const element of merged.notCarried)
115
+ lines.push(` not carried into the scene: ${element}`);
116
+ if (merged.dropped.length)
117
+ lines.push(`dropped: ${list(merged.dropped)}`);
118
+ lines.push(merged.images.length
119
+ ? `images (drop the ones the 3D scene replaces with --drop <image>,...; box is x0,y0,x1,y1 where the run declares it):`
120
+ : 'images: none');
121
+ for (const image of merged.images) {
122
+ lines.push(` ${image.ref}${image.box ? ` box ${formatBox(image.box)}` : ''} ${list(image.usedBy)}`);
123
+ }
124
+ for (const url of merged.fonts)
125
+ lines.push(`fonts: ${url}`);
126
+ for (const url of merged.remote)
127
+ lines.push(`remote (capture blocks it): ${url}`);
128
+ return lines;
129
+ };
130
+ //# sourceMappingURL=scene-merge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scene-merge.js","sourceRoot":"","sources":["../../src/scene/scene-merge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,cAAc,EAAuB,MAAM,kBAAkB,CAAC;AACvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAmB,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAoBrD,MAAM,SAAS,GAAG,KAAK,EAAE,IAAY,EAA+B,EAAE;IACpE,IAAI,CAAC;QACH,OAAO,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAE,KAA+B,CAAC,IAAI,IAAI,EAAE,CAAC;YAAE,OAAO,SAAS,CAAC;QAC5G,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,QAAgB,EAAsB,EAAE;IACpE,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC9C,OAAO,QAAQ,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;AACxF,CAAC,CAAC;AAEF,gGAAgG;AAChG,MAAM,WAAW,GAAG,KAAK,EAAE,OAAe,EAAE,KAAwB,EAAqB,EAAE;IACzF,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;QAC/E,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACrC,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACzD,IAAI,CAAC,GAAG;YAAE,SAAS;QACnB,KAAK,MAAM,GAAG,IAAI,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;YACrD,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM;gBAAE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC7G,CAAC;IACH,CAAC;IACD,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC;AAClB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EAAE,IAAmE,EAAwB,EAAE;IACjI,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,YAAY,CAAC,CAAC;IACvE,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,SAAS,CAAC,CAAC;IAC3C,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,kBAAkB,CAAC,GAAG,SAAS,oCAAoC,IAAI,CAAC,QAAQ,SAAS,CAAC,CAAC;IACnH,MAAM,MAAM,GAAG,SAAS,CAAC;QACvB,IAAI,EAAE,MAAM,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC;QACtC,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,IAAI,EAAE,IAAI,CAAC,IAAI;KAChB,CAAC,CAAC;IACH,MAAM,KAAK,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC,MAAM,UAAU,CAAC;IACvG,MAAM,QAAQ,GAAG,iBAAiB,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,SAAS,CAAC,CAAC;IAEzH,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACvC,MAAM,IAAI,GAA+E,EAAE,CAAC;IAC5F,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,QAAQ,IAAI,MAAM,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAChE,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC,CAAC;QACzD,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC3D,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;YACjC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACvB,SAAS;QACX,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5B,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC5B,SAAS;QACX,CAAC;QACD,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,IAAI,kBAAkB,CAAC,kBAAkB,QAAQ,SAAS,MAAM,yCAAyC;kBAC3G,sFAAsF,CAAC,CAAC;QAC9F,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;QACxB,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,MAAM,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3C,CAAC;IACD,MAAM,SAAS,CAAC,SAAS,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC1C,OAAO;QACL,GAAG;QACH,MAAM;QACN,SAAS;QACT,QAAQ,EAAE,QAAQ,CAAC,QAAQ;QAC3B,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC;QACzC,YAAY;QACZ,OAAO;KACR,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,IAAI,GAAG,CAAC,MAAyB,EAAU,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEtE,sGAAsG;AACtG,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,MAAmB,EAAE,KAAqC,EAAY,EAAE;IACxG,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAC/B,MAAM,KAAK,GAAG;QACZ,UAAU,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,MAAM,YAAY,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE;cACjI,uBAAuB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,YAAY,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,EAAE,EAAE;KACzH,CAAC;IACF,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC;IACrD,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;QACzD,KAAK,CAAC,IAAI,CAAC,eAAe,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM,wBAAwB,OAAO,CAAC,MAAM,mBAAmB;cACrI,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,MAAM,2CAA2C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACvH,CAAC;IACD,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,KAAK,CAAC,IAAI,CAAC,4BAA4B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACpJ,CAAC;IACD,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,cAAc;QAAE,KAAK,CAAC,IAAI,CAAC,2BAA2B,MAAM,EAAE,CAAC,CAAC;IAC5F,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,+BAA+B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC3F,IAAI,MAAM,CAAC,YAAY,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,gCAAgC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IACxG,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,4DAA4D,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC1H,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,UAAU;QAAE,KAAK,CAAC,IAAI,CAAC,iCAAiC,OAAO,EAAE,CAAC,CAAC;IAChG,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC1E,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM;QAC7B,CAAC,CAAC,qHAAqH;QACvH,CAAC,CAAC,cAAc,CAAC,CAAC;IACpB,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACzG,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,KAAK;QAAE,KAAK,CAAC,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC,CAAC;IAC5D,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,+BAA+B,GAAG,EAAE,CAAC,CAAC;IAClF,OAAO,KAAK,CAAC;AACf,CAAC,CAAC"}
@@ -1,4 +1,4 @@
1
1
  /** The `12ui scene` verbs, named once for the dispatcher and the capability record. */
2
- export declare const SCENE_VERBS: readonly ["init", "solve", "ray", "project", "rect", "serve", "capture", "sheet", "blend", "colors", "rectify"];
2
+ export declare const SCENE_VERBS: readonly ["init", "solve", "ray", "project", "rect", "serve", "capture", "sheet", "blend", "colors", "rectify", "merge"];
3
3
  export type SceneVerb = typeof SCENE_VERBS[number];
4
4
  //# sourceMappingURL=scene-verbs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"scene-verbs.d.ts","sourceRoot":"","sources":["../../src/scene/scene-verbs.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,eAAO,MAAM,WAAW,iHAEd,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC"}
1
+ {"version":3,"file":"scene-verbs.d.ts","sourceRoot":"","sources":["../../src/scene/scene-verbs.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,eAAO,MAAM,WAAW,0HAEd,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC"}
@@ -1,5 +1,5 @@
1
1
  /** The `12ui scene` verbs, named once for the dispatcher and the capability record. */
2
2
  export const SCENE_VERBS = [
3
- 'init', 'solve', 'ray', 'project', 'rect', 'serve', 'capture', 'sheet', 'blend', 'colors', 'rectify',
3
+ 'init', 'solve', 'ray', 'project', 'rect', 'serve', 'capture', 'sheet', 'blend', 'colors', 'rectify', 'merge',
4
4
  ];
5
5
  //# sourceMappingURL=scene-verbs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"scene-verbs.js","sourceRoot":"","sources":["../../src/scene/scene-verbs.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS;CAC5F,CAAC"}
1
+ {"version":3,"file":"scene-verbs.js","sourceRoot":"","sources":["../../src/scene/scene-verbs.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO;CACrG,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * `12ui scene serve --detach`: the server as its own detached process (a new
3
+ * session, no terminal, stdio in a log file), so it outlives the shell that
4
+ * launched it. An agent's tool shell ends, or kills its process group, when
5
+ * the command returns; a plain `serve ... &` died with it and the next capture
6
+ * met ERR_CONNECTION_REFUSED. The launcher returns only once the port answers
7
+ * with this child's pid, so a printed URL is a working URL.
8
+ */
9
+ export type DetachedServer = {
10
+ url: string;
11
+ port: number;
12
+ pid: number;
13
+ logFile: string;
14
+ };
15
+ export type DetachOptions = {
16
+ directory: string;
17
+ port: number;
18
+ /** The command that runs a foreground server on `--port <port>`; argv[0] is the executable. */
19
+ command: (port: number) => string[];
20
+ readyTimeoutMs?: number;
21
+ };
22
+ export declare const startDetachedServer: (options: DetachOptions) => Promise<DetachedServer>;
23
+ //# sourceMappingURL=serve-detach.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve-detach.d.ts","sourceRoot":"","sources":["../../src/scene/serve-detach.ts"],"names":[],"mappings":"AAUA;;;;;;;GAOG;AAEH,MAAM,MAAM,cAAc,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzF,MAAM,MAAM,aAAa,GAAG;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,+FAA+F;IAC/F,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;IACpC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAqCF,eAAO,MAAM,mBAAmB,GAAU,SAAS,aAAa,KAAG,OAAO,CAAC,cAAc,CA4CxF,CAAC"}