UNPKG

17.2 kBMarkdownView Raw
1# gatsby-remark-prismjs
2
3Adds syntax highlighting to code blocks in markdown files using
4[PrismJS](http://prismjs.com/).
5
6## Install
7
8`npm install gatsby-transformer-remark gatsby-remark-prismjs prismjs`
9
10## How to use
11
12```javascript
13// In your gatsby-config.js
14plugins: [
15 {
16 resolve: `gatsby-transformer-remark`,
17 options: {
18 plugins: [
19 {
20 resolve: `gatsby-remark-prismjs`,
21 options: {
22 // Class prefix for <pre> tags containing syntax highlighting;
23 // defaults to 'language-' (e.g. <pre class="language-js">).
24 // If your site loads Prism into the browser at runtime,
25 // (e.g. for use with libraries like react-live),
26 // you may use this to prevent Prism from re-processing syntax.
27 // This is an uncommon use-case though;
28 // If you're unsure, it's best to use the default value.
29 classPrefix: "language-",
30 // This is used to allow setting a language for inline code
31 // (i.e. single backticks) by creating a separator.
32 // This separator is a string and will do no white-space
33 // stripping.
34 // A suggested value for English speakers is the non-ascii
35 // character '›'.
36 inlineCodeMarker: null,
37 // This lets you set up language aliases. For example,
38 // setting this to '{ sh: "bash" }' will let you use
39 // the language "sh" which will highlight using the
40 // bash highlighter.
41 aliases: {},
42 // This toggles the display of line numbers globally alongside the code.
43 // To use it, add the following line in gatsby-browser.js
44 // right after importing the prism color scheme:
45 // require("prismjs/plugins/line-numbers/prism-line-numbers.css")
46 // Defaults to false.
47 // If you wish to only show line numbers on certain code blocks,
48 // leave false and use the {numberLines: true} syntax below
49 showLineNumbers: false,
50 // If setting this to true, the parser won't handle and highlight inline
51 // code used in markdown i.e. single backtick code like `this`.
52 noInlineHighlight: false,
53 // This adds a new language definition to Prism or extend an already
54 // existing language definition. More details on this option can be
55 // found under the header "Add new language definition or extend an
56 // existing language" below.
57 languageExtensions: [
58 {
59 language: "superscript",
60 extend: "javascript",
61 definition: {
62 superscript_types: /(SuperType)/,
63 },
64 insertBefore: {
65 function: {
66 superscript_keywords: /(superif|superelse)/,
67 },
68 },
69 },
70 ],
71 // Customize the prompt used in shell output
72 // Values below are default
73 prompt: {
74 user: "root",
75 host: "localhost",
76 global: false,
77 },
78 // By default the HTML entities <>&'" are escaped.
79 // Add additional HTML escapes by providing a mapping
80 // of HTML entities and their escape value IE: { '}': '&#123;' }
81 escapeEntities: {},
82 },
83 },
84 ],
85 },
86 },
87]
88```
89
90### Include CSS
91
92#### Required: Pick a PrismJS theme or create your own
93
94PrismJS ships with a number of [themes][5] (previewable on the [PrismJS
95website][6]) that you can easily include in your Gatsby site, or you can build
96your own by copying and modifying an example (which is what we've done for
97[gatsbyjs.org](https://gatsbyjs.org)).
98
99To load a theme, just require its CSS file in your `gatsby-browser.js` file, e.g.
100
101```javascript
102// gatsby-browser.js
103require("prismjs/themes/prism-solarizedlight.css")
104```
105
106#### Optional: Add line highlighting styles
107
108If you want to highlight lines of code, you also need to add some additional CSS
109that targets our _custom line highlighting implementation_ (which slightly
110differs from PrismJS's own plugin for that – more on that later).
111
112For line highlights similar to PrismJS's, try:
113
114```css
115.gatsby-highlight-code-line {
116 background-color: #feb;
117 display: block;
118 margin-right: -1em;
119 margin-left: -1em;
120 padding-right: 1em;
121 padding-left: 0.75em;
122 border-left: 0.25em solid #f99;
123}
124```
125
126This should work out quite nicely for the "Solarized Light" PrismJS theme we
127just added in the previous part. However, you will notice that when a
128highlighted line runs wider than the surrounding code block container (causing a
129horizontal scrollbar), its background won't be drawn for the initially hidden,
130overflowing part. :(
131
132We saw others fix that problem and decided to do so, too. Just add the following
133CSS along your PrismJS theme and the styles for `.gatsby-highlight-code-line`:
134
135```css
136/**
137 * Add back the container background-color, border-radius, padding, margin
138 * and overflow that we removed from <pre>.
139 */
140.gatsby-highlight {
141 background-color: #fdf6e3;
142 border-radius: 0.3em;
143 margin: 0.5em 0;
144 padding: 1em;
145 overflow: auto;
146}
147
148/**
149 * Remove the default PrismJS theme background-color, border-radius, margin,
150 * padding and overflow.
151 * 1. Make the element just wide enough to fit its content.
152 * 2. Always fill the visible space in .gatsby-highlight.
153 * 3. Adjust the position of the line numbers
154 */
155.gatsby-highlight pre[class*="language-"] {
156 background-color: transparent;
157 margin: 0;
158 padding: 0;
159 overflow: initial;
160 float: left; /* 1 */
161 min-width: 100%; /* 2 */
162}
163```
164
165#### Optional: Add line numbering
166
167If you want to add line numbering alongside your code, you need to
168import the corresponding CSS file from PrismJS, right after importing your
169colorscheme in `gatsby-browser.js`:
170
171```javascript
172// gatsby-browser.js
173require("prismjs/plugins/line-numbers/prism-line-numbers.css")
174```
175
176Then add in the corresponding CSS:
177
178```css
179/**
180 * If you already use line highlighting
181 */
182
183/* Adjust the position of the line numbers */
184.gatsby-highlight pre[class*="language-"].line-numbers {
185 padding-left: 2.8em;
186}
187
188/**
189 * If you only want to use line numbering
190 */
191
192.gatsby-highlight {
193 background-color: #fdf6e3;
194 border-radius: 0.3em;
195 margin: 0.5em 0;
196 padding: 1em;
197 overflow: auto;
198}
199
200.gatsby-highlight pre[class*="language-"].line-numbers {
201 padding: 0;
202 padding-left: 2.8em;
203 overflow: initial;
204}
205```
206
207#### Optional: Add shell prompt
208
209If you want a fancy prompt on anything with `shell` or `bash`, you need to import
210the following CSS file in `gatsby-browser.js`:
211
212```javascript
213// gatsby-browser.js
214require("prismjs/plugins/command-line/prism-command-line.css")
215```
216
217If you want to change the resulting prompt, use the following CSS:
218
219```css
220.command-line-prompt > span:before {
221 color: #999;
222 content: " ";
223 display: block;
224 padding-right: 0.8em;
225}
226
227/* Prompt for all users */
228.command-line-prompt > span[data-user]:before {
229 content: "[" attr(data-user) "@" attr(data-host) "] $";
230}
231
232/* Prompt for root */
233.command-line-prompt > span[data-user="root"]:before {
234 content: "[" attr(data-user) "@" attr(data-host) "] #";
235}
236
237.command-line-prompt > span[data-prompt]:before {
238 content: attr(data-prompt);
239}
240```
241
242### Usage in Markdown
243
244This is some beautiful code:
245
246 ```javascript
247 // In your gatsby-config.js
248 plugins: [
249 {
250 resolve: `gatsby-transformer-remark`,
251 options: {
252 plugins: [
253 `gatsby-remark-prismjs`,
254 ]
255 }
256 }
257 ]
258 ```
259
260### Line numbering
261
262To see the line numbers alongside your code, you can use the `numberLines` option:
263
264 ```javascript{numberLines: true}
265 // In your gatsby-config.js
266 plugins: [
267 {
268 resolve: `gatsby-transformer-remark`,
269 options: {
270 plugins: [
271 `gatsby-remark-prismjs`,
272 ]
273 }
274 }
275 ]
276 ```
277
278You can also start numbering at any index you wish (here, numbering
279will start at index 5):
280
281 ```javascript{numberLines: 5}
282 // In your gatsby-config.js
283 plugins: [
284 {
285 resolve: `gatsby-transformer-remark`,
286 options: {
287 plugins: [
288 `gatsby-remark-prismjs`,
289 ]
290 }
291 }
292 ]
293 ```
294
295### Line highlighting
296
297You can also add line highlighting. It adds a span around lines of code with a
298special class `.gatsby-highlight-code-line` that you can target with styles. See
299this README for more info.
300
301To highlight lines, you can use one of the following directives as comments in your
302code:
303
304- `highlight-line` highlights the current line;
305- `highlight-next-line` highlights the next line;
306- `highlight-start` highlights the lines until the matching `hightlight-end`;
307- `highlight-range{1, 4-6}` will highlight the next line, and the fourth, fifth and sixth lines.
308
309````
310```jsx
311class FlavorForm extends React.Component { // highlight-line
312 constructor(props) {
313 super(props);
314 this.state = {value: 'coconut'};
315
316 this.handleChange = this.handleChange.bind(this);
317 this.handleSubmit = this.handleSubmit.bind(this);
318 }
319
320 handleChange(event) {
321 // highlight-next-line
322 this.setState({value: event.target.value});
323 }
324
325 // highlight-start
326 handleSubmit(event) {
327 alert('Your favorite flavor is: ' + this.state.value);
328 event.preventDefault();
329 }
330 // highlight-end
331
332 render() {
333 return (
334 { /* highlight-range{1,4-9,12} */ }
335 <form onSubmit={this.handleSubmit}>
336 <label>
337 Pick your favorite flavor:
338 <select value={this.state.value} onChange={this.handleChange}>
339 <option value="grapefruit">Grapefruit</option>
340 <option value="lime">Lime</option>
341 <option value="coconut">Coconut</option>
342 <option value="mango">Mango</option>
343 </select>
344 </label>
345 <input type="submit" value="Submit" />
346 </form>
347 );
348 }
349}
350```
351````
352
353You can also specify the highlighted lines outside of the code block.
354In the following code snippet, lines 1 and 4 through 6 will get the line
355highlighting. The line range parsing is done with
356<https://www.npmjs.com/package/parse-numeric-range>.
357
358````
359```javascript{1,4-6}
360// In your gatsby-config.js
361plugins: [
362 {
363 resolve: `gatsby-transformer-remark`,
364 options: {
365 plugins: [
366 `gatsby-remark-prismjs`,
367 ]
368 }
369 }
370]
371```
372````
373
374### Shell prompt
375
376To show fancy prompts next to shell commands (only triggers on `bash` and `shell`), either set `prompt.global` to `true` in `gatsby-config.js`,
377or pass at least one of `{outputLines: <range>}`, `{promptUser: <user>}`, or `{promptHost: <host>}` to a snippet
378
379By default, every line gets a prompt appended to the start, this behaviour can be changed by specifying `{outputLines: <range>}`
380to the language.
381
382````
383```shell{outputLines: 2-10,12}
384````
385
386The user and host used in the appended prompt is pulled from the `prompt.user` and `prompt.host` values,
387unless explicitly overridden by the `promptUser` and `promptHost` options in the snippet, e.g.:
388
389````
390```shell{promptUser: alice}{promptHost: dev.localhost}
391````
392
393### Diff code blocks
394
395You can specify language for `diff` code blocks by using `diff-[language]` to enable syntax highlighting in diffs:
396
397````
398```diff-javascript
399````
400
401### Line hiding
402
403As well as highlighting lines, it's possible to _hide_ lines from the rendered output. Often this is handy when using `gatsby-remark-prismjs` along with [`gatsby-remark-embed-snippet`](https://www.gatsbyjs.org/packages/gatsby-remark-embed-snippet/).
404
405As with highlighting lines, you can control which lines to hide by adding directives as comments in your source code.
406
407The available directives are:
408
409- `hide-line` hides the current line;
410- `hide-next-line` hides the next line;
411- `hide-start` hides the lines until the matching `hide-end`;
412- `hide-range{1, 4-6}` will hide the next line, and the fourth, fifth and sixth lines.
413
414The hide-line directives will always be hidden too. Check out [the using-remark example site](https://using-remark.gatsbyjs.org/embed-snippets/) to see how this looks on a live site.
415
416### Inline code blocks
417
418In addition to fenced code blocks, inline code blocks will be passed through
419PrismJS as well.
420
421If you set the `inlineCodeMarker`, then you can also specify a format style.
422
423Here's an example of how to use this if the `inlineCodeMarker` was set to `±`:
424
425 I can highlight `css±.some-class { background-color: red }` with CSS syntax.
426
427This will be rendered in a `<code class=language-css>` with just the (syntax
428highlighted) text of `.some-class { background-color: red }`
429
430### Disabling syntax highlighting
431
432If you need to prevent any escaping or highlighting, you can use the `none`
433language; the inner contents will not be changed at all.
434
435### Add new language definition or extend an existing language
436
437You can provide a language extension by giving a single object or an array of
438language extension objects as the `languageExtensions` option.
439
440A language extension object looks like this:
441
442```javascript
443languageExtensions: [
444 {
445 language: "superscript",
446 extend: "javascript",
447 definition: {
448 superscript_types: /(SuperType)/,
449 },
450 insertBefore: {
451 function: {
452 superscript_keywords: /(superif|superelse)/,
453 },
454 },
455 },
456]
457```
458
459used options:
460
461- `language` (optional) The name of the new language.
462- `extend` (optional) The language you wish to extend.
463- `definition` (optional) This is the Prism language definition.
464- `insertBefore` (optional) Is used to define where in the language definition we want to insert our extension.
465
466More information of the format can be found here:
467https://prismjs.com/extending.html
468
469Note:
470
471- One of the parameters `language` and `extend` is needed.
472- If only `language` is given, a new language will be defined from scratch.
473- If only `extend` is given, an extension will be made to the given language.
474- If both `language` and `extend` is given, a new language that extends the `extend` language will
475 be defined.
476
477In case a language is extended, note that the definitions will not be merged.
478If the extended language definition and the given definition contains the same
479token, the original pattern will be overwritten.
480
481One of the parameters `definition` and `insertBefore` needs to be defined.
482`insertBefore` needs to be combined with `definition` or `extend` (otherwise
483there will not be any language definition tokens to insert before).
484
485In addition to this extension parameters the css also needs to be updated to
486get a style for the new tokens. Prism will wrap the matched tokens with a
487`span` element and give it the classes `token` and the token name you defined.
488In the example above we would match `superif` and `superelse`. In the html
489it would result in the following when a match is found:
490
491```html
492<span class="token superscript_keywords">superif</span>
493```
494
495## Implementation notes
496
497### Line highlighting
498
499Please note that we do _not_ use PrismJS's
500[line highlighting plugin](http://prismjs.com/plugins/line-highlight/). Here's
501why:
502
503- [PrismJS plugins][3] assume you're running things client side, but we are
504 _build-time folks_.
505- PrismJS's line highlighting plugin [implementation][1] does not allow for
506 solid background colors or 100% wide backgrounds that are drawn beyond the
507 _visible part_ of the container when content is overflowing.
508
509Our approach follows the [Pygments-based][2] implementation of the [React
510Tutorial/Documentation][4] for line highlights:
511
512- It uses a wrapper element `<div class="gatsby-highlight">` around the
513 PrismJS-formatted `<pre><code>`-blocks.
514- Highlighted lines are wrapped in `<span class="gatsby-highlight-code-line">`.
515- We insert a linebreak before the closing tag of `.gatsby-highlight-code-line`
516 so it ends up at the start of the following line.
517
518With all of this in place, we can apply `float:left; min-width:100%` to `<pre>`,
519throw our overflow and background on `.gatsby-highlight`, and use
520`display:block` on `.gatsby-highlight-code-line` – all of this coming together
521to facilitate the desired line highlight behavior.
522
523### Line numbering
524
525Because [the line numbering PrismJS plugin][7] runs client-side, a few adaptations were required to make it work:
526
527- A class `.line-numbers` is dynamically added to the `<pre>` element.
528- A new node `<span class="line-numbers-rows">` is added right before the closing `</pre>`
529 containing as many empty `<span>`s as there are lines.
530
531See the [client-side PrismJS implementation][8] for reference.
532
533[1]: https://github.com/PrismJS/prism/tree/8eb0ab6f76484ca47fa7acbf77657fab17b03ca7/plugins/line-highlight
534[2]: https://github.com/facebook/react/blob/00ba97a354e841701b4b83983c3a3904895e7b87/docs/_config.yml#L10
535[3]: http://prismjs.com/#plugins
536[4]: https://reactjs.org/tutorial/tutorial.html
537[5]: https://github.com/PrismJS/prism/tree/1d5047df37aacc900f8270b1c6215028f6988eb1/themes
538[6]: http://prismjs.com/
539[7]: https://prismjs.com/plugins/line-numbers/
540[8]: https://github.com/PrismJS/prism/blob/master/plugins/line-numbers/prism-line-numbers.js#L69-L115