jGleitz / markdown-it-prism

Highlight code blocks in markdown-it using prism
MIT License
85 stars 22 forks source link

Does Not Work Well With Webpack Applications #28

Open therealpaulgg opened 5 years ago

therealpaulgg commented 5 years ago

This plugin does not work on webpack applications. After doing some testing and looking into the source code of this project, Prism themselves say that this is because you should not call loadLanguages() in a webpack application, and that a babel plugin should be used instead. That plugin seems to be integral to this plugin, and so I was getting the same errors using this plugin that I was when I was simply using Prism without the plugin, but attempting to use loadLanguages().

I am using this plugin on a node.js express application, and it renders server-side with no issues (no webpack). However, when I am building my vue.js app and need to add preview functionality, it does not work, probably because I am using webpack.

If there would be any way to fix it so others could avoid the trouble of having to manually add prism to markdown, that would be great.

I am including source code below that I am using that is based off of the official markdown-it docs using highlight-js here https://markdown-it.github.io/markdown-it/, but instead using Prismjs. I hope this helps anyone who is trying to accomplish what I was. This is the code I'll be using for now.

import markdownit from "markdown-it"; 

let md = markdownit({
  highlight: (str, lang) => {
   if (lang) {
        let langObject = Prism.languages[lang]
      try {
        return (
            `<pre class="language-${lang}"><code>` + 
            Prism.highlight(str, langObject, lang) + 
            '</code></pre>'
        ) 
      } catch (__) {}
    }
    return `<pre class="language-${lang}><code>` + md.utils.escapeHtml(str) + "</code></pre>"
  }
});
jGleitz commented 5 years ago

Hi! I just realized that I never answered your issue. Sorry!

First of all: thank you for reporting this.

After you opened the issued I did some digging. However, I found no straightforward solution to the problem. I attempted to make this plugin compatible to babel-plugin-prismjs, but with no success.

How do you make sure that the languages are included in the Webpack result when you use your code snippet?

therealpaulgg commented 5 years ago

The workaround solution that I used is definitely not ideal and it is NOT by any means an elegant solution, but it works and I am currently not sure on how to load the languages automatically without calling that PrismJS function (But it breaks in webpack :/).

To load languages I had to import each language from prismjs individually. Many languages in prismJS have dependencies too, so the order of the import statements actually matters. For instance, JavaScript, C, and Java require the clike language to be loaded beforehand otherwise the application will throw an error.

I'll include some sample code that I used below (it is very long).

Main downside from this from a performance standpoint is that it increases the overall bundle size of the application by a significant amount.

Imports for all Prism languages ```js import markdownit from "markdown-it" import Prism from "prismjs/components/prism-core" import "prismjs/components/prism-abap" import "prismjs/components/prism-abnf" import "prismjs/components/prism-clike" import "prismjs/components/prism-javascript" import "prismjs/components/prism-actionscript" import "prismjs/components/prism-ada" import "prismjs/components/prism-apacheconf" import "prismjs/components/prism-apl" import "prismjs/components/prism-applescript" import "prismjs/components/prism-c" import "prismjs/components/prism-cpp" import "prismjs/components/prism-arduino" import "prismjs/components/prism-arff" import "prismjs/components/prism-asciidoc" import "prismjs/components/prism-asm6502" import "prismjs/components/prism-csharp" import "prismjs/components/prism-markup" import "prismjs/components/prism-aspnet" import "prismjs/components/prism-autohotkey" import "prismjs/components/prism-autoit" import "prismjs/components/prism-bash" import "prismjs/components/prism-basic" import "prismjs/components/prism-batch" import "prismjs/components/prism-bison" import "prismjs/components/prism-bnf" import "prismjs/components/prism-brainfuck" import "prismjs/components/prism-bro" import "prismjs/components/prism-cil" import "prismjs/components/prism-clojure" import "prismjs/components/prism-cmake" import "prismjs/components/prism-coffeescript" import "prismjs/components/prism-core" import "prismjs/components/prism-ruby" import "prismjs/components/prism-crystal" import "prismjs/components/prism-csp" import "prismjs/components/prism-css" import "prismjs/components/prism-d" import "prismjs/components/prism-dart" import "prismjs/components/prism-diff" import "prismjs/components/prism-dns-zone-file" import "prismjs/components/prism-docker" import "prismjs/components/prism-ebnf" import "prismjs/components/prism-eiffel" import "prismjs/components/prism-ejs" import "prismjs/components/prism-elixir" import "prismjs/components/prism-elm" import "prismjs/components/prism-erb" import "prismjs/components/prism-erlang" import "prismjs/components/prism-flow" import "prismjs/components/prism-fortran" import "prismjs/components/prism-fsharp" import "prismjs/components/prism-gcode" import "prismjs/components/prism-gedcom" import "prismjs/components/prism-gherkin" import "prismjs/components/prism-git" import "prismjs/components/prism-glsl" import "prismjs/components/prism-gml" import "prismjs/components/prism-go" import "prismjs/components/prism-graphql" import "prismjs/components/prism-groovy" import "prismjs/components/prism-haml" import "prismjs/components/prism-handlebars" import "prismjs/components/prism-haskell" import "prismjs/components/prism-haxe" import "prismjs/components/prism-hcl" import "prismjs/components/prism-hpkp" import "prismjs/components/prism-hsts" import "prismjs/components/prism-http" import "prismjs/components/prism-ichigojam" import "prismjs/components/prism-icon" import "prismjs/components/prism-inform7" import "prismjs/components/prism-ini" import "prismjs/components/prism-io" import "prismjs/components/prism-j" import "prismjs/components/prism-java" import "prismjs/components/prism-javadoclike" import "prismjs/components/prism-javadoc" import "prismjs/components/prism-javastacktrace" import "prismjs/components/prism-jolie" import "prismjs/components/prism-jq" import "prismjs/components/prism-js-extras" import "prismjs/components/prism-js-templates" import "prismjs/components/prism-jsdoc" import "prismjs/components/prism-json" import "prismjs/components/prism-json5" import "prismjs/components/prism-jsonp" import "prismjs/components/prism-jsx" import "prismjs/components/prism-julia" import "prismjs/components/prism-keyman" import "prismjs/components/prism-kotlin" import "prismjs/components/prism-latex" import "prismjs/components/prism-less" import "prismjs/components/prism-lilypond" import "prismjs/components/prism-liquid" import "prismjs/components/prism-lisp" import "prismjs/components/prism-livescript" import "prismjs/components/prism-lolcode" import "prismjs/components/prism-lua" import "prismjs/components/prism-makefile" import "prismjs/components/prism-markdown" import "prismjs/components/prism-markup-templating" import "prismjs/components/prism-django" import "prismjs/components/prism-matlab" import "prismjs/components/prism-mel" import "prismjs/components/prism-mizar" import "prismjs/components/prism-monkey" import "prismjs/components/prism-n1ql" import "prismjs/components/prism-n4js" import "prismjs/components/prism-nand2tetris-hdl" import "prismjs/components/prism-nasm" import "prismjs/components/prism-nginx" import "prismjs/components/prism-nim" import "prismjs/components/prism-nix" import "prismjs/components/prism-nsis" import "prismjs/components/prism-objectivec" import "prismjs/components/prism-ocaml" import "prismjs/components/prism-opencl" import "prismjs/components/prism-oz" import "prismjs/components/prism-parigp" import "prismjs/components/prism-parser" import "prismjs/components/prism-pascal" import "prismjs/components/prism-pascaligo" import "prismjs/components/prism-pcaxis" import "prismjs/components/prism-perl" import "prismjs/components/prism-php-extras" import "prismjs/components/prism-php" import "prismjs/components/prism-phpdoc" import "prismjs/components/prism-sql" import "prismjs/components/prism-plsql" import "prismjs/components/prism-powershell" import "prismjs/components/prism-processing" import "prismjs/components/prism-prolog" import "prismjs/components/prism-properties" import "prismjs/components/prism-protobuf" import "prismjs/components/prism-pug" import "prismjs/components/prism-puppet" import "prismjs/components/prism-pure" import "prismjs/components/prism-python" import "prismjs/components/prism-q" import "prismjs/components/prism-qore" import "prismjs/components/prism-r" import "prismjs/components/prism-reason" import "prismjs/components/prism-regex" import "prismjs/components/prism-renpy" import "prismjs/components/prism-rest" import "prismjs/components/prism-rip" import "prismjs/components/prism-roboconf" import "prismjs/components/prism-rust" import "prismjs/components/prism-sas" import "prismjs/components/prism-sass" import "prismjs/components/prism-scala" import "prismjs/components/prism-scheme" import "prismjs/components/prism-scss" import "prismjs/components/prism-shell-session" import "prismjs/components/prism-smalltalk" import "prismjs/components/prism-smarty" import "prismjs/components/prism-soy" import "prismjs/components/prism-splunk-spl" import "prismjs/components/prism-stylus" import "prismjs/components/prism-swift" import "prismjs/components/prism-t4-templating" import "prismjs/components/prism-t4-cs" import "prismjs/components/prism-t4-vb" import "prismjs/components/prism-tap" import "prismjs/components/prism-tcl" import "prismjs/components/prism-textile" import "prismjs/components/prism-toml" import "prismjs/components/prism-tsx" import "prismjs/components/prism-tt2" import "prismjs/components/prism-twig" import "prismjs/components/prism-typescript" import "prismjs/components/prism-vala" import "prismjs/components/prism-vbnet" import "prismjs/components/prism-velocity" import "prismjs/components/prism-verilog" import "prismjs/components/prism-vhdl" import "prismjs/components/prism-vim" import "prismjs/components/prism-visual-basic" import "prismjs/components/prism-wasm" import "prismjs/components/prism-wiki" import "prismjs/components/prism-xeora" import "prismjs/components/prism-xojo" import "prismjs/components/prism-xquery" import "prismjs/components/prism-yaml" ```
jGleitz commented 5 years ago

@PaulGG: You can use your approach (manually listing the language dependencies) with this plugin, too:

import MarkdownIt from 'markdown-it';
import prism from 'markdown-it-prism';

import "prismjs/components/prism-abap"
import "prismjs/components/prism-abnf"
import "prismjs/components/prism-clike"
import "prismjs/components/prism-java"
import "prismjs/components/prism-javadoclike"
import "prismjs/components/prism-javadoc"
import "prismjs/components/prism-javastacktrace"

function component() {
  const md = new MarkdownIt();
  md.use(prism);
  const element = document.createElement('div');
  element.innerHTML = md.render(`
Here is some *code*:
\`\`\`java
public class Test {
  public void foo() {}
}
\`\`\`
`);

  return element;
}

document.body.appendChild(component());

after npx webpack --mode=development, the div on the webpage has this content:

<div><p>Here is some <em>code</em>:</p>
<pre class=" language-java"><code class=" language-java"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Test</span> <span class="token punctuation">{</span>
  <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">foo</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre>
</div>

But this is not very helpful, is it? I will add a note about it in the README anyway.

winner106 commented 3 years ago

has this problem sovled?

jGleitz commented 3 years ago

@winner106 my last post still describes the state of this issue: you can use this plugin, but you will have to load the languages you need manually.

This is not something we can fix in the scope of this plugin. Prism loads the languages it needs dynamically, and it has no direct way of knowing ahead of time which languages will be needed. So you either have to preload the languages you know you need, or preemptively import all.