Skip to content
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

Allow markup in highlighted code block #59

Closed
KyleMit opened this issue Sep 10, 2019 · 2 comments
Closed

Allow markup in highlighted code block #59

KyleMit opened this issue Sep 10, 2019 · 2 comments
Assignees
Labels
enhancement New feature or request

Comments

@KyleMit
Copy link
Member

KyleMit commented Sep 10, 2019

Follow up to #15 add syntax highlighting

Allow pre-escaped code to include markup that will be preserved when adding syntax highlighting

For example, in github and stackoverflow, you can include html tags in pre-escaped code blocks:

<pre><code>&lt;a href="<b>url</b>"&gt; Link &lt;/a&gt;
</code></pre>

Which renders like this (with a bold tag around "url")

<a href="url"> Link </a>

So ideally, this markdown code sandbox would work

This might not be well equipped for markdown-it

References:

Maybe markdown-it-highlightjs will work with raw code blocks

@KyleMit KyleMit added the enhancement New feature or request label Sep 10, 2019
@KyleMit
Copy link
Member Author

KyleMit commented Sep 18, 2019

Possible syntax:

```js raw
CONST token = "<mark>your_token</mark>"
```

The way markdown-it hands off rendering to the fenced code block, it will parse any information that occurs after the initial ``` and will pass language like this:

langName = info.split(/\s+/g)[0];

Which means we cannot add spaces before any potential additional parameters - which breaks most language recognition in markdown rendering for github and vscode

If we do have to delimit with a character, I tried following the language tag with each of the following special chars |/,.-1?*_%$# in github, and the only one that was still correctly formatted was using the , like this:

```js,raw
CONST token = "<mark>your_token</mark>"
```

Which returns this:

CONST token = "<mark>your_token</mark>"

So we either need the resolution of #626 Pass additional context to highlight option from fence renderer or need to extend fenced code block handler

Prior Art (Possible Syntaxes)

Python - Fenced Code Blocks

~~~~{.python hl_lines="1 3"}
# This line is emphasized
# This line isn't
# This line is emphasized
~~~~

or

```python hl_lines="1 3"
# This line is emphasized
# This line isn't
# This line is emphasized
```

Eleventy - Syntax Highlighting Plugin

{% highlight js 1,3-5 %}
function myFunction() {
  // …
  return true;
}
{% endhighlight %}

Pandoc - Fenced Code Attributes

~~~~ {#mycode .haskell .numberLines startFrom="100"}
qsort []     = []
qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++
              qsort (filter (>= x) xs)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

JIRA Advanced Formatting

{code:title=Bar.java|borderStyle=solid}
// Some comments here
public String getFoo()
{
    return foo;
}
{code}

@KyleMit
Copy link
Member Author

KyleMit commented Jan 11, 2020

How to allow markup in pre-escaped code block in node.js

Out-of-the-box, highlight.js needs to be run in browser in order to preserve HTML markup within a code block

Here are a couple reference issues submitted to highlightjs:

All of which rely on using hljs.highlightBlock(node) which:

Applies highlighting to a DOM node containing code.

Here's an example of highlighting pre-escaped code using the browser API (live demo):

<pre><code class="language-html" id="block">
    &lt;a href="<mark>url</mark>"&gt; Link &lt;/a&gt;
</code></pre>
<script>
hljs.highlightBlock(document.getElementById('block'));
</script>

Option A - Wrapper

The implementation of highlightBlock does three core things:

  1. Parse text from block of html
  2. Call the method hljs.highlight
  3. Combine original HTML with Highlight Markup

If we can stub 1 & 3 in node, we can call highlight ourselves

Parsing HTML Text

Here are some strategies for extracting the text from an html block (live demo)

However, most suggestions rely on having access to the browser by using node.textContent or node.innerText

There are a couple regex options, but they feel brittle

Merging both html streams also feels non-trivial, so I stopped here

Option B - Add Window to Node

We can install window as an npm package and then use like this:

const hljs = require("highlight.js")

let lang = "html"
let htmlRaw = `&lt;a href="<mark>url</mark>"&gt; Link &lt;/a&gt;`

// create window
const Window = require('window');
const window = new Window();

// make document available globally w/o let
document = window.document

// create text as node
let pre = window.document.createElement('pre');
pre.innerHTML = `<code class="language-${lang}">${htmlRaw}</code>`
let node = pre.childNodes[0]

// highlight node
hljs.highlightBlock(node)

console.log(node.innerHTML);

The biggest tradeoff here is that you need to make document available globally because highlightBlock needs to be able to call document.createElement('div')

I added a minimal, complete verifiable example using node.js in KyleMit/highlightjs-markup

@KyleMit KyleMit changed the title Add advanced formatting to Syntax Highlighting Allow markup in highlighted code block Jan 11, 2020
@KyleMit KyleMit self-assigned this Jan 11, 2020
@KyleMit KyleMit moved this from To do to In progress in Site Enhancement & Bugs Jan 13, 2020
@KyleMit KyleMit moved this from In progress to Done in Site Enhancement & Bugs Jan 13, 2020
@KyleMit KyleMit closed this as completed Jan 13, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Development

No branches or pull requests

1 participant