Skip to content

[Request] Add scoping support to highlightAll() for Shadow DOM and specific elements #4278

Open
@cyber-sec0

Description

@cyber-sec0

I'd like to propose a feature enhancement for highlightAll() to support modern web development patterns, specifically Web Components and Shadow DOM.

The Current Limitation

Currently, hljs.highlightAll() is hardcoded to search the global document for code blocks to highlight. This works perfectly for static websites but presents a challenge when content is rendered within an encapsulated scope, such as a Shadow DOM root or a specific element loaded dynamically.

Proposed Solution

I propose that highlightAll() be updated to optionally accept a configuration object with a root property. This would allow developers to specify the parent element within which highlightAll should search for code blocks.

The new signature could look like this:
hljs.highlightAll({ root = document })

This would be fully backward-compatible. Calling hljs.highlightAll() with no arguments would default to the current behavior of using document as the root.

My Use Case

I am the author of a browser userscript that injects a UI onto third-party pages to interact with an AI. To prevent any CSS conflicts with the host page, my entire UI is rendered inside a Shadow DOM.

When the AI returns a response containing code blocks, they are added to my UI inside this shadow root. Because hljs.highlightAll() cannot see inside the Shadow DOM, I cannot use it.

Current Method (verbose and requires manual iteration):

My current, working solution requires manually querying the shadow root and iterating over the results, which is less convenient and elegant.

// This code must be run every time new content is added.
const shadowRoot = document.getElementById('my-script-container').shadowRoot;
shadowRoot.querySelectorAll('pre code').forEach(hljs.highlightElement);

Proposed Method (clean and intuitive):

If this feature were implemented, the code would be simplified to a single, intuitive call. This becomes especially powerful when dealing with dynamic content.

// This single call would handle everything within my UI's scope.
const shadowRoot = document.getElementById('my-script-container').shadowRoot;
hljs.highlightAll({ root: shadowRoot });

Why This Should Be a Feature

  1. Aligns with Modern Web Development: Web Components and the Shadow DOM are now standard browser features used to build encapsulated, reusable widgets. Libraries, browser extensions, and embedded components all rely on this encapsulation. A scoped highlightAll() would make the library significantly easier to use in these modern contexts.

  2. Improves Developer Experience (DX): It provides a much cleaner, more declarative API. The developer's intent is "highlight everything in this area," and hljs.highlightAll({ root: myArea }) expresses that perfectly. It removes the need for manual querying and looping boilerplate.

  3. Potential Performance Gains: In large Single-Page Applications (SPAs), re-running highlightAll() on the entire document can be inefficient. A scoped version would allow developers to efficiently re-highlight only the specific parts of the view that have been updated.

Thank you for your consideration. I believe this enhancement would be a great addition to an already fantastic library and would be highly appreciated by the developer community working with modern web components.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions