substitution in comments

This commit is contained in:
Sebastian Herrlinger
2026-02-19 18:09:02 +01:00
parent ba34df54ac
commit 832daaedaf
2 changed files with 44 additions and 9 deletions

View File

@@ -77,17 +77,27 @@ export namespace ConfigPaths {
return process.env[varName] || ""
})
const fileMatches = text.match(/\{file:[^}]+\}/g)
if (!fileMatches) return text
const fileMatches = Array.from(text.matchAll(/\{file:[^}]+\}/g))
if (!fileMatches.length) return text
const configDir = path.dirname(configFilepath)
const lines = text.split("\n")
let out = ""
let cursor = 0
for (const match of fileMatches) {
const lineIndex = lines.findIndex((line) => line.includes(match))
if (lineIndex !== -1 && lines[lineIndex].trim().startsWith("//")) continue
const token = match[0]
const index = match.index!
out += text.slice(cursor, index)
let filePath = match.replace(/^\{file:/, "").replace(/\}$/, "")
const lineStart = text.lastIndexOf("\n", index - 1) + 1
const prefix = text.slice(lineStart, index).trimStart()
if (prefix.startsWith("//")) {
out += token
cursor = index + token.length
continue
}
let filePath = token.replace(/^\{file:/, "").replace(/\}$/, "")
if (filePath.startsWith("~/")) {
filePath = path.join(os.homedir(), filePath.slice(2))
}
@@ -99,7 +109,7 @@ export namespace ConfigPaths {
.catch((error) => {
if (missing === "empty") return ""
const errMsg = `bad file reference: "${match}"`
const errMsg = `bad file reference: "${token}"`
if (error.code === "ENOENT") {
throw new InvalidError(
{
@@ -113,10 +123,12 @@ export namespace ConfigPaths {
})
).trim()
text = text.replace(match, () => JSON.stringify(fileContent).slice(1, -1))
out += JSON.stringify(fileContent).slice(1, -1)
cursor = index + token.length
}
return text
out += text.slice(cursor)
return out
}
/** Substitute and parse JSONC text, throwing JsonError on syntax errors. */

View File

@@ -384,6 +384,29 @@ test("applies env and file substitutions in tui.json", async () => {
}
})
test("applies file substitutions when first identical token is in a commented line", async () => {
await using tmp = await tmpdir({
init: async (dir) => {
await Bun.write(path.join(dir, "theme.txt"), "resolved-theme")
await Bun.write(
path.join(dir, "tui.jsonc"),
`{
// "theme": "{file:theme.txt}",
"theme": "{file:theme.txt}"
}`,
)
},
})
await Instance.provide({
directory: tmp.path,
fn: async () => {
const config = await TuiConfig.get()
expect(config.theme).toBe("resolved-theme")
},
})
})
test("loads managed tui config and gives it highest precedence", async () => {
await using tmp = await tmpdir({
init: async (dir) => {