obix-compiler 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,56 @@
1
+ # obix-compiler
2
+
3
+ **The OBIX compiler: `.obix` → canonical DOP IR → ES6.**
4
+
5
+ ```bash
6
+ npm install obix-compiler
7
+ ```
8
+
9
+ Installing this package installs accessibility analysis with it.
10
+
11
+ ## API
12
+
13
+ ```ts
14
+ import { compile, compileFile } from "obix-compiler";
15
+
16
+ const { ok, ir, code, a11y, diagnostics } = compile(source, { path: "Timer.obix" });
17
+ ```
18
+
19
+ ## Pipeline
20
+
21
+ ```
22
+ source
23
+ → scanSections (obix-parser)
24
+ → parseTemplate/Script (obix-parser)
25
+ → validateObixAST (obix-spec — the parser seal, Problem 7)
26
+ → analyzeTemplate (obix-template)
27
+ → semantic checks (unknown binding refs / unknown actions)
28
+ → analyzeA11y (obix-accessibility — BEFORE emit, blocks on error)
29
+ → createScopeToken + scopeCss (obix-spec + obix-styles — one token, Problem 10)
30
+ → buildIR (canonical DOP IR — DATA FIRST, nothing past here adds logic)
31
+ → emitModule (ES6; verbatim <script>, one definition of every action)
32
+ ```
33
+
34
+ ## No `--no-a11y` (Problem 5)
35
+
36
+ `analyzeA11y` runs unconditionally. `hasBlockingA11yError` → `compile()` returns
37
+ `ok: false` with no `code`. There is no option, flag or env var that skips it.
38
+ GATE 7 (`scripts/check-a11y-required.mjs`) proves it.
39
+
40
+ ## Emit modes (Problem 6)
41
+
42
+ `"linked"` (default) / `"bare"` are implemented for Level 0. `"inline"` /
43
+ `"shared-inline"` throw `UnsupportedFeatureError` (Level 1) — they do not
44
+ silently degrade.
45
+
46
+ ## Dependency role
47
+
48
+ `obix-spec`, `obix-ir`, `obix-parser`, `obix-template`, `obix-styles`,
49
+ `obix-accessibility`, `obix-validator`. Consumed by `obix-cli` and
50
+ `obix-language-server`. Never depends on any adapter, the runtime, or `obix-timer`.
51
+
52
+ ## Level 0 status
53
+
54
+ ✅ props, state, actions, derived, `every` effect, text/attr/bool/ARIA
55
+ interpolation, `on:` events, single-element `obix:if`, scoped CSS, native-mount
56
+ IR. Deferred: loops, slots, composition, hydration, SCSS, async.
@@ -0,0 +1,15 @@
1
+ import type { Diagnostic, DopIR, A11yModel, EmitMode } from "obix-spec";
2
+ export interface CompileOptions {
3
+ path?: string;
4
+ mode?: EmitMode;
5
+ irImport?: string;
6
+ }
7
+ export interface CompileResult {
8
+ ok: boolean;
9
+ ir?: DopIR;
10
+ code?: string;
11
+ a11y?: A11yModel;
12
+ diagnostics: Diagnostic[];
13
+ }
14
+ export declare function compile(source: string, options?: CompileOptions): CompileResult;
15
+ //# sourceMappingURL=compile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../src/compile.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAW,QAAQ,EAAE,MAAM,WAAW,CAAC;AAQjF,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,OAAO,CAAC;IACZ,EAAE,CAAC,EAAE,KAAK,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B;AAmBD,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,aAAa,CAqFnF"}
@@ -0,0 +1,99 @@
1
+ import { validateObixAST, DIAGNOSTIC_CODES, createScopeToken } from "obix-spec";
2
+ import { scanSections, parseTemplate, parseScript, parseStyles } from "obix-parser";
3
+ import { analyzeTemplate } from "obix-template";
4
+ import { scopeCss } from "obix-styles";
5
+ import { analyzeA11y, hasBlockingA11yError } from "obix-accessibility";
6
+ import { buildIR } from "./ir.js";
7
+ import { emitModule } from "./emit.js";
8
+ const PASCAL = /^[A-Z][A-Za-z0-9]*$/;
9
+ function componentNameFromPath(path) {
10
+ if (!path)
11
+ return "Component";
12
+ const base = path.replace(/\\/g, "/").split("/").pop() ?? "Component";
13
+ return base.replace(/\.obix$/, "");
14
+ }
15
+ export function compile(source, options = {}) {
16
+ const diagnostics = [];
17
+ const name = componentNameFromPath(options.path);
18
+ if (!PASCAL.test(name)) {
19
+ diagnostics.push({ code: DIAGNOSTIC_CODES.P008_BAD_COMPONENT_NAME, severity: "error", message: `component file must be PascalCase, got "${name}"` });
20
+ }
21
+ const scan = scanSections(source);
22
+ diagnostics.push(...scan.diagnostics);
23
+ const tpl = scan.sections.template ? parseTemplate(scan.sections.template.raw) : undefined;
24
+ if (tpl)
25
+ diagnostics.push(...tpl.diagnostics);
26
+ const scr = scan.sections.script ? parseScript(scan.sections.script.raw) : undefined;
27
+ if (scr)
28
+ diagnostics.push(...scr.diagnostics);
29
+ const styleRaw = scan.sections.style?.raw ?? "";
30
+ const sty = parseStyles(styleRaw);
31
+ diagnostics.push(...sty.diagnostics);
32
+ const ast = {
33
+ componentName: name,
34
+ sections: scan.sections,
35
+ template: tpl?.ast,
36
+ script: scr?.model,
37
+ };
38
+ const structural = validateObixAST(ast);
39
+ for (const v of structural.violations) {
40
+ diagnostics.push({ code: DIAGNOSTIC_CODES.S005_PIPELINE_INVARIANT, severity: "error", message: `${v.rule}: ${v.message}` });
41
+ }
42
+ if (!tpl?.ast || !scr?.model || hasErrors(diagnostics)) {
43
+ return { ok: false, diagnostics };
44
+ }
45
+ const template = analyzeTemplate(tpl.ast);
46
+ const known = new Set([
47
+ ...scr.model.actionNames,
48
+ ...scr.model.derivedNames,
49
+ ...keysOf(scr.model.stateInit),
50
+ ...keysOf(scr.model.propsInit),
51
+ ]);
52
+ for (const b of template.bindings) {
53
+ for (const dep of b.deps) {
54
+ if (!known.has(dep)) {
55
+ diagnostics.push({ code: DIAGNOSTIC_CODES.S002_UNKNOWN_BINDING_REF, severity: "error", message: `binding "${b.expr}" references unknown name "${dep}"` });
56
+ }
57
+ }
58
+ }
59
+ for (const ev of template.events) {
60
+ if (!scr.model.actionNames.includes(ev.action)) {
61
+ diagnostics.push({ code: DIAGNOSTIC_CODES.S001_UNKNOWN_ACTION, severity: "error", message: `on:${ev.event} references unknown action "${ev.action}"` });
62
+ }
63
+ }
64
+ const a11y = analyzeA11y(template);
65
+ diagnostics.push(...a11y.diagnostics);
66
+ if (hasBlockingA11yError(a11y.diagnostics)) {
67
+ return { ok: false, a11y: a11y.model, diagnostics };
68
+ }
69
+ if (hasErrors(diagnostics)) {
70
+ return { ok: false, a11y: a11y.model, diagnostics };
71
+ }
72
+ const token = createScopeToken(name, options.path);
73
+ const scoped = scopeCss(styleRaw, token);
74
+ diagnostics.push(...scoped.diagnostics);
75
+ const ir = buildIR({
76
+ name,
77
+ script: scr.model,
78
+ template,
79
+ a11y: a11y.model,
80
+ style: { token, css: scoped.css },
81
+ });
82
+ const code = emitModule(ir, scr.model, { mode: options.mode, irImport: options.irImport });
83
+ return { ok: true, ir, code, a11y: a11y.model, diagnostics };
84
+ }
85
+ function hasErrors(d) {
86
+ return d.some((x) => x.severity === "error");
87
+ }
88
+ function keysOf(objSrc) {
89
+ if (!objSrc)
90
+ return [];
91
+ const inner = objSrc.replace(/^\s*\{/, "").replace(/\}\s*$/, "");
92
+ const keys = [];
93
+ const re = /(?:^|,)\s*([A-Za-z_$][\w$]*)\s*:/g;
94
+ let m;
95
+ while ((m = re.exec(inner)) !== null)
96
+ keys.push(m[1]);
97
+ return keys;
98
+ }
99
+ //# sourceMappingURL=compile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile.js","sourceRoot":"","sources":["../src/compile.ts"],"names":[],"mappings":"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"}
package/dist/emit.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ import type { DopIR, EmitMode, ObixScriptModel } from "obix-spec";
2
+ export interface EmitOptions {
3
+ mode?: EmitMode;
4
+ irImport?: string;
5
+ }
6
+ export declare function emitModule(ir: DopIR, script: ObixScriptModel, opts?: EmitOptions): string;
7
+ //# sourceMappingURL=emit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../src/emit.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAElE,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAYD,wBAAgB,UAAU,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,IAAI,GAAE,WAAgB,GAAG,MAAM,CAiG7F"}
package/dist/emit.js ADDED
@@ -0,0 +1,105 @@
1
+ import { UnsupportedFeatureError } from "obix-spec";
2
+ export function emitModule(ir, script, opts = {}) {
3
+ const mode = opts.mode ?? "linked";
4
+ if (mode === "inline" || mode === "shared-inline") {
5
+ throw new UnsupportedFeatureError(`compiler emit mode "${mode}"`, 1);
6
+ }
7
+ const irImport = opts.irImport ?? "obix-ir";
8
+ const N = ir.name;
9
+ return `/* @generated by obix-compiler — OBIX ${ir.specVersion}, Level ${ir.level}, mode "${mode}" */
10
+ import { createDOP } from ${JSON.stringify(irImport)};
11
+
12
+ /* ---- verbatim <script> ---- */
13
+ ${script.raw.trim()}
14
+ /* ---- end <script> ---- */
15
+
16
+ const __TEMPLATE = ${JSON.stringify(ir.template)};
17
+ const __STYLE = ${JSON.stringify(ir.style)};
18
+ const __ACTION_PROP_DEPS = ${JSON.stringify(mapPropDeps(ir))};
19
+ const __DERIVED_DEPS = ${JSON.stringify(ir.derivedDeps)};
20
+
21
+ function __esc(v) {
22
+ return String(v == null ? "" : v)
23
+ .replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
24
+ }
25
+ function __resolve(expr, scope) {
26
+ const parts = String(expr).trim().split(".");
27
+ let cur = scope[parts[0]];
28
+ for (let i = 1; i < parts.length && cur != null; i++) cur = cur[parts[i]];
29
+ return cur;
30
+ }
31
+ function __renderEl(el, scope) {
32
+ const cond = el.attrs.find((a) => a.directive === "conditional");
33
+ if (cond && !__resolve(cond.value, scope)) return "";
34
+ const VOID = new Set(["br", "hr", "img", "input", "meta", "link"]);
35
+ const attrs = [];
36
+ for (const a of el.attrs) {
37
+ if (a.directive === "event" || a.directive === "conditional") continue;
38
+ if (a.interpolation != null) {
39
+ const v = __resolve(a.interpolation, scope);
40
+ if (a.directive === "bool") { if (v) attrs.push(a.name); }
41
+ else if (a.directive === "aria") attrs.push(a.name + '="' + (v === true ? "true" : v === false ? "false" : __esc(v)) + '"');
42
+ else if (v != null && v !== false) attrs.push(a.name + '="' + (v === true ? "" : __esc(v)) + '"');
43
+ } else if (a.value === null) attrs.push(a.name);
44
+ else attrs.push(a.name + '="' + __esc(a.value) + '"');
45
+ }
46
+ const open = "<" + el.tag + (attrs.length ? " " + attrs.join(" ") : "") + ">";
47
+ if (VOID.has(el.tag)) return open;
48
+ const inner = el.children.map((c) => __renderNode(c, scope)).join("");
49
+ return open + inner + "</" + el.tag + ">";
50
+ }
51
+ function __renderNode(node, scope) {
52
+ if (node.kind === "text") return __esc(node.value).replace(/\\s+/g, " ");
53
+ if (node.kind === "interpolation") return __esc(__resolve(node.expr, scope));
54
+ return __renderEl(node, scope);
55
+ }
56
+ function __render(state, props) {
57
+ const d = {};
58
+ const src = (typeof derived !== "undefined" && derived) || {};
59
+ for (const k of Object.keys(src)) { try { d[k] = src[k](state, props); } catch { d[k] = undefined; } }
60
+ return __renderEl(__TEMPLATE.root, { ...props, ...state, ...d });
61
+ }
62
+ function __validate(state, props) {
63
+ if (typeof validate === "function") return validate(state, props);
64
+ return { valid: true, violations: [] };
65
+ }
66
+ function __normalizeEffects(raw) {
67
+ const out = {};
68
+ for (const [name, e] of Object.entries(raw || {})) {
69
+ out[name] = {
70
+ name,
71
+ kind: e.every != null ? "every" : e.after != null ? "after" : "on",
72
+ every: e.every,
73
+ dispatch: e.dispatch,
74
+ whileExpr: typeof e.while === "function" ? e.while.toString() : e.whileExpr,
75
+ while: typeof e.while === "function" ? e.while : undefined,
76
+ };
77
+ }
78
+ return out;
79
+ }
80
+
81
+ export const ${N}DOP = createDOP({
82
+ name: ${JSON.stringify(N)},
83
+ initialState: state,
84
+ props: props,
85
+ actions: actions,
86
+ derived: typeof derived !== "undefined" ? derived : {},
87
+ effects: __normalizeEffects(typeof effects !== "undefined" ? effects : {}),
88
+ validate: __validate,
89
+ render: __render,
90
+ template: __TEMPLATE,
91
+ style: __STYLE,
92
+ actionPropDeps: __ACTION_PROP_DEPS,
93
+ derivedDeps: __DERIVED_DEPS,
94
+ });
95
+
96
+ export default ${N}DOP;
97
+ `;
98
+ }
99
+ function mapPropDeps(ir) {
100
+ const out = {};
101
+ for (const [name, decl] of Object.entries(ir.actionDecls))
102
+ out[name] = decl.propDeps;
103
+ return out;
104
+ }
105
+ //# sourceMappingURL=emit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emit.js","sourceRoot":"","sources":["../src/emit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AAkBpD,MAAM,UAAU,UAAU,CAAC,EAAS,EAAE,MAAuB,EAAE,OAAoB,EAAE;IACnF,MAAM,IAAI,GAAa,IAAI,CAAC,IAAI,IAAI,QAAQ,CAAC;IAC7C,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,eAAe,EAAE,CAAC;QAClD,MAAM,IAAI,uBAAuB,CAAC,uBAAuB,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC;IACvE,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,SAAS,CAAC;IAC5C,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;IAElB,OAAO,yCAAyC,EAAE,CAAC,WAAW,WAAW,EAAE,CAAC,KAAK,WAAW,IAAI;4BACtE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;;;EAGlD,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE;;;qBAGE,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,QAAQ,CAAC;kBAC9B,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,CAAC;6BACb,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;yBACnC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,WAAW,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;eA8DxC,CAAC;UACN,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;;;;;;;;;;;;;;iBAcV,CAAC;CACjB,CAAC;AACF,CAAC;AAED,SAAS,WAAW,CAAC,EAAS;IAC5B,MAAM,GAAG,GAAsC,EAAE,CAAC;IAClD,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,WAAW,CAAC;QAAE,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC;IACrF,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { type CompileOptions, type CompileResult } from "./compile.js";
2
+ export { compile } from "./compile.js";
3
+ export type { CompileOptions, CompileResult } from "./compile.js";
4
+ export { emitModule } from "./emit.js";
5
+ export { buildIR } from "./ir.js";
6
+ export declare function compileFile(path: string, options?: Omit<CompileOptions, "path">): CompileResult;
7
+ export declare function checkSource(source: string, path?: string): {
8
+ ok: boolean;
9
+ diagnostics: import("obix-spec").Diagnostic[];
10
+ };
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAUA,OAAO,EAAW,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAEhF,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGlC,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,IAAI,CAAC,cAAc,EAAE,MAAM,CAAM,GAAG,aAAa,CAGnG;AAGD,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM;;;EAGxD"}
package/dist/index.js ADDED
@@ -0,0 +1,14 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { compile } from "./compile.js";
3
+ export { compile } from "./compile.js";
4
+ export { emitModule } from "./emit.js";
5
+ export { buildIR } from "./ir.js";
6
+ export function compileFile(path, options = {}) {
7
+ const source = readFileSync(path, "utf8").replace(/\r\n/g, "\n");
8
+ return compile(source, { ...options, path });
9
+ }
10
+ export function checkSource(source, path) {
11
+ const result = compile(source, { path });
12
+ return { ok: result.ok, diagnostics: result.diagnostics };
13
+ }
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAA2C,MAAM,cAAc,CAAC;AAEhF,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGlC,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,UAAwC,EAAE;IAClF,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACjE,OAAO,OAAO,CAAC,MAAM,EAAE,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;AAC/C,CAAC;AAGD,MAAM,UAAU,WAAW,CAAC,MAAc,EAAE,IAAa;IACvD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC;AAC5D,CAAC"}
package/dist/ir.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ import type { DopIR, ObixScriptModel, TemplateDescriptor, A11yModel } from "obix-spec";
2
+ export interface BuildIROptions {
3
+ name: string;
4
+ script: ObixScriptModel;
5
+ template: TemplateDescriptor;
6
+ a11y: A11yModel;
7
+ style: {
8
+ token: string;
9
+ css: string;
10
+ };
11
+ }
12
+ export declare function buildIR(opts: BuildIROptions): DopIR;
13
+ //# sourceMappingURL=ir.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ir.d.ts","sourceRoot":"","sources":["../src/ir.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,KAAK,EACL,eAAe,EACf,kBAAkB,EAClB,SAAS,EAIV,MAAM,WAAW,CAAC;AAEnB,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,eAAe,CAAC;IACxB,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CACvC;AAMD,wBAAgB,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG,KAAK,CA4DnD"}
package/dist/ir.js ADDED
@@ -0,0 +1,69 @@
1
+ import { SPEC_VERSION, LEVEL } from "obix-spec";
2
+ export function buildIR(opts) {
3
+ const { name, script, template, a11y, style } = opts;
4
+ const stateShape = keysOf(script.stateInit);
5
+ const propsShape = keysOf(script.propsInit);
6
+ const mentions = (body, ident) => new RegExp(`\\b${ident}\\b`).test(body);
7
+ const actionDecls = {};
8
+ for (const a of script.actionNames) {
9
+ const body = script.members.actions[a] ?? "";
10
+ const propDeps = propsShape.filter((p) => mentions(body, p));
11
+ const usesProps = /\bprops\b/.test(body) || propDeps.length > 0;
12
+ actionDecls[a] = {
13
+ name: a,
14
+ arity: usesProps ? 3 : /\bpayload\b|_payload/.test(body) ? 2 : 1,
15
+ usesProps,
16
+ propDeps,
17
+ };
18
+ }
19
+ const derivedDeps = {};
20
+ for (const d of script.derivedNames) {
21
+ const body = script.members.derived[d] ?? "";
22
+ derivedDeps[d] = {
23
+ name: d,
24
+ propDeps: propsShape.filter((p) => mentions(body, p)),
25
+ stateDeps: stateShape.filter((s) => mentions(body, s)),
26
+ };
27
+ }
28
+ const effects = {};
29
+ for (const e of script.effectNames) {
30
+ const body = script.members.effects[e] ?? "";
31
+ const every = body.match(/every\s*:\s*(\d+)/);
32
+ const after = body.match(/after\s*:\s*(\d+)/);
33
+ const dispatch = body.match(/dispatch\s*:\s*["']([A-Za-z_$][\w$]*)["']/);
34
+ const whileM = body.match(/while\s*:\s*([^\n,]+)/);
35
+ effects[e] = {
36
+ name: e,
37
+ kind: every ? "every" : after ? "after" : "on",
38
+ dispatch: dispatch ? dispatch[1] : "",
39
+ every: every ? Number(every[1]) : undefined,
40
+ whileExpr: whileM ? whileM[1].trim().replace(/[,}]\s*$/, "").trim() : undefined,
41
+ };
42
+ }
43
+ return {
44
+ name,
45
+ specVersion: SPEC_VERSION,
46
+ level: LEVEL,
47
+ stateShape,
48
+ propsShape,
49
+ actionDecls,
50
+ derivedDeps,
51
+ template,
52
+ events: template.events,
53
+ style,
54
+ a11y,
55
+ effects,
56
+ };
57
+ }
58
+ function keysOf(objSrc) {
59
+ if (!objSrc)
60
+ return [];
61
+ const inner = objSrc.replace(/^\s*\{/, "").replace(/\}\s*$/, "");
62
+ const keys = [];
63
+ const re = /(?:^|,)\s*([A-Za-z_$][\w$]*)\s*:/g;
64
+ let m;
65
+ while ((m = re.exec(inner)) !== null)
66
+ keys.push(m[1]);
67
+ return keys;
68
+ }
69
+ //# sourceMappingURL=ir.js.map
package/dist/ir.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ir.js","sourceRoot":"","sources":["../src/ir.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "obix-compiler",
3
+ "version": "0.2.1",
4
+ "description": "The OBIX compiler: source -> sections -> AST -> semantic AST -> canonical DOP IR -> ES6 emit. Accessibility analysis is a HARD dependency; there is no --no-a11y mode.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "private": false,
8
+ "sideEffects": false,
9
+ "main": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js"
15
+ },
16
+ "./package.json": "./package.json"
17
+ },
18
+ "files": ["dist", "README.md", "LICENSE"],
19
+ "scripts": {
20
+ "build": "tsc -p tsconfig.json"
21
+ },
22
+ "dependencies": {
23
+ "obix-spec": "0.2.1",
24
+ "obix-ir": "0.2.1",
25
+ "obix-parser": "0.2.1",
26
+ "obix-template": "0.2.1",
27
+ "obix-styles": "0.2.1",
28
+ "obix-accessibility": "0.2.1",
29
+ "obix-validator": "0.2.1"
30
+ },
31
+ "publishConfig": {
32
+ "access": "public"
33
+ },
34
+ "engines": {
35
+ "node": ">=20.11.0"
36
+ },
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "git+https://github.com/obinexusmk2/obix-monorepo-2026.git",
40
+ "directory": "packages/obix-compiler"
41
+ }
42
+ }