Non aliased languages fail to import and prevent Copy plugin from loading

Created on 14 November 2023, about 1 year ago
Updated 13 July 2024, 4 months ago

Problem/Motivation

A code block with language-html will get its syntax highlighting apparently OK, but under the hood there is an import error as the JS language file doesn't exist:

GET https://unpkg.com/@highlightjs/cdn-assets@11.8.0/es/languages/html.min.js net::ERR_ABORTED 404 (Not Found)

Uncaught (in promise) TypeError: Failed to fetch dynamically imported module: https://unpkg.com/@highlightjs/cdn-assets@11.8.0/es/languages/html.min.js

This error and also prevents the Highlightjs-copy plugin from getting loaded, so this problem creates two issues.

In my case, this error appeared after an upgrade path from CKE4 CodeSnippet β†’ to CKE's own Code Block feature.

Effectively, https://unpkg.com/@highlightjs/cdn-assets@11.8.0/es/languages/html.min.jsdoesn't exist, but https://unpkg.com/@highlightjs/cdn-assets@11.8.0/es/languages/xml.min.js does.

This is standard Highlight.js behavior, as many languages are considered "aliases" (subsets) of others, like XML -> html, svg, rss. See the official docs.

When this module tries to impor the languages, it will fail anytime an alias is passed (instead of the "parent" language)

  const promises = languages.map(language => {
    return import(`https://unpkg.com/@highlightjs/cdn-assets@11.8.0/es/languages/${language}.min.js`)
      .then(module => hljs.registerLanguage(language, module.default));
  });

Steps to reproduce

- Create a Code Block using CKEditor 5 set to HTML.
- Visit the page. It will be correctly highlighted due to Highlight.js auto-formatting, but there will be errors in the console.

Proposed resolution

A solution is to prompt developers to change their language-alias classes to language-parent

But: CKEditor5 Code Block allows to set HTML as the language, and sets a language-html class, so I think this module should support it and asking users to manually switch to XML is not an acceptable solution for many reasons (this is a different scenario than this other issue πŸ› When you change the code snippet lang from original to something else it breaks Closed: works as designed ).

Also, Highlight.js itself proposes on its official documentation the use of aliases, like <pre><code class="language-html">...

, so I'd argue that this module should be able to support this feature as well. While HTML might actually be a subset of XML, users might want to show the user that they are highlighting an HTML code sample, not XML.

Therefore, languages should be aliased before trying to import the language min.js file. This info should be part of highlightjs itself, but I don't know if it is publicly accessible. If it was, we could get the info from there in order to preprocess the language after import:

Something like this (fake code)

  const promises = languages.map(language => {
    language = hljs.getAliasLanguage(language);
    return import(`https://unpkg.com/@highlightjs/cdn-assets@11.8.0/es/languages/${language}.min.js`)
      .then(module => hljs.registerLanguage(language, module.default));
  });

If not, the alias resolution could be made on the filter itself.

Remaining tasks

User interface changes

None

API changes

None

Data model changes

None

πŸ› Bug report
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

  • Issue created by @idiaz.roncero
  • πŸ‡ͺπŸ‡ΈSpain idiaz.roncero Madrid

    The only HLJS API that can be applied is of little use:

    hljs.getLanguage('html');
    

    returns

    {
        "aliases": [
            "html"
        ]
    }
    

    So it seems the only solution should be to manually maintain the list of aliases inside this module.

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

    This error also prevents the Copy plugin for getting loaded, and will break this functionality. Updating issue to reflect this.

  • Merge request !5Proof of concept for alias resolver β†’ (Merged) created by idiaz.roncero
  • πŸ‡ͺπŸ‡ΈSpain idiaz.roncero Madrid

    Lacking a JS API, I think the best place to perform the alias resolution is inside the filter.

    This way, the language will be correctly marked as its alias (HTML) bu the correct *.min.js file will be loaded from unpkg.

    It will also have better performance as filters are only executed on content update while a client-side resolution would be executed every time.

    I've created a draft MR with my proposal. I've only added aliases for HTML, but it would need to have any possible Highlightjs alias added, which is the main pain point (it introduces maintainability problems!).

    Any ideas on how to solve the "getting-the-alias-info" problem is welcome!

  • Status changed to Needs review about 1 year ago
  • πŸ‡ͺπŸ‡ΈSpain idiaz.roncero Madrid

    Changing to Needs Review and upgrading priority as this is breaking the Copy functionality.

  • Status changed to Needs work 12 months ago
  • πŸ‡¨πŸ‡¦Canada stickton

    I can't comment on if the architecture idea is good or not as I'm only starting out with this module, but this change seems to work.
    line 50 needs updating to the fixed multiples issue πŸ› Error when several instances of same language on the page Fixed
    'highlightJsLanguages' => array_values(array_unique($languages)),

  • Status changed to Needs review 9 months ago
  • πŸ‡³πŸ‡ΏNew Zealand siramsay

    #11 was committed but didn't get in https://www.drupal.org/project/highlightjs_input_filter/issues/3402489#c... πŸ› Error when several instances of same language on the page Fixed

    I have tested the code from https://git.drupalcode.org/project/highlightjs_input_filter/-/merge_requ... and this work good.

    I had found the same with the HTML when updating from a custom highlight.js file I had been using with 1.0.1. I found that HTML was breaking the rendering due to highlight.js not having an HTML language file at the route

    . This resolve alias function works as I hoped. Thank you.

  • πŸ‡ΊπŸ‡ΈUnited States nmangold United States

    @idiaz.roncero Thank you for working on this. I have been trying to solve the language alias issue since the start.

    As you have discovered, the highlightjs code does not allow getting the aliased languages, and it is not a trivial change. Also, I would rather not maintain that list in the filter due to the maintainability problem.

    Can you look at https://github.com/highlightjs/highlight.js/issues/3938, which is the upstream issue regarding this problem. The best solution might be a third-party plugin to bridge the gap, but that is currently beyond my knowledge of library.

  • πŸ‡ΊπŸ‡ΈUnited States kentr

    Having to choose XML for HTML out-of-the-box feels like bad UX to me. HTML isn't a subset of XML.

    A compromise is only maintaining a small set of aliases for common cases. I'd put HTML in that group.

    That group could be limited to the default languages supported by the core Code Block plugin. Once someone starts adding their own languages to the Code Block config for their site, they can specify the correct aliases.

    Of the current Code Block defaults, I believe that the only entries that don't have their own highlight.js language files are HTML and C#.

    languages:
      -
        label: 'Plain text'
        language: plaintext
      -
        label: C
        language: c
      -
        label: 'C#'
        language: cs // "csharp" in highlight.js
      -
        label: C++
        language: cpp
      -
        label: CSS
        language: css
      -
        label: Diff
        language: diff
      -
        label: HTML
        language: html // "xml" in highlight.js
      -
        label: Java
        language: java
      -
        label: JavaScript
        language: javascript
      -
        label: PHP
        language: php
      -
        label: Python
        language: python
      -
        label: Ruby
        language: ruby
      -
        label: TypeScript
        language: typescript
      -
        label: XML
        language: xml
    




    Another solution is using (or offering the option to use) the pre-built highlight.js bundle with common languages. My guess is that would solve most cases, but that's just a guess. I don't know how they decide what languages to include in the bundle.

    Granted, loading unnecessary assets is also bad UX. It may be the lesser of two evils for some sites.

  • πŸ‡ͺπŸ‡¨Ecuador andres.torres

    Hi all,

    I'm trying this module for the first time on a fresh Drupal 10.2.7 install, followed the instructions on the documentation, but seems the issue is still present on v 1.1.2 of the module. See screenshots for reference, Chrome/Firefox Dev tools pretty much shows the same error described here for all the snippets supported by ckeditor 5 code snippets in Core (php, xml, bash, etc etc) also it doesn't seem to apply the hljs theme.

  • πŸ‡¨πŸ‡¦Canada stickton

    You can still use a patched version which is what I'm doing.

    From what I can see @idiaz.roncero's pull request didn't make it in:
    https://git.drupalcode.org/project/highlightjs_input_filter/-/merge_requ...

  • πŸ‡ͺπŸ‡¨Ecuador andres.torres

    Thanks @TheTomatoFarmerReturns, just quick question here, i dont see a patch attached + not sure if you are using the dev version of the module or a custom patch ( or git repo code )? if you can provide more instructions on how to make this module usable for the time being, it'll be great. Changing the issue to Critical since the module is unusable as it is on v 1.1.2.

  • Status changed to Active 5 months ago
  • πŸ‡³πŸ‡ΏNew Zealand siramsay

    @Andres.torres

    I have it working with 1.1.2.

    See my comment #12

    In short, use this https://git.drupalcode.org/project/highlightjs_input_filter/-/merge_requ...
    I think this was included in latest release https://www.drupal.org/project/highlightjs_input_filter/issues/3402489#c... πŸ› Error when several instances of same language on the page Fixed

  • πŸ‡ͺπŸ‡¨Ecuador andres.torres

    Thanks @siramsay! good to know! as i mentioned, V. 1.1.2/dev of this module current release on a D-10.2/10.3 fresh install is not a working version, so ideally for the sake of having a Drupal working workflow, we might need to provide a tested patch (through composer) here on this issue and/or wait 'till the MR goes into the main line asap.

  • πŸ‡³πŸ‡ΏNew Zealand siramsay

    @andres.torres

    I'm using 10.2.6. I will test update to 10.3.0 this/next week.

    The reason for the code not being included is that someone would need to manage an alias list.

    I think the best way around this would be to have an alias list for any of the Drupal core code block module that ships with CKEditor 5. #14
    Having a UI administration page could be the way to go for people that want to enhance the alias list.

  • πŸ‡ΊπŸ‡ΈUnited States kentr

    @andres.torres Except for the alias issues outlined here and the separate issues of πŸ› Filter has false positives Needs review , I've been using this module on a lot of languages without a problem (bash, ini, javascript, json, shell, xml, yaml, probably more).

    Currently using v1.1.2 of the module on core 10.1.7, with the patch in πŸ› Filter has false positives Needs review . The browser console error in that case is similar to the error described here.

    I wonder if your issue is something besides this one, at least partly.

    Excuse me if you know this, I can't tell from your comments:

    You can get a raw text patch from a merge request by adding .patch to the merge request URL, and you can use that URL in composer.json to patch with composer. Here for MR #5.

  • πŸ‡ΊπŸ‡ΈUnited States kentr

    I meant core version 10.2.7 in my previous comment.

  • πŸ‡ΊπŸ‡ΈUnited States nmangold United States

    Aside from this issue, and potentially other open issues, this module works as expected on fresh vanilla Drupal installs for both 10.2.x and 10.3.x, as I just tested.

    @andres.torres I assume your issue is a conflict within your environment. I see the incorrect mime type and CORS request errors in your console log. I suggest investigating those. Others are also using this module successfully.

    I have not merged this MR yet as there was some discussion about how to improve the solution. The problem is maintaining the list of aliases. I am leaning towards only supporting the CKEditor 5 code block languages by default as that seems reasonable. Hopefully, this will be easier to solve upstream in the future.

  • πŸ‡ͺπŸ‡¨Ecuador andres.torres

    Thank you all for your input here guys! really appreciated! I'm using Radix and a sub-theme generated from it so probably the error i'm facing comes from there, i'll keep testing and keep you posted.

  • Pipeline finished with Skipped
    5 months ago
    #211482
  • Status changed to Fixed 5 months ago
  • πŸ‡ΊπŸ‡ΈUnited States nmangold United States
  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.71.5 2024