Need to add an attribute to actionable elements in all Angular template files using script

Discussão em 'Angular' iniciado por Tom Adam, Dezembro 19, 2024.

  1. Tom Adam

    Tom Adam Guest

    I’m trying to write a JavaScript script to add an attribute (data-cy) to all actionable elements (button, input, a, etc.) across Angular templates in my app using the Cheerio library. However, I’m encountering the following issues:

    Unwanted <html>, <head>, and <body> tags When Cheerio loads the HTML fragments, it wraps them in , , and tags. This breaks the Angular template structure.

    Unintended modifications Angular directives and bindings like are being converted to invalid formats, such as <input [formcontrol]>. This makes the app fail to compile.

    Issues with custom Angular components When loading HTML files as XML (xmlMode: true), Cheerio does not recognize Angular custom tags. For example:

    <app-navbar id="navbar" *ngIf="_router.url !== 'login'"></app-navbar>


    and turn them to self closing tags like that

    <app-navbar id="navbar" *ngIf="_router.url !== 'login'"/>


    The app contains a large number of files, so manually handling each case isn’t feasible.

    Here’s a simplified version of my code:

    const processHtmlFileArray = (htmlFileArray) => {
    // Define the array of actionable elements
    const actionableElementArray = ["button", "input", "a", "textarea", "mat-select"];
    // Join the array to create a CSS selector string
    const selector = actionableElementArray.join(", ");
    // loop to each HTML file
    htmlFileArray.forEach((filePath) => {
    const fileName = path.basename(filePath, ".html");
    // Extract file name
    let fileContent = readHtmlFile(filePath);
    //if ( fileName == "test") console.log(fileContent);
    // Parse HTML with Cheerio (do not add `html`/`body` tags)
    const htmlParser = cheerio.load(fileContent, {
    xmlMode: true,
    decodeEntities: false, // Prevent character escaping
    normalizeWhitespace: false // Retain original formatting
    });
    //if ( fileName == "test") console.log(htmlParser.html());
    // Identify Actionable Elements
    const IdentifiedActionableElement = htmlParser(selector);
    //if ( fileName == "test") console.log(actionableElementArray);
    IdentifiedActionableElement.each((index, element) => {
    // Get the tag name
    const tagName = htmlParser(element).prop("tagName").toLowerCase();
    const elementId = htmlParser(element).attr("id") || "";
    // Generate data-cy attribute
    const dataCy = generateDataCyAttribute(fileName, tagName, elementId);
    htmlParser(element).attr("data-cy", dataCy);
    });
    const updatedHtml = htmlParser.html();
    // Write the updated HTML to the file
    writeUpdatedHtmlFile(filePath, updatedHtml);
    });
    };


    What I’ve Tried Setting xmlMode: true to preserve custom elements:

    const htmlParser = cheerio.load(fileContent, {
    xmlMode: true,
    decodeEntities: false,
    normalizeWhitespace: false,
    })


    Question

    Is there a way to configure Cheerio to handle Angular templates correctly, or is there an alternative MIT-licensed library better suited for this use case?

    Continue reading...

Compartilhe esta Página