@cimplify/cli 0.15.3 → 0.17.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/LICENSE +21 -0
- package/README.md +2 -2
- package/dist/add-C3DPTVH3.mjs +140 -0
- package/dist/{add-KRIIKAS4.mjs → add-JX2GXWXU.mjs} +4 -4
- package/dist/ai-HUZTVJIQ.mjs +17 -0
- package/dist/{assets-CWB72PZG.mjs → assets-MPESJSUV.mjs} +12 -7
- package/dist/{auth-step-up-Z6KOTTV7.mjs → auth-step-up-VJAFGSW6.mjs} +5 -5
- package/dist/build-E7RRQWVF.mjs +616 -0
- package/dist/{cancel-ZHVVILOU.mjs → cancel-UMKR274A.mjs} +4 -4
- package/dist/capture-TK4NIUYM.mjs +69 -0
- package/dist/chunk-25ZPFHLF.mjs +51 -0
- package/dist/{chunk-OLZKNUMK.mjs → chunk-3LJG22FS.mjs} +6 -6
- package/dist/chunk-454RQ6NR.mjs +10614 -0
- package/dist/{chunk-O2TO2J4I.mjs → chunk-6CQMRZ2W.mjs} +2 -2
- package/dist/chunk-6KKLF5KG.mjs +32 -0
- package/dist/chunk-74QZQSCL.mjs +84 -0
- package/dist/chunk-BGM7CH5G.mjs +81 -0
- package/dist/chunk-BTNVYAC4.mjs +5557 -0
- package/dist/{chunk-I2UP7YTG.mjs → chunk-ECGDRU56.mjs} +1 -1
- package/dist/{chunk-UTD34C2H.mjs → chunk-EOOOXVHR.mjs} +2 -4
- package/dist/chunk-EYEMPIMP.mjs +74 -0
- package/dist/{chunk-3RPR33MO.mjs → chunk-FV273ECI.mjs} +11 -7
- package/dist/{chunk-MLE4MVYC.mjs → chunk-GGPN4QYQ.mjs} +2 -2
- package/dist/chunk-HQPZQIWW.mjs +1456 -0
- package/dist/{chunk-3QUK5BPY.mjs → chunk-I7GEHLDD.mjs} +16 -1
- package/dist/chunk-ITDAICBY.mjs +363 -0
- package/dist/chunk-JKECUAAV.mjs +2169 -0
- package/dist/chunk-JNCEKW2Y.mjs +41 -0
- package/dist/chunk-JTYVGORV.mjs +101 -0
- package/dist/chunk-KQNZKV6E.mjs +535 -0
- package/dist/chunk-LJDIQ4PF.mjs +6463 -0
- package/dist/{chunk-2MKZKUVH.mjs → chunk-LLRUOIMU.mjs} +1 -2
- package/dist/chunk-MJMRIMR7.mjs +86 -0
- package/dist/chunk-N2WZJX5P.mjs +1989 -0
- package/dist/chunk-NEB372WD.mjs +1152 -0
- package/dist/chunk-OPX7KPOU.mjs +68 -0
- package/dist/chunk-PHUBMRAS.mjs +623 -0
- package/dist/chunk-PQBALZUH.mjs +1941 -0
- package/dist/chunk-PVW5D5AW.mjs +42 -0
- package/dist/{chunk-LZEG3FEY.mjs → chunk-QQWYQ2HS.mjs} +7 -7
- package/dist/chunk-QVR6V6QP.mjs +46 -0
- package/dist/chunk-SGT5IJVW.mjs +28 -0
- package/dist/chunk-SZXO6YSX.mjs +502 -0
- package/dist/chunk-THATLMEX.mjs +1227 -0
- package/dist/chunk-TYR4Q37L.mjs +391 -0
- package/dist/{chunk-DMLQBAGC.mjs → chunk-V3R2NYQR.mjs} +1 -1
- package/dist/chunk-VHK7WBO3.mjs +189 -0
- package/dist/{chunk-TH4XENKH.mjs → chunk-XASDB7YS.mjs} +1 -1
- package/dist/{chunk-NYXA6X56.mjs → chunk-XBQ4LO2N.mjs} +31 -11
- package/dist/chunk-XF3MGADK.mjs +2946 -0
- package/dist/{chunk-5KYR6WJB.mjs → chunk-XQAHREKO.mjs} +17 -1
- package/dist/chunk-XZG3DTXV.mjs +696 -0
- package/dist/chunk-Y4YGR2NY.mjs +52 -0
- package/dist/{chunk-LJEKKFC7.mjs → chunk-YS2JUNSQ.mjs} +19 -11
- package/dist/chunk-ZG7NJLXN.mjs +104 -0
- package/dist/create-3TGG7B3X.mjs +10 -0
- package/dist/credits-MEG7V5DI.mjs +33 -0
- package/dist/{deploy-STWZ3OSM.mjs → deploy-CNRORHJ7.mjs} +11 -11
- package/dist/dev-RXSBY7U4.mjs +8 -0
- package/dist/dev-YLYC6B7R.mjs +401 -0
- package/dist/dispatcher.mjs +131 -30
- package/dist/{doctor-3RW3OGZJ.mjs → doctor-XRTNG2IT.mjs} +13 -21
- package/dist/{domains-FTNK4IKY.mjs → domains-JIHFKDWR.mjs} +6 -6
- package/dist/engine-runtime-fetch-QVKJVC3W.mjs +10 -0
- package/dist/{env-TNCYUAMT.mjs → env-LJ3DCAA5.mjs} +7 -7
- package/dist/env-R72AHBT2.mjs +19 -0
- package/dist/explain-32RSXEXC.mjs +251 -0
- package/dist/inspect-PYLYN45K.mjs +86 -0
- package/dist/{inspect-X3M7WSTL.mjs → inspect-ZOLZHNSZ.mjs} +28 -13
- package/dist/introspect-27MMTACH.mjs +9 -0
- package/dist/kernel-IC4ZC54Z.mjs +662 -0
- package/dist/kernel-plugin.js +6862 -0
- package/dist/keys-WKOQ4KQE.mjs +71 -0
- package/dist/lines-I6ZB2IOU.mjs +56 -0
- package/dist/{link-76Z6V6CJ.mjs → link-TE2FUX74.mjs} +6 -6
- package/dist/{lint-DDZ7HUQN.mjs → lint-735IPMC6.mjs} +2 -2
- package/dist/{list-2MFOQKKQ.mjs → list-CHYY2P4T.mjs} +7 -11
- package/dist/lock-XVR3RRZ6.mjs +57 -0
- package/dist/{login-RLMDEWAL.mjs → login-LW7CHZDZ.mjs} +10 -8
- package/dist/{logout-Z57X6HPE.mjs → logout-6U6OP5DM.mjs} +2 -2
- package/dist/{logs-TNDM4RFE.mjs → logs-HKH4H6PT.mjs} +5 -5
- package/dist/logs-SCQC5HNO.mjs +44 -0
- package/dist/mcp-VRHQOEGG.mjs +1077 -0
- package/dist/{mock-EVER34IX.mjs → mock-5H3CVPHC.mjs} +2 -2
- package/dist/outdated-T7QW6F3Z.mjs +58 -0
- package/dist/port-24R7ZNP4.mjs +2408 -0
- package/dist/{projects-YL4T24VV.mjs → projects-HYITVEXS.mjs} +6 -6
- package/dist/publish-DZRR5A5X.mjs +20 -0
- package/dist/remix-4HVXRIEB.mjs +125 -0
- package/dist/repo-FG3CMZQS.mjs +9 -0
- package/dist/report-M7F4ZYP7.mjs +2 -0
- package/dist/rollback-H7Q4XYGX.mjs +43 -0
- package/dist/{rollback-47VQ4HJK.mjs → rollback-OM64O67F.mjs} +6 -6
- package/dist/scene-QTHT3ZPL.mjs +324 -0
- package/dist/{status-TWPOMWNA.mjs → status-5D4RR3MM.mjs} +5 -5
- package/dist/status-AKI6E3JK.mjs +18 -0
- package/dist/test-W6MURUGZ.mjs +233 -0
- package/dist/testers-EI32JB5F.mjs +49 -0
- package/dist/{unlink-H3BO3DOQ.mjs → unlink-BND47IWW.mjs} +2 -2
- package/dist/{update-FLY46XI3.mjs → update-XKKFREKH.mjs} +4 -4
- package/dist/{whoami-CQPPARRS.mjs → whoami-WHLGCVRC.mjs} +3 -3
- package/dist/workshop-F2T4IDOU.mjs +1703 -0
- package/package.json +11 -7
- package/templates/storefront-auto/app/products/[slug]/page.tsx +1 -1
- package/templates/storefront-auto/package.json +1 -1
- package/templates/storefront-bakery/package.json +1 -1
- package/templates/storefront-fashion/app/products/[slug]/page.tsx +1 -1
- package/templates/storefront-fashion/package.json +1 -1
- package/templates/storefront-grocery/package.json +1 -1
- package/templates/storefront-pharmacy/app/products/[slug]/page.tsx +1 -1
- package/templates/storefront-pharmacy/package.json +1 -1
- package/templates/storefront-restaurant/package.json +1 -1
- package/templates/storefront-retail/app/products/[slug]/page.tsx +1 -1
- package/templates/storefront-retail/package.json +1 -1
- package/templates/storefront-services/package.json +1 -1
- package/dist/chunk-ARIDYKLO.mjs +0 -6463
- package/dist/dev-7O65HY6C.mjs +0 -8
- package/dist/explain-DLRUUCNS.mjs +0 -251
- package/dist/introspect-RC265ACF.mjs +0 -9
- package/dist/repo-UUT3AZ3L.mjs +0 -9
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { parseManifest, MANIFEST_FILE } from './chunk-HQPZQIWW.mjs';
|
|
3
|
+
import { formatDiagnostic } from './chunk-SGT5IJVW.mjs';
|
|
4
|
+
import { CliError, CLI_ERROR_CODE } from './chunk-I7GEHLDD.mjs';
|
|
5
|
+
import { promises } from 'fs';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
|
|
8
|
+
// src/interactives/remote/port.ts
|
|
9
|
+
var CHANNELS = ["live", "test"];
|
|
10
|
+
var RemoteError = class extends Error {
|
|
11
|
+
code;
|
|
12
|
+
constructor(code, message) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = "RemoteError";
|
|
15
|
+
this.code = code;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
async function readInteractiveId(root) {
|
|
19
|
+
const parsed = parseManifest(await promises.readFile(path.join(root, MANIFEST_FILE), "utf8"));
|
|
20
|
+
if (parsed.manifest === null) {
|
|
21
|
+
throw new CliError(CLI_ERROR_CODE.INVALID_INPUT, `${MANIFEST_FILE} is invalid:
|
|
22
|
+
${parsed.diagnostics.map(formatDiagnostic).join("\n")}`);
|
|
23
|
+
}
|
|
24
|
+
if (parsed.manifest.identity.id === null) {
|
|
25
|
+
throw new CliError(CLI_ERROR_CODE.NOT_LINKED, "this Interactive has not been published yet", {
|
|
26
|
+
remediation: "Run `cimplify publish --channel test` to publish it."
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
return parsed.manifest.identity.id;
|
|
30
|
+
}
|
|
31
|
+
async function remoteCall(call) {
|
|
32
|
+
try {
|
|
33
|
+
return await call();
|
|
34
|
+
} catch (err) {
|
|
35
|
+
if (!(err instanceof RemoteError)) throw err;
|
|
36
|
+
const code = err.code === "not_found" ? CLI_ERROR_CODE.NOT_FOUND : err.code === "unauthorized" ? CLI_ERROR_CODE.UNAUTHORIZED : CLI_ERROR_CODE.INVALID_INPUT;
|
|
37
|
+
throw new CliError(code, err.message);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export { CHANNELS, RemoteError, readInteractiveId, remoteCall };
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { SessionError, CaptureSession, FRAME_MS, DEFAULT_EPOCH_MS } from './chunk-SZXO6YSX.mjs';
|
|
3
|
+
import { buildLocal, workPath } from './chunk-BTNVYAC4.mjs';
|
|
4
|
+
import { writeLoopProfile, LOOP_PROFILE_FILE } from './chunk-454RQ6NR.mjs';
|
|
5
|
+
import { locateToolchain } from './chunk-N2WZJX5P.mjs';
|
|
6
|
+
import { formatDiagnostic } from './chunk-SGT5IJVW.mjs';
|
|
7
|
+
import { createHash } from 'crypto';
|
|
8
|
+
import { promises } from 'fs';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
|
|
11
|
+
var CAPTURE_SCHEMA = "cimplify.capture/1";
|
|
12
|
+
var FINAL_CAPTURE = "final";
|
|
13
|
+
async function prepareSession(root) {
|
|
14
|
+
const toolchain = locateToolchain(root);
|
|
15
|
+
if (toolchain === null) throw new SessionError("the pinned SDK is not installed, so the game cannot be served; run your package manager's install");
|
|
16
|
+
const build = await buildLocal(root, { uiSites: true, loops: { probe: true } });
|
|
17
|
+
const errors = build.result.diagnostics.filter((d) => d.severity === "error");
|
|
18
|
+
if (errors.length > 0) throw new SessionError(`the build failed:
|
|
19
|
+
${errors.map(formatDiagnostic).join("\n")}`);
|
|
20
|
+
return { root, build, toolchain };
|
|
21
|
+
}
|
|
22
|
+
function digest(bytes) {
|
|
23
|
+
return createHash("sha256").update(bytes).digest("hex");
|
|
24
|
+
}
|
|
25
|
+
async function runSession(setup, request) {
|
|
26
|
+
const session = await CaptureSession.open(setup, { device: request.device, backend: request.backend, seed: request.seed, scene: request.scene });
|
|
27
|
+
const out = [];
|
|
28
|
+
const take = async (name) => {
|
|
29
|
+
const png = request.screenshots || request.inspect ? await session.screenshot() : new Uint8Array(0);
|
|
30
|
+
const inspection = request.inspect ? await session.inspect(png) : null;
|
|
31
|
+
const snapshot = inspection === null ? await session.snapshot() : null;
|
|
32
|
+
const report = inspection?.report ?? null;
|
|
33
|
+
const readiness = await session.readiness();
|
|
34
|
+
const device = request.device;
|
|
35
|
+
out.push({
|
|
36
|
+
png,
|
|
37
|
+
inspect: report,
|
|
38
|
+
sidecar: {
|
|
39
|
+
schema: CAPTURE_SCHEMA,
|
|
40
|
+
name,
|
|
41
|
+
png: "",
|
|
42
|
+
sha256: png.length === 0 ? "" : digest(png),
|
|
43
|
+
frame: session.frame,
|
|
44
|
+
time_ms: Math.round(session.frame * FRAME_MS * 1e3) / 1e3,
|
|
45
|
+
seed: request.seed,
|
|
46
|
+
epoch_ms: DEFAULT_EPOCH_MS,
|
|
47
|
+
device: { name: device.name, width: device.width, height: device.height, scale: device.scale, insets: device.insets },
|
|
48
|
+
backend: request.backend,
|
|
49
|
+
css_safe_area: session.cssSafeArea,
|
|
50
|
+
scene: report?.scene ?? snapshot?.scene ?? { requested: request.scene, applied: null, current: null },
|
|
51
|
+
script: request.scriptPath,
|
|
52
|
+
ui: report === null ? null : { nodes: report.nodes.length, findings: report.checks.findings.length },
|
|
53
|
+
readiness
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
try {
|
|
58
|
+
if (request.script !== null) await session.run(request.script, take);
|
|
59
|
+
await session.advanceTo(request.frame);
|
|
60
|
+
await take(FINAL_CAPTURE);
|
|
61
|
+
await recordLoopProfile(setup.root, session);
|
|
62
|
+
return out;
|
|
63
|
+
} finally {
|
|
64
|
+
await session.close();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async function recordLoopProfile(root, session) {
|
|
68
|
+
const samples = await session.loopSamples();
|
|
69
|
+
const keys = Object.keys(samples);
|
|
70
|
+
if (keys.length === 0 || session.frame <= 0) return null;
|
|
71
|
+
const loops = {};
|
|
72
|
+
for (const key of keys) {
|
|
73
|
+
const [ms, calls, rows] = samples[key];
|
|
74
|
+
loops[key] = { ms, calls, rows };
|
|
75
|
+
}
|
|
76
|
+
return writeLoopProfile(workPath(root, LOOP_PROFILE_FILE), session.frame, loops);
|
|
77
|
+
}
|
|
78
|
+
async function writeCapture(frame, pngPath) {
|
|
79
|
+
await promises.mkdir(path.dirname(pngPath), { recursive: true });
|
|
80
|
+
await promises.writeFile(pngPath, frame.png);
|
|
81
|
+
const sidecar = { ...frame.sidecar, png: path.basename(pngPath) };
|
|
82
|
+
await promises.writeFile(`${pngPath.slice(0, -path.extname(pngPath).length)}.json`, `${JSON.stringify({ ...sidecar, inspect: frame.inspect }, null, 2)}
|
|
83
|
+
`);
|
|
84
|
+
return sidecar;
|
|
85
|
+
}
|
|
86
|
+
function framesFor(time, frame, fallback) {
|
|
87
|
+
if (time !== void 0 && frame !== void 0) return "pass --frame or --time, not both";
|
|
88
|
+
if (frame !== void 0) {
|
|
89
|
+
const n = Number(frame);
|
|
90
|
+
return Number.isInteger(n) && n >= 0 ? n : `--frame takes a whole number; got "${frame}"`;
|
|
91
|
+
}
|
|
92
|
+
if (time !== void 0) {
|
|
93
|
+
const match = /^(\d+(?:\.\d+)?)(ms|s)?$/.exec(time);
|
|
94
|
+
if (match === null) return `--time takes seconds or milliseconds, such as 2.5s or 2500ms; got "${time}"`;
|
|
95
|
+
const ms = Number(match[1]) * (match[2] === "ms" ? 1 : 1e3);
|
|
96
|
+
return Math.round(ms / FRAME_MS);
|
|
97
|
+
}
|
|
98
|
+
return fallback;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export { CAPTURE_SCHEMA, FINAL_CAPTURE, framesFor, prepareSession, runSession, writeCapture };
|
|
@@ -0,0 +1,535 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// src/interactives/toml.ts
|
|
3
|
+
var TomlSyntaxError = class extends Error {
|
|
4
|
+
line;
|
|
5
|
+
column;
|
|
6
|
+
reason;
|
|
7
|
+
constructor(reason, at) {
|
|
8
|
+
super(`${at.line}:${at.column}: ${reason}`);
|
|
9
|
+
this.name = "TomlSyntaxError";
|
|
10
|
+
this.reason = reason;
|
|
11
|
+
this.line = at.line;
|
|
12
|
+
this.column = at.column;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
var CH_TAB = 9;
|
|
16
|
+
var CH_LF = 10;
|
|
17
|
+
var CH_CR = 13;
|
|
18
|
+
var CH_SPACE = 32;
|
|
19
|
+
var CH_QUOTE = 34;
|
|
20
|
+
var CH_HASH = 35;
|
|
21
|
+
var CH_APOS = 39;
|
|
22
|
+
var CH_PLUS = 43;
|
|
23
|
+
var CH_COMMA = 44;
|
|
24
|
+
var CH_MINUS = 45;
|
|
25
|
+
var CH_DOT = 46;
|
|
26
|
+
var CH_0 = 48;
|
|
27
|
+
var CH_9 = 57;
|
|
28
|
+
var CH_EQUALS = 61;
|
|
29
|
+
var CH_A = 65;
|
|
30
|
+
var CH_Z = 90;
|
|
31
|
+
var CH_LBRACKET = 91;
|
|
32
|
+
var CH_BACKSLASH = 92;
|
|
33
|
+
var CH_RBRACKET = 93;
|
|
34
|
+
var CH_UNDERSCORE = 95;
|
|
35
|
+
var CH_LOWER_A = 97;
|
|
36
|
+
var CH_LOWER_Z = 122;
|
|
37
|
+
var CH_LBRACE = 123;
|
|
38
|
+
var CH_RBRACE = 125;
|
|
39
|
+
var CH_DEL = 127;
|
|
40
|
+
var DATE_SEPARATOR_INDEX = 4;
|
|
41
|
+
var MAX_CODE_POINT = 1114111;
|
|
42
|
+
var SURROGATE_LOW = 55296;
|
|
43
|
+
var SURROGATE_HIGH = 57343;
|
|
44
|
+
function isBare(c) {
|
|
45
|
+
return c >= CH_A && c <= CH_Z || c >= CH_LOWER_A && c <= CH_LOWER_Z || c >= CH_0 && c <= CH_9 || c === CH_UNDERSCORE || c === CH_MINUS;
|
|
46
|
+
}
|
|
47
|
+
function isDigit(c) {
|
|
48
|
+
return c >= CH_0 && c <= CH_9;
|
|
49
|
+
}
|
|
50
|
+
function isControl(c) {
|
|
51
|
+
return c < CH_SPACE && c !== CH_TAB || c === CH_DEL;
|
|
52
|
+
}
|
|
53
|
+
var Cursor = class {
|
|
54
|
+
src;
|
|
55
|
+
pos = 0;
|
|
56
|
+
line = 1;
|
|
57
|
+
lineStart = 0;
|
|
58
|
+
constructor(src) {
|
|
59
|
+
this.src = src;
|
|
60
|
+
}
|
|
61
|
+
at() {
|
|
62
|
+
return { line: this.line, column: this.pos - this.lineStart + 1 };
|
|
63
|
+
}
|
|
64
|
+
peek(offset = 0) {
|
|
65
|
+
const i = this.pos + offset;
|
|
66
|
+
return i < this.src.length ? this.src.charCodeAt(i) : -1;
|
|
67
|
+
}
|
|
68
|
+
done() {
|
|
69
|
+
return this.pos >= this.src.length;
|
|
70
|
+
}
|
|
71
|
+
fail(reason, at = this.at()) {
|
|
72
|
+
throw new TomlSyntaxError(reason, at);
|
|
73
|
+
}
|
|
74
|
+
advance() {
|
|
75
|
+
this.pos++;
|
|
76
|
+
}
|
|
77
|
+
newline() {
|
|
78
|
+
if (this.peek() === CH_CR) {
|
|
79
|
+
if (this.peek(1) !== CH_LF) this.fail("carriage return must be followed by a line feed");
|
|
80
|
+
this.pos++;
|
|
81
|
+
}
|
|
82
|
+
this.pos++;
|
|
83
|
+
this.line++;
|
|
84
|
+
this.lineStart = this.pos;
|
|
85
|
+
}
|
|
86
|
+
isNewline() {
|
|
87
|
+
const c = this.peek();
|
|
88
|
+
return c === CH_LF || c === CH_CR && this.peek(1) === CH_LF;
|
|
89
|
+
}
|
|
90
|
+
skipSpaces() {
|
|
91
|
+
for (; ; ) {
|
|
92
|
+
const c = this.peek();
|
|
93
|
+
if (c !== CH_SPACE && c !== CH_TAB) return;
|
|
94
|
+
this.pos++;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
skipComment() {
|
|
98
|
+
if (this.peek() !== CH_HASH) return;
|
|
99
|
+
while (!this.done() && !this.isNewline()) {
|
|
100
|
+
if (isControl(this.peek())) this.fail("control characters are not allowed in comments");
|
|
101
|
+
this.pos++;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
skipBlank() {
|
|
105
|
+
for (; ; ) {
|
|
106
|
+
this.skipSpaces();
|
|
107
|
+
this.skipComment();
|
|
108
|
+
if (!this.isNewline()) return;
|
|
109
|
+
this.newline();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
endOfLine() {
|
|
113
|
+
this.skipSpaces();
|
|
114
|
+
this.skipComment();
|
|
115
|
+
if (this.done()) return;
|
|
116
|
+
if (!this.isNewline()) this.fail(`unexpected ${describe(this.peek())} after value`);
|
|
117
|
+
this.newline();
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
function describe(c) {
|
|
121
|
+
if (c < 0) return "end of input";
|
|
122
|
+
if (c === CH_LF || c === CH_CR) return "end of line";
|
|
123
|
+
return `character '${String.fromCharCode(c)}'`;
|
|
124
|
+
}
|
|
125
|
+
function define(table, part, value) {
|
|
126
|
+
table.entries.set(part.name, value);
|
|
127
|
+
table.keyAt.set(part.name, part.at);
|
|
128
|
+
}
|
|
129
|
+
function newTable(at, origin) {
|
|
130
|
+
return { kind: "table", entries: /* @__PURE__ */ new Map(), keyAt: /* @__PURE__ */ new Map(), at, origin };
|
|
131
|
+
}
|
|
132
|
+
function parseKey(cur) {
|
|
133
|
+
const parts = [];
|
|
134
|
+
for (; ; ) {
|
|
135
|
+
cur.skipSpaces();
|
|
136
|
+
const at = cur.at();
|
|
137
|
+
const c = cur.peek();
|
|
138
|
+
let name;
|
|
139
|
+
if (c === CH_QUOTE) {
|
|
140
|
+
if (cur.peek(1) === CH_QUOTE && cur.peek(2) === CH_QUOTE) cur.fail("multi-line strings cannot be keys");
|
|
141
|
+
name = parseBasicString(cur);
|
|
142
|
+
} else if (c === CH_APOS) {
|
|
143
|
+
if (cur.peek(1) === CH_APOS && cur.peek(2) === CH_APOS) cur.fail("multi-line strings cannot be keys");
|
|
144
|
+
name = parseLiteralString(cur);
|
|
145
|
+
} else if (isBare(c)) {
|
|
146
|
+
const start = cur.pos;
|
|
147
|
+
while (isBare(cur.peek())) cur.advance();
|
|
148
|
+
name = cur.src.slice(start, cur.pos);
|
|
149
|
+
} else {
|
|
150
|
+
cur.fail(`expected a key, found ${describe(c)}`);
|
|
151
|
+
}
|
|
152
|
+
parts.push({ name, at });
|
|
153
|
+
cur.skipSpaces();
|
|
154
|
+
if (cur.peek() !== CH_DOT) return parts;
|
|
155
|
+
cur.advance();
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
function parseBasicString(cur) {
|
|
159
|
+
cur.advance();
|
|
160
|
+
let out = "";
|
|
161
|
+
let runStart = cur.pos;
|
|
162
|
+
for (; ; ) {
|
|
163
|
+
const c = cur.peek();
|
|
164
|
+
if (c < 0 || c === CH_LF || c === CH_CR) cur.fail("unterminated string");
|
|
165
|
+
if (c === CH_QUOTE) {
|
|
166
|
+
out += cur.src.slice(runStart, cur.pos);
|
|
167
|
+
cur.advance();
|
|
168
|
+
return out;
|
|
169
|
+
}
|
|
170
|
+
if (c === CH_BACKSLASH) {
|
|
171
|
+
out += cur.src.slice(runStart, cur.pos);
|
|
172
|
+
out += parseEscape(cur);
|
|
173
|
+
runStart = cur.pos;
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
if (isControl(c)) cur.fail("control characters must be escaped in strings");
|
|
177
|
+
cur.advance();
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
function parseMultilineBasicString(cur) {
|
|
181
|
+
cur.pos += 3;
|
|
182
|
+
if (cur.isNewline()) cur.newline();
|
|
183
|
+
let out = "";
|
|
184
|
+
let runStart = cur.pos;
|
|
185
|
+
for (; ; ) {
|
|
186
|
+
const c = cur.peek();
|
|
187
|
+
if (c < 0) cur.fail("unterminated multi-line string");
|
|
188
|
+
if (c === CH_QUOTE && cur.peek(1) === CH_QUOTE && cur.peek(2) === CH_QUOTE) {
|
|
189
|
+
let extra = 0;
|
|
190
|
+
while (extra < 2 && cur.peek(3 + extra) === CH_QUOTE) extra++;
|
|
191
|
+
out += cur.src.slice(runStart, cur.pos + extra);
|
|
192
|
+
cur.pos += 3 + extra;
|
|
193
|
+
return out;
|
|
194
|
+
}
|
|
195
|
+
if (c === CH_BACKSLASH) {
|
|
196
|
+
out += cur.src.slice(runStart, cur.pos);
|
|
197
|
+
const save = cur.pos;
|
|
198
|
+
cur.advance();
|
|
199
|
+
cur.skipSpaces();
|
|
200
|
+
if (cur.isNewline()) {
|
|
201
|
+
cur.skipBlank();
|
|
202
|
+
runStart = cur.pos;
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
cur.pos = save;
|
|
206
|
+
out += parseEscape(cur);
|
|
207
|
+
runStart = cur.pos;
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
if (cur.isNewline()) {
|
|
211
|
+
out += cur.src.slice(runStart, cur.pos);
|
|
212
|
+
out += "\n";
|
|
213
|
+
cur.newline();
|
|
214
|
+
runStart = cur.pos;
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
if (isControl(c)) cur.fail("control characters must be escaped in strings");
|
|
218
|
+
cur.advance();
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
function parseEscape(cur) {
|
|
222
|
+
const at = cur.at();
|
|
223
|
+
cur.advance();
|
|
224
|
+
const e = cur.peek();
|
|
225
|
+
cur.advance();
|
|
226
|
+
switch (e) {
|
|
227
|
+
case 98:
|
|
228
|
+
return "\b";
|
|
229
|
+
case 116:
|
|
230
|
+
return " ";
|
|
231
|
+
case 110:
|
|
232
|
+
return "\n";
|
|
233
|
+
case 102:
|
|
234
|
+
return "\f";
|
|
235
|
+
case 114:
|
|
236
|
+
return "\r";
|
|
237
|
+
case 101:
|
|
238
|
+
return "\x1B";
|
|
239
|
+
case CH_QUOTE:
|
|
240
|
+
return '"';
|
|
241
|
+
case CH_BACKSLASH:
|
|
242
|
+
return "\\";
|
|
243
|
+
case 120:
|
|
244
|
+
return unicodeEscape(cur, 2, at);
|
|
245
|
+
case 117:
|
|
246
|
+
return unicodeEscape(cur, 4, at);
|
|
247
|
+
case 85:
|
|
248
|
+
return unicodeEscape(cur, 8, at);
|
|
249
|
+
default:
|
|
250
|
+
return cur.fail(`invalid escape sequence \\${e < 0 ? "" : String.fromCharCode(e)}`, at);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
function unicodeEscape(cur, digits, at) {
|
|
254
|
+
const hex = cur.src.slice(cur.pos, cur.pos + digits);
|
|
255
|
+
if (hex.length !== digits || !/^[0-9A-Fa-f]+$/.test(hex)) cur.fail(`escape needs ${digits} hex digits`, at);
|
|
256
|
+
const code = Number.parseInt(hex, 16);
|
|
257
|
+
if (code > MAX_CODE_POINT || code >= SURROGATE_LOW && code <= SURROGATE_HIGH) {
|
|
258
|
+
cur.fail("escape is not a Unicode scalar value", at);
|
|
259
|
+
}
|
|
260
|
+
cur.pos += digits;
|
|
261
|
+
return String.fromCodePoint(code);
|
|
262
|
+
}
|
|
263
|
+
function parseLiteralString(cur) {
|
|
264
|
+
cur.advance();
|
|
265
|
+
const start = cur.pos;
|
|
266
|
+
for (; ; ) {
|
|
267
|
+
const c = cur.peek();
|
|
268
|
+
if (c < 0 || c === CH_LF || c === CH_CR) cur.fail("unterminated string");
|
|
269
|
+
if (c === CH_APOS) {
|
|
270
|
+
const value = cur.src.slice(start, cur.pos);
|
|
271
|
+
cur.advance();
|
|
272
|
+
return value;
|
|
273
|
+
}
|
|
274
|
+
if (isControl(c)) cur.fail("control characters are not allowed in literal strings");
|
|
275
|
+
cur.advance();
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
function parseMultilineLiteralString(cur) {
|
|
279
|
+
cur.pos += 3;
|
|
280
|
+
if (cur.isNewline()) cur.newline();
|
|
281
|
+
let out = "";
|
|
282
|
+
let runStart = cur.pos;
|
|
283
|
+
for (; ; ) {
|
|
284
|
+
const c = cur.peek();
|
|
285
|
+
if (c < 0) cur.fail("unterminated multi-line string");
|
|
286
|
+
if (c === CH_APOS && cur.peek(1) === CH_APOS && cur.peek(2) === CH_APOS) {
|
|
287
|
+
let extra = 0;
|
|
288
|
+
while (extra < 2 && cur.peek(3 + extra) === CH_APOS) extra++;
|
|
289
|
+
out += cur.src.slice(runStart, cur.pos + extra);
|
|
290
|
+
cur.pos += 3 + extra;
|
|
291
|
+
return out;
|
|
292
|
+
}
|
|
293
|
+
if (cur.isNewline()) {
|
|
294
|
+
out += cur.src.slice(runStart, cur.pos);
|
|
295
|
+
out += "\n";
|
|
296
|
+
cur.newline();
|
|
297
|
+
runStart = cur.pos;
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
if (isControl(c)) cur.fail("control characters are not allowed in literal strings");
|
|
301
|
+
cur.advance();
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
var INTEGER_DEC = /^[+-]?(0|[1-9](_?[0-9])*)$/;
|
|
305
|
+
var INTEGER_HEX = /^0x[0-9A-Fa-f](_?[0-9A-Fa-f])*$/;
|
|
306
|
+
var INTEGER_OCT = /^0o[0-7](_?[0-7])*$/;
|
|
307
|
+
var INTEGER_BIN = /^0b[01](_?[01])*$/;
|
|
308
|
+
var FLOAT = /^[+-]?(0|[1-9](_?[0-9])*)(\.[0-9](_?[0-9])*)?([eE][+-]?[0-9](_?[0-9])*)?$/;
|
|
309
|
+
var FLOAT_SPECIAL = /^[+-]?(inf|nan)$/;
|
|
310
|
+
function parseNumberOrBool(cur) {
|
|
311
|
+
const at = cur.at();
|
|
312
|
+
const start = cur.pos;
|
|
313
|
+
for (; ; ) {
|
|
314
|
+
const c = cur.peek();
|
|
315
|
+
if (isBare(c) || c === CH_PLUS || c === CH_DOT) {
|
|
316
|
+
cur.advance();
|
|
317
|
+
continue;
|
|
318
|
+
}
|
|
319
|
+
break;
|
|
320
|
+
}
|
|
321
|
+
const raw = cur.src.slice(start, cur.pos);
|
|
322
|
+
if (raw.length === 0) cur.fail(`expected a value, found ${describe(cur.peek())}`, at);
|
|
323
|
+
if (raw === "true") return { kind: "boolean", value: true, at };
|
|
324
|
+
if (raw === "false") return { kind: "boolean", value: false, at };
|
|
325
|
+
if (raw.length > DATE_SEPARATOR_INDEX && isDigit(raw.charCodeAt(0)) && raw.charCodeAt(DATE_SEPARATOR_INDEX) === CH_MINUS) {
|
|
326
|
+
cur.fail("dates and times are not supported in this file", at);
|
|
327
|
+
}
|
|
328
|
+
if (cur.peek() === 58) cur.fail("dates and times are not supported in this file", at);
|
|
329
|
+
if (INTEGER_DEC.test(raw)) return integer(cur, Number(raw.replaceAll("_", "")), at);
|
|
330
|
+
if (INTEGER_HEX.test(raw) || INTEGER_OCT.test(raw) || INTEGER_BIN.test(raw)) {
|
|
331
|
+
return integer(cur, Number(raw.replaceAll("_", "")), at);
|
|
332
|
+
}
|
|
333
|
+
if (FLOAT_SPECIAL.test(raw)) {
|
|
334
|
+
const negative = raw.charCodeAt(0) === CH_MINUS;
|
|
335
|
+
const value = raw.endsWith("nan") ? Number.NaN : negative ? -Infinity : Infinity;
|
|
336
|
+
return { kind: "float", value, at };
|
|
337
|
+
}
|
|
338
|
+
if (FLOAT.test(raw)) return { kind: "float", value: Number(raw.replaceAll("_", "")), at };
|
|
339
|
+
return cur.fail(`invalid value '${raw}'`, at);
|
|
340
|
+
}
|
|
341
|
+
function integer(cur, value, at) {
|
|
342
|
+
if (!Number.isSafeInteger(value)) cur.fail("integer is outside the safe range", at);
|
|
343
|
+
return { kind: "integer", value, at };
|
|
344
|
+
}
|
|
345
|
+
function parseValue(cur) {
|
|
346
|
+
const at = cur.at();
|
|
347
|
+
const c = cur.peek();
|
|
348
|
+
if (c === CH_QUOTE) {
|
|
349
|
+
if (cur.peek(1) === CH_QUOTE && cur.peek(2) === CH_QUOTE) {
|
|
350
|
+
return { kind: "string", value: parseMultilineBasicString(cur), at };
|
|
351
|
+
}
|
|
352
|
+
return { kind: "string", value: parseBasicString(cur), at };
|
|
353
|
+
}
|
|
354
|
+
if (c === CH_APOS) {
|
|
355
|
+
if (cur.peek(1) === CH_APOS && cur.peek(2) === CH_APOS) {
|
|
356
|
+
return { kind: "string", value: parseMultilineLiteralString(cur), at };
|
|
357
|
+
}
|
|
358
|
+
return { kind: "string", value: parseLiteralString(cur), at };
|
|
359
|
+
}
|
|
360
|
+
if (c === CH_LBRACKET) return parseArray(cur);
|
|
361
|
+
if (c === CH_LBRACE) return parseInlineTable(cur);
|
|
362
|
+
return parseNumberOrBool(cur);
|
|
363
|
+
}
|
|
364
|
+
function parseArray(cur) {
|
|
365
|
+
const at = cur.at();
|
|
366
|
+
cur.advance();
|
|
367
|
+
const items = [];
|
|
368
|
+
for (; ; ) {
|
|
369
|
+
cur.skipBlank();
|
|
370
|
+
if (cur.peek() === CH_RBRACKET) {
|
|
371
|
+
cur.advance();
|
|
372
|
+
return { kind: "array", items, at, ofTables: false };
|
|
373
|
+
}
|
|
374
|
+
items.push(parseValue(cur));
|
|
375
|
+
cur.skipBlank();
|
|
376
|
+
const c = cur.peek();
|
|
377
|
+
if (c === CH_COMMA) {
|
|
378
|
+
cur.advance();
|
|
379
|
+
continue;
|
|
380
|
+
}
|
|
381
|
+
if (c === CH_RBRACKET) {
|
|
382
|
+
cur.advance();
|
|
383
|
+
return { kind: "array", items, at, ofTables: false };
|
|
384
|
+
}
|
|
385
|
+
cur.fail(`expected ',' or ']' in array, found ${describe(c)}`);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
function parseInlineTable(cur) {
|
|
389
|
+
const table = newTable(cur.at(), "inline");
|
|
390
|
+
cur.advance();
|
|
391
|
+
cur.skipSpaces();
|
|
392
|
+
if (cur.peek() === CH_RBRACE) {
|
|
393
|
+
cur.advance();
|
|
394
|
+
return table;
|
|
395
|
+
}
|
|
396
|
+
for (; ; ) {
|
|
397
|
+
const key = parseKey(cur);
|
|
398
|
+
if (cur.peek() !== CH_EQUALS) cur.fail(`expected '=' after key, found ${describe(cur.peek())}`);
|
|
399
|
+
cur.advance();
|
|
400
|
+
cur.skipSpaces();
|
|
401
|
+
const value = parseValue(cur);
|
|
402
|
+
assignDotted(cur, table, key, value, "inline");
|
|
403
|
+
cur.skipSpaces();
|
|
404
|
+
const c = cur.peek();
|
|
405
|
+
if (c === CH_COMMA) {
|
|
406
|
+
cur.advance();
|
|
407
|
+
cur.skipSpaces();
|
|
408
|
+
if (cur.peek() === CH_RBRACE) cur.fail("trailing comma is not allowed in an inline table");
|
|
409
|
+
continue;
|
|
410
|
+
}
|
|
411
|
+
if (c === CH_RBRACE) {
|
|
412
|
+
cur.advance();
|
|
413
|
+
return table;
|
|
414
|
+
}
|
|
415
|
+
cur.fail(`expected ',' or '}' in inline table, found ${describe(c)}`);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
function joinKey(parts, upTo) {
|
|
419
|
+
let out = "";
|
|
420
|
+
for (let i = 0; i <= upTo; i++) out += i === 0 ? parts[i].name : `.${parts[i].name}`;
|
|
421
|
+
return out;
|
|
422
|
+
}
|
|
423
|
+
function assignDotted(cur, root, key, value, scope) {
|
|
424
|
+
let table = root;
|
|
425
|
+
for (let i = 0; i < key.length - 1; i++) {
|
|
426
|
+
const part = key[i];
|
|
427
|
+
const existing = table.entries.get(part.name);
|
|
428
|
+
if (existing === void 0) {
|
|
429
|
+
const child = newTable(part.at, "dotted");
|
|
430
|
+
define(table, part, child);
|
|
431
|
+
table = child;
|
|
432
|
+
continue;
|
|
433
|
+
}
|
|
434
|
+
if (existing.kind !== "table" || existing.origin === "inline" || scope === "body" && existing.origin === "header") {
|
|
435
|
+
cur.fail(`key '${joinKey(key, i)}' is already defined`, part.at);
|
|
436
|
+
}
|
|
437
|
+
if (scope === "body" && existing.origin === "implicit") {
|
|
438
|
+
cur.fail(`key '${joinKey(key, i)}' is already defined as a table`, part.at);
|
|
439
|
+
}
|
|
440
|
+
table = existing;
|
|
441
|
+
}
|
|
442
|
+
const last = key[key.length - 1];
|
|
443
|
+
if (table.entries.has(last.name)) cur.fail(`key '${joinKey(key, key.length - 1)}' is already defined`, last.at);
|
|
444
|
+
define(table, last, value);
|
|
445
|
+
}
|
|
446
|
+
function openHeader(cur, root, key, arrayOfTables) {
|
|
447
|
+
let table = root;
|
|
448
|
+
for (let i = 0; i < key.length - 1; i++) {
|
|
449
|
+
const part = key[i];
|
|
450
|
+
const existing2 = table.entries.get(part.name);
|
|
451
|
+
if (existing2 === void 0) {
|
|
452
|
+
const child = newTable(part.at, "implicit");
|
|
453
|
+
define(table, part, child);
|
|
454
|
+
table = child;
|
|
455
|
+
continue;
|
|
456
|
+
}
|
|
457
|
+
if (existing2.kind === "array" && existing2.ofTables) {
|
|
458
|
+
table = existing2.items[existing2.items.length - 1];
|
|
459
|
+
continue;
|
|
460
|
+
}
|
|
461
|
+
if (existing2.kind !== "table" || existing2.origin === "inline") {
|
|
462
|
+
cur.fail(`key '${joinKey(key, i)}' is already defined as a value`, part.at);
|
|
463
|
+
}
|
|
464
|
+
table = existing2;
|
|
465
|
+
}
|
|
466
|
+
const last = key[key.length - 1];
|
|
467
|
+
const existing = table.entries.get(last.name);
|
|
468
|
+
if (arrayOfTables) {
|
|
469
|
+
const element = newTable(last.at, "array_element");
|
|
470
|
+
if (existing === void 0) {
|
|
471
|
+
define(table, last, { kind: "array", items: [element], at: last.at, ofTables: true });
|
|
472
|
+
return element;
|
|
473
|
+
}
|
|
474
|
+
if (existing.kind !== "array" || !existing.ofTables) {
|
|
475
|
+
cur.fail(`key '${joinKey(key, key.length - 1)}' is already defined and is not an array of tables`, last.at);
|
|
476
|
+
}
|
|
477
|
+
existing.items.push(element);
|
|
478
|
+
return element;
|
|
479
|
+
}
|
|
480
|
+
if (existing === void 0) {
|
|
481
|
+
const child = newTable(last.at, "header");
|
|
482
|
+
define(table, last, child);
|
|
483
|
+
return child;
|
|
484
|
+
}
|
|
485
|
+
if (existing.kind === "table" && existing.origin === "implicit") {
|
|
486
|
+
existing.origin = "header";
|
|
487
|
+
return existing;
|
|
488
|
+
}
|
|
489
|
+
return cur.fail(`table '${joinKey(key, key.length - 1)}' is already defined`, last.at);
|
|
490
|
+
}
|
|
491
|
+
function parseToml(source) {
|
|
492
|
+
const cur = new Cursor(source.charCodeAt(0) === 65279 ? source.slice(1) : source);
|
|
493
|
+
const root = newTable({ line: 1, column: 1 }, "root");
|
|
494
|
+
let current = root;
|
|
495
|
+
for (; ; ) {
|
|
496
|
+
cur.skipBlank();
|
|
497
|
+
if (cur.done()) return root;
|
|
498
|
+
if (cur.peek() === CH_LBRACKET) {
|
|
499
|
+
const arrayOfTables = cur.peek(1) === CH_LBRACKET;
|
|
500
|
+
cur.pos += arrayOfTables ? 2 : 1;
|
|
501
|
+
const key2 = parseKey(cur);
|
|
502
|
+
if (cur.peek() !== CH_RBRACKET || arrayOfTables && cur.peek(1) !== CH_RBRACKET) {
|
|
503
|
+
cur.fail(arrayOfTables ? "expected ']]' to close the table header" : "expected ']' to close the table header");
|
|
504
|
+
}
|
|
505
|
+
cur.pos += arrayOfTables ? 2 : 1;
|
|
506
|
+
current = openHeader(cur, root, key2, arrayOfTables);
|
|
507
|
+
cur.endOfLine();
|
|
508
|
+
continue;
|
|
509
|
+
}
|
|
510
|
+
const key = parseKey(cur);
|
|
511
|
+
if (cur.peek() !== CH_EQUALS) cur.fail(`expected '=' after key, found ${describe(cur.peek())}`);
|
|
512
|
+
cur.advance();
|
|
513
|
+
cur.skipSpaces();
|
|
514
|
+
if (cur.done() || cur.isNewline()) cur.fail("expected a value after '='");
|
|
515
|
+
const value = parseValue(cur);
|
|
516
|
+
assignDotted(cur, current, key, value, "body");
|
|
517
|
+
cur.endOfLine();
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
function quoteTomlString(value) {
|
|
521
|
+
let out = '"';
|
|
522
|
+
for (let i = 0; i < value.length; i++) {
|
|
523
|
+
const c = value.charCodeAt(i);
|
|
524
|
+
if (c === CH_QUOTE) out += '\\"';
|
|
525
|
+
else if (c === CH_BACKSLASH) out += "\\\\";
|
|
526
|
+
else if (c === CH_LF) out += "\\n";
|
|
527
|
+
else if (c === CH_TAB) out += "\\t";
|
|
528
|
+
else if (c === CH_CR) out += "\\r";
|
|
529
|
+
else if (c < CH_SPACE || c === CH_DEL) out += `\\u${c.toString(16).padStart(4, "0")}`;
|
|
530
|
+
else out += value[i];
|
|
531
|
+
}
|
|
532
|
+
return `${out}"`;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
export { TomlSyntaxError, parseToml, quoteTomlString };
|