jGleitz / markdown-it-prism

Highlight code blocks in markdown-it using prism

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

DOM-Based Plugins won't work (notably `line-numbers`)

nicovank opened this issue · comments

The line-numbers plugin (and all the other plugins I have checked so far) won't work.

This is due to a statement in every of them:

if (typeof self === 'undefined' || !self.Prism || !self.document) {
	return;
}

which prevents anything from being registered. Further, most of them use the document and browser-only methods.

I guess the only way to make them work would be to rewrite all of them to make them work...

I guess the only way to make them work would be to rewrite all of them to make them work...

Unfortunately, I guess you’re right. Most Prism plugins manipulate the DOM and can thus not be used outside the browser without further hassle.

There are some plugins that work though, like highlight-keywords.

If you want to use line-numbers anyway, you can do so quite easily. The plugin simply counts newlines in the output and adds a <span> for every line, which then gets to styled using CSS’s counters (see the plugin’s stylesheet).
That’s what I did for my personal website. I was disappointed to find that Prism’s plugins don’t really work outside the browser, too.

Hi,
Shouldn’t you specify this point in the readme?

Aside this point, this plugin remain useful; prism isn't just "plain dead simple" to add to markdown-it, and this does the job very well.

@EmmanuelBeziat I added a note and a link to this issue to the README.

Glad to hear that this plugin is nevertheless useful to you!

Do you have a link to your website where you implement that at all @jGleitz? I can get the counter bit working, but I'm having a little trouble figuring out how to create a <span /> for every line (and the HTML structure you're specifically talking about there).

@sbrl for my purposes, this simple regex replace did the trick (from code.pug):

const LINEREGEX = /\n(?!$)([\t ]*)(<[^>]*?class="[^>]*?comment[^>]*?>)?/g;
function wrapInLineSpans(code, idprefix) {
	let linespan = () => `<span class="line">`;
	if (typeof idprefix === 'string') {
		let lineindex = 1;
		linespan = () => `<span class="line" id="${lineid(idprefix, lineindex++)}">`;
	}
	return linespan() + code.replace(LINEREGEX, (match, nextLineStart, optionalComment) =>
		`</span>\n${optionalComment || ""}${linespan()}${nextLineStart}`);
}

If idprefix is set, then the code gives every line its own id. This allows having line references in the hash part of URIs.

Of course, this regex is bound to break on some input. However, it worked well for all code excerpts I had.

from prismjs.com: https://prismjs.com/plugins/line-numbers/
"Add the line-numbers class to your desired <pre> or any of its ancestors, and the Line Numbers plugin will take care of the rest. To give all code blocks line numbers, add the line-numbers class to the <body> of the page. This is part of a general activation mechanism where adding the line-numbers (or no-line-numbers) class to any element will enable (or disable) the Line Numbers plugin for all code blocks in that element. "

I insert line-numbers class to body, it works for me.

<body class='line-numbers' ...>
</body>

I actually have another question about line-highlight.

```javascript{10,12-22}
//  code
```

Insert data-line="{10,12-22}" to <pre> as follow, it also works:

<pre data-line="{10,12-22}" class="language-javascript line-numbers" tabindex="0">

Are there any markdown-it plugins that can do similar things?extract {...} from language{....} and insert <pre coustomname="{...}" >. A callback function is required for converting customname or {...}

for example:(I use markdown-it to convert MD file to HTML )

const md = require('markdown-it')();
const prism = require('markdown-it-xxxxplugin');

md.use(prism, {callback: xxxxCallbackFunction});
md.render(content)

I insert line-numbers class to body, it works for me.

This probably means that you have prismjs installed on your site at runtime. This works, of course, but it is not how this plugin is meant to be used. Most use it to render static content, and since no DOM is presented at that time, line-numbers does not work.


Are there any markdown-it plugins that can do similar things?

I think you could try markdow-it-attrs. It will give you <pre><code data-line="foo"> for ```{data-line=foo}. If you want to have the attribute on the <pre> instead of the <code>, you can use a custom renderer, as described in the docs of markdown-it-attrs.

@andreas-mausch That works great for line numbering!

Any idea how I could use this to statically highlight a particular line of code? I'm currently using markdown-it-attrs to add file names to code blocks using a pseudo-element trick: https://github.com/AleksandrHovhannisyan/aleksandrhovhannisyan.com/blob/bced0ba4278a066334bed3ac710f53ab11838bb7/config/plugins/markdown.js#L26

The best I can think of is to have one :nth-child rule per line number, for maybe the most common lines, and then to target that line using something like pre[data-line-highlight="42"] .line-highlight:nth-of-type(42). With the code block looking like this in my source file:

```js {data-line-highlight="42"}
const foo = 'bar';
```

Edit: Hmm, this would only work for single-line highlights, not for multiline.