@fraczak/k 7.0.2 → 7.2.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 +75 -0
- package/DOCS/CODECS.md +37 -2
- package/DOCS/CODEC_ARCHITECTURE.md +12 -5
- package/DOCS/FILE_FORMATS.md +238 -15
- package/DOCS/POLYMORPHIC_IR.md +104 -0
- package/DOCS/REPL.md +11 -3
- package/DOCS/WEB_REPL_REQUIREMENTS.md +1 -1
- package/JOURNAL.md +288 -0
- package/README.md +12 -3
- package/Value.mjs +28 -3
- package/access-table.mjs +343 -0
- package/backend-api.mjs +23 -1
- package/backends/llvm/README.md +20 -21
- package/backends/llvm/bin/k-llvm-build.mjs +105 -32
- package/backends/llvm/bin/k-llvm-compile.mjs +63 -24
- package/backends/llvm/bin/k-llvm.mjs +292 -0
- package/backends/llvm/runtime/krt.c +8 -0
- package/backends/llvm/runtime/krt.h +1 -0
- package/backends/llvm/src/cli.mjs +95 -17
- package/backends/llvm/src/executable.mjs +128 -11
- package/backends/llvm/src/kvm2llvm.mjs +10 -5
- package/backends/llvm/src/llvm.mjs +121 -9
- package/backends/llvm/tests/integration.sh +11 -11
- package/backends/llvm/{bin → tests}/k-llvm-run.mjs +48 -22
- package/backends/llvm/tests/perf-support.mjs +24 -3
- package/backends/llvm/tests/test-llvm.mjs +22 -1
- package/backends/wasm/bin/k-wasm-compile.mjs +46 -20
- package/backends/wasm/bin/k-wasm-run.mjs +61 -20
- package/backends/wasm/bin/k-wasm.mjs +47 -13
- package/backends/wasm/src/cli.mjs +141 -19
- package/backends/wasm/src/wasm.mjs +130 -23
- package/browser/repl-browser.mjs +16 -5
- package/browser/tree-view.mjs +47 -8
- package/browser/vfs-data.mjs +6 -5
- package/codecs/README.md +1 -0
- package/codecs/djson.mjs +270 -0
- package/codecs/int.mjs +2 -1
- package/codecs/json.mjs +7 -2
- package/codecs/k-parse.mjs +36 -9
- package/codecs/k-print.mjs +26 -6
- package/codecs/runtime/codec-sdk.mjs +24 -6
- package/codecs/runtime/pattern-json.mjs +80 -1
- package/codecs/runtime/prefix-codec.mjs +629 -67
- package/codecs/runtime/show-value.mjs +93 -51
- package/codecs/runtime/unicode-string.mjs +29 -6
- package/codecs/show.mjs +24 -6
- package/codecs/utf16.mjs +2 -1
- package/k.mjs +56 -16
- package/kir.mjs +58 -19
- package/kvm.mjs +49 -12
- package/objects/compile.mjs +37 -23
- package/objects/decompile.mjs +40 -10
- package/objects/extract-aliases.mjs +44 -14
- package/objects/inspect.mjs +19 -14
- package/objects/validate.mjs +18 -11
- package/package.json +11 -3
- package/pkir.mjs +772 -0
- package/repl.mjs +92 -23
- package/scripts/build-repl-html.mjs +22 -3
- package/scripts/perf-ieee.mjs +264 -13
- package/scripts/perf-int.mjs +315 -22
- package/scripts/perf-multiplication.mjs +58 -7
- package/scripts/perf-poly.mjs +306 -24
- package/scripts/run-tests.mjs +3 -0
- package/tests/test-access-table.mjs +213 -0
- package/tests/test-codecs.mjs +168 -0
- package/tests/test-pkir.mjs +530 -0
- package/tests/test-polymorphic-tdd.mjs +196 -0
- package/tests/test-repl-html.mjs +16 -2
- package/tests/test-repl.mjs +63 -1
- package/backends/llvm/bin/k-llvm-jit.mjs +0 -160
|
@@ -14,7 +14,9 @@ import {
|
|
|
14
14
|
propertyListToPattern,
|
|
15
15
|
Value,
|
|
16
16
|
specializeKVM,
|
|
17
|
-
specializeObjectRelations
|
|
17
|
+
specializeObjectRelations,
|
|
18
|
+
compileRelationToPKIR,
|
|
19
|
+
lowerPKIRToKVM
|
|
18
20
|
} from "@fraczak/k/backend-api.mjs";
|
|
19
21
|
import { intersectPropertyListPatterns } from "@fraczak/k/codecs/runtime/codec.mjs";
|
|
20
22
|
import { propertyListToFilter } from "@fraczak/k/codecs/runtime/show-value.mjs";
|
|
@@ -283,7 +285,7 @@ function cloneKVMFunction(kvmFunc) {
|
|
|
283
285
|
};
|
|
284
286
|
}
|
|
285
287
|
|
|
286
|
-
function compileModule(mainRelName, defs) {
|
|
288
|
+
function compileModule(mainRelName, defs, { usePKIR = false } = {}) {
|
|
287
289
|
const compiled = new Set();
|
|
288
290
|
const queue = [mainRelName];
|
|
289
291
|
const wats = [];
|
|
@@ -299,8 +301,14 @@ function compileModule(mainRelName, defs) {
|
|
|
299
301
|
throw new Error(`Relation ${name} not found`);
|
|
300
302
|
}
|
|
301
303
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
+
let kvmFunc;
|
|
305
|
+
if (usePKIR) {
|
|
306
|
+
const pkir = compileRelationToPKIR(relDef, name);
|
|
307
|
+
kvmFunc = lowerPKIRToKVM(pkir);
|
|
308
|
+
} else {
|
|
309
|
+
kvmFunc = lowerToKVM(relDef, name);
|
|
310
|
+
kvmFunc.typePatternGraph = relDef.typePatternGraph;
|
|
311
|
+
}
|
|
304
312
|
scanCalls(kvmFunc.body, compiled, queue);
|
|
305
313
|
|
|
306
314
|
kvmFunc.name = nameMap.get(name) || cleanName(name);
|
|
@@ -502,7 +510,7 @@ function buildExportPreamble(exportSpecs, libraries) {
|
|
|
502
510
|
async function compileWasmArtifactFromDefs(
|
|
503
511
|
defs,
|
|
504
512
|
mainRelName = "__main__",
|
|
505
|
-
{ typingMode = "generic" } = {}
|
|
513
|
+
{ typingMode = "generic", usePKIR = false } = {}
|
|
506
514
|
) {
|
|
507
515
|
resetTagIds();
|
|
508
516
|
const mainRel = defs.rels[mainRelName];
|
|
@@ -510,7 +518,11 @@ async function compileWasmArtifactFromDefs(
|
|
|
510
518
|
throw new Error(`No main relation (${mainRelName}) defined in script`);
|
|
511
519
|
}
|
|
512
520
|
|
|
513
|
-
const { wat: moduleWatBody, relationNames, entryName } = compileModule(
|
|
521
|
+
const { wat: moduleWatBody, relationNames, entryName } = compileModule(
|
|
522
|
+
mainRelName,
|
|
523
|
+
defs,
|
|
524
|
+
{ usePKIR }
|
|
525
|
+
);
|
|
514
526
|
assertRelationsConverged(defs, relationNames);
|
|
515
527
|
const fullWat = runtimeWat.trim().slice(0, -1) + "\n" + moduleWatBody + "\n)";
|
|
516
528
|
const graph = mainRel.typePatternGraph;
|
|
@@ -523,7 +535,12 @@ async function compileWasmArtifactFromDefs(
|
|
|
523
535
|
entry: entryName || cleanName(mainRelName),
|
|
524
536
|
inputPattern,
|
|
525
537
|
outputPattern,
|
|
526
|
-
typing: classifyTyping(
|
|
538
|
+
typing: classifyTyping(
|
|
539
|
+
inputPattern,
|
|
540
|
+
outputPattern,
|
|
541
|
+
relTypeStatus(defs, mainRelName),
|
|
542
|
+
typingMode
|
|
543
|
+
),
|
|
527
544
|
tags: getTagEntries()
|
|
528
545
|
};
|
|
529
546
|
return appendCustomSection(await compileWat(fullWat), METADATA_SECTION, JSON.stringify(metadata));
|
|
@@ -598,12 +615,17 @@ async function compileWasmArtifactFromKVM(kvmInput, options = {}) {
|
|
|
598
615
|
return appendCustomSection(await compileWat(fullWat), METADATA_SECTION, JSON.stringify(metadata));
|
|
599
616
|
}
|
|
600
617
|
|
|
601
|
-
async function compileWasmArtifactFromObject(
|
|
618
|
+
async function compileWasmArtifactFromObject(
|
|
619
|
+
object,
|
|
620
|
+
{ entry = null, inputEnvelopePattern = null, usePKIR = false } = {}
|
|
621
|
+
) {
|
|
602
622
|
if (!object?.rels) {
|
|
603
623
|
throw new Error("Expected .ko input to contain k object relations");
|
|
604
624
|
}
|
|
605
625
|
if (object.main == null) {
|
|
606
|
-
throw new Error(
|
|
626
|
+
throw new Error(
|
|
627
|
+
"Cannot compile a .klib library to WebAssembly without a main relation"
|
|
628
|
+
);
|
|
607
629
|
}
|
|
608
630
|
const mainRelName = entry || object.main || "__main__";
|
|
609
631
|
let defs = { rels: object.rels, compileStats: object.compileStats };
|
|
@@ -611,43 +633,126 @@ async function compileWasmArtifactFromObject(object, { entry = null, inputEnvelo
|
|
|
611
633
|
|
|
612
634
|
if (inputEnvelopePattern) {
|
|
613
635
|
const mainRel = object.rels[mainRelName];
|
|
614
|
-
if (!mainRel)
|
|
615
|
-
|
|
616
|
-
|
|
636
|
+
if (!mainRel) {
|
|
637
|
+
throw new Error(`No main relation (${mainRelName}) defined in object`);
|
|
638
|
+
}
|
|
639
|
+
const inputPattern = getPatternPropertyList(
|
|
640
|
+
mainRel.typePatternGraph,
|
|
641
|
+
mainRel.def.patterns[0]
|
|
642
|
+
);
|
|
643
|
+
const outputPattern = getPatternPropertyList(
|
|
644
|
+
mainRel.typePatternGraph,
|
|
645
|
+
mainRel.def.patterns[1]
|
|
646
|
+
);
|
|
617
647
|
const typing = classifyTyping(inputPattern, outputPattern);
|
|
618
648
|
if (typing.program === "polymorphic") {
|
|
619
|
-
const specialized = specializeObjectRelations(
|
|
620
|
-
|
|
649
|
+
const specialized = specializeObjectRelations(
|
|
650
|
+
object,
|
|
651
|
+
mainRelName,
|
|
652
|
+
inputEnvelopePattern
|
|
653
|
+
);
|
|
654
|
+
defs = {
|
|
655
|
+
rels: specialized.rels,
|
|
656
|
+
relAlias: specialized.relAlias,
|
|
657
|
+
compileStats: specialized.compileStats
|
|
658
|
+
};
|
|
621
659
|
typingMode = "specialized";
|
|
622
660
|
}
|
|
623
661
|
}
|
|
624
662
|
|
|
625
|
-
return compileWasmArtifactFromDefs(defs, mainRelName, {
|
|
663
|
+
return compileWasmArtifactFromDefs(defs, mainRelName, {
|
|
664
|
+
typingMode,
|
|
665
|
+
usePKIR
|
|
666
|
+
});
|
|
626
667
|
}
|
|
627
668
|
|
|
628
669
|
async function compileWasmArtifact(
|
|
629
670
|
source,
|
|
630
|
-
{
|
|
671
|
+
{
|
|
672
|
+
libraries = [],
|
|
673
|
+
exports = [],
|
|
674
|
+
source: sourceName = null,
|
|
675
|
+
inputEnvelopePattern = null,
|
|
676
|
+
usePKIR = false
|
|
677
|
+
} = {}
|
|
631
678
|
) {
|
|
632
679
|
const preamble = buildExportPreamble(exports, libraries);
|
|
633
680
|
const fullSource = preamble + source;
|
|
634
|
-
const options = {
|
|
681
|
+
const options = {
|
|
682
|
+
libraries,
|
|
683
|
+
...(sourceName ? { source: sourceName } : {})
|
|
684
|
+
};
|
|
635
685
|
let defs = annotate(fullSource, options);
|
|
636
686
|
|
|
637
687
|
let typingMode = "generic";
|
|
638
688
|
if (inputEnvelopePattern) {
|
|
639
689
|
const mainRel = defs.rels.__main__;
|
|
640
|
-
const inputPattern = getPatternPropertyList(
|
|
641
|
-
|
|
690
|
+
const inputPattern = getPatternPropertyList(
|
|
691
|
+
mainRel.typePatternGraph,
|
|
692
|
+
mainRel.def.patterns[0]
|
|
693
|
+
);
|
|
694
|
+
const outputPattern = getPatternPropertyList(
|
|
695
|
+
mainRel.typePatternGraph,
|
|
696
|
+
mainRel.def.patterns[1]
|
|
697
|
+
);
|
|
642
698
|
if (classifyTyping(inputPattern, outputPattern).program === "polymorphic") {
|
|
643
|
-
const obj = {
|
|
644
|
-
|
|
645
|
-
|
|
699
|
+
const obj = {
|
|
700
|
+
format: "k-object",
|
|
701
|
+
rels: defs.rels,
|
|
702
|
+
relAlias: defs.relAlias,
|
|
703
|
+
compileStats: defs.compileStats,
|
|
704
|
+
main: "__main__"
|
|
705
|
+
};
|
|
706
|
+
const specialized = specializeObjectRelations(
|
|
707
|
+
obj,
|
|
708
|
+
"__main__",
|
|
709
|
+
inputEnvelopePattern
|
|
710
|
+
);
|
|
711
|
+
defs = {
|
|
712
|
+
rels: specialized.rels,
|
|
713
|
+
relAlias: specialized.relAlias,
|
|
714
|
+
compileStats: specialized.compileStats
|
|
715
|
+
};
|
|
646
716
|
typingMode = "specialized";
|
|
647
717
|
}
|
|
648
718
|
}
|
|
649
719
|
|
|
650
|
-
return compileWasmArtifactFromDefs(defs, "__main__", {
|
|
720
|
+
return compileWasmArtifactFromDefs(defs, "__main__", {
|
|
721
|
+
typingMode,
|
|
722
|
+
usePKIR
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
async function compileWasmArtifactFromPKIR(pkirInput, options = {}) {
|
|
727
|
+
let kvmProgram;
|
|
728
|
+
let entry = options.entry || "__main__";
|
|
729
|
+
if (pkirInput && typeof pkirInput === "object") {
|
|
730
|
+
if (pkirInput.format === "pk-ir" && pkirInput.functions) {
|
|
731
|
+
entry = pkirInput.entry || entry;
|
|
732
|
+
kvmProgram = {};
|
|
733
|
+
for (const [name, f] of Object.entries(pkirInput.functions)) {
|
|
734
|
+
kvmProgram[name] = lowerPKIRToKVM(f);
|
|
735
|
+
}
|
|
736
|
+
} else if (pkirInput.instructions) {
|
|
737
|
+
const kvm = lowerPKIRToKVM(pkirInput);
|
|
738
|
+
entry = kvm.name || entry;
|
|
739
|
+
kvmProgram = { [entry]: kvm };
|
|
740
|
+
} else if (pkirInput.functions) {
|
|
741
|
+
entry = pkirInput.entry || entry;
|
|
742
|
+
kvmProgram = {};
|
|
743
|
+
for (const [name, f] of Object.entries(pkirInput.functions)) {
|
|
744
|
+
kvmProgram[name] = lowerPKIRToKVM(f);
|
|
745
|
+
}
|
|
746
|
+
} else {
|
|
747
|
+
throw new Error("Invalid PKIR input for WebAssembly compilation");
|
|
748
|
+
}
|
|
749
|
+
} else {
|
|
750
|
+
throw new Error("Expected PKIR input object");
|
|
751
|
+
}
|
|
752
|
+
return compileWasmArtifactFromKVM(
|
|
753
|
+
{ format: "k-vm", layer: "KVM", entry, functions: kvmProgram },
|
|
754
|
+
options
|
|
755
|
+
);
|
|
651
756
|
}
|
|
652
757
|
|
|
653
758
|
function createTagRegistry(entries) {
|
|
@@ -1050,6 +1155,7 @@ export {
|
|
|
1050
1155
|
appendCustomSection,
|
|
1051
1156
|
compileWasmArtifactFromKVM,
|
|
1052
1157
|
compileWasmArtifactFromObject,
|
|
1158
|
+
compileWasmArtifactFromPKIR,
|
|
1053
1159
|
compileWasmArtifact,
|
|
1054
1160
|
instantiateWasmArtifact,
|
|
1055
1161
|
metadataFromModule,
|
|
@@ -1067,6 +1173,7 @@ export default {
|
|
|
1067
1173
|
appendCustomSection,
|
|
1068
1174
|
compileWasmArtifactFromKVM,
|
|
1069
1175
|
compileWasmArtifactFromObject,
|
|
1176
|
+
compileWasmArtifactFromPKIR,
|
|
1070
1177
|
compileWasmArtifact,
|
|
1071
1178
|
metadataFromModule,
|
|
1072
1179
|
readArenaValue,
|
package/browser/repl-browser.mjs
CHANGED
|
@@ -311,13 +311,17 @@ export async function executeCommand(input) {
|
|
|
311
311
|
function updateEngineUI() {
|
|
312
312
|
const badge = document.getElementById("engine-badge");
|
|
313
313
|
if (!badge) return;
|
|
314
|
-
badge.
|
|
315
|
-
badge.title = `Engine: ${state.engine} (click to toggle wasm/js)`;
|
|
314
|
+
badge.classList.remove("js-mode", "pkir-mode");
|
|
316
315
|
if (state.engine === "js") {
|
|
316
|
+
badge.textContent = "js-in-process";
|
|
317
317
|
badge.classList.add("js-mode");
|
|
318
|
+
} else if (state.engine === "pkir") {
|
|
319
|
+
badge.textContent = "pkir-wasm";
|
|
320
|
+
badge.classList.add("pkir-mode");
|
|
318
321
|
} else {
|
|
319
|
-
badge.
|
|
322
|
+
badge.textContent = "wasm-in-process";
|
|
320
323
|
}
|
|
324
|
+
badge.title = `Engine: ${state.engine} (click to toggle wasm/pkir/js)`;
|
|
321
325
|
}
|
|
322
326
|
|
|
323
327
|
function adjustInputHeight() {
|
|
@@ -979,11 +983,18 @@ export function initRepl() {
|
|
|
979
983
|
}
|
|
980
984
|
});
|
|
981
985
|
|
|
982
|
-
// Engine Badge toggle (wasm
|
|
986
|
+
// Engine Badge toggle (wasm -> pkir -> js -> wasm)
|
|
983
987
|
const engineBadge = document.getElementById("engine-badge");
|
|
984
988
|
if (engineBadge) {
|
|
985
989
|
engineBadge.onclick = () => {
|
|
986
|
-
|
|
990
|
+
let nextEngine;
|
|
991
|
+
if (state.engine === "wasm") {
|
|
992
|
+
nextEngine = "pkir";
|
|
993
|
+
} else if (state.engine === "pkir") {
|
|
994
|
+
nextEngine = "js";
|
|
995
|
+
} else {
|
|
996
|
+
nextEngine = "wasm";
|
|
997
|
+
}
|
|
987
998
|
executeCommand(`:engine ${nextEngine}`);
|
|
988
999
|
};
|
|
989
1000
|
}
|
package/browser/tree-view.mjs
CHANGED
|
@@ -101,7 +101,9 @@ export function renderValueNode(val, currentDepth = 1, depthLimit = 3) {
|
|
|
101
101
|
const populateChildren = () => {
|
|
102
102
|
if (populated) return;
|
|
103
103
|
populated = true;
|
|
104
|
-
|
|
104
|
+
const maxFields = 100;
|
|
105
|
+
const displayKeys = keys.slice(0, maxFields);
|
|
106
|
+
for (const k of displayKeys) {
|
|
105
107
|
const row = document.createElement("div");
|
|
106
108
|
row.className = "k-tree-row";
|
|
107
109
|
|
|
@@ -113,12 +115,25 @@ export function renderValueNode(val, currentDepth = 1, depthLimit = 3) {
|
|
|
113
115
|
const childContainer = document.createElement("div");
|
|
114
116
|
childContainer.className = "k-tree-child-val";
|
|
115
117
|
childContainer.appendChild(
|
|
116
|
-
renderValueNode(
|
|
118
|
+
renderValueNode(
|
|
119
|
+
val.product[k],
|
|
120
|
+
isOpen ? currentDepth + 1 : 1,
|
|
121
|
+
depthLimit
|
|
122
|
+
)
|
|
117
123
|
);
|
|
118
124
|
row.appendChild(childContainer);
|
|
119
125
|
|
|
120
126
|
childrenContainer.appendChild(row);
|
|
121
127
|
}
|
|
128
|
+
if (keys.length > maxFields) {
|
|
129
|
+
const moreRow = document.createElement("div");
|
|
130
|
+
moreRow.className = "k-tree-row k-tree-more";
|
|
131
|
+
moreRow.style.color = "var(--color-muted)";
|
|
132
|
+
moreRow.style.paddingLeft = "1.2rem";
|
|
133
|
+
moreRow.textContent =
|
|
134
|
+
`... and ${keys.length - maxFields} more fields`;
|
|
135
|
+
childrenContainer.appendChild(moreRow);
|
|
136
|
+
}
|
|
122
137
|
};
|
|
123
138
|
|
|
124
139
|
if (isOpen) {
|
|
@@ -169,13 +184,15 @@ export function renderValueNode(val, currentDepth = 1, depthLimit = 3) {
|
|
|
169
184
|
if (isVariant(val.value)) {
|
|
170
185
|
let chainCount = 0;
|
|
171
186
|
let curr = val.value;
|
|
172
|
-
while (isVariant(curr)) {
|
|
187
|
+
while (isVariant(curr) && chainCount < 20) {
|
|
173
188
|
chainCount++;
|
|
174
189
|
curr = curr.value;
|
|
175
190
|
}
|
|
176
191
|
const badge = document.createElement("span");
|
|
177
192
|
badge.className = "k-tree-badge";
|
|
178
|
-
badge.textContent =
|
|
193
|
+
badge.textContent = isVariant(curr)
|
|
194
|
+
? "+20+ tags"
|
|
195
|
+
: `+${chainCount} tags`;
|
|
179
196
|
summary.appendChild(badge);
|
|
180
197
|
}
|
|
181
198
|
|
|
@@ -486,7 +503,15 @@ export function createOutputEntryElement({
|
|
|
486
503
|
|
|
487
504
|
const valSummary = document.createElement("summary");
|
|
488
505
|
valSummary.className = "k-tree-section-summary";
|
|
489
|
-
|
|
506
|
+
const rawValPreview = valueToK(value, 120);
|
|
507
|
+
const valPreview = rawValPreview.length > 120
|
|
508
|
+
? `${rawValPreview.slice(0, 120)}...`
|
|
509
|
+
: rawValPreview;
|
|
510
|
+
const valEscaped = escapeHtml(valPreview);
|
|
511
|
+
valSummary.innerHTML =
|
|
512
|
+
`<span class="k-tree-arrow">▶</span> ` +
|
|
513
|
+
`<span class="k-section-title">🌲 Value</span> ` +
|
|
514
|
+
`<span class="k-section-preview">${valEscaped}</span>`;
|
|
490
515
|
valSection.appendChild(valSummary);
|
|
491
516
|
|
|
492
517
|
const valBody = document.createElement("div");
|
|
@@ -504,8 +529,15 @@ export function createOutputEntryElement({
|
|
|
504
529
|
|
|
505
530
|
const patSummary = document.createElement("summary");
|
|
506
531
|
patSummary.className = "k-tree-section-summary";
|
|
507
|
-
const
|
|
508
|
-
|
|
532
|
+
const rawPatPreview = propertyListToFilter(value.pattern, "X", 120);
|
|
533
|
+
const patPreview = rawPatPreview.length > 120
|
|
534
|
+
? `${rawPatPreview.slice(0, 120)}...`
|
|
535
|
+
: rawPatPreview;
|
|
536
|
+
const patEscaped = escapeHtml(patPreview);
|
|
537
|
+
patSummary.innerHTML =
|
|
538
|
+
`<span class="k-tree-arrow">▶</span> ` +
|
|
539
|
+
`<span class="k-section-title">🌿 Pattern</span> ` +
|
|
540
|
+
`<span class="k-section-preview">?${patEscaped}</span>`;
|
|
509
541
|
patSection.appendChild(patSummary);
|
|
510
542
|
|
|
511
543
|
patBody = document.createElement("div");
|
|
@@ -545,7 +577,14 @@ export function createOutputEntryElement({
|
|
|
545
577
|
|
|
546
578
|
const rawPre = document.createElement("pre");
|
|
547
579
|
rawPre.className = "k-raw-pre";
|
|
548
|
-
|
|
580
|
+
const MAX_RAW_PRE_CHARS = 100000;
|
|
581
|
+
if (rawText.length > MAX_RAW_PRE_CHARS) {
|
|
582
|
+
rawPre.textContent =
|
|
583
|
+
rawText.slice(0, MAX_RAW_PRE_CHARS) +
|
|
584
|
+
`\n\n... [truncated, ${rawText.length - MAX_RAW_PRE_CHARS} more characters]`;
|
|
585
|
+
} else {
|
|
586
|
+
rawPre.textContent = rawText;
|
|
587
|
+
}
|
|
549
588
|
rawWrapper.appendChild(rawPre);
|
|
550
589
|
|
|
551
590
|
container.appendChild(rawWrapper);
|