Provide a way to act after highlightAll() is fired

Created on 14 November 2023, 8 months ago
Updated 25 January 2024, 5 months ago

Problem/Motivation

Steps to reproduce

Right now, there is no easy way to add custom code from other modules or themes after Highlightjs is loaded and highlightAll is executed

Take for example this way of adding code labels to the highlights. Right now can't be implemented on Drupal because of the Promise.all() wrapper that makes the code asyncronous. The execution of highlightAll will always be delayed and there is no way to "hook into" the .then in order to ensure code execution order is OK.

Take, for example, the following scenario:

This module executes the highlighting, but it is wrapped inside a Promise.all.

highlightjs_input_filter.js

      Promise.all(promises).then(() => {
        hljs.highlightAll();
        # We want to act AFTER highlightAll() is executed.
      })

Another module might want to execute the following code, but even if the loading order of the JS is OK (the new JS file comes AFTER highlightjs_input_filter.js), the code will execute before the Promise is resolved.

my_module.js

      const highlight = document.querySelectorAll('.my-selector');
      highlight.forEach(element => {
        # element.result is data added by highlightjs!
        if (element.result) {
          const language = element.result.language;
          element.insertAdjacentHTML("afterbegin",`<span class="hljs__label">${language}</span class="hljs__label">`)
        }
      });

...and it won't work as element.result will still be empty.

Proposed resolution

Provide a small JS API in order to allow other modules or themes to "hook into" at the desired point.

Specifically, we could benefit of the very simple, straightforward and well-known Event api.

An event could be sent to the document when hljs has been actually started.

      const initEvent = new Event("highlightjs:init");
      Promise.all(promises).then(() => {
        hljs.highlightAll();
        document.dispatchEvent(initEvent);
      })

This public, global event could be listened to from every other module or theme:

document.addEventListener('highlightjs:init', function(){
  # This code will execute AFTER highlightJs has been initialized
}

Remaining tasks

User interface changes

None

API changes

Added a "highlightjs:init" event that can be listened on the document.

Data model changes

None

✨ Feature request
Status

Fixed

Version

1.1

Component

Code

Created by

πŸ‡ͺπŸ‡ΈSpain idiaz.roncero Madrid

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

Production build 0.69.0 2024