importEdit

tcmts.studio.importEdit · #alafd6kg · term · runs anywhere

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 };
}

used by