highlightjs / highlight.js

JavaScript syntax highlighter with language auto-detection and zero dependencies.
https://highlightjs.org/
BSD 3-Clause "New" or "Revised" License
23.68k stars 3.59k forks source link

Proper ES6 module support #4100

Open sudo-barun opened 2 months ago

sudo-barun commented 2 months ago

Is your request related to a specific problem you're having?

I am having problem importing ES6 modules from highlight.js. Although the README mentions about ES6 Modules / import, it does not work in Browser.

I have installed highlight.js using npm install highlight.js. The following are the contents of files in project:

package.json:

{
  "dependencies": {
    "highlight.js": "^11.10.0"
  },
  "type": "module"
}

index.html:

<!DOCTYPE html>
<html>
<head>

<link rel="stylesheet" href="./node_modules/highlight.js/styles/default.min.css">

</head>
<body>

<pre><code class="language-html">&lt;span&gt;Hello World!&lt;/span&gt;</code></pre>

<script src="script.js" type="module"></script>

</body>
</html>

script.js:

import hljs from "./node_modules/highlight.js/lib/core.js";
import xml from './node_modules/highlight.js/lib/languages/xml.js';

hljs.registerLanguage('xml', xml);

const highlightedCode = hljs.highlight(
    '<span>Hello World!</span>',
    { language: 'xml' }
).value;

console.log(highlightedCode);

if (typeof window === 'object') { // check if currently running in browser
    hljs.highlightAll();
}

All the above three files are located inside same directory.

When opening the index.html in Firefox, there is error with following message in console:

Uncaught SyntaxError: The requested module 'http://localhost/node_modules/highlight.js/lib/core.js' doesn't provide an export named: 'default'

However, running node script.js works fine with following output:

<span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Hello World!<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>

It seems both the core.js and xml.js are not ES6 modules at all despite what the documentation says. They are just CommonJS modules. They seem to work in NodeJS despite being imported from ES6 modules.

I tried CDN links and they worked. But I needed local copy of those files. I downloaded those files from CDN and used that. But later, after going through the documentation thoroughly, I found that there is another package @highlightjs/cdn-assets that provide those files. After installing @highlightjs/cdn-assets, I replaced import in script.js with the following code and everything works now:

script.js:

import hljs from './node_modules/@highlightjs/cdn-assets/es/core.js';
import xml from './node_modules/@highlightjs/cdn-assets/es/languages/xml.min.js';

hljs.registerLanguage('xml', xml);

const highlightedCode = hljs.highlight(
    '<span>Hello World!</span>',
    { language: 'xml' }
).value;

console.log(highlightedCode);

hljs.highlightAll();

Although this works, the problem is that @highlightjs/cdn-assets contains generated code, not the original source code. For example, all the language files inside ./node_modules/@highlightjs/cdn-assets/es/languages/ are minified files.

The solution you'd prefer / feature you'd like to see added...

I think any JS library meant for browser should be developed using ES6 modules. It is better to drop support for CommonJS as ES6 module is already supported in Node.

Additional context... highlight.js version: 11.10.0

joshgoebel commented 2 months ago

It is better to drop support for CommonJS

Version 12 plans to do this, but it's a big change (along with other changes) and I don't have much free time these days.

minified files.

Curious, what's the issue with minified files? We could consider shipping both, we've done it already for things like CSS assets, etc.

contains generated code, not the original source code.

If you want the "raw" ES6 code you can use this repository (and a custom build process)... future versions might ship non-minified but we always plan to ship "cooked" releases because we want to manage some of dependencies and inter-dependencies ourselves, not leave that up to the end user.

sudo-barun commented 2 months ago

Version 12 plans to do this, but it's a big change (along with other changes) and I don't have much free time these days.

I can see that you have started working on version 12 but it has been more than a year since last commit. If you can provide roadmap for version 12, I can help you with the new version.

Curious, what's the issue with minified files? We could consider shipping both, we've done it already for things like CSS assets, etc.

Minified files are not readable. This is a problem when debugging them interactively in the browser.

If you want the "raw" ES6 code you can use this repository (and a custom build process)...

IMO, we should be able to use ES6 source code without having to use build process. Since highlight.js has no dependencies (only devDependencies), this should not be a big deal.

we always plan to ship "cooked" releases

I have no problem with this. We should be able to use hightlight.js in other ways beside ES6 import.