Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1585,6 +1585,7 @@ pub fn build(b: *std.Build) void {
b.step("test-ts-static-markup-specialized", "Compare static specialized metadata, forwarded handlers, tab triggers and complete failure effects").dependOn(&b.addRunArtifact(filteredTestArtifact(b, ts_core_artifacts.surface_layout.root_module, "ts-static-markup-specialized-tests", &.{ "static markup", "compiled markup values", "compiled markup metadata", "compiled markup options", "compiled markup postprocessing", "compiled markup numeric", "compiled markup admission", "compiled markup literals" })).step);
b.step("test-ts-static-markup-typography", "Compare static spans, interpolation, callback order and complete failure effects").dependOn(&b.addRunArtifact(filteredTestArtifact(b, ts_core_artifacts.surface_layout.root_module, "ts-static-markup-typography-tests", &.{ "static markup", "compiled markup specialized", "compiled markup runtime" })).step);
b.step("test-ts-static-markup-builders", "Compare static forms, timelines, charts, video and complete failure effects").dependOn(&b.addRunArtifact(filteredTestArtifact(b, ts_core_artifacts.surface_layout.root_module, "ts-static-markup-builder-tests", &.{ "static markup builders", "compiled markup specialized" })).step);
b.step("test-ts-static-markup-content", "Compare static markdown, code and stepper construction and complete failure effects").dependOn(&b.addRunArtifact(filteredTestArtifact(b, ts_core_artifacts.surface_layout.root_module, "ts-static-markup-content-tests", &.{ "static markup content builders", "compiled markup specialized" })).step);
b.step("test-ts-markup-postprocessing", "Compare forwarded handlers, provenance, tabs and borrowed binding paths").dependOn(&b.addRunArtifact(filteredTestArtifact(b, ts_core_artifacts.surface_layout.root_module, "ts-markup-postprocessing-tests", &.{ "compiled markup postprocessing", "compiled markup literals", "compiled markup admission", "compiled markup construction" })).step);
b.step("test-ts-markup-literals", "Compare exact literal inference, template defaults and lexical capture ownership").dependOn(&b.addRunArtifact(filteredTestArtifact(b, ts_core_artifacts.surface_layout.root_module, "ts-markup-literal-tests", &.{ "compiled markup literals", "compiled markup admission", "compiled markup construction" })).step);
b.step("test-ts-markup-admission", "Compare specialized attribute forms, raw flags and complete eager failure effects").dependOn(&b.addRunArtifact(filteredTestArtifact(b, ts_core_artifacts.surface_layout.root_module, "ts-markup-admission-tests", &.{ "compiled markup admission", "compiled markup specialized", "compiled markup options", "compiled markup metadata" })).step);
Expand Down
20 changes: 19 additions & 1 deletion packages/core/src/markup_specialized.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,24 @@ function nscsNode(r: NscElementReader, out: number[], mode: number): void {
nscsStaticAttrs(node, out, ["src", "controls", "autoplay", "loop", "muted", "width", "height", "grow", "label", "key", "global-key"]);
nsceEmit(out, 200); return;
}
if (mode === 29) {
nscsStaticAttrs(node, out, ["source", "on-link", "on-details", "details-expanded", "images", "issue-link-base"]);
nsceEmit(out, 200); return;
}
if (mode === 30) {
nscsStaticAttrs(node, out, ["source", "language", "line-numbers", "added-lines", "removed-lines", "editable", "on-input", "wrap", "width", "height", "min-width", "grow", "label", "key", "global-key"]);
nsceEmit(out, 200); return;
}
if (mode === 31) {
// Inherited slot steps interpolate in their lexical site scope; ordinary
// steps use the stepper's scope. The step array precedes every label.
const steps = r.word(), slot = r.flag();
if (slot ? node.children.length !== 1 : steps !== node.children.length) throw new Error("invalid static stepper facts");
nscsStaticAttrs(node, out, ["active", "key", "global-key", "label"]);
nsceEmit(out, 100);
for (let i = 0; i < steps; i++) nsceEmit(out, slot ? 102 : 101, 0, i);
nsceEmit(out, 200); return;
}
if (mode === 2) {
if (node.children.length !== 0) { nsceFail(out, 1, 1); return; }
if (!nscsAttrs(node, out, ["source", "on-link", "on-details", "details-expanded", "images", "issue-link-base"], 2, true)) return;
Expand Down Expand Up @@ -192,7 +210,7 @@ function nscsNode(r: NscElementReader, out: number[], mode: number): void {
throw new Error("invalid specialized node mode");
}
function nscvMarkupSpecialized(input: Uint8Array): Uint8Array {
if (input.length < 4 || input[0] !== 112 || input[1] !== 1 || input[2]! > 28 || input[3]! > 1) throw new Error("invalid specialized header");
if (input.length < 4 || input[0] !== 112 || input[1] !== 1 || input[2]! > 31 || input[3]! > 1) throw new Error("invalid specialized header");
const r = new NscElementReader(input), out: number[] = [], mode = input[2]!;
if (mode === 15) {
const count = r.word(), expected = r.word();
Expand Down
38 changes: 38 additions & 0 deletions packages/core/test/markup_specialized.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,41 @@ test("runtime specialized builders retain source order and repeated attributes",
[11, "series", ["label", "values", "label"], [], [4, 2, 4, 200]],
] as const) assert.deepEqual(actions(new Packet(mode).node(name, attrs(...names), [...children])), expected);
});

test("static markdown code and stepper programs fix source and active before first-occurrence channels", () => {
const specs = [
[29, "markdown", ["source", "on-link", "on-details", "details-expanded", "images", "issue-link-base"], [], [200]],
[30, "code", ["source", "language", "line-numbers", "added-lines", "removed-lines", "editable", "on-input", "wrap", "width", "height", "min-width", "grow", "label", "key", "global-key"], [], [200]],
[31, "stepper", ["active", "key", "global-key", "label"], [{ name: "step" }, { name: "step" }], [100, 101, 101, 200]],
] as const;
for (const [mode, name, names, children, tail] of specs) {
const facts = mode === 31 ? [children.length, 0] : [];
const all = (1 << names.length) - 1;
const masks = [1, all, (all & 0x5555) | 1, all & 0x2aaa | 1, ...names.flatMap((_, i) => [1 | (1 << i), all ^ (i === 0 ? 0 : 1 << i)])];
for (const mask of masks) {
const selected = names.filter((_, i) => (mask & (1 << i)) !== 0).reverse();
const rows = new Packet(mode).node(name, attrs("kind", ...selected, ...selected), [...children]).word(...facts).actions();
const channels = names.flatMap((_, i) => (mask & (1 << i)) !== 0 ? [i + 1] : []);
assert.deepEqual(rows.map(row => row.action), [...channels, ...tail]);
for (const row of rows.slice(0, channels.length)) assert.equal(row.fields[0], selected.indexOf(names[row.action - 1]!) + 1);
if (mode === 31) assert.deepEqual(rows.filter(row => row.action === 101).map(row => row.fields[0]), [0, 1]);
}
const bytes = new Packet(mode).node(name, attrs(...names), [...children]).word(...facts).bytes();
for (let end = 0; end < bytes.length; end++) assert.throws(() => run(bytes.subarray(0, end)));
assert.throws(() => run(Uint8Array.of(...bytes, 0)));
const sizing = bytes.slice(); sizing[3] = 0;
assert.equal(new DataView(run(sizing).buffer).getFloat64(8, true), names.length + tail.length);
}
const slot = new Packet(31).node("stepper", attrs("label", "active"), [{ kind: 6 }]).word(3, 1).actions();
assert.deepEqual(slot.map(row => [row.action, row.fields[0]]), [[1, 1], [4, 0], [100, 0], [102, 0], [102, 1], [102, 2], [200, 0]]);
assert.deepEqual(actions(new Packet(31).node("stepper", attrs("active"), [{ kind: 6 }]).word(0, 1)), [1, 100, 200]);
assert.deepEqual(actions(new Packet(31).node("stepper", attrs("active")).word(0, 0)), [1, 100, 200]);
for (const facts of [[1, 0], [0, 1], [2, 1], [0, 2]]) assert.throws(() => run(new Packet(31).node("stepper", attrs("active")).word(...facts).bytes()));
assert.throws(() => run(new Packet(32).node("markdown", attrs("source")).bytes()));
});

test("runtime markdown code and stepper programs retain source order and repeated attributes", () => {
assert.deepEqual(actions(new Packet(2).node("markdown", attrs("images", "source", "images"))), [5, 1, 5, 200]);
assert.deepEqual(actions(new Packet(3).node("code", attrs("label", "source", "label"))), [15, 1, 15, 200]);
assert.deepEqual(actions(new Packet(4).node("stepper", attrs("label", "active", "label"))), [4, 1, 4, 100]);
});
Loading
Loading