@fraczak/k 6.8.0 โ 6.9.0
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/CHANGELOG.md +10 -0
- package/DOCS/CODECS.md +80 -181
- package/DOCS/CODEC_ARCHITECTURE.md +194 -0
- package/DOCS/REPL.md +41 -39
- package/Examples/arithmetics.k +1 -0
- package/Examples/poly.k +46 -0
- package/browser/repl-browser.mjs +109 -782
- package/browser/shims/process.mjs +7 -0
- package/browser/tree-view.mjs +5 -2
- package/browser/vfs-data.mjs +14 -14
- package/codecs/README.md +7 -0
- package/codecs/ieee.mjs +50 -75
- package/codecs/int.mjs +83 -62
- package/codecs/json-codec.mjs +5 -77
- package/codecs/json.mjs +12 -56
- package/codecs/k-parse.mjs +3 -19
- package/codecs/runtime/codec-sdk.mjs +94 -0
- package/codecs/runtime/pattern-k.mjs +45 -0
- package/codecs/string-codec.mjs +48 -74
- package/codecs/unit.mjs +13 -61
- package/codecs/utf16.mjs +13 -56
- package/codecs/utf8.mjs +11 -55
- package/package.json +1 -1
- package/patterns/from-k.mjs +2 -22
- package/repl-codecs.mjs +69 -196
- package/repl.mjs +63 -187
- package/scripts/build-repl-html.mjs +87 -379
- package/scripts/run-tests.mjs +1 -0
- package/tests/test-codecs.mjs +186 -0
- package/tests/test-poly.mjs +44 -0
- package/tests/test-repl-html.mjs +123 -64
- package/tests/test-repl.mjs +120 -134
- package/tests/test-structural-values.mjs +17 -0
- package/tests/test-tree-view.mjs +3 -0
- package/codecs/example-pipeline.mjs +0 -163
- package/codecs/runtime/ieee-pattern.mjs +0 -30
- package/codecs/runtime/test-codec.mjs +0 -89
- package/codecs/runtime/typeFromValue.mjs +0 -34
|
@@ -12,7 +12,40 @@ const workspaceRoot = path.resolve(projectRoot, "..");
|
|
|
12
12
|
|
|
13
13
|
console.log("=== Building Self-Contained K REPL HTML ===");
|
|
14
14
|
|
|
15
|
-
// 1.
|
|
15
|
+
// 1. Node shims plugin for esbuild
|
|
16
|
+
const nodeShimsPlugin = {
|
|
17
|
+
name: "node-shims",
|
|
18
|
+
setup(build) {
|
|
19
|
+
const shims = {
|
|
20
|
+
"fs": path.join(projectRoot, "browser/shims/fs.mjs"),
|
|
21
|
+
"node:fs": path.join(projectRoot, "browser/shims/fs.mjs"),
|
|
22
|
+
"path": path.join(projectRoot, "browser/shims/path.mjs"),
|
|
23
|
+
"node:path": path.join(projectRoot, "browser/shims/path.mjs"),
|
|
24
|
+
"crypto": path.join(projectRoot, "browser/shims/crypto.mjs"),
|
|
25
|
+
"node:crypto": path.join(projectRoot, "browser/shims/crypto.mjs"),
|
|
26
|
+
"buffer": path.join(projectRoot, "browser/shims/buffer.mjs"),
|
|
27
|
+
"node:buffer": path.join(projectRoot, "browser/shims/buffer.mjs"),
|
|
28
|
+
"os": path.join(projectRoot, "browser/shims/os.mjs"),
|
|
29
|
+
"node:os": path.join(projectRoot, "browser/shims/os.mjs"),
|
|
30
|
+
"process": path.join(projectRoot, "browser/shims/process.mjs"),
|
|
31
|
+
"node:process": path.join(projectRoot, "browser/shims/process.mjs"),
|
|
32
|
+
"readline": path.join(projectRoot, "browser/shims/readline.mjs"),
|
|
33
|
+
"node:readline": path.join(projectRoot, "browser/shims/readline.mjs"),
|
|
34
|
+
"url": path.join(projectRoot, "browser/shims/url.mjs"),
|
|
35
|
+
"node:url": path.join(projectRoot, "browser/shims/url.mjs"),
|
|
36
|
+
"assert": path.join(projectRoot, "browser/shims/assert.mjs"),
|
|
37
|
+
"node:assert": path.join(projectRoot, "browser/shims/assert.mjs"),
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
build.onResolve({ filter: /^(node:)?(fs|path|crypto|buffer|os|process|readline|url|assert)$/ }, (args) => {
|
|
41
|
+
if (shims[args.path]) {
|
|
42
|
+
return { path: shims[args.path] };
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// 2. Scan and generate browser/vfs-data.mjs
|
|
16
49
|
console.log("1. Generating VFS data...");
|
|
17
50
|
const vfsFiles = {};
|
|
18
51
|
|
|
@@ -40,15 +73,48 @@ for (const filename of verifiedExamples) {
|
|
|
40
73
|
}
|
|
41
74
|
}
|
|
42
75
|
|
|
43
|
-
//
|
|
76
|
+
// Bundle verified codecs for browser VFS as 100% self-contained ES modules
|
|
44
77
|
const verifiedCodecs = ["json.mjs", "utf8.mjs", "int.mjs", "unit.mjs", "ieee.mjs"];
|
|
45
78
|
const codecsDir = path.join(projectRoot, "codecs");
|
|
79
|
+
|
|
80
|
+
const browserCodecSdkShim = `
|
|
81
|
+
export { Value, isProduct, isVariant, withPattern } from "../../Value.mjs";
|
|
82
|
+
export function runCodecCLI() {}
|
|
83
|
+
export function encodeToWire() {}
|
|
84
|
+
export function decodeWire() {}
|
|
85
|
+
export function patternFromFilter(script, options) {
|
|
86
|
+
if (typeof globalThis !== "undefined" && typeof globalThis.patternFromFilter === "function") {
|
|
87
|
+
return globalThis.patternFromFilter(script, options);
|
|
88
|
+
}
|
|
89
|
+
throw new Error("patternFromFilter is not available in browser environment");
|
|
90
|
+
}
|
|
91
|
+
`;
|
|
92
|
+
|
|
46
93
|
for (const filename of verifiedCodecs) {
|
|
47
94
|
const fullPath = path.join(codecsDir, filename);
|
|
48
95
|
if (fs.existsSync(fullPath) && fs.statSync(fullPath).isFile()) {
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
96
|
+
const buildRes = await esbuild.build({
|
|
97
|
+
entryPoints: [fullPath],
|
|
98
|
+
bundle: true,
|
|
99
|
+
format: "esm",
|
|
100
|
+
write: false,
|
|
101
|
+
plugins: [{
|
|
102
|
+
name: "codec-sdk-shim",
|
|
103
|
+
setup(build) {
|
|
104
|
+
build.onResolve({ filter: /(codec-sdk|pattern-k)\.mjs$/ }, (args) => ({
|
|
105
|
+
path: args.path,
|
|
106
|
+
namespace: "codec-sdk-shim"
|
|
107
|
+
}));
|
|
108
|
+
build.onLoad({ filter: /.*/, namespace: "codec-sdk-shim" }, () => ({
|
|
109
|
+
contents: browserCodecSdkShim,
|
|
110
|
+
resolveDir: path.join(codecsDir, "runtime")
|
|
111
|
+
}));
|
|
112
|
+
}
|
|
113
|
+
}]
|
|
114
|
+
});
|
|
115
|
+
const bundledContent = buildRes.outputFiles[0].text;
|
|
116
|
+
vfsFiles[filename] = bundledContent;
|
|
117
|
+
vfsFiles[`codecs/${filename}`] = bundledContent;
|
|
52
118
|
}
|
|
53
119
|
}
|
|
54
120
|
|
|
@@ -59,39 +125,6 @@ const vfsDataPath = path.join(projectRoot, "browser/vfs-data.mjs");
|
|
|
59
125
|
fs.writeFileSync(vfsDataPath, vfsDataContent, "utf8");
|
|
60
126
|
console.log(` Generated ${vfsDataPath} with ${Object.keys(vfsFiles).length} files.`);
|
|
61
127
|
|
|
62
|
-
// 2. Node shims plugin for esbuild
|
|
63
|
-
const nodeShimsPlugin = {
|
|
64
|
-
name: "node-shims",
|
|
65
|
-
setup(build) {
|
|
66
|
-
const shims = {
|
|
67
|
-
"fs": path.join(projectRoot, "browser/shims/fs.mjs"),
|
|
68
|
-
"node:fs": path.join(projectRoot, "browser/shims/fs.mjs"),
|
|
69
|
-
"path": path.join(projectRoot, "browser/shims/path.mjs"),
|
|
70
|
-
"node:path": path.join(projectRoot, "browser/shims/path.mjs"),
|
|
71
|
-
"crypto": path.join(projectRoot, "browser/shims/crypto.mjs"),
|
|
72
|
-
"node:crypto": path.join(projectRoot, "browser/shims/crypto.mjs"),
|
|
73
|
-
"buffer": path.join(projectRoot, "browser/shims/buffer.mjs"),
|
|
74
|
-
"node:buffer": path.join(projectRoot, "browser/shims/buffer.mjs"),
|
|
75
|
-
"os": path.join(projectRoot, "browser/shims/os.mjs"),
|
|
76
|
-
"node:os": path.join(projectRoot, "browser/shims/os.mjs"),
|
|
77
|
-
"process": path.join(projectRoot, "browser/shims/process.mjs"),
|
|
78
|
-
"node:process": path.join(projectRoot, "browser/shims/process.mjs"),
|
|
79
|
-
"readline": path.join(projectRoot, "browser/shims/readline.mjs"),
|
|
80
|
-
"node:readline": path.join(projectRoot, "browser/shims/readline.mjs"),
|
|
81
|
-
"url": path.join(projectRoot, "browser/shims/url.mjs"),
|
|
82
|
-
"node:url": path.join(projectRoot, "browser/shims/url.mjs"),
|
|
83
|
-
"assert": path.join(projectRoot, "browser/shims/assert.mjs"),
|
|
84
|
-
"node:assert": path.join(projectRoot, "browser/shims/assert.mjs"),
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
build.onResolve({ filter: /^(node:)?(fs|path|crypto|buffer|os|process|readline|url|assert)$/ }, (args) => {
|
|
88
|
-
if (shims[args.path]) {
|
|
89
|
-
return { path: shims[args.path] };
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
|
|
95
128
|
// 3. Bundle browser/repl-browser.mjs
|
|
96
129
|
console.log("2. Bundling with esbuild...");
|
|
97
130
|
const entryPoint = path.join(projectRoot, "browser/repl-browser.mjs");
|
|
@@ -1531,110 +1564,6 @@ const htmlContent = `<!DOCTYPE html>
|
|
|
1531
1564
|
min-height: 20px;
|
|
1532
1565
|
}
|
|
1533
1566
|
|
|
1534
|
-
/* Input Popup Modal */
|
|
1535
|
-
.input-popup-dialog {
|
|
1536
|
-
max-width: 580px;
|
|
1537
|
-
width: 90%;
|
|
1538
|
-
}
|
|
1539
|
-
|
|
1540
|
-
.input-popup-body {
|
|
1541
|
-
padding: 16px 20px;
|
|
1542
|
-
display: flex;
|
|
1543
|
-
flex-direction: column;
|
|
1544
|
-
gap: 12px;
|
|
1545
|
-
}
|
|
1546
|
-
|
|
1547
|
-
.input-popup-banner {
|
|
1548
|
-
background: var(--bg-base);
|
|
1549
|
-
border: 1px solid var(--border-color);
|
|
1550
|
-
border-radius: 6px;
|
|
1551
|
-
padding: 10px 14px;
|
|
1552
|
-
font-size: 12px;
|
|
1553
|
-
color: var(--text-main);
|
|
1554
|
-
display: flex;
|
|
1555
|
-
align-items: center;
|
|
1556
|
-
gap: 8px;
|
|
1557
|
-
}
|
|
1558
|
-
|
|
1559
|
-
.input-popup-form-row {
|
|
1560
|
-
display: flex;
|
|
1561
|
-
gap: 12px;
|
|
1562
|
-
flex-wrap: wrap;
|
|
1563
|
-
}
|
|
1564
|
-
|
|
1565
|
-
.input-popup-field {
|
|
1566
|
-
display: flex;
|
|
1567
|
-
flex-direction: column;
|
|
1568
|
-
}
|
|
1569
|
-
|
|
1570
|
-
.input-popup-textarea {
|
|
1571
|
-
width: 100%;
|
|
1572
|
-
background: #090d12;
|
|
1573
|
-
color: var(--text-main);
|
|
1574
|
-
border: 1px solid var(--border-color);
|
|
1575
|
-
border-radius: 6px;
|
|
1576
|
-
padding: 10px 12px;
|
|
1577
|
-
font-family: var(--font-mono);
|
|
1578
|
-
font-size: 13px;
|
|
1579
|
-
line-height: 1.4;
|
|
1580
|
-
resize: vertical;
|
|
1581
|
-
min-height: 90px;
|
|
1582
|
-
max-height: 280px;
|
|
1583
|
-
}
|
|
1584
|
-
|
|
1585
|
-
.input-popup-textarea:focus {
|
|
1586
|
-
border-color: var(--border-focus);
|
|
1587
|
-
box-shadow: 0 0 0 2px rgba(88, 166, 255, 0.2);
|
|
1588
|
-
outline: none;
|
|
1589
|
-
}
|
|
1590
|
-
|
|
1591
|
-
.input-popup-samples {
|
|
1592
|
-
display: flex;
|
|
1593
|
-
align-items: center;
|
|
1594
|
-
gap: 8px;
|
|
1595
|
-
font-size: 11px;
|
|
1596
|
-
color: var(--text-muted);
|
|
1597
|
-
flex-wrap: wrap;
|
|
1598
|
-
}
|
|
1599
|
-
|
|
1600
|
-
.samples-list {
|
|
1601
|
-
display: flex;
|
|
1602
|
-
gap: 6px;
|
|
1603
|
-
flex-wrap: wrap;
|
|
1604
|
-
}
|
|
1605
|
-
|
|
1606
|
-
.sample-pill {
|
|
1607
|
-
background: var(--bg-subtle);
|
|
1608
|
-
border: 1px solid var(--border-color);
|
|
1609
|
-
color: var(--color-prompt);
|
|
1610
|
-
padding: 2px 8px;
|
|
1611
|
-
border-radius: 12px;
|
|
1612
|
-
cursor: pointer;
|
|
1613
|
-
font-family: var(--font-mono);
|
|
1614
|
-
font-size: 11px;
|
|
1615
|
-
transition: all 0.15s;
|
|
1616
|
-
}
|
|
1617
|
-
|
|
1618
|
-
.sample-pill:hover {
|
|
1619
|
-
background: rgba(88, 166, 255, 0.2);
|
|
1620
|
-
border-color: var(--border-focus);
|
|
1621
|
-
}
|
|
1622
|
-
|
|
1623
|
-
.input-popup-status {
|
|
1624
|
-
font-size: 12px;
|
|
1625
|
-
min-height: 22px;
|
|
1626
|
-
border-radius: 4px;
|
|
1627
|
-
padding: 4px 8px;
|
|
1628
|
-
background: rgba(22, 27, 34, 0.5);
|
|
1629
|
-
}
|
|
1630
|
-
|
|
1631
|
-
.input-popup-actions {
|
|
1632
|
-
display: flex;
|
|
1633
|
-
justify-content: flex-end;
|
|
1634
|
-
gap: 8px;
|
|
1635
|
-
border-top: 1px solid var(--border-color);
|
|
1636
|
-
padding-top: 12px;
|
|
1637
|
-
}
|
|
1638
1567
|
|
|
1639
1568
|
/* Responsive */
|
|
1640
1569
|
@media (max-width: 768px) {
|
|
@@ -1712,12 +1641,13 @@ const htmlContent = `<!DOCTYPE html>
|
|
|
1712
1641
|
<optgroup label="Codecs & Format Adapters">
|
|
1713
1642
|
<option value="expr::codecs">:codecs</option>
|
|
1714
1643
|
<option value="expr::input">:input (interactive dialog)</option>
|
|
1715
|
-
<option value="expr::codec load int">:codec load int</option>
|
|
1716
|
-
<option value="expr::codec load utf8">:codec load utf8</option>
|
|
1717
|
-
<option value="expr::codec load json">:codec load json</option>
|
|
1718
|
-
<option value="expr::codec load ieee">:codec load ieee</option>
|
|
1719
|
-
<option value="expr::codec load unit">:codec load unit</option>
|
|
1720
|
-
<option value="expr::input {
|
|
1644
|
+
<option value="expr::codec load int.mjs">:codec load int.mjs</option>
|
|
1645
|
+
<option value="expr::codec load utf8.mjs">:codec load utf8.mjs</option>
|
|
1646
|
+
<option value="expr::codec load json.mjs">:codec load json.mjs</option>
|
|
1647
|
+
<option value="expr::codec load ieee.mjs">:codec load ieee.mjs</option>
|
|
1648
|
+
<option value="expr::codec load unit.mjs">:codec load unit.mjs</option>
|
|
1649
|
+
<option value="expr::input json.mjs {"a":12,"b":"hello"}">:input json.mjs {"a":12,"b":"hello"}</option>
|
|
1650
|
+
<option value="expr::input int.mjs [0,1,2]">:input int.mjs [0,1,2]</option>
|
|
1721
1651
|
</optgroup>
|
|
1722
1652
|
</select>
|
|
1723
1653
|
<button id="btn-load-example" class="btn btn-primary">Load</button>
|
|
@@ -1735,8 +1665,6 @@ const htmlContent = `<!DOCTYPE html>
|
|
|
1735
1665
|
<!-- Codecs Subsystem -->
|
|
1736
1666
|
<button id="btn-codecs" class="btn btn-secondary" title="Codecs & Custom Serializers (:codecs)">โ Codecs <span id="codecs-count-badge" class="badge-count">0</span></button>
|
|
1737
1667
|
|
|
1738
|
-
<!-- Codec Input Popup -->
|
|
1739
|
-
<button id="btn-input-popup" class="btn btn-secondary" title="Open Codec Input Popup (:input)">๐ฅ Input</button>
|
|
1740
1668
|
|
|
1741
1669
|
<!-- Clear -->
|
|
1742
1670
|
<button id="btn-clear" class="btn btn-secondary" title="Clear terminal screen (Ctrl+L)">โซ Clear</button>
|
|
@@ -1805,245 +1733,25 @@ const htmlContent = `<!DOCTYPE html>
|
|
|
1805
1733
|
<div class="modal-dialog codecs-dialog">
|
|
1806
1734
|
<div class="modal-header">
|
|
1807
1735
|
<div style="display: flex; align-items: center; gap: 10px;">
|
|
1808
|
-
<h3>
|
|
1736
|
+
<h3>Enabled Codecs</h3>
|
|
1809
1737
|
<span class="engine-badge">:codecs subsystem</span>
|
|
1810
1738
|
</div>
|
|
1811
1739
|
<button id="btn-close-codecs" class="btn-close">×</button>
|
|
1812
1740
|
</div>
|
|
1813
1741
|
<div class="modal-body codecs-body">
|
|
1814
|
-
<!-- Section 1: Available Format Codecs -->
|
|
1815
1742
|
<div class="codecs-section">
|
|
1816
1743
|
<div class="codecs-section-header">
|
|
1817
|
-
<h4>
|
|
1818
|
-
<span class="section-subtitle">
|
|
1744
|
+
<h4>Active Codecs in Current Session</h4>
|
|
1745
|
+
<span class="section-subtitle">Codecs format evaluation results and parse input for <code>:input <codec.mjs> [text]</code>. Codecs can only be loaded through <code>:codec load <file.mjs></code> in the REPL or through the <b>Files</b> explorer.</span>
|
|
1819
1746
|
</div>
|
|
1820
|
-
<div class="codec-grid">
|
|
1821
|
-
<!--
|
|
1822
|
-
<div class="codec-card" id="card-codec-int">
|
|
1823
|
-
<div class="codec-card-top">
|
|
1824
|
-
<div class="codec-card-title">
|
|
1825
|
-
<span class="codec-icon">๐ข</span>
|
|
1826
|
-
<span class="codec-name">int</span>
|
|
1827
|
-
<span id="codec-badge-int" class="codec-status-badge">Inactive</span>
|
|
1828
|
-
</div>
|
|
1829
|
-
<div class="codec-types">Target: <span class="badge-type">$ int</span></div>
|
|
1830
|
-
<div class="codec-desc">Converts decimal integers to/from <code>$ int = < bits '+', bits '-' ></code>.</div>
|
|
1831
|
-
</div>
|
|
1832
|
-
<div class="codec-card-footer">
|
|
1833
|
-
<div class="codec-caps">
|
|
1834
|
-
<span class="cap-badge print">Serializer</span>
|
|
1835
|
-
<span class="cap-badge parse">Deserializer</span>
|
|
1836
|
-
</div>
|
|
1837
|
-
<button id="btn-toggle-codec-int" class="btn btn-sm btn-primary">Load</button>
|
|
1838
|
-
</div>
|
|
1839
|
-
</div>
|
|
1840
|
-
|
|
1841
|
-
<!-- utf8 card -->
|
|
1842
|
-
<div class="codec-card" id="card-codec-utf8">
|
|
1843
|
-
<div class="codec-card-top">
|
|
1844
|
-
<div class="codec-card-title">
|
|
1845
|
-
<span class="codec-icon">๐ค</span>
|
|
1846
|
-
<span class="codec-name">utf8</span>
|
|
1847
|
-
<span id="codec-badge-utf8" class="codec-status-badge">Inactive</span>
|
|
1848
|
-
</div>
|
|
1849
|
-
<div class="codec-types">Target: <span class="badge-type">$ string ($ utf8)</span></div>
|
|
1850
|
-
<div class="codec-desc">Converts text to/from <code>$ string</code>, a list of Unicode scalar values (<code>$ unicode</code>) partitioned by Unicode planes.</div>
|
|
1851
|
-
</div>
|
|
1852
|
-
<div class="codec-card-footer">
|
|
1853
|
-
<div class="codec-caps">
|
|
1854
|
-
<span class="cap-badge print">Serializer</span>
|
|
1855
|
-
<span class="cap-badge parse">Deserializer</span>
|
|
1856
|
-
</div>
|
|
1857
|
-
<button id="btn-toggle-codec-utf8" class="btn btn-sm btn-primary">Load</button>
|
|
1858
|
-
</div>
|
|
1859
|
-
</div>
|
|
1860
|
-
|
|
1861
|
-
<!-- json card -->
|
|
1862
|
-
<div class="codec-card" id="card-codec-json">
|
|
1863
|
-
<div class="codec-card-top">
|
|
1864
|
-
<div class="codec-card-title">
|
|
1865
|
-
<span class="codec-icon">๐</span>
|
|
1866
|
-
<span class="codec-name">json</span>
|
|
1867
|
-
<span id="codec-badge-json" class="codec-status-badge">Inactive</span>
|
|
1868
|
-
</div>
|
|
1869
|
-
<div class="codec-types">Target: <span class="badge-type parameterized">Pattern / Universal</span></div>
|
|
1870
|
-
<div class="codec-desc">Universal / pattern-driven codec. Deserializes JSON text into <i>k</i> values using a pattern expression (e.g. <code>:input ? {float64 x, string n} json</code> or <code>:input json</code>), or serializes <i>k</i> values to JSON.</div>
|
|
1871
|
-
</div>
|
|
1872
|
-
<div class="codec-card-footer">
|
|
1873
|
-
<div class="codec-caps">
|
|
1874
|
-
<span class="cap-badge print">Serializer</span>
|
|
1875
|
-
<span class="cap-badge parse">Deserializer</span>
|
|
1876
|
-
</div>
|
|
1877
|
-
<button id="btn-toggle-codec-json" class="btn btn-sm btn-primary">Load</button>
|
|
1878
|
-
</div>
|
|
1879
|
-
</div>
|
|
1880
|
-
|
|
1881
|
-
<!-- ieee card -->
|
|
1882
|
-
<div class="codec-card" id="card-codec-ieee">
|
|
1883
|
-
<div class="codec-card-top">
|
|
1884
|
-
<div class="codec-card-title">
|
|
1885
|
-
<span class="codec-icon">๐งฎ</span>
|
|
1886
|
-
<span class="codec-name">ieee</span>
|
|
1887
|
-
<span id="codec-badge-ieee" class="codec-status-badge">Inactive</span>
|
|
1888
|
-
</div>
|
|
1889
|
-
<div class="codec-types">Target: <span class="badge-type">$ float64</span></div>
|
|
1890
|
-
<div class="codec-desc">IEEE 754 floating point numbers serialized to/from sign, exponent, and fraction fields.</div>
|
|
1891
|
-
</div>
|
|
1892
|
-
<div class="codec-card-footer">
|
|
1893
|
-
<div class="codec-caps">
|
|
1894
|
-
<span class="cap-badge print">Serializer</span>
|
|
1895
|
-
<span class="cap-badge parse">Deserializer</span>
|
|
1896
|
-
</div>
|
|
1897
|
-
<button id="btn-toggle-codec-ieee" class="btn btn-sm btn-primary">Load</button>
|
|
1898
|
-
</div>
|
|
1899
|
-
</div>
|
|
1900
|
-
</div>
|
|
1901
|
-
</div>
|
|
1902
|
-
|
|
1903
|
-
<!-- Section 2: Active Registered Codecs -->
|
|
1904
|
-
<div class="codecs-section">
|
|
1905
|
-
<div class="codecs-section-header">
|
|
1906
|
-
<h4>Active Registered Codecs in Current Session</h4>
|
|
1907
|
-
<span class="section-subtitle">Active codecs intercept evaluation formatting and :input commands</span>
|
|
1908
|
-
</div>
|
|
1909
|
-
<div class="codecs-table-container">
|
|
1910
|
-
<table class="codec-table">
|
|
1911
|
-
<thead>
|
|
1912
|
-
<tr>
|
|
1913
|
-
<th>Codec Name</th>
|
|
1914
|
-
<th>Target Type Binding</th>
|
|
1915
|
-
<th>Capabilities</th>
|
|
1916
|
-
<th>Source</th>
|
|
1917
|
-
<th>Action</th>
|
|
1918
|
-
</tr>
|
|
1919
|
-
</thead>
|
|
1920
|
-
<tbody id="active-codecs-tbody">
|
|
1921
|
-
<!-- dynamically populated by renderCodecsModal() -->
|
|
1922
|
-
</tbody>
|
|
1923
|
-
</table>
|
|
1924
|
-
</div>
|
|
1925
|
-
</div>
|
|
1926
|
-
|
|
1927
|
-
<!-- Section 3: Custom Codec Studio -->
|
|
1928
|
-
<div class="codecs-section">
|
|
1929
|
-
<div class="codecs-section-header">
|
|
1930
|
-
<h4>Custom Serializer & Deserializer Studio</h4>
|
|
1931
|
-
<span class="section-subtitle">Codecs convert external text representations to/from <i>k</i> values defined as pairs <code>(filter, tree)</code>.</span>
|
|
1932
|
-
</div>
|
|
1933
|
-
|
|
1934
|
-
<div class="codec-studio-box">
|
|
1935
|
-
<div class="studio-top-bar">
|
|
1936
|
-
<div class="studio-field">
|
|
1937
|
-
<label for="codec-preset-select">Preset Template:</label>
|
|
1938
|
-
<select id="codec-preset-select">
|
|
1939
|
-
<option value="yn">Yes / No ($ yes_no)</option>
|
|
1940
|
-
<option value="hex">Hexadecimal 0x... ($ int)</option>
|
|
1941
|
-
<option value="currency">Currency $XX.YY ($ int cents)</option>
|
|
1942
|
-
<option value="blank">Blank / Custom</option>
|
|
1943
|
-
</select>
|
|
1944
|
-
</div>
|
|
1945
|
-
|
|
1946
|
-
<div class="studio-field">
|
|
1947
|
-
<label for="codec-custom-name">Codec Name:</label>
|
|
1948
|
-
<input type="text" id="codec-custom-name" placeholder="e.g. yn" value="yn">
|
|
1949
|
-
</div>
|
|
1950
|
-
|
|
1951
|
-
<div class="studio-field" style="flex: 1;">
|
|
1952
|
-
<label for="codec-custom-type">Target Type:</label>
|
|
1953
|
-
<select id="codec-custom-type">
|
|
1954
|
-
<!-- populated dynamically from state.typeAliases -->
|
|
1955
|
-
</select>
|
|
1956
|
-
</div>
|
|
1957
|
-
</div>
|
|
1958
|
-
|
|
1959
|
-
<div class="studio-editors-grid">
|
|
1960
|
-
<div class="studio-editor-pane">
|
|
1961
|
-
<div class="pane-title">
|
|
1962
|
-
<span class="cap-badge parse">Deserializer (parse)</span>
|
|
1963
|
-
<span class="pane-hint"><code>(text, context) => Value</code></span>
|
|
1964
|
-
</div>
|
|
1965
|
-
<textarea id="codec-custom-parse" class="codec-code-area" spellcheck="false" rows="7"></textarea>
|
|
1966
|
-
</div>
|
|
1967
|
-
|
|
1968
|
-
<div class="studio-editor-pane">
|
|
1969
|
-
<div class="pane-title">
|
|
1970
|
-
<span class="cap-badge print">Serializer (print)</span>
|
|
1971
|
-
<span class="pane-hint"><code>(value, context) => string</code></span>
|
|
1972
|
-
</div>
|
|
1973
|
-
<textarea id="codec-custom-print" class="codec-code-area" spellcheck="false" rows="7"></textarea>
|
|
1974
|
-
</div>
|
|
1975
|
-
</div>
|
|
1976
|
-
|
|
1977
|
-
<div class="studio-test-bar">
|
|
1978
|
-
<div class="studio-test-input-wrap">
|
|
1979
|
-
<label for="codec-test-input">Test Input:</label>
|
|
1980
|
-
<input type="text" id="codec-test-input" placeholder="e.g. yes or 0xFF or $42.50" value="yes">
|
|
1981
|
-
</div>
|
|
1982
|
-
<button id="btn-test-parse" class="btn btn-secondary btn-sm" title="Test parse function against test input">๐งช Test Parse</button>
|
|
1983
|
-
<button id="btn-test-print" class="btn btn-secondary btn-sm" title="Test print function against current REPL value">๐จ Test Print</button>
|
|
1984
|
-
<button id="btn-register-codec" class="btn btn-primary btn-sm" title="Register codec in active REPL state">โ Register in REPL</button>
|
|
1985
|
-
<button id="btn-save-codec-vfs" class="btn btn-secondary btn-sm" title="Export as standalone .mjs file to VFS">๐พ Save to VFS</button>
|
|
1986
|
-
</div>
|
|
1987
|
-
|
|
1988
|
-
<div id="codec-studio-status" class="studio-status-box"></div>
|
|
1747
|
+
<div id="enabled-codecs-grid" class="codec-grid">
|
|
1748
|
+
<!-- dynamically populated: cards for only enabled/loaded codecs -->
|
|
1989
1749
|
</div>
|
|
1990
1750
|
</div>
|
|
1991
1751
|
</div>
|
|
1992
1752
|
</div>
|
|
1993
1753
|
</div>
|
|
1994
1754
|
|
|
1995
|
-
<!-- Input Popup Modal -->
|
|
1996
|
-
<div id="input-popup-modal" class="modal">
|
|
1997
|
-
<div class="modal-dialog input-popup-dialog">
|
|
1998
|
-
<div class="modal-header">
|
|
1999
|
-
<div style="display: flex; align-items: center; gap: 10px;">
|
|
2000
|
-
<h3>๐ฅ Code Input</h3>
|
|
2001
|
-
<span class="engine-badge">:input directive</span>
|
|
2002
|
-
</div>
|
|
2003
|
-
<button id="btn-close-input-popup" class="btn-close">×</button>
|
|
2004
|
-
</div>
|
|
2005
|
-
<div class="modal-body input-popup-body">
|
|
2006
|
-
<div id="input-popup-banner" class="input-popup-banner">
|
|
2007
|
-
<span id="input-popup-hint">Enter input string to deserialize into a K value:</span>
|
|
2008
|
-
</div>
|
|
2009
|
-
|
|
2010
|
-
<div class="input-popup-form-row">
|
|
2011
|
-
<div class="studio-field" style="flex: 1;">
|
|
2012
|
-
<label for="input-popup-type">Target Pattern:</label>
|
|
2013
|
-
<input type="text" id="input-popup-type" list="input-popup-type-list" placeholder="e.g. (...) or $ int or ? {float64 x, string n}" autocomplete="off">
|
|
2014
|
-
<datalist id="input-popup-type-list"></datalist>
|
|
2015
|
-
</div>
|
|
2016
|
-
<div class="studio-field" style="flex: 1;">
|
|
2017
|
-
<label for="input-popup-codec">Deserializer Codec:</label>
|
|
2018
|
-
<select id="input-popup-codec">
|
|
2019
|
-
<!-- populated dynamically -->
|
|
2020
|
-
</select>
|
|
2021
|
-
<div id="input-popup-codec-hint" class="input-popup-codec-hint" style="font-size:11px;color:var(--text-muted);margin-top:4px;"></div>
|
|
2022
|
-
</div>
|
|
2023
|
-
</div>
|
|
2024
|
-
|
|
2025
|
-
<div class="input-popup-field">
|
|
2026
|
-
<div class="pane-title" style="margin-bottom: 6px;">
|
|
2027
|
-
<label for="input-popup-text" style="font-size: 11px; color: var(--text-muted); font-weight: 500;">Input String / Payload:</label>
|
|
2028
|
-
<span class="pane-hint">Enter: submit • Shift+Enter: newline</span>
|
|
2029
|
-
</div>
|
|
2030
|
-
<textarea id="input-popup-text" class="input-popup-textarea" rows="4" spellcheck="false" placeholder="Type or paste input string (e.g. 42, yes, hello, {...})..."></textarea>
|
|
2031
|
-
</div>
|
|
2032
|
-
|
|
2033
|
-
<div id="input-popup-samples" class="input-popup-samples">
|
|
2034
|
-
<span class="samples-label">Quick samples:</span>
|
|
2035
|
-
<div id="input-samples-list" class="samples-list"></div>
|
|
2036
|
-
</div>
|
|
2037
|
-
|
|
2038
|
-
<div id="input-popup-status" class="input-popup-status"></div>
|
|
2039
|
-
|
|
2040
|
-
<div class="input-popup-actions">
|
|
2041
|
-
<button id="btn-cancel-input" class="btn btn-secondary">Cancel</button>
|
|
2042
|
-
<button id="btn-submit-input" class="btn btn-primary">โ Submit to REPL</button>
|
|
2043
|
-
</div>
|
|
2044
|
-
</div>
|
|
2045
|
-
</div>
|
|
2046
|
-
</div>
|
|
2047
1755
|
|
|
2048
1756
|
<!-- Help Modal -->
|
|
2049
1757
|
<div id="help-modal" class="modal">
|
|
@@ -2154,10 +1862,10 @@ const htmlContent = `<!DOCTYPE html>
|
|
|
2154
1862
|
<tr><td><code>:type <name></code></td><td>Display definition of type <code><name></code></td></tr>
|
|
2155
1863
|
<tr><td><code>:codes</code></td><td>List all type aliases and canonical hashes</td></tr>
|
|
2156
1864
|
<tr><td><code>:rels</code></td><td>List all relation aliases</td></tr>
|
|
2157
|
-
<tr><td><code>:codecs</code></td><td>List all
|
|
2158
|
-
<tr><td><code>:codec load <
|
|
2159
|
-
<tr><td><code>:codec unload <
|
|
2160
|
-
<tr><td><code>:input
|
|
1865
|
+
<tr><td><code>:codecs</code></td><td>List all loaded format codecs</td></tr>
|
|
1866
|
+
<tr><td><code>:codec load <file.mjs></code></td><td>Load a codec from file (or load through Files)</td></tr>
|
|
1867
|
+
<tr><td><code>:codec unload <file.mjs></code></td><td>Unload a loaded codec</td></tr>
|
|
1868
|
+
<tr><td><code>:input <codec.mjs> [text]</code></td><td>Parse input using specified codec (opens dialog if text omitted)</td></tr>
|
|
2161
1869
|
<tr><td><code>:time <expr></code></td><td>Evaluate <code><expr></code> and report execution time</td></tr>
|
|
2162
1870
|
<tr><td><code>:klib <file></code></td><td>Export current state as a <code>.klib</code> binary file</td></tr>
|
|
2163
1871
|
<tr><td><code>:reset</code></td><td>Clear state and reset to initial environment</td></tr>
|
package/scripts/run-tests.mjs
CHANGED
|
@@ -19,6 +19,7 @@ const tests = [
|
|
|
19
19
|
["tests/test-hash-fuzz.mjs", node, ["tests/test-hash-fuzz.mjs"]],
|
|
20
20
|
["tests/test-hash-normalization.mjs", node, ["tests/test-hash-normalization.mjs"]],
|
|
21
21
|
["tests/test-structural-values.mjs", node, ["tests/test-structural-values.mjs"]],
|
|
22
|
+
["tests/test-codecs.mjs", node, ["tests/test-codecs.mjs"]],
|
|
22
23
|
["tests/test-deep-wire-value.mjs", node, ["tests/test-deep-wire-value.mjs"]],
|
|
23
24
|
["tests/test-k-object.mjs", node, ["tests/test-k-object.mjs"]],
|
|
24
25
|
["tests/test-kir.mjs", node, ["tests/test-kir.mjs"]],
|