From 837711f01aa7ec1f4b60daa4e5fda8e3cd4d8561 Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Tue, 28 Jul 2026 10:30:57 +0000 Subject: [PATCH 1/2] Allow arrays and booleans for the knitr cache-globals cell option cache-globals was declared as a bare `string`, while the analogous cache-vars uses `maybeArrayOf: string`. Since `maybeArrayOf: string` desugars to `anyOf(string, arrayOf(string))` and plain `string` does not, a YAML array failed cell metadata validation -- which runs before the engine, so it failed even with no R installed. The same declaration rejected `cache-globals: false`, a value the option's own long description documents, so the schema contradicted its own prose. knitr's cache_globals() takes a character vector directly, treats FALSE as "find all symbols", and otherwise auto-detects; it declares the option as a list type in opts_chunk_attr. Per knitr's NEWS.md, vectors are supported since 1.17 and booleans since 1.34. Widen the schema to `anyOf(maybeArrayOf: string, boolean)`, matching dependson in the same file, and regenerate the editor tooling artifacts. Fixes #14735 Co-Authored-By: Claude Opus 5 --- news/changelog-1.11.md | 4 + src/resources/editor/tools/vs-code.mjs | 357 +++++++++--------- src/resources/editor/tools/yaml/web-worker.js | 347 ++++++++--------- .../yaml/yaml-intelligence-resources.json | 15 +- src/resources/schema/cell-cache.yml | 5 +- 5 files changed, 382 insertions(+), 346 deletions(-) diff --git a/news/changelog-1.11.md b/news/changelog-1.11.md index 4c11a6001e4..35f6ee3a280 100644 --- a/news/changelog-1.11.md +++ b/news/changelog-1.11.md @@ -1,3 +1,7 @@ All changes included in 1.11: +## Engines +### `knitr` + +- ([#14735](https://github.com/quarto-dev/quarto-cli/issues/14735)): Fix `cache-globals` rejecting arrays and booleans, so it now accepts the same forms as `cache-vars` and as knitr itself. Previously only a single string validated, which rejected both `cache-globals: [var_1, var_2]` and the documented `cache-globals: false`. diff --git a/src/resources/editor/tools/vs-code.mjs b/src/resources/editor/tools/vs-code.mjs index ff2c9d82a6a..cffe8505309 100644 --- a/src/resources/editor/tools/vs-code.mjs +++ b/src/resources/editor/tools/vs-code.mjs @@ -6997,7 +6997,11 @@ var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __commonJS = (cb, mod) => function __require() { - return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; + try { + return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; + } catch (e) { + throw mod = 0, e; + } }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { @@ -7119,7 +7123,14 @@ var require_yaml_intelligence_resources = __commonJS({ tags: { engine: "knitr" }, - schema: "string", + schema: { + anyOf: [ + { + maybeArrayOf: "string" + }, + "boolean" + ] + }, description: { short: "Variables names that are not created from the current chunk", long: "Variables names that are not created from the current chunk.\n\nThis option is mainly for `autodep: true` to work more precisely---a chunk\n`B` depends on chunk `A` when any of `B`'s global variables are `A`'s local \nvariables. In case the automatic detection of global variables in a chunk \nfails, you may manually specify the names of global variables via this option.\nIn addition, `cache-globals: false` means detecting all variables in a code\nchunk, no matter if they are global or local variables.\n" @@ -25376,12 +25387,12 @@ var require_yaml_intelligence_resources = __commonJS({ mermaid: "%%" }, "handlers/mermaid/schema.yml": { - _internalId: 223022, + _internalId: 223031, type: "object", description: "be an object", properties: { "mermaid-format": { - _internalId: 223014, + _internalId: 223023, type: "enum", enum: [ "png", @@ -25397,7 +25408,7 @@ var require_yaml_intelligence_resources = __commonJS({ exhaustiveCompletions: true }, theme: { - _internalId: 223021, + _internalId: 223030, type: "anyOf", anyOf: [ { @@ -25780,13 +25791,13 @@ function formatLineRange(text, firstLine, lastLine) { const pad = " ".repeat(lineWidth); const ls = lines(text); const result = []; - for (let i = firstLine; i <= lastLine; ++i) { - const numberStr = `${pad}${i + 1}: `.slice(-(lineWidth + 2)); - const lineStr = ls[i]; + for (let i2 = firstLine; i2 <= lastLine; ++i2) { + const numberStr = `${pad}${i2 + 1}: `.slice(-(lineWidth + 2)); + const lineStr = ls[i2]; result.push({ - lineNumber: i, + lineNumber: i2, content: numberStr + quotedStringColor(lineStr), - rawLine: ls[i] + rawLine: ls[i2] }); } return { @@ -25821,19 +25832,19 @@ function editDistance(w1, w2) { const s1 = w1.length + 1; const s2 = w2.length + 1; const v = new Int32Array(s1 * s2); - for (let i = 0; i < s1; ++i) { + for (let i2 = 0; i2 < s1; ++i2) { for (let j = 0; j < s2; ++j) { - if (i === 0 && j === 0) { + if (i2 === 0 && j === 0) { continue; - } else if (i === 0) { - v[i * s2 + j] = v[i * s2 + (j - 1)] + cost(w2[j - 1]); + } else if (i2 === 0) { + v[i2 * s2 + j] = v[i2 * s2 + (j - 1)] + cost(w2[j - 1]); } else if (j === 0) { - v[i * s2 + j] = v[(i - 1) * s2 + j] + cost(w1[i - 1]); + v[i2 * s2 + j] = v[(i2 - 1) * s2 + j] + cost(w1[i2 - 1]); } else { - v[i * s2 + j] = Math.min( - v[(i - 1) * s2 + (j - 1)] + cost2(w1[i - 1], w2[j - 1]), - v[i * s2 + (j - 1)] + cost(w2[j - 1]), - v[(i - 1) * s2 + j] + cost(w1[i - 1]) + v[i2 * s2 + j] = Math.min( + v[(i2 - 1) * s2 + (j - 1)] + cost2(w1[i2 - 1], w2[j - 1]), + v[i2 * s2 + (j - 1)] + cost(w2[j - 1]), + v[(i2 - 1) * s2 + j] + cost(w1[i2 - 1]) ); } } @@ -26209,26 +26220,26 @@ function getYamlIndentTree(code2) { const indents = []; let indentation = -1; let prevPredecessor = -1; - for (let i = 0; i < ls.length; ++i) { - const line = ls[i]; + for (let i2 = 0; i2 < ls.length; ++i2) { + const line = ls[i2]; const lineIndent = getIndent(line); indents.push(lineIndent); if (lineIndent > indentation) { - predecessor[i] = prevPredecessor; - prevPredecessor = i; + predecessor[i2] = prevPredecessor; + prevPredecessor = i2; indentation = lineIndent; } else if (line.trim().length === 0) { - predecessor[i] = predecessor[prevPredecessor]; + predecessor[i2] = predecessor[prevPredecessor]; } else if (lineIndent === indentation) { - predecessor[i] = predecessor[prevPredecessor]; - prevPredecessor = i; + predecessor[i2] = predecessor[prevPredecessor]; + prevPredecessor = i2; } else if (lineIndent < indentation) { let v = prevPredecessor; while (v >= 0 && indents[v] >= lineIndent) { v = predecessor[v]; } - predecessor[i] = v; - prevPredecessor = i; + predecessor[i2] = v; + prevPredecessor = i2; indentation = lineIndent; } else { throw new UnreachableError(); @@ -26406,22 +26417,22 @@ function makeSnippet(mark, options) { } } if (foundLineNo < 0) foundLineNo = lineStarts.length - 1; - var result = "", i, line; + var result = "", i2, line; var lineNoLength = Math.min( mark.line + options.linesAfter, lineEnds.length ).toString().length; var maxLineLength = options.maxLength - (options.indent + lineNoLength + 3); - for (i = 1; i <= options.linesBefore; i++) { - if (foundLineNo - i < 0) break; + for (i2 = 1; i2 <= options.linesBefore; i2++) { + if (foundLineNo - i2 < 0) break; line = getLine( mark.buffer, - lineStarts[foundLineNo - i], - lineEnds[foundLineNo - i], - mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]), + lineStarts[foundLineNo - i2], + lineEnds[foundLineNo - i2], + mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i2]), maxLineLength ); - result = common.repeat(" ", options.indent) + padStart((mark.line - i + 1).toString(), lineNoLength) + " | " + line.str + "\n" + result; + result = common.repeat(" ", options.indent) + padStart((mark.line - i2 + 1).toString(), lineNoLength) + " | " + line.str + "\n" + result; } line = getLine( mark.buffer, @@ -26432,16 +26443,16 @@ function makeSnippet(mark, options) { ); result += common.repeat(" ", options.indent) + padStart((mark.line + 1).toString(), lineNoLength) + " | " + line.str + "\n"; result += common.repeat("-", options.indent + lineNoLength + 3 + line.pos) + "^\n"; - for (i = 1; i <= options.linesAfter; i++) { - if (foundLineNo + i >= lineEnds.length) break; + for (i2 = 1; i2 <= options.linesAfter; i2++) { + if (foundLineNo + i2 >= lineEnds.length) break; line = getLine( mark.buffer, - lineStarts[foundLineNo + i], - lineEnds[foundLineNo + i], - mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]), + lineStarts[foundLineNo + i2], + lineEnds[foundLineNo + i2], + mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i2]), maxLineLength ); - result += common.repeat(" ", options.indent) + padStart((mark.line + i + 1).toString(), lineNoLength) + " | " + line.str + "\n"; + result += common.repeat(" ", options.indent) + padStart((mark.line + i2 + 1).toString(), lineNoLength) + " | " + line.str + "\n"; } return result.replace(/\n$/, ""); } @@ -28565,7 +28576,7 @@ var STYLE_LITERAL = 3; var STYLE_FOLDED = 4; var STYLE_DOUBLE = 5; function chooseScalarStyle(string, singleLineOnly, indentPerLevel, lineWidth, testAmbiguousType, quotingType, forceQuotes, inblock) { - var i; + var i2; var char = 0; var prevChar = null; var hasLineBreak = false; @@ -28574,8 +28585,8 @@ function chooseScalarStyle(string, singleLineOnly, indentPerLevel, lineWidth, te var previousLineBreak = -1; var plain = isPlainSafeFirst(codePointAt(string, 0)) && isPlainSafeLast(codePointAt(string, string.length - 1)); if (singleLineOnly || forceQuotes) { - for (i = 0; i < string.length; char >= 65536 ? i += 2 : i++) { - char = codePointAt(string, i); + for (i2 = 0; i2 < string.length; char >= 65536 ? i2 += 2 : i2++) { + char = codePointAt(string, i2); if (!isPrintable(char)) { return STYLE_DOUBLE; } @@ -28583,13 +28594,13 @@ function chooseScalarStyle(string, singleLineOnly, indentPerLevel, lineWidth, te prevChar = char; } } else { - for (i = 0; i < string.length; char >= 65536 ? i += 2 : i++) { - char = codePointAt(string, i); + for (i2 = 0; i2 < string.length; char >= 65536 ? i2 += 2 : i2++) { + char = codePointAt(string, i2); if (char === CHAR_LINE_FEED) { hasLineBreak = true; if (shouldTrackWidth) { - hasFoldableLine = hasFoldableLine || i - previousLineBreak - 1 > lineWidth && string[previousLineBreak + 1] !== " "; - previousLineBreak = i; + hasFoldableLine = hasFoldableLine || i2 - previousLineBreak - 1 > lineWidth && string[previousLineBreak + 1] !== " "; + previousLineBreak = i2; } } else if (!isPrintable(char)) { return STYLE_DOUBLE; @@ -28597,7 +28608,7 @@ function chooseScalarStyle(string, singleLineOnly, indentPerLevel, lineWidth, te plain = plain && isPlainSafe(char, prevChar, inblock); prevChar = char; } - hasFoldableLine = hasFoldableLine || shouldTrackWidth && i - previousLineBreak - 1 > lineWidth && string[previousLineBreak + 1] !== " "; + hasFoldableLine = hasFoldableLine || shouldTrackWidth && i2 - previousLineBreak - 1 > lineWidth && string[previousLineBreak + 1] !== " "; } if (!hasLineBreak && !hasFoldableLine) { if (plain && !forceQuotes && !testAmbiguousType(string)) { @@ -28710,12 +28721,12 @@ function escapeString(string) { var result = ""; var char = 0; var escapeSeq; - for (var i = 0; i < string.length; char >= 65536 ? i += 2 : i++) { - char = codePointAt(string, i); + for (var i2 = 0; i2 < string.length; char >= 65536 ? i2 += 2 : i2++) { + char = codePointAt(string, i2); escapeSeq = ESCAPE_SEQUENCES[char]; if (!escapeSeq && isPrintable(char)) { - result += string[i]; - if (char >= 65536) result += string[i + 1]; + result += string[i2]; + if (char >= 65536) result += string[i2 + 1]; } else { result += escapeSeq || encodeHex(char); } @@ -29116,8 +29127,8 @@ function expandAliasesFrom(lst, defs) { const aliases = defs; const result = []; lst = lst.slice(); - for (let i = 0; i < lst.length; ++i) { - const el = lst[i]; + for (let i2 = 0; i2 < lst.length; ++i2) { + const el = lst[i2]; if (el.startsWith("$")) { const v = aliases[el.slice(1)]; if (v === void 0) { @@ -29232,15 +29243,15 @@ function initLargeIdContinueRanges() { return restoreRanges("53 0 g9 33 o 0 70 4 7e 18 2 0 2 1 2 1 2 0 21 a 1d u 7 0 2u 6 3 5 3 1 2 3 3 9 o 0 v q 2k a g 9 y 8 a 0 p 3 2 8 2 2 2 4 18 2 3c e 2 w 1j 2 2 h 2 6 b 1 3 9 i 2 1l 0 2 6 3 1 3 2 a 0 b 1 3 9 f 0 3 2 1l 0 2 4 5 1 3 2 4 0 l b 4 0 c 2 1l 0 2 7 2 2 2 2 l 1 3 9 b 5 2 2 1l 0 2 6 3 1 3 2 8 2 b 1 3 9 j 0 1o 4 4 2 2 3 a 0 f 9 h 4 1m 6 2 2 2 3 8 1 c 1 3 9 i 2 1l 0 2 6 2 2 2 3 8 1 c 1 3 9 h 3 1k 1 2 6 2 2 2 3 a 0 b 1 3 9 i 2 1z 0 5 5 2 0 2 7 7 9 3 1 1q 0 3 6 d 7 2 9 2g 0 3 8 c 5 3 9 1r 1 7 9 c 0 2 0 2 0 5 1 1e j 2 1 6 a 2 z a 0 2t j 2 9 d 3 5 2 2 2 3 6 4 3 e b 2 e jk 2 a 8 pt 2 u 2 u 1 v 1 1t v a 0 3 9 y 2 3 9 40 0 3b b 5 b b 9 3l a 1p 4 1m 9 2 s 3 a 7 9 n d 2 1 1s 4 1c g c 9 i 8 d 2 v c 3 9 19 d 1d j 9 9 7 9 3b 2 2 k 5 0 7 0 3 2 5j 1l 2 4 g0 1 k 0 3g c 5 0 4 b 2db 2 3y 0 2p v ff 5 2y 1 n7q 9 1y 0 5 9 x 1 29 1 7l 0 4 0 5 0 o 4 5 0 2c 1 1f h b 9 7 h e a t 7 q c 19 3 1c d g 9 c 0 b 9 1c d d 0 9 1 3 9 y 2 1f 0 2 2 3 1 6 1 2 0 16 4 6 1 6l 7 2 1 3 9 fmt 0 ki f h f 4 1 p 2 5d 9 12 0 ji 0 6b 0 46 4 86 9 120 2 2 1 6 3 15 2 5 0 4m 1 fy 3 9 9 aa 1 4a a 4w 2 1i e w 9 g 3 1a a 1i 9 7 2 11 d 2 9 6 1 19 0 d 2 1d d 9 3 2 b 2b b 7 0 4h b 6 9 7 3 1k 1 2 6 3 1 3 2 a 0 b 1 3 6 4 4 5d h a 9 5 0 2a j d 9 5y 6 3 8 s 1 2b g g 9 2a c 9 9 2c e 5 9 6r e 4m 9 1z 5 2 1 3 3 2 0 2 1 d 9 3c 6 3 6 4 0 t 9 15 6 2 3 9 0 a a 1b f ba 7 2 7 h 9 1l l 2 d 3f 5 4 0 2 1 2 6 2 0 9 9 1d 4 2 1 2 4 9 9 96 3 ewa 9 3r 4 1o 6 q 9 s6 0 2 1i 8 3 2a 0 c 1 f58 1 43r 4 4 5 9 7 3 6 v 3 45 2 13e 1d e9 1i 5 1d 9 0 f 0 n 4 2 e 11t 6 2 g 3 6 2 1 2 4 7a 6 a 9 bn d 15j 6 32 6 6 9 3o7 9 gvt3 6n"); } function isInRange(cp, ranges) { - let l = 0, r = ranges.length / 2 | 0, i = 0, min = 0, max = 0; + let l = 0, r = ranges.length / 2 | 0, i2 = 0, min = 0, max = 0; while (l < r) { - i = (l + r) / 2 | 0; - min = ranges[2 * i]; - max = ranges[2 * i + 1]; + i2 = (l + r) / 2 | 0; + min = ranges[2 * i2]; + max = ranges[2 * i2 + 1]; if (cp < min) { - r = i; + r = i2; } else if (cp > max) { - l = i + 1; + l = i2 + 1; } else { return true; } @@ -29392,16 +29403,16 @@ function combineSurrogatePair(lead, trail) { return (lead - 55296) * 1024 + (trail - 56320) + 65536; } var legacyImpl = { - at(s, end, i) { - return i < end ? s.charCodeAt(i) : -1; + at(s, end, i2) { + return i2 < end ? s.charCodeAt(i2) : -1; }, width(c) { return 1; } }; var unicodeImpl = { - at(s, end, i) { - return i < end ? s.codePointAt(i) : -1; + at(s, end, i2) { + return i2 < end ? s.codePointAt(i2) : -1; }, width(c) { return c > 65535 ? 2 : 1; @@ -29564,10 +29575,10 @@ var RegExpValidator = class { let unicode = false; let dotAll = false; let hasIndices = false; - for (let i = start; i < end; ++i) { - const flag = source.charCodeAt(i); + for (let i2 = start; i2 < end; ++i2) { + const flag = source.charCodeAt(i2); if (existingFlags.has(flag)) { - this.raise(`Duplicated flag '${source[i]}'`); + this.raise(`Duplicated flag '${source[i2]}'`); } existingFlags.add(flag); if (flag === LatinSmallLetterG) { @@ -29585,7 +29596,7 @@ var RegExpValidator = class { } else if (flag === LatinSmallLetterD && this.ecmaVersion >= 2022) { hasIndices = true; } else { - this.raise(`Invalid flag '${source[i]}'`); + this.raise(`Invalid flag '${source[i2]}'`); } } this.onFlags(start, end, global, ignoreCase, multiline, unicode, sticky, dotAll, hasIndices); @@ -29854,10 +29865,10 @@ var RegExpValidator = class { } consumeDisjunction() { const start = this.index; - let i = 0; + let i2 = 0; this.onDisjunctionEnter(start); do { - this.consumeAlternative(i++); + this.consumeAlternative(i2++); } while (this.eat(VerticalLine)); if (this.consumeQuantifier(true)) { this.raise("Nothing to repeat"); @@ -29867,12 +29878,12 @@ var RegExpValidator = class { } this.onDisjunctionLeave(start, this.index); } - consumeAlternative(i) { + consumeAlternative(i2) { const start = this.index; - this.onAlternativeEnter(start, i); + this.onAlternativeEnter(start, i2); while (this.currentCodePoint !== -1 && this.consumeTerm()) { } - this.onAlternativeLeave(start, this.index, i); + this.onAlternativeLeave(start, this.index, i2); } consumeTerm() { if (this._uFlag || this.strict) { @@ -30545,7 +30556,7 @@ var RegExpValidator = class { eatFixedHexDigits(length) { const start = this.index; this._lastIntValue = 0; - for (let i = 0; i < length; ++i) { + for (let i2 = 0; i2 < length; ++i2) { const cp = this.currentCodePoint; if (!isHexDigit(cp)) { this.rewind(start); @@ -30946,12 +30957,12 @@ function prefixesFromParse(parse) { return `(${alternatives.join("|")})`; } else if (parse.type === "Alternative") { const result = []; - for (let i = 0; i < parse.elements.length; ++i) { + for (let i2 = 0; i2 < parse.elements.length; ++i2) { const thisRe = []; - for (let j = 0; j < i; ++j) { + for (let j = 0; j < i2; ++j) { thisRe.push(parse.elements[j].raw); } - thisRe.push(prefixesFromParse(parse.elements[i])); + thisRe.push(prefixesFromParse(parse.elements[i2])); result.push(thisRe.join("")); } return `(${result.join("|")})`; @@ -31382,7 +31393,7 @@ function schemaPathMatches(error, strs) { if (schemaPath.length !== strs.length) { return false; } - return strs.every((str2, i) => str2 === schemaPath[i]); + return strs.every((str2, i2) => str2 === schemaPath[i2]); } function getBadKey(error) { if (error.schemaPath.indexOf("propertyNames") === -1 && error.schemaPath.indexOf("closed") === -1) { @@ -31410,13 +31421,13 @@ function navigate(path, annotation, returnKey = false, pathIndex = 0) { const { components } = annotation; const searchKey = path[pathIndex]; const lastKeyIndex = ~~((components.length - 1) / 2) * 2; - for (let i = lastKeyIndex; i >= 0; i -= 2) { - const key = components[i].result; + for (let i2 = lastKeyIndex; i2 >= 0; i2 -= 2) { + const key = components[i2].result; if (key === searchKey) { if (returnKey && pathIndex === path.length - 1) { - return navigate(path, components[i], returnKey, pathIndex + 1); + return navigate(path, components[i2], returnKey, pathIndex + 1); } else { - return navigate(path, components[i + 1], returnKey, pathIndex + 1); + return navigate(path, components[i2 + 1], returnKey, pathIndex + 1); } } } @@ -32276,8 +32287,8 @@ function buildTreeSitterAnnotation(tree, mappedSource2) { }, "block_sequence": (node) => { const result2 = [], components = []; - for (let i = 0; i < node.childCount; ++i) { - const child = node.child(i); + for (let i2 = 0; i2 < node.childCount; ++i2) { + const child = node.child(i2); if (child.type !== "block_sequence_item") { continue; } @@ -32296,8 +32307,8 @@ function buildTreeSitterAnnotation(tree, mappedSource2) { }, "flow_sequence": (node) => { const result2 = [], components = []; - for (let i = 0; i < node.childCount; ++i) { - const child = node.child(i); + for (let i2 = 0; i2 < node.childCount; ++i2) { + const child = node.child(i2); if (child.type !== "flow_node") { continue; } @@ -32309,8 +32320,8 @@ function buildTreeSitterAnnotation(tree, mappedSource2) { }, "block_mapping": (node) => { const result2 = {}, components = []; - for (let i = 0; i < node.childCount; ++i) { - const child = node.child(i); + for (let i2 = 0; i2 < node.childCount; ++i2) { + const child = node.child(i2); let component; if (child.type === "ERROR") { result2[child.text] = "<>"; @@ -32334,8 +32345,8 @@ function buildTreeSitterAnnotation(tree, mappedSource2) { "flow_pair": buildPair, "flow_mapping": (node) => { const result2 = {}, components = []; - for (let i = 0; i < node.childCount; ++i) { - const child = node.child(i); + for (let i2 = 0; i2 < node.childCount; ++i2) { + const child = node.child(i2); if (child.type === "flow_node") { continue; } @@ -32370,8 +32381,8 @@ function locateCursor(annotation, position) { const kInternalLocateError = "Cursor outside bounds in sequence locate"; function locate(node) { if (node.kind === "block_mapping" || node.kind === "flow_mapping" || node.kind === "mapping") { - for (let i = 0; i < node.components.length; i += 2) { - const keyC = node.components[i], valueC = node.components[i + 1]; + for (let i2 = 0; i2 < node.components.length; i2 += 2) { + const keyC = node.components[i2], valueC = node.components[i2 + 1]; if (keyC.start <= position && position <= keyC.end) { innermostAnnotation = keyC; result.push(keyC.result); @@ -32386,18 +32397,18 @@ function locateCursor(annotation, position) { failedLast = true; return; } else if (node.kind === "block_sequence" || node.kind === "flow_sequence") { - for (let i = 0; i < node.components.length; ++i) { - const valueC = node.components[i]; + for (let i2 = 0; i2 < node.components.length; ++i2) { + const valueC = node.components[i2]; if (valueC.start <= position && position <= valueC.end) { - result.push(i); + result.push(i2); innermostAnnotation = valueC; return locate(valueC); } if (valueC.start > position) { - if (i === 0) { + if (i2 === 0) { return; } else { - result.push(i - 1); + result.push(i2 - 1); return; } } @@ -32434,8 +32445,8 @@ function locateCursor(annotation, position) { function locateAnnotation(annotation, position, kind) { const originalSource = annotation.source; kind = kind || "value"; - for (let i = 0; i < position.length; ++i) { - const value = position[i]; + for (let i2 = 0; i2 < position.length; ++i2) { + const value = position[i2]; if (typeof value === "number") { const inner = annotation.components[value]; if (inner === void 0) { @@ -32449,7 +32460,7 @@ function locateAnnotation(annotation, position, kind) { annotation.components[j].start, annotation.components[j].end ).trim() === value) { - if (i === position.length - 1) { + if (i2 === position.length - 1) { if (kind === "key") { annotation = annotation.components[j]; } else { @@ -32697,11 +32708,11 @@ var ValidationContext = class { return 1; }; const errorComparator = (a, b) => { - for (let i = 0; i < a.length; ++i) { - if (a[i] < b[i]) { + for (let i2 = 0; i2 < a.length; ++i2) { + if (a[i2] < b[i2]) { return -1; } - if (a[i] > b[i]) { + if (a[i2] > b[i2]) { return 1; } } @@ -32897,9 +32908,9 @@ function validateEnum(value, schema2, context) { } function validateAnyOf(value, schema2, context) { let passingSchemas = 0; - for (let i = 0; i < schema2.anyOf.length; ++i) { - const subSchema = schema2.anyOf[i]; - context.withSchemaPath(i, () => { + for (let i2 = 0; i2 < schema2.anyOf.length; ++i2) { + const subSchema = schema2.anyOf[i2]; + context.withSchemaPath(i2, () => { if (validateGeneric(value, subSchema, context)) { passingSchemas++; return true; @@ -32911,9 +32922,9 @@ function validateAnyOf(value, schema2, context) { } function validateAllOf(value, schema2, context) { let passingSchemas = 0; - for (let i = 0; i < schema2.allOf.length; ++i) { - const subSchema = schema2.allOf[i]; - context.withSchemaPath(i, () => { + for (let i2 = 0; i2 < schema2.allOf.length; ++i2) { + const subSchema = schema2.allOf[i2]; + context.withSchemaPath(i2, () => { if (validateGeneric(value, subSchema, context)) { passingSchemas++; return true; @@ -32960,9 +32971,9 @@ function validateArray(value, schema2, context) { if (schema2.items !== void 0) { result = context.withSchemaPath("items", () => { let result2 = true; - for (let i = 0; i < value.components.length; ++i) { - context.pushInstance(i); - result2 = validateGeneric(value.components[i], schema2.items, context) && result2; + for (let i2 = 0; i2 < value.components.length; ++i2) { + context.pushInstance(i2); + result2 = validateGeneric(value.components[i2], schema2.items, context) && result2; context.popInstance(); } return result2; @@ -32981,12 +32992,12 @@ function validateObject(value, schema2, context) { ); const objResult = value.result; const locate = (key, keyOrValue = "value") => { - for (let i = 0; i < value.components.length; i += 2) { - if (String(value.components[i].result) === key) { + for (let i2 = 0; i2 < value.components.length; i2 += 2) { + if (String(value.components[i2].result) === key) { if (keyOrValue === "value") { - return value.components[i + 1]; + return value.components[i2 + 1]; } else { - return value.components[i]; + return value.components[i2]; } } } @@ -33632,39 +33643,39 @@ function globToRegExp(glob, { let inRange = false; let inEscape = false; let endsWithSep = false; - let i = j; - for (; i < glob.length && !seps.includes(glob[i]); i++) { + let i2 = j; + for (; i2 < glob.length && !seps.includes(glob[i2]); i2++) { if (inEscape) { inEscape = false; const escapeChars = inRange ? rangeEscapeChars : regExpEscapeChars; - segment += escapeChars.includes(glob[i]) ? `\\${glob[i]}` : glob[i]; + segment += escapeChars.includes(glob[i2]) ? `\\${glob[i2]}` : glob[i2]; continue; } - if (glob[i] == escapePrefix) { + if (glob[i2] == escapePrefix) { inEscape = true; continue; } - if (glob[i] == "[") { + if (glob[i2] == "[") { if (!inRange) { inRange = true; segment += "["; - if (glob[i + 1] == "!") { - i++; + if (glob[i2 + 1] == "!") { + i2++; segment += "^"; - } else if (glob[i + 1] == "^") { - i++; + } else if (glob[i2 + 1] == "^") { + i2++; segment += "\\^"; } continue; - } else if (glob[i + 1] == ":") { - let k = i + 1; + } else if (glob[i2 + 1] == ":") { + let k = i2 + 1; let value = ""; while (glob[k + 1] != null && glob[k + 1] != ":") { value += glob[k + 1]; k++; } if (glob[k + 1] == ":" && glob[k + 2] == "]") { - i = k + 2; + i2 = k + 2; if (value == "alnum") segment += "\\dA-Za-z"; else if (value == "alpha") segment += "A-Za-z"; else if (value == "ascii") segment += "\0-\x7F"; @@ -33684,20 +33695,20 @@ function globToRegExp(glob, { } } } - if (glob[i] == "]" && inRange) { + if (glob[i2] == "]" && inRange) { inRange = false; segment += "]"; continue; } if (inRange) { - if (glob[i] == "\\") { + if (glob[i2] == "\\") { segment += `\\\\`; } else { - segment += glob[i]; + segment += glob[i2]; } continue; } - if (glob[i] == ")" && groupStack.length > 0 && groupStack[groupStack.length - 1] != "BRACE") { + if (glob[i2] == ")" && groupStack.length > 0 && groupStack[groupStack.length - 1] != "BRACE") { segment += ")"; const type2 = groupStack.pop(); if (type2 == "!") { @@ -33707,25 +33718,25 @@ function globToRegExp(glob, { } continue; } - if (glob[i] == "|" && groupStack.length > 0 && groupStack[groupStack.length - 1] != "BRACE") { + if (glob[i2] == "|" && groupStack.length > 0 && groupStack[groupStack.length - 1] != "BRACE") { segment += "|"; continue; } - if (glob[i] == "+" && extended && glob[i + 1] == "(") { - i++; + if (glob[i2] == "+" && extended && glob[i2 + 1] == "(") { + i2++; groupStack.push("+"); segment += "(?:"; continue; } - if (glob[i] == "@" && extended && glob[i + 1] == "(") { - i++; + if (glob[i2] == "@" && extended && glob[i2 + 1] == "(") { + i2++; groupStack.push("@"); segment += "(?:"; continue; } - if (glob[i] == "?") { - if (extended && glob[i + 1] == "(") { - i++; + if (glob[i2] == "?") { + if (extended && glob[i2 + 1] == "(") { + i2++; groupStack.push("?"); segment += "(?:"; } else { @@ -33733,39 +33744,39 @@ function globToRegExp(glob, { } continue; } - if (glob[i] == "!" && extended && glob[i + 1] == "(") { - i++; + if (glob[i2] == "!" && extended && glob[i2 + 1] == "(") { + i2++; groupStack.push("!"); segment += "(?!"; continue; } - if (glob[i] == "{") { + if (glob[i2] == "{") { groupStack.push("BRACE"); segment += "(?:"; continue; } - if (glob[i] == "}" && groupStack[groupStack.length - 1] == "BRACE") { + if (glob[i2] == "}" && groupStack[groupStack.length - 1] == "BRACE") { groupStack.pop(); segment += ")"; continue; } - if (glob[i] == "," && groupStack[groupStack.length - 1] == "BRACE") { + if (glob[i2] == "," && groupStack[groupStack.length - 1] == "BRACE") { segment += "|"; continue; } - if (glob[i] == "*") { - if (extended && glob[i + 1] == "(") { - i++; + if (glob[i2] == "*") { + if (extended && glob[i2 + 1] == "(") { + i2++; groupStack.push("*"); segment += "(?:"; } else { - const prevChar = glob[i - 1]; + const prevChar = glob[i2 - 1]; let numStars = 1; - while (glob[i + 1] == "*") { - i++; + while (glob[i2 + 1] == "*") { + i2++; numStars++; } - const nextChar = glob[i + 1]; + const nextChar = glob[i2 + 1]; if (globstarOption && numStars == 2 && [...seps, void 0].includes(prevChar) && [...seps, void 0].includes(nextChar)) { segment += globstar; endsWithSep = true; @@ -33775,25 +33786,25 @@ function globToRegExp(glob, { } continue; } - segment += regExpEscapeChars.includes(glob[i]) ? `\\${glob[i]}` : glob[i]; + segment += regExpEscapeChars.includes(glob[i2]) ? `\\${glob[i2]}` : glob[i2]; } if (groupStack.length > 0 || inRange || inEscape) { segment = ""; - for (const c of glob.slice(j, i)) { + for (const c of glob.slice(j, i2)) { segment += regExpEscapeChars.includes(c) ? `\\${c}` : c; endsWithSep = false; } } regExpString += segment; if (!endsWithSep) { - regExpString += i < glob.length ? sep : sepMaybe; + regExpString += i2 < glob.length ? sep : sepMaybe; endsWithSep = true; } - while (seps.includes(glob[i])) i++; - if (!(i > j)) { + while (seps.includes(glob[i2])) i2++; + if (!(i2 > j)) { throw new Error("Assertion failure: i > j (potential infinite loop)"); } - j = i; + j = i2; } regExpString = `^${regExpString}$`; return new RegExp(regExpString, caseInsensitive ? "i" : ""); @@ -34901,28 +34912,28 @@ async function breakQuartoMd(src, validate2 = false, lenient = false, startCodeC return true; }; const srcLines = rangedLines(src.value, true); - for (let i = 0; i < srcLines.length; ++i) { - const line = srcLines[i]; + for (let i2 = 0; i2 < srcLines.length; ++i2) { + const line = srcLines[i2]; const directiveMatch = isBlockShortcode(line.substring, true); - if (isYamlDelimiter(line.substring, i, !inYaml) && !inCodeCell && !inCode) { + if (isYamlDelimiter(line.substring, i2, !inYaml) && !inCodeCell && !inCode) { if (inYaml) { lineBuffer.push(line); - await flushLineBuffer("raw", i); + await flushLineBuffer("raw", i2); inYaml = false; } else { - await flushLineBuffer("markdown", i); + await flushLineBuffer("markdown", i2); lineBuffer.push(line); inYaml = true; } } else if (inPlainText() && directiveMatch) { - await flushLineBuffer("markdown", i); + await flushLineBuffer("markdown", i2); directiveParams = directiveMatch; lineBuffer.push(line); - await flushLineBuffer("directive", i); + await flushLineBuffer("directive", i2); } else if (startCodeCellRegEx.test(line.substring) && inPlainText()) { const m = line.substring.match(startCodeCellRegEx); language = m[2]; - await flushLineBuffer("markdown", i); + await flushLineBuffer("markdown", i2); inCodeCell = true; inCode = m[1].length; codeStartRange = line; @@ -34931,7 +34942,7 @@ async function breakQuartoMd(src, validate2 = false, lenient = false, startCodeC codeEndRange = line; inCodeCell = false; inCode = 0; - await flushLineBuffer("code", i); + await flushLineBuffer("code", i2); } else { inCode = 0; lineBuffer.push(line); @@ -35251,13 +35262,13 @@ function buildLineMap(annotation, document) { } const { annotation: annotation2, path } = s; const isMapping = ["block_mapping", "flow_mapping", "mapping"].indexOf(annotation2.kind) !== -1; - for (let i = 0; i < annotation2.components.length; ++i) { - const child = annotation2.components[i]; - const keyOrValue = isMapping && (i & 1) === 0 ? "key" : "value"; + for (let i2 = 0; i2 < annotation2.components.length; ++i2) { + const child = annotation2.components[i2]; + const keyOrValue = isMapping && (i2 & 1) === 0 ? "key" : "value"; if (isMapping) { - path.push(annotation2.components[i & ~1].result); + path.push(annotation2.components[i2 & ~1].result); } else { - path.push(i); + path.push(i2); } walk({ annotation: child, position: keyOrValue, path }, f2); path.pop(); diff --git a/src/resources/editor/tools/yaml/web-worker.js b/src/resources/editor/tools/yaml/web-worker.js index e1f69e73c2f..40095dd9c7a 100644 --- a/src/resources/editor/tools/yaml/web-worker.js +++ b/src/resources/editor/tools/yaml/web-worker.js @@ -6998,7 +6998,11 @@ try { var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __commonJS = (cb, mod) => function __require() { - return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; + try { + return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; + } catch (e) { + throw mod = 0, e; + } }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { @@ -7120,7 +7124,14 @@ try { tags: { engine: "knitr" }, - schema: "string", + schema: { + anyOf: [ + { + maybeArrayOf: "string" + }, + "boolean" + ] + }, description: { short: "Variables names that are not created from the current chunk", long: "Variables names that are not created from the current chunk.\n\nThis option is mainly for `autodep: true` to work more precisely---a chunk\n`B` depends on chunk `A` when any of `B`'s global variables are `A`'s local \nvariables. In case the automatic detection of global variables in a chunk \nfails, you may manually specify the names of global variables via this option.\nIn addition, `cache-globals: false` means detecting all variables in a code\nchunk, no matter if they are global or local variables.\n" @@ -25377,12 +25388,12 @@ try { mermaid: "%%" }, "handlers/mermaid/schema.yml": { - _internalId: 223022, + _internalId: 223031, type: "object", description: "be an object", properties: { "mermaid-format": { - _internalId: 223014, + _internalId: 223023, type: "enum", enum: [ "png", @@ -25398,7 +25409,7 @@ try { exhaustiveCompletions: true }, theme: { - _internalId: 223021, + _internalId: 223030, type: "anyOf", anyOf: [ { @@ -25794,13 +25805,13 @@ ${heading}`; const pad = " ".repeat(lineWidth); const ls = lines(text); const result = []; - for (let i = firstLine; i <= lastLine; ++i) { - const numberStr = `${pad}${i + 1}: `.slice(-(lineWidth + 2)); - const lineStr = ls[i]; + for (let i2 = firstLine; i2 <= lastLine; ++i2) { + const numberStr = `${pad}${i2 + 1}: `.slice(-(lineWidth + 2)); + const lineStr = ls[i2]; result.push({ - lineNumber: i, + lineNumber: i2, content: numberStr + quotedStringColor(lineStr), - rawLine: ls[i] + rawLine: ls[i2] }); } return { @@ -25835,19 +25846,19 @@ ${heading}`; const s1 = w1.length + 1; const s2 = w2.length + 1; const v = new Int32Array(s1 * s2); - for (let i = 0; i < s1; ++i) { + for (let i2 = 0; i2 < s1; ++i2) { for (let j = 0; j < s2; ++j) { - if (i === 0 && j === 0) { + if (i2 === 0 && j === 0) { continue; - } else if (i === 0) { - v[i * s2 + j] = v[i * s2 + (j - 1)] + cost(w2[j - 1]); + } else if (i2 === 0) { + v[i2 * s2 + j] = v[i2 * s2 + (j - 1)] + cost(w2[j - 1]); } else if (j === 0) { - v[i * s2 + j] = v[(i - 1) * s2 + j] + cost(w1[i - 1]); + v[i2 * s2 + j] = v[(i2 - 1) * s2 + j] + cost(w1[i2 - 1]); } else { - v[i * s2 + j] = Math.min( - v[(i - 1) * s2 + (j - 1)] + cost2(w1[i - 1], w2[j - 1]), - v[i * s2 + (j - 1)] + cost(w2[j - 1]), - v[(i - 1) * s2 + j] + cost(w1[i - 1]) + v[i2 * s2 + j] = Math.min( + v[(i2 - 1) * s2 + (j - 1)] + cost2(w1[i2 - 1], w2[j - 1]), + v[i2 * s2 + (j - 1)] + cost(w2[j - 1]), + v[(i2 - 1) * s2 + j] + cost(w1[i2 - 1]) ); } } @@ -26223,26 +26234,26 @@ ${heading}`; const indents = []; let indentation = -1; let prevPredecessor = -1; - for (let i = 0; i < ls.length; ++i) { - const line = ls[i]; + for (let i2 = 0; i2 < ls.length; ++i2) { + const line = ls[i2]; const lineIndent = getIndent(line); indents.push(lineIndent); if (lineIndent > indentation) { - predecessor[i] = prevPredecessor; - prevPredecessor = i; + predecessor[i2] = prevPredecessor; + prevPredecessor = i2; indentation = lineIndent; } else if (line.trim().length === 0) { - predecessor[i] = predecessor[prevPredecessor]; + predecessor[i2] = predecessor[prevPredecessor]; } else if (lineIndent === indentation) { - predecessor[i] = predecessor[prevPredecessor]; - prevPredecessor = i; + predecessor[i2] = predecessor[prevPredecessor]; + prevPredecessor = i2; } else if (lineIndent < indentation) { let v = prevPredecessor; while (v >= 0 && indents[v] >= lineIndent) { v = predecessor[v]; } - predecessor[i] = v; - prevPredecessor = i; + predecessor[i2] = v; + prevPredecessor = i2; indentation = lineIndent; } else { throw new UnreachableError(); @@ -26420,22 +26431,22 @@ ${heading}`; } } if (foundLineNo < 0) foundLineNo = lineStarts.length - 1; - var result = "", i, line; + var result = "", i2, line; var lineNoLength = Math.min( mark.line + options.linesAfter, lineEnds.length ).toString().length; var maxLineLength = options.maxLength - (options.indent + lineNoLength + 3); - for (i = 1; i <= options.linesBefore; i++) { - if (foundLineNo - i < 0) break; + for (i2 = 1; i2 <= options.linesBefore; i2++) { + if (foundLineNo - i2 < 0) break; line = getLine( mark.buffer, - lineStarts[foundLineNo - i], - lineEnds[foundLineNo - i], - mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]), + lineStarts[foundLineNo - i2], + lineEnds[foundLineNo - i2], + mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i2]), maxLineLength ); - result = common.repeat(" ", options.indent) + padStart((mark.line - i + 1).toString(), lineNoLength) + " | " + line.str + "\n" + result; + result = common.repeat(" ", options.indent) + padStart((mark.line - i2 + 1).toString(), lineNoLength) + " | " + line.str + "\n" + result; } line = getLine( mark.buffer, @@ -26446,16 +26457,16 @@ ${heading}`; ); result += common.repeat(" ", options.indent) + padStart((mark.line + 1).toString(), lineNoLength) + " | " + line.str + "\n"; result += common.repeat("-", options.indent + lineNoLength + 3 + line.pos) + "^\n"; - for (i = 1; i <= options.linesAfter; i++) { - if (foundLineNo + i >= lineEnds.length) break; + for (i2 = 1; i2 <= options.linesAfter; i2++) { + if (foundLineNo + i2 >= lineEnds.length) break; line = getLine( mark.buffer, - lineStarts[foundLineNo + i], - lineEnds[foundLineNo + i], - mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]), + lineStarts[foundLineNo + i2], + lineEnds[foundLineNo + i2], + mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i2]), maxLineLength ); - result += common.repeat(" ", options.indent) + padStart((mark.line + i + 1).toString(), lineNoLength) + " | " + line.str + "\n"; + result += common.repeat(" ", options.indent) + padStart((mark.line + i2 + 1).toString(), lineNoLength) + " | " + line.str + "\n"; } return result.replace(/\n$/, ""); } @@ -28579,7 +28590,7 @@ ${heading}`; var STYLE_FOLDED = 4; var STYLE_DOUBLE = 5; function chooseScalarStyle(string, singleLineOnly, indentPerLevel, lineWidth, testAmbiguousType, quotingType, forceQuotes, inblock) { - var i; + var i2; var char = 0; var prevChar = null; var hasLineBreak = false; @@ -28588,8 +28599,8 @@ ${heading}`; var previousLineBreak = -1; var plain = isPlainSafeFirst(codePointAt(string, 0)) && isPlainSafeLast(codePointAt(string, string.length - 1)); if (singleLineOnly || forceQuotes) { - for (i = 0; i < string.length; char >= 65536 ? i += 2 : i++) { - char = codePointAt(string, i); + for (i2 = 0; i2 < string.length; char >= 65536 ? i2 += 2 : i2++) { + char = codePointAt(string, i2); if (!isPrintable(char)) { return STYLE_DOUBLE; } @@ -28597,13 +28608,13 @@ ${heading}`; prevChar = char; } } else { - for (i = 0; i < string.length; char >= 65536 ? i += 2 : i++) { - char = codePointAt(string, i); + for (i2 = 0; i2 < string.length; char >= 65536 ? i2 += 2 : i2++) { + char = codePointAt(string, i2); if (char === CHAR_LINE_FEED) { hasLineBreak = true; if (shouldTrackWidth) { - hasFoldableLine = hasFoldableLine || i - previousLineBreak - 1 > lineWidth && string[previousLineBreak + 1] !== " "; - previousLineBreak = i; + hasFoldableLine = hasFoldableLine || i2 - previousLineBreak - 1 > lineWidth && string[previousLineBreak + 1] !== " "; + previousLineBreak = i2; } } else if (!isPrintable(char)) { return STYLE_DOUBLE; @@ -28611,7 +28622,7 @@ ${heading}`; plain = plain && isPlainSafe(char, prevChar, inblock); prevChar = char; } - hasFoldableLine = hasFoldableLine || shouldTrackWidth && i - previousLineBreak - 1 > lineWidth && string[previousLineBreak + 1] !== " "; + hasFoldableLine = hasFoldableLine || shouldTrackWidth && i2 - previousLineBreak - 1 > lineWidth && string[previousLineBreak + 1] !== " "; } if (!hasLineBreak && !hasFoldableLine) { if (plain && !forceQuotes && !testAmbiguousType(string)) { @@ -28724,12 +28735,12 @@ ${heading}`; var result = ""; var char = 0; var escapeSeq; - for (var i = 0; i < string.length; char >= 65536 ? i += 2 : i++) { - char = codePointAt(string, i); + for (var i2 = 0; i2 < string.length; char >= 65536 ? i2 += 2 : i2++) { + char = codePointAt(string, i2); escapeSeq = ESCAPE_SEQUENCES[char]; if (!escapeSeq && isPrintable(char)) { - result += string[i]; - if (char >= 65536) result += string[i + 1]; + result += string[i2]; + if (char >= 65536) result += string[i2 + 1]; } else { result += escapeSeq || encodeHex(char); } @@ -29130,8 +29141,8 @@ ${heading}`; const aliases = defs; const result = []; lst = lst.slice(); - for (let i = 0; i < lst.length; ++i) { - const el = lst[i]; + for (let i2 = 0; i2 < lst.length; ++i2) { + const el = lst[i2]; if (el.startsWith("$")) { const v = aliases[el.slice(1)]; if (v === void 0) { @@ -29246,15 +29257,15 @@ ${heading}`; return restoreRanges("53 0 g9 33 o 0 70 4 7e 18 2 0 2 1 2 1 2 0 21 a 1d u 7 0 2u 6 3 5 3 1 2 3 3 9 o 0 v q 2k a g 9 y 8 a 0 p 3 2 8 2 2 2 4 18 2 3c e 2 w 1j 2 2 h 2 6 b 1 3 9 i 2 1l 0 2 6 3 1 3 2 a 0 b 1 3 9 f 0 3 2 1l 0 2 4 5 1 3 2 4 0 l b 4 0 c 2 1l 0 2 7 2 2 2 2 l 1 3 9 b 5 2 2 1l 0 2 6 3 1 3 2 8 2 b 1 3 9 j 0 1o 4 4 2 2 3 a 0 f 9 h 4 1m 6 2 2 2 3 8 1 c 1 3 9 i 2 1l 0 2 6 2 2 2 3 8 1 c 1 3 9 h 3 1k 1 2 6 2 2 2 3 a 0 b 1 3 9 i 2 1z 0 5 5 2 0 2 7 7 9 3 1 1q 0 3 6 d 7 2 9 2g 0 3 8 c 5 3 9 1r 1 7 9 c 0 2 0 2 0 5 1 1e j 2 1 6 a 2 z a 0 2t j 2 9 d 3 5 2 2 2 3 6 4 3 e b 2 e jk 2 a 8 pt 2 u 2 u 1 v 1 1t v a 0 3 9 y 2 3 9 40 0 3b b 5 b b 9 3l a 1p 4 1m 9 2 s 3 a 7 9 n d 2 1 1s 4 1c g c 9 i 8 d 2 v c 3 9 19 d 1d j 9 9 7 9 3b 2 2 k 5 0 7 0 3 2 5j 1l 2 4 g0 1 k 0 3g c 5 0 4 b 2db 2 3y 0 2p v ff 5 2y 1 n7q 9 1y 0 5 9 x 1 29 1 7l 0 4 0 5 0 o 4 5 0 2c 1 1f h b 9 7 h e a t 7 q c 19 3 1c d g 9 c 0 b 9 1c d d 0 9 1 3 9 y 2 1f 0 2 2 3 1 6 1 2 0 16 4 6 1 6l 7 2 1 3 9 fmt 0 ki f h f 4 1 p 2 5d 9 12 0 ji 0 6b 0 46 4 86 9 120 2 2 1 6 3 15 2 5 0 4m 1 fy 3 9 9 aa 1 4a a 4w 2 1i e w 9 g 3 1a a 1i 9 7 2 11 d 2 9 6 1 19 0 d 2 1d d 9 3 2 b 2b b 7 0 4h b 6 9 7 3 1k 1 2 6 3 1 3 2 a 0 b 1 3 6 4 4 5d h a 9 5 0 2a j d 9 5y 6 3 8 s 1 2b g g 9 2a c 9 9 2c e 5 9 6r e 4m 9 1z 5 2 1 3 3 2 0 2 1 d 9 3c 6 3 6 4 0 t 9 15 6 2 3 9 0 a a 1b f ba 7 2 7 h 9 1l l 2 d 3f 5 4 0 2 1 2 6 2 0 9 9 1d 4 2 1 2 4 9 9 96 3 ewa 9 3r 4 1o 6 q 9 s6 0 2 1i 8 3 2a 0 c 1 f58 1 43r 4 4 5 9 7 3 6 v 3 45 2 13e 1d e9 1i 5 1d 9 0 f 0 n 4 2 e 11t 6 2 g 3 6 2 1 2 4 7a 6 a 9 bn d 15j 6 32 6 6 9 3o7 9 gvt3 6n"); } function isInRange(cp, ranges) { - let l = 0, r = ranges.length / 2 | 0, i = 0, min = 0, max = 0; + let l = 0, r = ranges.length / 2 | 0, i2 = 0, min = 0, max = 0; while (l < r) { - i = (l + r) / 2 | 0; - min = ranges[2 * i]; - max = ranges[2 * i + 1]; + i2 = (l + r) / 2 | 0; + min = ranges[2 * i2]; + max = ranges[2 * i2 + 1]; if (cp < min) { - r = i; + r = i2; } else if (cp > max) { - l = i + 1; + l = i2 + 1; } else { return true; } @@ -29406,16 +29417,16 @@ ${heading}`; return (lead - 55296) * 1024 + (trail - 56320) + 65536; } var legacyImpl = { - at(s, end, i) { - return i < end ? s.charCodeAt(i) : -1; + at(s, end, i2) { + return i2 < end ? s.charCodeAt(i2) : -1; }, width(c) { return 1; } }; var unicodeImpl = { - at(s, end, i) { - return i < end ? s.codePointAt(i) : -1; + at(s, end, i2) { + return i2 < end ? s.codePointAt(i2) : -1; }, width(c) { return c > 65535 ? 2 : 1; @@ -29578,10 +29589,10 @@ ${heading}`; let unicode = false; let dotAll = false; let hasIndices = false; - for (let i = start; i < end; ++i) { - const flag = source.charCodeAt(i); + for (let i2 = start; i2 < end; ++i2) { + const flag = source.charCodeAt(i2); if (existingFlags.has(flag)) { - this.raise(`Duplicated flag '${source[i]}'`); + this.raise(`Duplicated flag '${source[i2]}'`); } existingFlags.add(flag); if (flag === LatinSmallLetterG) { @@ -29599,7 +29610,7 @@ ${heading}`; } else if (flag === LatinSmallLetterD && this.ecmaVersion >= 2022) { hasIndices = true; } else { - this.raise(`Invalid flag '${source[i]}'`); + this.raise(`Invalid flag '${source[i2]}'`); } } this.onFlags(start, end, global, ignoreCase, multiline, unicode, sticky, dotAll, hasIndices); @@ -29868,10 +29879,10 @@ ${heading}`; } consumeDisjunction() { const start = this.index; - let i = 0; + let i2 = 0; this.onDisjunctionEnter(start); do { - this.consumeAlternative(i++); + this.consumeAlternative(i2++); } while (this.eat(VerticalLine)); if (this.consumeQuantifier(true)) { this.raise("Nothing to repeat"); @@ -29881,12 +29892,12 @@ ${heading}`; } this.onDisjunctionLeave(start, this.index); } - consumeAlternative(i) { + consumeAlternative(i2) { const start = this.index; - this.onAlternativeEnter(start, i); + this.onAlternativeEnter(start, i2); while (this.currentCodePoint !== -1 && this.consumeTerm()) { } - this.onAlternativeLeave(start, this.index, i); + this.onAlternativeLeave(start, this.index, i2); } consumeTerm() { if (this._uFlag || this.strict) { @@ -30559,7 +30570,7 @@ ${heading}`; eatFixedHexDigits(length) { const start = this.index; this._lastIntValue = 0; - for (let i = 0; i < length; ++i) { + for (let i2 = 0; i2 < length; ++i2) { const cp = this.currentCodePoint; if (!isHexDigit(cp)) { this.rewind(start); @@ -30960,12 +30971,12 @@ ${heading}`; return `(${alternatives.join("|")})`; } else if (parse.type === "Alternative") { const result = []; - for (let i = 0; i < parse.elements.length; ++i) { + for (let i2 = 0; i2 < parse.elements.length; ++i2) { const thisRe = []; - for (let j = 0; j < i; ++j) { + for (let j = 0; j < i2; ++j) { thisRe.push(parse.elements[j].raw); } - thisRe.push(prefixesFromParse(parse.elements[i])); + thisRe.push(prefixesFromParse(parse.elements[i2])); result.push(thisRe.join("")); } return `(${result.join("|")})`; @@ -31396,7 +31407,7 @@ ${heading}`; if (schemaPath.length !== strs.length) { return false; } - return strs.every((str2, i) => str2 === schemaPath[i]); + return strs.every((str2, i2) => str2 === schemaPath[i2]); } function getBadKey(error) { if (error.schemaPath.indexOf("propertyNames") === -1 && error.schemaPath.indexOf("closed") === -1) { @@ -31424,13 +31435,13 @@ ${heading}`; const { components } = annotation; const searchKey = path[pathIndex]; const lastKeyIndex = ~~((components.length - 1) / 2) * 2; - for (let i = lastKeyIndex; i >= 0; i -= 2) { - const key = components[i].result; + for (let i2 = lastKeyIndex; i2 >= 0; i2 -= 2) { + const key = components[i2].result; if (key === searchKey) { if (returnKey && pathIndex === path.length - 1) { - return navigate(path, components[i], returnKey, pathIndex + 1); + return navigate(path, components[i2], returnKey, pathIndex + 1); } else { - return navigate(path, components[i + 1], returnKey, pathIndex + 1); + return navigate(path, components[i2 + 1], returnKey, pathIndex + 1); } } } @@ -32290,8 +32301,8 @@ ${tidyverseInfo( }, "block_sequence": (node) => { const result2 = [], components = []; - for (let i = 0; i < node.childCount; ++i) { - const child = node.child(i); + for (let i2 = 0; i2 < node.childCount; ++i2) { + const child = node.child(i2); if (child.type !== "block_sequence_item") { continue; } @@ -32310,8 +32321,8 @@ ${tidyverseInfo( }, "flow_sequence": (node) => { const result2 = [], components = []; - for (let i = 0; i < node.childCount; ++i) { - const child = node.child(i); + for (let i2 = 0; i2 < node.childCount; ++i2) { + const child = node.child(i2); if (child.type !== "flow_node") { continue; } @@ -32323,8 +32334,8 @@ ${tidyverseInfo( }, "block_mapping": (node) => { const result2 = {}, components = []; - for (let i = 0; i < node.childCount; ++i) { - const child = node.child(i); + for (let i2 = 0; i2 < node.childCount; ++i2) { + const child = node.child(i2); let component; if (child.type === "ERROR") { result2[child.text] = "<>"; @@ -32348,8 +32359,8 @@ ${tidyverseInfo( "flow_pair": buildPair, "flow_mapping": (node) => { const result2 = {}, components = []; - for (let i = 0; i < node.childCount; ++i) { - const child = node.child(i); + for (let i2 = 0; i2 < node.childCount; ++i2) { + const child = node.child(i2); if (child.type === "flow_node") { continue; } @@ -32384,8 +32395,8 @@ ${tidyverseInfo( const kInternalLocateError = "Cursor outside bounds in sequence locate"; function locate(node) { if (node.kind === "block_mapping" || node.kind === "flow_mapping" || node.kind === "mapping") { - for (let i = 0; i < node.components.length; i += 2) { - const keyC = node.components[i], valueC = node.components[i + 1]; + for (let i2 = 0; i2 < node.components.length; i2 += 2) { + const keyC = node.components[i2], valueC = node.components[i2 + 1]; if (keyC.start <= position && position <= keyC.end) { innermostAnnotation = keyC; result.push(keyC.result); @@ -32400,18 +32411,18 @@ ${tidyverseInfo( failedLast = true; return; } else if (node.kind === "block_sequence" || node.kind === "flow_sequence") { - for (let i = 0; i < node.components.length; ++i) { - const valueC = node.components[i]; + for (let i2 = 0; i2 < node.components.length; ++i2) { + const valueC = node.components[i2]; if (valueC.start <= position && position <= valueC.end) { - result.push(i); + result.push(i2); innermostAnnotation = valueC; return locate(valueC); } if (valueC.start > position) { - if (i === 0) { + if (i2 === 0) { return; } else { - result.push(i - 1); + result.push(i2 - 1); return; } } @@ -32448,8 +32459,8 @@ ${tidyverseInfo( function locateAnnotation(annotation, position, kind) { const originalSource = annotation.source; kind = kind || "value"; - for (let i = 0; i < position.length; ++i) { - const value = position[i]; + for (let i2 = 0; i2 < position.length; ++i2) { + const value = position[i2]; if (typeof value === "number") { const inner = annotation.components[value]; if (inner === void 0) { @@ -32463,7 +32474,7 @@ ${tidyverseInfo( annotation.components[j].start, annotation.components[j].end ).trim() === value) { - if (i === position.length - 1) { + if (i2 === position.length - 1) { if (kind === "key") { annotation = annotation.components[j]; } else { @@ -32711,11 +32722,11 @@ ${tidyverseInfo( return 1; }; const errorComparator = (a, b) => { - for (let i = 0; i < a.length; ++i) { - if (a[i] < b[i]) { + for (let i2 = 0; i2 < a.length; ++i2) { + if (a[i2] < b[i2]) { return -1; } - if (a[i] > b[i]) { + if (a[i2] > b[i2]) { return 1; } } @@ -32911,9 +32922,9 @@ ${tidyverseInfo( } function validateAnyOf(value, schema2, context) { let passingSchemas = 0; - for (let i = 0; i < schema2.anyOf.length; ++i) { - const subSchema = schema2.anyOf[i]; - context.withSchemaPath(i, () => { + for (let i2 = 0; i2 < schema2.anyOf.length; ++i2) { + const subSchema = schema2.anyOf[i2]; + context.withSchemaPath(i2, () => { if (validateGeneric(value, subSchema, context)) { passingSchemas++; return true; @@ -32925,9 +32936,9 @@ ${tidyverseInfo( } function validateAllOf(value, schema2, context) { let passingSchemas = 0; - for (let i = 0; i < schema2.allOf.length; ++i) { - const subSchema = schema2.allOf[i]; - context.withSchemaPath(i, () => { + for (let i2 = 0; i2 < schema2.allOf.length; ++i2) { + const subSchema = schema2.allOf[i2]; + context.withSchemaPath(i2, () => { if (validateGeneric(value, subSchema, context)) { passingSchemas++; return true; @@ -32974,9 +32985,9 @@ ${tidyverseInfo( if (schema2.items !== void 0) { result = context.withSchemaPath("items", () => { let result2 = true; - for (let i = 0; i < value.components.length; ++i) { - context.pushInstance(i); - result2 = validateGeneric(value.components[i], schema2.items, context) && result2; + for (let i2 = 0; i2 < value.components.length; ++i2) { + context.pushInstance(i2); + result2 = validateGeneric(value.components[i2], schema2.items, context) && result2; context.popInstance(); } return result2; @@ -32995,12 +33006,12 @@ ${tidyverseInfo( ); const objResult = value.result; const locate = (key, keyOrValue = "value") => { - for (let i = 0; i < value.components.length; i += 2) { - if (String(value.components[i].result) === key) { + for (let i2 = 0; i2 < value.components.length; i2 += 2) { + if (String(value.components[i2].result) === key) { if (keyOrValue === "value") { - return value.components[i + 1]; + return value.components[i2 + 1]; } else { - return value.components[i]; + return value.components[i2]; } } } @@ -33646,39 +33657,39 @@ ${tidyverseInfo( let inRange = false; let inEscape = false; let endsWithSep = false; - let i = j; - for (; i < glob.length && !seps.includes(glob[i]); i++) { + let i2 = j; + for (; i2 < glob.length && !seps.includes(glob[i2]); i2++) { if (inEscape) { inEscape = false; const escapeChars = inRange ? rangeEscapeChars : regExpEscapeChars; - segment += escapeChars.includes(glob[i]) ? `\\${glob[i]}` : glob[i]; + segment += escapeChars.includes(glob[i2]) ? `\\${glob[i2]}` : glob[i2]; continue; } - if (glob[i] == escapePrefix) { + if (glob[i2] == escapePrefix) { inEscape = true; continue; } - if (glob[i] == "[") { + if (glob[i2] == "[") { if (!inRange) { inRange = true; segment += "["; - if (glob[i + 1] == "!") { - i++; + if (glob[i2 + 1] == "!") { + i2++; segment += "^"; - } else if (glob[i + 1] == "^") { - i++; + } else if (glob[i2 + 1] == "^") { + i2++; segment += "\\^"; } continue; - } else if (glob[i + 1] == ":") { - let k = i + 1; + } else if (glob[i2 + 1] == ":") { + let k = i2 + 1; let value = ""; while (glob[k + 1] != null && glob[k + 1] != ":") { value += glob[k + 1]; k++; } if (glob[k + 1] == ":" && glob[k + 2] == "]") { - i = k + 2; + i2 = k + 2; if (value == "alnum") segment += "\\dA-Za-z"; else if (value == "alpha") segment += "A-Za-z"; else if (value == "ascii") segment += "\0-\x7F"; @@ -33698,20 +33709,20 @@ ${tidyverseInfo( } } } - if (glob[i] == "]" && inRange) { + if (glob[i2] == "]" && inRange) { inRange = false; segment += "]"; continue; } if (inRange) { - if (glob[i] == "\\") { + if (glob[i2] == "\\") { segment += `\\\\`; } else { - segment += glob[i]; + segment += glob[i2]; } continue; } - if (glob[i] == ")" && groupStack.length > 0 && groupStack[groupStack.length - 1] != "BRACE") { + if (glob[i2] == ")" && groupStack.length > 0 && groupStack[groupStack.length - 1] != "BRACE") { segment += ")"; const type2 = groupStack.pop(); if (type2 == "!") { @@ -33721,25 +33732,25 @@ ${tidyverseInfo( } continue; } - if (glob[i] == "|" && groupStack.length > 0 && groupStack[groupStack.length - 1] != "BRACE") { + if (glob[i2] == "|" && groupStack.length > 0 && groupStack[groupStack.length - 1] != "BRACE") { segment += "|"; continue; } - if (glob[i] == "+" && extended && glob[i + 1] == "(") { - i++; + if (glob[i2] == "+" && extended && glob[i2 + 1] == "(") { + i2++; groupStack.push("+"); segment += "(?:"; continue; } - if (glob[i] == "@" && extended && glob[i + 1] == "(") { - i++; + if (glob[i2] == "@" && extended && glob[i2 + 1] == "(") { + i2++; groupStack.push("@"); segment += "(?:"; continue; } - if (glob[i] == "?") { - if (extended && glob[i + 1] == "(") { - i++; + if (glob[i2] == "?") { + if (extended && glob[i2 + 1] == "(") { + i2++; groupStack.push("?"); segment += "(?:"; } else { @@ -33747,39 +33758,39 @@ ${tidyverseInfo( } continue; } - if (glob[i] == "!" && extended && glob[i + 1] == "(") { - i++; + if (glob[i2] == "!" && extended && glob[i2 + 1] == "(") { + i2++; groupStack.push("!"); segment += "(?!"; continue; } - if (glob[i] == "{") { + if (glob[i2] == "{") { groupStack.push("BRACE"); segment += "(?:"; continue; } - if (glob[i] == "}" && groupStack[groupStack.length - 1] == "BRACE") { + if (glob[i2] == "}" && groupStack[groupStack.length - 1] == "BRACE") { groupStack.pop(); segment += ")"; continue; } - if (glob[i] == "," && groupStack[groupStack.length - 1] == "BRACE") { + if (glob[i2] == "," && groupStack[groupStack.length - 1] == "BRACE") { segment += "|"; continue; } - if (glob[i] == "*") { - if (extended && glob[i + 1] == "(") { - i++; + if (glob[i2] == "*") { + if (extended && glob[i2 + 1] == "(") { + i2++; groupStack.push("*"); segment += "(?:"; } else { - const prevChar = glob[i - 1]; + const prevChar = glob[i2 - 1]; let numStars = 1; - while (glob[i + 1] == "*") { - i++; + while (glob[i2 + 1] == "*") { + i2++; numStars++; } - const nextChar = glob[i + 1]; + const nextChar = glob[i2 + 1]; if (globstarOption && numStars == 2 && [...seps, void 0].includes(prevChar) && [...seps, void 0].includes(nextChar)) { segment += globstar; endsWithSep = true; @@ -33789,25 +33800,25 @@ ${tidyverseInfo( } continue; } - segment += regExpEscapeChars.includes(glob[i]) ? `\\${glob[i]}` : glob[i]; + segment += regExpEscapeChars.includes(glob[i2]) ? `\\${glob[i2]}` : glob[i2]; } if (groupStack.length > 0 || inRange || inEscape) { segment = ""; - for (const c of glob.slice(j, i)) { + for (const c of glob.slice(j, i2)) { segment += regExpEscapeChars.includes(c) ? `\\${c}` : c; endsWithSep = false; } } regExpString += segment; if (!endsWithSep) { - regExpString += i < glob.length ? sep : sepMaybe; + regExpString += i2 < glob.length ? sep : sepMaybe; endsWithSep = true; } - while (seps.includes(glob[i])) i++; - if (!(i > j)) { + while (seps.includes(glob[i2])) i2++; + if (!(i2 > j)) { throw new Error("Assertion failure: i > j (potential infinite loop)"); } - j = i; + j = i2; } regExpString = `^${regExpString}$`; return new RegExp(regExpString, caseInsensitive ? "i" : ""); @@ -34915,28 +34926,28 @@ ${tidyverseInfo( return true; }; const srcLines = rangedLines(src.value, true); - for (let i = 0; i < srcLines.length; ++i) { - const line = srcLines[i]; + for (let i2 = 0; i2 < srcLines.length; ++i2) { + const line = srcLines[i2]; const directiveMatch = isBlockShortcode(line.substring, true); - if (isYamlDelimiter(line.substring, i, !inYaml) && !inCodeCell && !inCode) { + if (isYamlDelimiter(line.substring, i2, !inYaml) && !inCodeCell && !inCode) { if (inYaml) { lineBuffer.push(line); - await flushLineBuffer("raw", i); + await flushLineBuffer("raw", i2); inYaml = false; } else { - await flushLineBuffer("markdown", i); + await flushLineBuffer("markdown", i2); lineBuffer.push(line); inYaml = true; } } else if (inPlainText() && directiveMatch) { - await flushLineBuffer("markdown", i); + await flushLineBuffer("markdown", i2); directiveParams = directiveMatch; lineBuffer.push(line); - await flushLineBuffer("directive", i); + await flushLineBuffer("directive", i2); } else if (startCodeCellRegEx.test(line.substring) && inPlainText()) { const m = line.substring.match(startCodeCellRegEx); language = m[2]; - await flushLineBuffer("markdown", i); + await flushLineBuffer("markdown", i2); inCodeCell = true; inCode = m[1].length; codeStartRange = line; @@ -34945,7 +34956,7 @@ ${tidyverseInfo( codeEndRange = line; inCodeCell = false; inCode = 0; - await flushLineBuffer("code", i); + await flushLineBuffer("code", i2); } else { inCode = 0; lineBuffer.push(line); diff --git a/src/resources/editor/tools/yaml/yaml-intelligence-resources.json b/src/resources/editor/tools/yaml/yaml-intelligence-resources.json index f88c7704e5c..e8f8fa3d3d2 100644 --- a/src/resources/editor/tools/yaml/yaml-intelligence-resources.json +++ b/src/resources/editor/tools/yaml/yaml-intelligence-resources.json @@ -91,7 +91,14 @@ "tags": { "engine": "knitr" }, - "schema": "string", + "schema": { + "anyOf": [ + { + "maybeArrayOf": "string" + }, + "boolean" + ] + }, "description": { "short": "Variables names that are not created from the current chunk", "long": "Variables names that are not created from the current chunk.\n\nThis option is mainly for `autodep: true` to work more precisely---a chunk\n`B` depends on chunk `A` when any of `B`'s global variables are `A`'s local \nvariables. In case the automatic detection of global variables in a chunk \nfails, you may manually specify the names of global variables via this option.\nIn addition, `cache-globals: false` means detecting all variables in a code\nchunk, no matter if they are global or local variables.\n" @@ -18348,12 +18355,12 @@ "mermaid": "%%" }, "handlers/mermaid/schema.yml": { - "_internalId": 223022, + "_internalId": 223031, "type": "object", "description": "be an object", "properties": { "mermaid-format": { - "_internalId": 223014, + "_internalId": 223023, "type": "enum", "enum": [ "png", @@ -18369,7 +18376,7 @@ "exhaustiveCompletions": true }, "theme": { - "_internalId": 223021, + "_internalId": 223030, "type": "anyOf", "anyOf": [ { diff --git a/src/resources/schema/cell-cache.yml b/src/resources/schema/cell-cache.yml index aab09b2caca..2e07de46e8f 100644 --- a/src/resources/schema/cell-cache.yml +++ b/src/resources/schema/cell-cache.yml @@ -40,7 +40,10 @@ - name: cache-globals tags: engine: knitr - schema: string + schema: + anyOf: + - maybeArrayOf: string + - boolean description: short: "Variables names that are not created from the current chunk" long: | From 355bbb7ae0194e462e7c286fc2b01bbab327f953 Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Tue, 28 Jul 2026 10:30:57 +0000 Subject: [PATCH 2/2] Add regression test for cache-globals cell option validation Covers the array, boolean and single-string forms through parseAndValidateCellOptions, the function render itself calls. Runs without an R toolchain, since the defect was in TypeScript-side schema validation that happens before any engine runs. Initializes via setInitializer(initYamlIntelligenceResourcesFromFilesystem) rather than fullInit(): fullInit() also runs ensureSchemaResources(), which overlays the source schema yml on top of the generated artifact, so a test using it would pass even when dev-call build-artifacts had not been re-run. Co-Authored-By: Claude Opus 5 --- .../cell-options-knitr-cache-globals.test.ts | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 tests/unit/schema-validation/cell-options-knitr-cache-globals.test.ts diff --git a/tests/unit/schema-validation/cell-options-knitr-cache-globals.test.ts b/tests/unit/schema-validation/cell-options-knitr-cache-globals.test.ts new file mode 100644 index 00000000000..9a298edade8 --- /dev/null +++ b/tests/unit/schema-validation/cell-options-knitr-cache-globals.test.ts @@ -0,0 +1,56 @@ +/* + * cell-options-knitr-cache-globals.test.ts + * + * Copyright (C) 2026 Posit Software, PBC + * + */ + +import { assertEquals } from "testing/asserts"; +import { asMappedString } from "../../../src/core/lib/mapped-text.ts"; +import { parseAndValidateCellOptions } from "../../../src/core/lib/partition-cell-options.ts"; +import { + initState, + setInitializer, +} from "../../../src/core/lib/yaml-validation/state.ts"; +import { initYamlIntelligenceResourcesFromFilesystem } from "../../../src/core/schema/utils.ts"; +import { unitTest } from "../../test.ts"; + +// Deliberately not using `fullInit()` from ./utils.ts here: that also runs +// `ensureSchemaResources()`, which overlays the source `src/resources/schema/` +// yml on top of the generated artifact. Rendering only loads the generated +// artifact, so initializing the same way keeps this test honest about what +// ships -- it fails if `dev-call build-artifacts` was not re-run. +const validateKnitrCell = async (yaml: string) => { + setInitializer(initYamlIntelligenceResourcesFromFilesystem); + await initState(); + return await parseAndValidateCellOptions( + asMappedString(yaml), + "r", + true, + "knitr", + ); +}; + +// https://github.com/quarto-dev/quarto-cli/issues/14735 +// `cache-globals` was declared as a bare string, so an array (the form +// `cache-vars` accepts) and the documented `false` both failed validation. +unitTest("cache-globals - accepts an array of strings", async () => { + assertEquals( + await validateKnitrCell(`cache-globals:\n - var_1\n - var_2\n`), + { "cache-globals": ["var_1", "var_2"] }, + ); +}); + +unitTest("cache-globals - accepts a boolean", async () => { + assertEquals( + await validateKnitrCell(`cache-globals: false\n`), + { "cache-globals": false }, + ); +}); + +unitTest("cache-globals - still accepts a single string", async () => { + assertEquals( + await validateKnitrCell(`cache-globals: var_1\n`), + { "cache-globals": "var_1" }, + ); +});