in src/lib/utils/snippets.ts [60:206]
function insertPropertiesInternal(
snippet: string,
newProperties: Record<string, unknown>,
blockStartMarker: RegExp, // Regex to find the character *opening* the block (e.g., '{' or '(')
openChar: string, // The opening character, e.g., '{' or '('
closeChar: string, // The closing character, e.g., '}' or ')'
propFormatter: (key: string, formattedValue: string, indent: string) => string,
valueFormatter: (value: unknown, baseIndent: string) => string
): string {
if (Object.keys(newProperties).length === 0) {
return snippet;
}
const match = snippet.match(blockStartMarker);
// match.index is the start of the whole marker, e.g. "client.chatCompletionStream("
// We need the index of the openChar itself.
if (!match || typeof match.index !== "number") {
return snippet;
}
const openCharIndex = snippet.indexOf(openChar, match.index + match[0].length - 1);
if (openCharIndex === -1) {
return snippet;
}
let balance = 1;
let closeCharIndex = -1;
for (let i = openCharIndex + 1; i < snippet.length; i++) {
if (snippet[i] === openChar) {
balance++;
} else if (snippet[i] === closeChar) {
balance--;
}
if (balance === 0) {
closeCharIndex = i;
break;
}
}
if (closeCharIndex === -1) {
return snippet; // Malformed or not found
}
const contentBeforeBlock = snippet.substring(0, openCharIndex + 1);
const currentContent = snippet.substring(openCharIndex + 1, closeCharIndex);
const contentAfterBlock = snippet.substring(closeCharIndex);
// Determine indentation
let indent = "";
const lines = currentContent.split("\n");
if (lines.length > 1) {
for (const line of lines) {
const lineIndentMatch = line.match(/^(\s+)\S/);
if (lineIndentMatch) {
indent = lineIndentMatch[1] ?? "";
break;
}
}
}
if (!indent) {
// If no indent found, or content is empty/single line, derive from openChar line
const lineOfOpenCharStart = snippet.lastIndexOf("\n", openCharIndex) + 1;
const lineOfOpenChar = snippet.substring(lineOfOpenCharStart, openCharIndex);
const openCharLineIndentMatch = lineOfOpenChar.match(/^(\s*)/);
indent = (openCharLineIndentMatch ? openCharLineIndentMatch[1] : "") + " "; // Default to 4 spaces more
}
let newPropsStr = "";
Object.entries(newProperties).forEach(([key, value]) => {
newPropsStr += propFormatter(key, valueFormatter(value, indent), indent);
});
const trimmedOriginalContent = currentContent.trim();
let combinedContent;
if (trimmedOriginalContent) {
// There was actual non-whitespace content.
// Preserve original currentContent structure as much as possible.
// Find the end of the textual part of currentContent (before any pure trailing whitespace).
let endOfTextualPart = currentContent.length;
while (endOfTextualPart > 0 && /\s/.test(currentContent.charAt(endOfTextualPart - 1))) {
endOfTextualPart--;
}
const textualPartOfCurrentContent = currentContent.substring(0, endOfTextualPart);
const trailingWhitespaceOfCurrentContent = currentContent.substring(endOfTextualPart);
let processedTextualPart = textualPartOfCurrentContent;
if (processedTextualPart && !processedTextualPart.endsWith(",")) {
processedTextualPart += ",";
}
// Add a newline separator if the original trailing whitespace doesn't end with one.
const separator =
trailingWhitespaceOfCurrentContent.endsWith("\n") || trailingWhitespaceOfCurrentContent.endsWith("\r")
? ""
: "\n";
combinedContent = processedTextualPart + trailingWhitespaceOfCurrentContent + separator + newPropsStr;
} else {
// currentContent was empty or contained only whitespace.
// Check if the original block opening (e.g., '{' or '(') was immediately followed by a newline.
const openCharFollowedByNewline =
snippet[openCharIndex + 1] === "\n" ||
(snippet[openCharIndex + 1] === "\r" && snippet[openCharIndex + 2] === "\n");
if (openCharFollowedByNewline) {
combinedContent = newPropsStr; // newPropsStr already starts with indent
} else {
combinedContent = "\n" + newPropsStr; // Add a newline first, then newPropsStr
}
}
// Remove the trailing comma (and its trailing whitespace/newline) from the last property added.
combinedContent = combinedContent.replace(/,\s*$/, "");
// Ensure the block content ends with a newline, and the closing character is on its own line, indented.
if (combinedContent.trim()) {
// If there's any actual content in the block
if (!combinedContent.endsWith("\n")) {
combinedContent += "\n";
}
// Determine the base indent for the closing character's line
const lineOfOpenCharStart = snippet.lastIndexOf("\n", openCharIndex) + 1;
const openCharLine = snippet.substring(lineOfOpenCharStart, openCharIndex);
const baseIndentMatch = openCharLine.match(/^(\s*)/);
const baseIndent = baseIndentMatch ? baseIndentMatch[1] : "";
combinedContent += baseIndent;
} else {
// Block is effectively empty (e.g., was {} and no properties added, or newPropsStr was empty - though current logic prevents this if newProperties is not empty).
// Format as an empty block with the closing char on a new, indented line.
const lineOfOpenCharStart = snippet.lastIndexOf("\n", openCharIndex) + 1;
const openCharLine = snippet.substring(lineOfOpenCharStart, openCharIndex);
const baseIndentMatch = openCharLine.match(/^(\s*)/);
const baseIndent = baseIndentMatch ? baseIndentMatch[1] : "";
const openCharFollowedByNewline =
snippet[openCharIndex + 1] === "\n" ||
(snippet[openCharIndex + 1] === "\r" && snippet[openCharIndex + 2] === "\n");
if (openCharFollowedByNewline) {
// Original was like {\n}
combinedContent = baseIndent; // Just the indent for the closing char
} else {
// Original was like {}
combinedContent = "\n" + baseIndent; // Newline, then indent for closing char
}
}
return contentBeforeBlock + combinedContent + contentAfterBlock;
}