groldsf_obsidian_check_plugin/esbuild-debug-wrap-plugin.mjs

79 lines
3.8 KiB
JavaScript
Raw Permalink Normal View History

import { promises } from "fs";
/**
* Плагин esbuild для обертывания вызовов console.* в условие.
* @param {object} options
* @param {string} [options.debugFlagName='DEBUG_WRAP_CONSOLE_PLUGIN_FLAG'] - Имя глобальной переменной для проверки.
* @param {string[]} [options.methods=['log', 'warn', 'info', 'debug', 'error']] - Методы console, которые нужно обернуть.
* @returns {import('esbuild').Plugin}
*/
export const debugWrapConsolePlugin = ({
debugFlagName = "DEBUG_WRAP_CONSOLE_PLUGIN_FLAG", // Имя глобального флага (лучше сделать уникальным для вашего плагина)
methods = ["log", "warn", "info", "debug", "error"], // Какие методы console оборачивать
} = {}) => ({
name: "debug-wrap-console",
setup(build) {
// Создаем фильтр для методов console
const methodsPattern = methods.join("|");
// Регулярное выражение для поиска вызовов console.method(...)
// Оно пытается обработать простые случаи, но может быть неидеальным для сложных вложенных выражений или многострочных вызовов.
// $& в замене представляет всю совпавшую строку.
const consoleRegex = new RegExp(
// Match 'console.' followed by one of the specified methods
`(^|\\s+|\\{|\\;)(console\\.(${methodsPattern}))\\s*\\(` +
// Match arguments (non-greedy) - this is the tricky part and might not capture perfectly balanced parentheses in all complex cases
`([\\s\\S]*?)` +
// Match the closing parenthesis and optional semicolon
`\\)(;?)`,
"g" // Global search
);
const wrapperStart = `if (window.${debugFlagName}) { `;
const wrapperEnd = ` }`;
// Перехватываем загрузку JS/TS файлов
build.onLoad({ filter: /\.[jt]sx?$/ }, async (args) => {
try {
// Читаем содержимое файла
const source = await promises.readFile(args.path, "utf8");
// Заменяем вызовы console.*
const contents = source.replace(
consoleRegex,
(match, prefix, fullCall, methodName, argsContent, semicolon) => {
// prefix: Пробел, начало строки, {, ; перед вызовом console
// fullCall: Сам вызов, например, console.log
// methodName: Имя метода, например, log
// argsContent: Содержимое скобок
// semicolon: Завершающая точка с запятой (если была)
// Собираем обернутый вызов
// Мы используем 'match' целиком, чтобы сохранить оригинальное форматирование и содержимое,
// но убираем исходный префикс (пробел/начало строки/итд) и добавляем его перед if.
const originalCall = match.substring(prefix.length);
return `${prefix}${wrapperStart}${originalCall}${wrapperEnd}`;
}
);
// Возвращаем измененное содержимое и указываем esbuild,
// что это все еще JS/TS код (в зависимости от исходного файла)
const loader =
args.path.endsWith(".ts") || args.path.endsWith(".tsx") ? "ts" : "js";
return {
contents,
loader,
};
} catch (error) {
console.error(
`Error processing file ${args.path} in debug-wrap-console plugin:`,
error
);
// В случае ошибки возвращаем null или выбрасываем ошибку, чтобы сборка прервалась
return null;
}
});
},
});