@typecad/cuttlefish 1.0.0-alpha.12 → 1.0.0-alpha.13
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/add-preset.d.ts +4 -0
- package/dist/add-preset.js +74 -0
- package/dist/api/config.d.ts +0 -4
- package/dist/api/shared/display-adapters/sdl.js +1 -1
- package/dist/api/shared/display-profile.d.ts +11 -0
- package/dist/api/shared/display-profile.js +3 -0
- package/dist/api/shared/hal-op-ir.d.ts +19 -0
- package/dist/api/shared/toolchain-types.d.ts +0 -1
- package/dist/cli.js +15 -4
- package/dist/config-loader.d.ts +0 -2
- package/dist/config-loader.js +10 -5
- package/dist/config-schema.d.ts +87 -94
- package/dist/config-schema.js +0 -3
- package/dist/create/debug-artifacts.d.ts +20 -0
- package/dist/create/debug-artifacts.js +69 -0
- package/dist/create/index.d.ts +2 -0
- package/dist/create/index.js +1 -0
- package/dist/create/init-scaffold.d.ts +1 -0
- package/dist/create/init-scaffold.js +5 -0
- package/dist/create/init-templates.js +0 -2
- package/dist/emit/compliance/rules.js +18 -4
- package/dist/emit/emitters/function-emitter-impl.js +7 -1
- package/dist/emit/emitters/line-appender.js +6 -0
- package/dist/emit/emitters/ui-emitter.js +40 -15
- package/dist/emit/route-hal-op.js +55 -1
- package/dist/emit/statement-renderer.js +5 -2
- package/dist/ir/build-ir.js +22 -1
- package/dist/ir/expression-to-ir.js +17 -0
- package/dist/ir/hal/hal-emitter.js +23 -5
- package/dist/ir/hal/hal-plugins.js +11 -0
- package/dist/ir/pin-mode-validation.js +32 -9
- package/dist/ir/pin-state-tracking.d.ts +58 -0
- package/dist/ir/pin-state-tracking.js +182 -0
- package/dist/ir/program-analysis.d.ts +6 -0
- package/dist/ir/program-analysis.js +38 -0
- package/dist/ir/statement-to-ir.js +14 -0
- package/dist/ir/transformers/control-flow.js +29 -0
- package/dist/ir/transformers/ui-call-resolver.js +105 -1
- package/dist/ir/ui-element-auto-wire.js +7 -4
- package/dist/orchestrator/graph-builder.d.ts +4 -1
- package/dist/orchestrator/graph-builder.js +7 -1
- package/dist/preview/api-shared-shim.d.ts +1 -0
- package/dist/preview/api-shared-shim.js +7 -0
- package/dist/preview/client.js +220 -1
- package/dist/preview/server.js +154 -62
- package/dist/theme-tokens.d.ts +22 -0
- package/dist/theme-tokens.js +172 -0
- package/dist/transpile.js +35 -5
- package/dist/types.d.ts +5 -0
- package/dist/ui-hook.d.ts +7 -0
- package/dist/utils/cli.js +9 -0
- package/dist/utils/ui.d.ts +5 -0
- package/dist/utils/ui.js +7 -0
- package/package.json +7 -6
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// shadcn kit themes — the included token sets under assets/shadcn/themes/.
|
|
3
|
+
//
|
|
4
|
+
// A theme file is two CSS blocks (:root = light tokens, .dark = dark tokens)
|
|
5
|
+
// plus an optional header comment. Selecting a theme MERGES each block into
|
|
6
|
+
// the kit's stylesheet: declarations the theme defines override the kit's,
|
|
7
|
+
// and kit-specific extras the theme lacks (notably --destructive-background,
|
|
8
|
+
// which stock shadcn themes don't carry) keep their current values — so any
|
|
9
|
+
// stock theme from ui.shadcn.com or tweakcn pastes cleanly.
|
|
10
|
+
//
|
|
11
|
+
// Used by `cuttlefish add shadcn --theme <name>` (scaffold time) and
|
|
12
|
+
// `cuttlefish theme <name>` (swap an existing project's kit stylesheet).
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
import fs from "node:fs";
|
|
15
|
+
import path from "node:path";
|
|
16
|
+
import { fileURLToPath } from "node:url";
|
|
17
|
+
const THEMES_DIR = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../assets/shadcn/themes");
|
|
18
|
+
/** The tokens the kit's recipes reference; every merged theme must cover them. */
|
|
19
|
+
const REQUIRED_TOKENS = [
|
|
20
|
+
"--background", "--foreground",
|
|
21
|
+
"--card", "--card-foreground",
|
|
22
|
+
"--primary", "--primary-foreground",
|
|
23
|
+
"--secondary", "--secondary-foreground",
|
|
24
|
+
"--muted", "--muted-foreground",
|
|
25
|
+
"--accent", "--accent-foreground",
|
|
26
|
+
"--destructive", "--destructive-foreground", "--destructive-background",
|
|
27
|
+
"--border", "--input", "--radius",
|
|
28
|
+
];
|
|
29
|
+
/** Blank out /* … */ comment interiors (same length) so selector searches
|
|
30
|
+
* can't match inside a comment while byte offsets stay valid against the
|
|
31
|
+
* original text. The kit's header comment literally contains `.dark { ... }`
|
|
32
|
+
* as documentation — an unmasked search spliced tokens into the comment and
|
|
33
|
+
* left the real block untouched. */
|
|
34
|
+
function maskComments(css) {
|
|
35
|
+
return css.replace(/\/\*[\s\S]*?\*\//g, (m) => " ".repeat(m.length));
|
|
36
|
+
}
|
|
37
|
+
/** Locate `selector {` in css, skipping comment spans. Custom-property values
|
|
38
|
+
* contain no braces, so the block ends at the first `}` after the opening
|
|
39
|
+
* one. */
|
|
40
|
+
function blockRange(css, selector) {
|
|
41
|
+
const escaped = selector.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
42
|
+
const m = new RegExp(escaped + "\\s*\\{").exec(maskComments(css));
|
|
43
|
+
if (!m)
|
|
44
|
+
return null;
|
|
45
|
+
const open = m.index + m[0].length;
|
|
46
|
+
const close = css.indexOf("}", open);
|
|
47
|
+
if (close < 0)
|
|
48
|
+
return null;
|
|
49
|
+
return { selStart: m.index, open, close };
|
|
50
|
+
}
|
|
51
|
+
/** Parse a token block's declarations (line-oriented; one decl per line, the
|
|
52
|
+
* format both the kit and stock shadcn themes use). */
|
|
53
|
+
function parseDecls(block) {
|
|
54
|
+
const out = [];
|
|
55
|
+
for (const line of block.split("\n")) {
|
|
56
|
+
const m = /^\s*(--[\w-]+)\s*:\s*([^;]+);/.exec(line);
|
|
57
|
+
if (m)
|
|
58
|
+
out.push([m[1], m[2].trim()]);
|
|
59
|
+
}
|
|
60
|
+
return out;
|
|
61
|
+
}
|
|
62
|
+
function emitBlock(selector, decls) {
|
|
63
|
+
const body = decls.map(([k, v]) => ` ${k}: ${v};`).join("\n");
|
|
64
|
+
return `${selector} {\n${body}\n}`;
|
|
65
|
+
}
|
|
66
|
+
/** Order-preserving override merge: base order, overrides in place, theme-only
|
|
67
|
+
* declarations appended. */
|
|
68
|
+
function mergeDecls(base, override) {
|
|
69
|
+
const out = base.map(([k, v]) => [k, v]);
|
|
70
|
+
const indexByName = new Map(out.map(([k], i) => [k, i]));
|
|
71
|
+
for (const [k, v] of override) {
|
|
72
|
+
const existing = indexByName.get(k);
|
|
73
|
+
if (existing !== undefined)
|
|
74
|
+
out[existing][1] = v;
|
|
75
|
+
else {
|
|
76
|
+
indexByName.set(k, out.length);
|
|
77
|
+
out.push([k, v]);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return out;
|
|
81
|
+
}
|
|
82
|
+
/** Where a project keeps its own themes: src/styles/themes/*.css next to
|
|
83
|
+
* the kit stylesheet. Project themes win over same-named package ones —
|
|
84
|
+
* pasting a theme is dropping a file into YOUR project, never node_modules. */
|
|
85
|
+
export function projectThemesDir(projectRoot) {
|
|
86
|
+
return path.resolve(projectRoot, "src/styles/themes");
|
|
87
|
+
}
|
|
88
|
+
function themeNamesIn(dir) {
|
|
89
|
+
if (!fs.existsSync(dir))
|
|
90
|
+
return [];
|
|
91
|
+
return fs.readdirSync(dir)
|
|
92
|
+
.filter((f) => f.endsWith(".css") && !f.startsWith("_"))
|
|
93
|
+
.map((f) => f.replace(/\.css$/, ""))
|
|
94
|
+
.sort();
|
|
95
|
+
}
|
|
96
|
+
/** Theme names, project-local (src/styles/themes/) first, then the ones
|
|
97
|
+
* shipped in the package (assets/shadcn/themes/). */
|
|
98
|
+
export function listShadcnThemes(projectRoot) {
|
|
99
|
+
const local = projectRoot ? themeNamesIn(projectThemesDir(projectRoot)) : [];
|
|
100
|
+
const included = themeNamesIn(THEMES_DIR);
|
|
101
|
+
return [...new Set([...local, ...included])].sort();
|
|
102
|
+
}
|
|
103
|
+
function formatThemeList(projectRoot) {
|
|
104
|
+
const local = projectRoot ? themeNamesIn(projectThemesDir(projectRoot)) : [];
|
|
105
|
+
const included = themeNamesIn(THEMES_DIR);
|
|
106
|
+
const lines = [];
|
|
107
|
+
if (local.length > 0) {
|
|
108
|
+
lines.push("project (src/styles/themes/):");
|
|
109
|
+
for (const n of local)
|
|
110
|
+
lines.push(` ${n}`);
|
|
111
|
+
}
|
|
112
|
+
lines.push("included with cuttlefish:");
|
|
113
|
+
for (const n of included)
|
|
114
|
+
lines.push(` ${n}`);
|
|
115
|
+
lines.push("(paste your own: src/styles/themes/<name>.css in this project)");
|
|
116
|
+
return lines.join("\n");
|
|
117
|
+
}
|
|
118
|
+
/** Load a theme by name — project-local directory first, then the package
|
|
119
|
+
* included set. Throws with the available names when missing. */
|
|
120
|
+
export function loadShadcnTheme(name, projectRoot) {
|
|
121
|
+
if (!/^[a-z0-9-]+$/.test(name)) {
|
|
122
|
+
throw new Error(`Invalid theme name "${name}" — use letters, digits, and dashes.`);
|
|
123
|
+
}
|
|
124
|
+
const candidates = projectRoot
|
|
125
|
+
? [path.join(projectThemesDir(projectRoot), `${name}.css`), path.join(THEMES_DIR, `${name}.css`)]
|
|
126
|
+
: [path.join(THEMES_DIR, `${name}.css`)];
|
|
127
|
+
const file = candidates.find((c) => fs.existsSync(c));
|
|
128
|
+
if (!file) {
|
|
129
|
+
throw new Error(`Unknown theme "${name}". Available themes:\n${formatThemeList(projectRoot)}`);
|
|
130
|
+
}
|
|
131
|
+
const text = fs.readFileSync(file, "utf-8");
|
|
132
|
+
const rootRange = blockRange(text, ":root");
|
|
133
|
+
const darkRange = blockRange(text, ".dark");
|
|
134
|
+
if (!rootRange || !darkRange) {
|
|
135
|
+
throw new Error(`Theme "${name}" must define both a :root and a .dark token block.`);
|
|
136
|
+
}
|
|
137
|
+
const light = parseDecls(text.slice(rootRange.open, rootRange.close));
|
|
138
|
+
const dark = parseDecls(text.slice(darkRange.open, darkRange.close));
|
|
139
|
+
if (light.length === 0 || dark.length === 0) {
|
|
140
|
+
throw new Error(`Theme "${name}" has empty token blocks — paste the theme's :root and .dark declarations.`);
|
|
141
|
+
}
|
|
142
|
+
return { name, light, dark };
|
|
143
|
+
}
|
|
144
|
+
/** Merge a theme's tokens into a kit stylesheet's :root/.dark blocks and
|
|
145
|
+
* return the rewritten text. Throws when a merged block is missing any
|
|
146
|
+
* token the kit's recipes reference. */
|
|
147
|
+
export function applyShadcnTheme(cssText, theme) {
|
|
148
|
+
let out = cssText;
|
|
149
|
+
for (const [selector, themeDecls] of [[".dark", theme.dark], [":root", theme.light]]) {
|
|
150
|
+
const range = blockRange(out, selector);
|
|
151
|
+
if (!range) {
|
|
152
|
+
throw new Error(`The kit stylesheet has no ${selector} token block to replace.`);
|
|
153
|
+
}
|
|
154
|
+
const merged = mergeDecls(parseDecls(out.slice(range.open, range.close)), themeDecls);
|
|
155
|
+
out = out.slice(0, range.selStart) + emitBlock(selector, merged) + out.slice(range.close + 1);
|
|
156
|
+
}
|
|
157
|
+
// Validate AFTER both merges (a token can live in either block).
|
|
158
|
+
const rootRange = blockRange(out, ":root");
|
|
159
|
+
const darkRange = blockRange(out, ".dark");
|
|
160
|
+
const names = new Set();
|
|
161
|
+
if (rootRange)
|
|
162
|
+
for (const [k] of parseDecls(out.slice(rootRange.open, rootRange.close)))
|
|
163
|
+
names.add(k);
|
|
164
|
+
if (darkRange)
|
|
165
|
+
for (const [k] of parseDecls(out.slice(darkRange.open, darkRange.close)))
|
|
166
|
+
names.add(k);
|
|
167
|
+
const missing = REQUIRED_TOKENS.filter((t) => !names.has(t));
|
|
168
|
+
if (missing.length > 0) {
|
|
169
|
+
throw new Error(`Theme "${theme.name}" leaves required tokens unset: ${missing.join(", ")}`);
|
|
170
|
+
}
|
|
171
|
+
return out;
|
|
172
|
+
}
|
package/dist/transpile.js
CHANGED
|
@@ -26,11 +26,12 @@ import { requireUIHook, hasUIHook } from "./ui-hook.js";
|
|
|
26
26
|
import { loadUIEngine } from "./ui/ui-bridge.js";
|
|
27
27
|
import { hasSafetyHook, requireSafetyHook } from "./safety-hook.js";
|
|
28
28
|
import { loadSafetyEngine } from "./safety/safety-bridge.js";
|
|
29
|
-
import { setDisplayProfile, resetDisplayProfile } from "./stores/display-profile-store.js";
|
|
29
|
+
import { setDisplayProfile, resetDisplayProfile, getDisplayProfile } from "./stores/display-profile-store.js";
|
|
30
30
|
import { setThemeCss, resetThemeCss, setThemeClass } from "./stores/theme-store.js";
|
|
31
31
|
import { emitCpp, registerAllEnumNames } from "./emit/cpp-emitter.js";
|
|
32
32
|
import { readText, writeText, resetWrittenFiles, wasWrittenThisRun } from "./utils/fs.js";
|
|
33
33
|
import { debug as logDebug, info } from "./utils/logger.js";
|
|
34
|
+
import { printDebugStrategy } from "./utils/ui.js";
|
|
34
35
|
import { loadLibraryDefinitions, generateLibdefStubs } from "./libdef/registry.js";
|
|
35
36
|
import { buildCallGraph } from "./ir/call-graph.js";
|
|
36
37
|
import { clearCaches, } from "./cache.js";
|
|
@@ -201,6 +202,15 @@ import { loadFrameworkPackage } from "./framework-package.js";
|
|
|
201
202
|
export { loadFrameworkPackage };
|
|
202
203
|
export { getLoadedFramework, hasLoadedFramework } from "./framework-registry.js";
|
|
203
204
|
import { getLoadedFramework, hasLoadedFramework } from "./framework-registry.js";
|
|
205
|
+
/** Under --strict-css, UI CSS-compatibility warnings (code css-*: ignored
|
|
206
|
+
* alpha, quantized font sizes, unsupported display/position values, ...) are
|
|
207
|
+
* upgraded to errors so the build fails instead of approximating silently. */
|
|
208
|
+
function upgradeStrictCss(d, strict) {
|
|
209
|
+
if (strict && d.severity === "warning" && typeof d.code === "string" && d.code.startsWith("css-")) {
|
|
210
|
+
return { ...d, severity: "error" };
|
|
211
|
+
}
|
|
212
|
+
return d;
|
|
213
|
+
}
|
|
204
214
|
function formatFatalDiagnostics(entries) {
|
|
205
215
|
const errors = entries.filter(({ diagnostic }) => diagnostic.severity === "error");
|
|
206
216
|
const lines = [
|
|
@@ -260,7 +270,11 @@ function loadPlatformStrategy(frameworkPackage, _boardPackage, fromDir, debug) {
|
|
|
260
270
|
if (hasLoadedFramework()) {
|
|
261
271
|
const { strategy } = getLoadedFramework();
|
|
262
272
|
if (debug) {
|
|
263
|
-
|
|
273
|
+
// Styled like the other step lines (cyan ⇉) — says what the debug
|
|
274
|
+
// build is actually doing, in user terms. Falls back to the package
|
|
275
|
+
// name when the strategy carries no id.
|
|
276
|
+
const frameworkName = strategy.id || frameworkPackage.replace(/^@typecad\/framework-/, "");
|
|
277
|
+
printDebugStrategy(frameworkName);
|
|
264
278
|
}
|
|
265
279
|
return strategy;
|
|
266
280
|
}
|
|
@@ -351,7 +365,19 @@ export async function transpileFile(options) {
|
|
|
351
365
|
// see incremental-cache.ts — so we always transpile the full graph.)
|
|
352
366
|
cleanOutput(entryDir, outDir);
|
|
353
367
|
profiler.startTimer("graph:collect");
|
|
354
|
-
|
|
368
|
+
// Image-conversion cap: never decode larger than the physical panel —
|
|
369
|
+
// converted <img> assets downscale to fit (no 24MB C arrays from photos).
|
|
370
|
+
const imageDecodeMax = await (async () => {
|
|
371
|
+
try {
|
|
372
|
+
const { effectiveDisplaySize } = await import("./api/shared/display-profile.js");
|
|
373
|
+
const size = effectiveDisplaySize(getDisplayProfile());
|
|
374
|
+
return { maxW: size.width, maxH: size.height };
|
|
375
|
+
}
|
|
376
|
+
catch {
|
|
377
|
+
return {};
|
|
378
|
+
}
|
|
379
|
+
})();
|
|
380
|
+
const graphResult = await collectTranspileGraph(entryFile, options.boardPackage, imageDecodeMax);
|
|
355
381
|
profiler.endTimer("graph:collect");
|
|
356
382
|
const transpileFiles = graphResult.files;
|
|
357
383
|
// ── Type-check all files before transpiling ────────────────────────────────
|
|
@@ -449,10 +475,12 @@ export async function transpileFile(options) {
|
|
|
449
475
|
// parser warnings (unknown CSS properties, unknown HTML tags) here so the
|
|
450
476
|
// author sees typos and unsupported features instead of silent drops.
|
|
451
477
|
// Guarded: @typecad/ui is optional, so there may be no UI engine loaded.
|
|
478
|
+
// --strict-css upgrades the css-* compatibility warnings to errors.
|
|
452
479
|
if (hasUIHook()) {
|
|
453
480
|
for (const mod of requireUIHook().allUIModules()) {
|
|
454
481
|
for (const d of mod.diagnostics) {
|
|
455
|
-
|
|
482
|
+
const upgraded = upgradeStrictCss(d, options.strictCss);
|
|
483
|
+
diagnostics.push({ ...upgraded, filePath: d.filePath ?? path.basename(mod.htmlPath) });
|
|
456
484
|
}
|
|
457
485
|
}
|
|
458
486
|
}
|
|
@@ -582,10 +610,12 @@ export async function transpileFile(options) {
|
|
|
582
610
|
profiler.endTimer("ir:build-all");
|
|
583
611
|
// ── UI mount-time warnings (scroll memory budget, etc.) ─────────────────
|
|
584
612
|
// Guarded: @typecad/ui is optional; no engine means no UI modules.
|
|
613
|
+
// --strict-css upgrades the css-* compatibility warnings to errors.
|
|
585
614
|
if (hasUIHook()) {
|
|
586
615
|
for (const mod of requireUIHook().allUIModules()) {
|
|
587
616
|
for (const d of mod.mountDiagnostics) {
|
|
588
|
-
|
|
617
|
+
const upgraded = upgradeStrictCss(d, options.strictCss);
|
|
618
|
+
diagnostics.push({ ...upgraded, filePath: d.filePath ?? path.basename(mod.htmlPath) });
|
|
589
619
|
}
|
|
590
620
|
}
|
|
591
621
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -100,6 +100,8 @@ export interface TranspileOptions {
|
|
|
100
100
|
autosar?: ComplianceMode;
|
|
101
101
|
/** When true (and autosar is warn/strict), also emit the .autosar-deviations.arxml sidecar. */
|
|
102
102
|
autosarArxml?: boolean;
|
|
103
|
+
/** Upgrade UI CSS-compatibility warnings (css-* diagnostics) to errors. */
|
|
104
|
+
strictCss?: boolean;
|
|
103
105
|
}
|
|
104
106
|
export interface LibraryDefinitionCondition {
|
|
105
107
|
target?: TargetProfile;
|
|
@@ -179,6 +181,8 @@ export interface CommandLineOptions {
|
|
|
179
181
|
autosar?: ComplianceMode;
|
|
180
182
|
/** When true (and autosar is warn/strict), also emit the .autosar-deviations.arxml sidecar. */
|
|
181
183
|
autosarArxml?: boolean;
|
|
184
|
+
/** Upgrade UI CSS-compatibility warnings (css-* diagnostics) to errors. */
|
|
185
|
+
strictCss?: boolean;
|
|
182
186
|
/** Config file for preview command */
|
|
183
187
|
configPath?: string;
|
|
184
188
|
/** Project root (dir of cuttlefish.config.ts); passed to transpileFile for the ESLint gate. */
|
|
@@ -188,6 +192,7 @@ export interface GenerateLibdefOptions {
|
|
|
188
192
|
inputFile: string;
|
|
189
193
|
outDir: string;
|
|
190
194
|
}
|
|
195
|
+
/** `cuttlefish add <preset>` — scaffold a copy-and-own asset into the project. */
|
|
191
196
|
export interface GeneratedOutputs {
|
|
192
197
|
headerPath?: string;
|
|
193
198
|
sourcePath: string;
|
package/dist/ui-hook.d.ts
CHANGED
|
@@ -75,6 +75,13 @@ export interface TranspilerUIHook {
|
|
|
75
75
|
nativeDisplayActive?: boolean;
|
|
76
76
|
}): string;
|
|
77
77
|
splitUiFile(src: string): UiFileParts;
|
|
78
|
+
/** Pre-decode src="…" image references (png/jpg/ico/…) into the RGB565
|
|
79
|
+
* asset cache. Must be awaited BEFORE loadUIModule/loadUIModuleFromText —
|
|
80
|
+
* the synchronous asset reader and natural-size layout read the cache. */
|
|
81
|
+
warmUpImageDecoding(sourceText: string, baseDir: string, opts?: {
|
|
82
|
+
maxW?: number;
|
|
83
|
+
maxH?: number;
|
|
84
|
+
}): Promise<void>;
|
|
78
85
|
generateProjectUITypeDeclarations(projectRoot: string): {
|
|
79
86
|
written: string[];
|
|
80
87
|
errors: Array<{
|
package/dist/utils/cli.js
CHANGED
|
@@ -49,6 +49,10 @@ export function printHelp() {
|
|
|
49
49
|
console.log(` --autosar-arxml Also write <name>.autosar-deviations.arxml (Artop/DaVinci).`);
|
|
50
50
|
console.log(` No-op unless --autosar is warn or strict.`);
|
|
51
51
|
console.log();
|
|
52
|
+
console.log(` --strict-css Treat UI CSS-compatibility warnings as errors (css-*`);
|
|
53
|
+
console.log(` diagnostics: ignored alpha, quantized font sizes,`);
|
|
54
|
+
console.log(` unsupported display/position values, viewport-hogging sizes).`);
|
|
55
|
+
console.log();
|
|
52
56
|
console.log(chalk.cyan(`BUILD COMMANDS`) + chalk.gray(` (chain in order: --compile → --upload → --monitor)`));
|
|
53
57
|
console.log();
|
|
54
58
|
console.log(` --compile Compile the generated output using the framework toolchain.`);
|
|
@@ -277,6 +281,10 @@ function parsePipelineCommand(argv, command, inputFile) {
|
|
|
277
281
|
// --autosar-arxml: also write the .autosar-deviations.arxml sidecar
|
|
278
282
|
// (Artop/DaVinci tooling). No-op unless --autosar is warn or strict.
|
|
279
283
|
const autosarArxml = readBooleanFlag(argv, ["--autosar-arxml"]);
|
|
284
|
+
// --strict-css: upgrade UI CSS-compatibility warnings (css-* diagnostics,
|
|
285
|
+
// e.g. ignored alpha, quantized font sizes, unsupported display values) to
|
|
286
|
+
// errors so builds fail instead of silently approximating.
|
|
287
|
+
const strictCss = readBooleanFlag(argv, ["--strict-css"]);
|
|
280
288
|
const emitMode = emitFlag === "cpp" || emitFlag === "split" ? emitFlag : "split";
|
|
281
289
|
const emitMaps = emitMapsFlag === undefined ? true : emitMapsFlag !== "false";
|
|
282
290
|
// Accept any target string — the framework package registers its own strategy id.
|
|
@@ -329,6 +337,7 @@ function parsePipelineCommand(argv, command, inputFile) {
|
|
|
329
337
|
frameworkPackage: frameworkFlag,
|
|
330
338
|
autosar,
|
|
331
339
|
autosarArxml,
|
|
340
|
+
strictCss,
|
|
332
341
|
};
|
|
333
342
|
}
|
|
334
343
|
export function parseCommandLine(argv) {
|
package/dist/utils/ui.d.ts
CHANGED
|
@@ -27,6 +27,11 @@ export declare function printTranspiling(): void;
|
|
|
27
27
|
* Print compiling step
|
|
28
28
|
*/
|
|
29
29
|
export declare function printCompiling(target: string): void;
|
|
30
|
+
/**
|
|
31
|
+
* Print the debug-session strategy notice (debug builds only): which
|
|
32
|
+
* framework's code-generation strategy is preparing the debug build.
|
|
33
|
+
*/
|
|
34
|
+
export declare function printDebugStrategy(framework: string): void;
|
|
30
35
|
/**
|
|
31
36
|
* Print uploading step
|
|
32
37
|
*/
|
package/dist/utils/ui.js
CHANGED
|
@@ -69,6 +69,13 @@ export function printTranspiling() {
|
|
|
69
69
|
export function printCompiling(target) {
|
|
70
70
|
console.log(chalk.cyan(`${ICON_COMPILE} Compiling for `) + chalk.white(target));
|
|
71
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* Print the debug-session strategy notice (debug builds only): which
|
|
74
|
+
* framework's code-generation strategy is preparing the debug build.
|
|
75
|
+
*/
|
|
76
|
+
export function printDebugStrategy(framework) {
|
|
77
|
+
console.log(chalk.cyan(`${ICON_COMPILE} Preparing to debug using `) + chalk.white(framework));
|
|
78
|
+
}
|
|
72
79
|
/**
|
|
73
80
|
* Print uploading step
|
|
74
81
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@typecad/cuttlefish",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.13",
|
|
4
4
|
"description": "TypeScript to C++ transpiler — native, Arduino, and bare-metal targets",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/transpile.js",
|
|
@@ -83,7 +83,8 @@
|
|
|
83
83
|
}
|
|
84
84
|
},
|
|
85
85
|
"files": [
|
|
86
|
-
"dist"
|
|
86
|
+
"dist",
|
|
87
|
+
"assets"
|
|
87
88
|
],
|
|
88
89
|
"publishConfig": {
|
|
89
90
|
"access": "public"
|
|
@@ -99,8 +100,8 @@
|
|
|
99
100
|
"zod": "^3.24.0"
|
|
100
101
|
},
|
|
101
102
|
"peerDependencies": {
|
|
102
|
-
"@typecad/ui": "1.0.0-alpha.
|
|
103
|
-
"@typecad/safety": "1.0.0-alpha.
|
|
103
|
+
"@typecad/ui": "1.0.0-alpha.13",
|
|
104
|
+
"@typecad/safety": "1.0.0-alpha.13"
|
|
104
105
|
},
|
|
105
106
|
"peerDependenciesMeta": {
|
|
106
107
|
"@typecad/ui": {
|
|
@@ -111,8 +112,8 @@
|
|
|
111
112
|
}
|
|
112
113
|
},
|
|
113
114
|
"optionalDependencies": {
|
|
114
|
-
"@typecad/expect": "1.0.0-alpha.
|
|
115
|
-
"@typecad/framework-native": "1.0.0-alpha.
|
|
115
|
+
"@typecad/expect": "1.0.0-alpha.13",
|
|
116
|
+
"@typecad/framework-native": "1.0.0-alpha.13"
|
|
116
117
|
},
|
|
117
118
|
"devDependencies": {
|
|
118
119
|
"@types/node": "^22.10.7"
|