@idomatic/parser-html
Version:
HTML/Vue/Angular parser for idomatic CLI
78 lines (64 loc) • 2.87 kB
JavaScript
import MagicString from "magic-string";
import { randomUUID } from "crypto";
/**
* Processes a Vue template content by inserting unique IDs while preserving formatting.
*
* @param {string} templateContent - The content inside the Vue <template> tag.
* @param {object} config - The configuration object.
* @param {string} config.attributeName - The attribute name to add (e.g. "id" or "data-id").
* @param {string} config.prefix - The prefix for generated IDs.
* @param {string[]} [config.excludeTags] - An array of tag names to exclude (optional).
* @returns {string} - The updated template content.
*/
export function processVueTemplate(templateContent, config) {
const { attributeName, prefix, excludeTags = [] } = config;
const ms = new MagicString(templateContent);
// A generic regex to match opening tags:
// - It captures the tag name and its attributes.
// - This regex is simplified, so you might need additional adjustments for complex cases.
const tagRegex = /<([a-zA-Z][^\s/>]*)([^>]*?)(\/?)>/g;
let match;
while ((match = tagRegex.exec(templateContent)) !== null) {
const fullMatch = match[0]; // entire opening tag text
const tagName = match[1]; // tag name, e.g., v-btn, i, etc.
const attributesStr = match[2]; // all attributes as a string
const selfClosing = match[3] || ""; // self-closing slash if present
// If the tag is in the exclude list, skip processing.
if (excludeTags.includes(tagName)) continue;
// Check if this tag already has the attribute
const idRegex = new RegExp(`\\s${attributeName}\\s*=`);
if (idRegex.test(attributesStr)) continue;
// Insert the attribute just before the closing of the tag.
// We subtract the length of any trailing self-closing slash and the ">" character.
const insertPosition =
match.index + fullMatch.length - (selfClosing.length + 1);
ms.appendLeft(
insertPosition,
` ${attributeName}="${prefix}${randomUUID()}"`
);
}
return ms.toString();
}
export function processHtmlContent(htmlContent, config) {
const { attributeName, prefix, excludeTags = [] } = config;
const ms = new MagicString(htmlContent);
// This regex is similar to the Vue one.
const tagRegex = /<([a-zA-Z][^\s/>]*)([^>]*?)(\/?)>/g;
let match;
while ((match = tagRegex.exec(htmlContent)) !== null) {
const fullMatch = match[0];
const tagName = match[1];
const attributesStr = match[2];
const selfClosing = match[3] || "";
if (excludeTags.includes(tagName)) continue;
const idRegex = new RegExp(`\\s${attributeName}\\s*=`);
if (idRegex.test(attributesStr)) continue;
const insertPosition =
match.index + fullMatch.length - (selfClosing.length + 1);
ms.appendLeft(
insertPosition,
` ${attributeName}="${prefix}${randomUUID()}"`
);
}
return ms.toString();
}