replace-quotes
Version:
Swap quote styles in strings effortlessly
63 lines (62 loc) • 2.34 kB
JavaScript
// src/index.ts
import { z } from "zod";
import { inspect } from "node-inspect-extracted";
var matchSchema = z.union([
z.string(),
z.tuple([z.string(), z.string()]),
z.tuple([z.string(), z.string(), z.boolean()])
]);
var replaceSchema = z.union([z.string(), z.tuple([z.string(), z.string()])]);
var matchString = "string | [string, string] | [string, string, boolean]";
var replaceString = "string | [string, string]";
var double = String.fromCharCode(34);
var single = String.fromCharCode(39);
var backtick = String.fromCharCode(96);
function replaceQuotes(...quotes) {
if (quotes.length < 2) throw new Error("At least two arguments are required");
quotes.forEach((quote, index) => {
const isLast = index + 1 === quotes.length;
const result = (isLast ? replaceSchema : matchSchema).safeParse(quote);
if (!result.success) {
throw new Error(
"Invalid argument at index " + index + "\nExpected: " + (isLast ? replaceString : matchString) + "\nGot: " + inspect(quote)
);
}
});
const sourceQuotesPairs = quotes.map((f) => Array.isArray(f) ? f : [f, f]);
const [targetStartQuote, targetEndQuote] = sourceQuotesPairs.pop();
const getLiteralsRegex = new RegExp(
sourceQuotesPairs.map(
// to match string literal
([start, end]) => "(" + start + "(?:[^" + end + "\\\\]|\\\\.)*" + end + ")"
).concat(
// to match regex literal
"/(?:[^/\\\\]|\\\\.)*/",
"\\[Function:? .*?\\]",
"\\[class .*?\\]",
"Symbol\\(.*?\\)"
).join("|"),
"g"
);
const getUnescapedTargetEndQuotesRegex = new RegExp(
"(?<!\\\\)(?:\\\\\\\\)*" + targetEndQuote,
"g"
);
return (text) => text.replaceAll(getLiteralsRegex, (...match) => {
const groups = match.slice(1, sourceQuotesPairs.length + 1);
if (!groups.some(Boolean)) return match[0];
const [matchedSourceStartQuote, matchedSourceEndQuote, onlyForContext] = sourceQuotesPairs[groups.findIndex(Boolean)];
if (onlyForContext) return match[0];
let newString = match[0].slice(1, -1).replaceAll(
new RegExp("\\\\" + matchedSourceEndQuote, "g"),
matchedSourceEndQuote
).replaceAll(getUnescapedTargetEndQuotesRegex, (m) => "\\" + m);
return targetStartQuote + newString + targetEndQuote;
});
}
export {
backtick,
replaceQuotes as default,
double,
single
};