Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[HTML] Nested templates in html/javascript not correctly handled #290

Open
GlasslessPizza opened this issue Nov 18, 2024 · 3 comments
Open
Labels
html Caused by the hypertext lexer javascript Caused for JavaScript by the cpp or html lexer

Comments

@GlasslessPizza
Copy link

I'm coming from this comment in a notepad++ issue. Writing here the text for convenience:

There's still a problem with nested string templates. Paste the following example code in notepad++ 8.7.1 with language set to "HTML" and the innerHTML line in the script will be shown completely unstyled:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Card Listing Example</title>
    <style>
        .card {
            border: 1px solid #ddd;
            padding: 16px;
            margin: 10px;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
        }
    </style>
</head>
<body>
    <div id="content"></div>

    <script>
        // Sample data
        const users = [
            { name: "Alice", age: 30, interests: ["Reading", "Traveling"] },
            { name: "Bob", age: 25, interests: ["Cooking", "Gaming"] },
            { name: "Charlie", age: 35, interests: ["Hiking", "Photography"] }
        ];

        // Nested template literal to generate user cards
        const generateUserCard = (user) => `
            <div class="card">
                <h2>${user.name}</h2>
                <p>Age: ${user.age}</p>
                <ul>
                    ${user.interests.map(interest => `<li>${interest}</li>`).join('')}
                </ul>
            </div>
        `;

        // Render all user cards into the content div
        document.getElementById('content').innerHTML = users.map(user => generateUserCard(user)).join('');
    </script>
</body>
</html>

@nyamatongwe nyamatongwe added html Caused by the hypertext lexer javascript Caused for JavaScript by the cpp or html lexer labels Nov 18, 2024
@that-ar-guy
Copy link

hey @nyamatongwe can i try this

@nyamatongwe
Copy link
Member

It's fine for anyone to propose changes. I don't assign ownership to bugs as they are often more complex than a contributor expects and the contributor eventually goes silent with no clear signal that they have stopped.

This issue is likely more difficult than it seems. #280 was a deliberately simplified solution by a contributor with experience in this area. #94 is an implementation of template strings with expressions for stand-alone JavaScript files.

@zufuliu
Copy link
Contributor

zufuliu commented Nov 20, 2024

The complex is that there are three places that enters JavaScript operator styles (so needs to handle end of interpolating on braces).

lexilla/lexers/LexHTML.cxx

Lines 2226 to 2230 in 942ac3f

} else if (IsOperator(ch)) {
styler.ColourTo(i - 1, StateToPrint);
styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType));
state = SCE_HJ_DEFAULT;
} else if ((ch == ' ') || (ch == '\t')) {

lexilla/lexers/LexHTML.cxx

Lines 2261 to 2264 in 942ac3f

} else if (IsOperator(ch)) {
styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType));
state = SCE_HJ_DEFAULT;
}

lexilla/lexers/LexHTML.cxx

Lines 2734 to 2736 in 942ac3f

} else if (IsOperator(ch)) {
styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType));
}

Copy end of interpolating handling code from LexCPP into the three places may just work (need tests to test off-by-one error).

lexilla/lexers/LexCPP.cxx

Lines 1450 to 1465 in 942ac3f

} else if (isoperator(sc.ch)) {
sc.SetState(SCE_C_OPERATOR|activitySet);
if (!interpolatingStack.empty() && AnyOf(sc.ch, '{', '}')) {
InterpolatingState &current = interpolatingStack.back();
if (sc.ch == '{') {
current.braceCount += 1;
} else {
current.braceCount -= 1;
if (current.braceCount == 0) {
sc.ForwardSetState(current.state);
interpolatingStack.pop_back();
continue;
}
}
}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
html Caused by the hypertext lexer javascript Caused for JavaScript by the cpp or html lexer
Projects
None yet
Development

No branches or pull requests

4 participants