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

Look at using a heftier but more robust syntax highlighter #32

Open
zachleat opened this issue Aug 21, 2020 · 9 comments
Open

Look at using a heftier but more robust syntax highlighter #32

zachleat opened this issue Aug 21, 2020 · 9 comments
Labels
enhancement New feature or request

Comments

@zachleat
Copy link
Member

A couple of options:

@zachleat zachleat added the enhancement New feature or request label Aug 21, 2020
@codechips
Copy link

How about Shiki? https://github.com/shikijs/shiki

@codechips
Copy link

BTW, I tried to implement it in my own Eleventy setup, but Shiki is async and Eleventy config does not support async functions. Any ideas on how to tackle this?

Also, don't know if people have seen this one. I've switched to it https://github.com/b-kelly/eleventy-plugin-highlightjs

@zachleat
Copy link
Member Author

zachleat commented Sep 8, 2020

If you want to use async you’ll need to do it inside of a shortcode or filter

Async docs here:

Liquid might support async filters too—honestly I’m not sure yet

@zachleat
Copy link
Member Author

zachleat commented Sep 8, 2020

See also 11ty/eleventy#614

@surjithctly
Copy link

Yes. Please add this.

The current highlighter is adding extra <br> charactor while including from normal njk file. And no way to remove this.

@Snapstromegon
Copy link
Member

Snapstromegon commented Jan 31, 2023

I've spend yesterday evening playing around with shiki in elventy and I must say, that I think shiki is just awesome.

It's really barebones and its aproach is completely different compared to prismjs and it still has some rough edges, but with about 50 lines of JS (11ty config) + 50 lines of CSS I was able to reproduce the following features of torchlight.dev (which was mentioned as a potential replacement in #74):

  • focus (blurring everything else except on hover)
  • highlight
  • line numbers
  • add/remove/changed markers
  • correct combination of the features
  • line numbers and add/remove markers working together
  • custom classes per line

I just made it work with annotations for each line, but it should be easy to adapt for the range one. Currently it's just a test, but I want to expand on this one.

Here is an example screenshot with some proof of concept styling:
image

@codechips I also solved your problem with the async getHighligher() function!
Just use the "eleventy.before" event which can execute and await an async function.

const markdownIt = require("markdown-it");
const shiki = require("shiki");

module.exports = (eleventyConfig) => {
  // Move highlighter to this scope, so it's available everywhere
  let highlighter;

  // Async setup of shiki highlighter
  eleventyConfig.on("eleventy.before", async () => {
    highlighter = await shiki.getHighlighter({ theme: "dark-plus" });
  });

  // build markdownIt options
  let options = {
    html: true,
    highlight: (code, lang) => highlighter.codeToHtml(code, {lang}),
  };

  // switch to custom markdownIt
  eleventyConfig.setLibrary("md", markdownIt(options));
};

For v2.x.x it's even shorter:

const markdownIt = require("markdown-it");
const shiki = require("shiki");

module.exports = (eleventyConfig) => {
  eleventyConfig.on("eleventy.before", async () => {
    const highlighter = await shiki.getHighlighter({ theme: "dark-plus" });
    eleventyConfig.amendLibrary("md", (mdLib) =>
      mdLib.set({
        highlight: (code, lang) => highlighter.codeToHtml(code, { lang }),
      })
    );
  });

  // This is a hack to let eleventy know that we touch that library
  eleventyConfig.amendLibrary("md", () => {});
};

@zachleat Could you please check if the "hack" above is a bug and/or okay to use?

@tarasis
Copy link

tarasis commented Feb 11, 2023

I'd definitely love to see something else used than PrismJS, Shiki definitely looks interesting and I wish I'd come across it the other week. @Snapstromegon your sample output looks promising.

I've released a WIP plugin using the Chroma library written in Go. It supports line numbers, highlighting range of lines, tab width, and custom color for highlighted lines. (I think I'll add the focus mode as an experiment, also note I am inlining the code styling atm)

But it's slow (finding about 7-8 times slower the PrismJS & HighlightJS on the same demo files) because each code block is a call out to a Go executable. . I want to look and see if there is a JavaScript→Go bridge

@dave-kennedy
Copy link

I think Highlight.js does a much better job than Prism. Very easy to setup too. Just npm i highlight.js then update your config as follows:

import hljs from 'highlight.js';

export default function (eleventy) {
  eleventy.amendLibrary('md', md => {
    md.options.highlight = (str, lang) => {
      if (lang && hljs.getLanguage(lang)) {
        try {
          return hljs.highlight(str, { language: lang }).value;
        } catch (__) {}
      }

      return ''; // use external default escaping
    };
  });
};

Finally, add a theme, e.g.:

<link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/monokai.min.css" rel="stylesheet" />

Browse the themes here: https://highlightjs.org/demo

@Snapstromegon
Copy link
Member

Since my last post here, shiki did a 1.0 release and more and in my opinion this is right now the bar to beat as it behaves most like VSCode with theming and highlighting / language support. It also offers a fairly good flexibility and plugin system with good features out of the box and even though I didn't do the major upgrade, because my blog has some incompatible custom things, I think that this is right now the best was forward.

Also Shiki natively supports dual-themeing (so light/dark), is easy to modify/adapt and to include into 11ty. It's also used in other SSGs like Astro.

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
None yet
Development

No branches or pull requests

6 participants