Skip to content

highlight.js: support for JSONL, JSON-Seq, basic multipart, improve text/event-stream #4553

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

Merged
merged 3 commits into from
May 8, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 82 additions & 5 deletions scripts/md2html/md2html.js
Original file line number Diff line number Diff line change
@@ -48,22 +48,99 @@ hljs.registerLanguage('uri', function() {
],
}
});
hljs.registerLanguage('eventstream', function() {
hljs.registerLanguage('multipart', function() {
return {
// This is a very limited approach that only
// detects boundaries and headers that start
// with "Content-"
contains: [
{
scope: "attr",
begin: /^/,
end: ":",
scope: "meta",
match: /^--.*$/,
},
{
scope: "literal",
begin: /: */,
begin: /^Content-/,
end: /$/,
contains: [
{
scope: "attr",
begin: " ",
end: /$/,
},
]
},
],
}
});
hljs.registerLanguage('eventstream', function() {
return {
contains: [
{
scope: "comment",
begin: /^:/,
end: /$/,
},
{
scope: "attr",
match: /^[^:]+/
},
],
}
});
hljs.registerLanguage('jsonseq', function() {
return {
keywords: ["true", "false", "null"],
contains: [
{
scope: "meta",
match: /0[xX]1[eE]/,
},
{
scope: "attr",
begin: /"(\\.|[^\\"\r\n])*"(?=\s*:)/,
relevance: 1.01
},
{
scope: "punctuation",
match: /[{}[\],:]/,
relevance: 0
},
{
scope: "literals",
beginKeywords: ["true", "false" , "null"].join(" "),
},
hljs.QUOTE_STRING_MODE,
hljs.C_NUMBER_MODE
]
}
});
hljs.registerLanguage('jsonl', function() {
return {
aliases: ["ndjson"],
keywords: ["true", "false", "null"],
contains: [
{
scope: 'attr',
begin: /"(\\.|[^\\"\r\n])*"(?=\s*:)/,
relevance: 1.01
},
{
scope: "punctuation",
match: /[{}[\],:]/,
relevance: 0
},
{
scope: "literals",
beginKeywords: ["true", "false" , "null"].join(" "),
},
hljs.QUOTE_STRING_MODE,
hljs.C_NUMBER_MODE
]
}
});


const cheerio = require('cheerio');

let argv = require('yargs')
62 changes: 55 additions & 7 deletions tests/md2html/fixtures/basic-new.html
Original file line number Diff line number Diff line change
@@ -45,14 +45,62 @@
</code></pre>
<pre class="nohighlight" tabindex="0"><code>https://foo.com/bar{<span class="hljs-attr">?baz*</span>,<span class="hljs-attr">qux</span>}
</code></pre>
<pre class="nohighlight" tabindex="0"><code><span class="hljs-attr">data:</span> This data is formatted
<span class="hljs-attr">data:</span> across two lines
<span class="hljs-attr">retry:</span> 5
<pre class="nohighlight" tabindex="0"><code><span class="hljs-meta">--boundary-example</span>
<span class="hljs-literal">Content-Type:<span class="hljs-attr"> application/openapi+yaml</span></span>
<span class="hljs-literal">Content-Location:<span class="hljs-attr"> https://inaccessible-domain.com/api/openapi.yaml</span></span>

openapi: 3.2.0
info:
title: Example API
version: 1.0
externalDocs:
url: docs.html

<span class="hljs-meta">--boundary-example</span>
<span class="hljs-literal">Content-Type:<span class="hljs-attr"> text/html</span></span>
<span class="hljs-literal">Content-Location:<span class="hljs-attr"> https://example.com/api/docs.html</span></span>

&lt;html&gt;
&lt;head&gt;
&lt;title&gt;API Documentation&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;Awesome documentation goes here&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<pre class="nohighlight" tabindex="0"><code><span class="hljs-attr">event</span>: addString
<span class="hljs-attr">data</span>: This data is formatted
<span class="hljs-attr">data</span>: across two lines
<span class="hljs-attr">retry</span>: 5
<span class="hljs-attr">
event</span>: addNumber
<span class="hljs-attr">data</span>: 1234.5678
<span class="hljs-attr">unknownField</span>: this is ignored
<span class="hljs-attr">
event:</span> add
<span class="hljs-attr">data:</span> 1234.5678
<span class="hljs-attr">unknown-field:</span> this is ignored
<span class="hljs-attr"></span></code></pre>
</span><span class="hljs-comment">: This is a comment</span>
<span class="hljs-attr">event</span>: addJSON
<span class="hljs-attr">data</span>: {&quot;foo&quot;: 42}
</code></pre>
<pre class="nohighlight" tabindex="0"><code><span class="hljs-punctuation">{</span><span class="hljs-attr">&quot;event&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;addString&quot;</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">&quot;data&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;This data is formatted\nacross two lines&quot;</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">&quot;retry&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-number">5</span><span class="hljs-punctuation">}</span>
<span class="hljs-punctuation">{</span><span class="hljs-attr">&quot;event&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;addNumber&quot;</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">&quot;data&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;1234.5678&quot;</span><span class="hljs-punctuation">}</span>
<span class="hljs-punctuation">{</span><span class="hljs-attr">&quot;event&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;addJSON&quot;</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">&quot;data&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;{\&quot;foo\&quot;: 42}&quot;</span><span class="hljs-punctuation">}</span>
</code></pre>
<pre class="nohighlight" tabindex="0"><code><span class="hljs-punctuation">{</span><span class="hljs-attr">&quot;event&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;addString&quot;</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">&quot;data&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;This data is formatted\nacross two lines&quot;</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">&quot;retry&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-number">5</span><span class="hljs-punctuation">}</span>
<span class="hljs-punctuation">{</span><span class="hljs-attr">&quot;event&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;addNumber&quot;</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">&quot;data&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;1234.5678&quot;</span><span class="hljs-punctuation">}</span>
<span class="hljs-punctuation">{</span><span class="hljs-attr">&quot;event&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;addJSON&quot;</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">&quot;data&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;{\&quot;foo\&quot;: 42}&quot;</span><span class="hljs-punctuation">}</span>
</code></pre>
<pre class="nohighlight" tabindex="0"><code><span class="hljs-meta">0x1E</span><span class="hljs-punctuation">{</span>
<span class="hljs-attr">&quot;timestamp&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;1985-04-12T23:20:50.52Z&quot;</span><span class="hljs-punctuation">,</span>
<span class="hljs-attr">&quot;level&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-number">1</span><span class="hljs-punctuation">,</span>
<span class="hljs-attr">&quot;message&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;Hi!&quot;</span>
<span class="hljs-punctuation">}</span>
<span class="hljs-meta">0x1E</span><span class="hljs-punctuation">{</span>
<span class="hljs-attr">&quot;timestamp&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;1985-04-12T23:20:51.37Z&quot;</span><span class="hljs-punctuation">,</span>
<span class="hljs-attr">&quot;level&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-number">1</span><span class="hljs-punctuation">,</span>
<span class="hljs-attr">&quot;message&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;Bye!&quot;</span>
<span class="hljs-punctuation">}</span>
</code></pre>
</section></section><section class="appendix"><h1>Appendix A: Revision History</h1>
<table>
<thead>
60 changes: 58 additions & 2 deletions tests/md2html/fixtures/basic-new.md
Original file line number Diff line number Diff line change
@@ -62,14 +62,70 @@ https://foo.com/bar?baz=qux&fred=waldo#fragment
https://foo.com/bar{?baz*,qux}
```

```multipart
--boundary-example
Content-Type: application/openapi+yaml
Content-Location: https://inaccessible-domain.com/api/openapi.yaml

openapi: 3.2.0
info:
title: Example API
version: 1.0
externalDocs:
url: docs.html

--boundary-example
Content-Type: text/html
Content-Location: https://example.com/api/docs.html

<html>
<head>
<title>API Documentation</title>
</head>
<body>
<p>Awesome documentation goes here</p>
</body>
</html>
```

```eventstream
event: addString
data: This data is formatted
data: across two lines
retry: 5

event: add
event: addNumber
data: 1234.5678
unknown-field: this is ignored
unknownField: this is ignored

: This is a comment
event: addJSON
data: {"foo": 42}
```

```jsonl
{"event": "addString", "data": "This data is formatted\nacross two lines", "retry": 5}
{"event": "addNumber", "data": "1234.5678"}
{"event": "addJSON", "data": "{\"foo\": 42}"}
```

```ndjson
{"event": "addString", "data": "This data is formatted\nacross two lines", "retry": 5}
{"event": "addNumber", "data": "1234.5678"}
{"event": "addJSON", "data": "{\"foo\": 42}"}
```

```jsonseq
0x1E{
"timestamp": "1985-04-12T23:20:50.52Z",
"level": 1,
"message": "Hi!"
}
0x1E{
"timestamp": "1985-04-12T23:20:51.37Z",
"level": 1,
"message": "Bye!"
}
```

## Appendix A: Revision History