importEdit
The change to a scratch file's imports (text being what it holds) that brings in leaf from module: added to
the import there is from it (import type for a type), or a line of its own after the imports at the top (and the
namespace pragma). Nothing, if it's imported already.
export function importEdit( text: string, module: string, leaf: string, typeOnly: boolean, ): { from: number; to: number; insert: string } | undefined { const quoted = module.replace(/[.*+?^${}()|[\]\\/]/g, "\\$&"); const m = new RegExp( `^import ${typeOnly ? "type " : ""}\\{([^}]*)\\} from ["']${quoted}["'];?[ \\t]*$`, "m", ).exec(text); if (m) { const names = m[1]! .split(",") .map((s) => s.trim()) .filter(Boolean); if (names.includes(leaf)) return undefined; const from = m.index + m[0].indexOf("{") + 1; return { from, to: from + m[1]!.length, insert: ` ${[...names, leaf].sort((x, y) => x.localeCompare(y)).join(", ")} `, }; } let pos = 0; let at = 0; let inImport = false; for (const line of text.split("\n")) { const end = pos + line.length + 1; const t = line.trim(); if (inImport) { if (/["'];?$/.test(t)) { inImport = false; at = end; } } else if (/^import\b/.test(t)) { if (/["'];?$/.test(t)) at = end; else inImport = true; } else if (t.startsWith("// tcm:")) at = end; else if (t !== "" && !t.startsWith("//")) break; pos = end; } const line = `import ${typeOnly ? "type " : ""}{ ${leaf} } from "${module}";\n`; return at > text.length ? { from: text.length, to: text.length, insert: `\n${line}` } : { from: at, to: at, insert: line }; }