metalsmith-prism 4.3.0 → 5.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +56 -36
  2. package/lib/index.js +40 -48
  3. package/package.json +5 -4
package/README.md CHANGED
@@ -1,45 +1,69 @@
1
1
  # metalsmith-prism
2
2
 
3
- A Metalsmith plugin that **adds Prism specific HTML markup** to code sections for syntax coloring.
3
+ A Metalsmith plugin that **adds Prism specific HTML markup** to code sections for syntax coloring.
4
4
 
5
5
  [![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square&label=license)](http://opensource.org/licenses/MIT)
6
6
  [![NPM](http://img.shields.io/npm/v/metalsmith-prism.svg?style=flat-square&label=npm)](https://npmjs.org/package/metalsmith-prism)
7
7
  [![Linux Passing](https://img.shields.io/travis/Availity/metalsmith-prism.svg?style=flat-square&label=linux)](https://travis-ci.org/Availity/metalsmith-prism)
8
8
  [![Windows Passing](https://img.shields.io/appveyor/ci/robmcguinness/metalsmith-prism.svg?style=flat-square&label=windows)](https://ci.appveyor.com/project/robmcguinness/metalsmith-prism)
9
9
 
10
- While this plugin adds all the required Prism HTML markup, **prism.css** must be included on the page to provide the syntax coloring.
10
+ While this plugin adds all the required Prism HTML markup, **prism.css** must be included on the page to provide the syntax coloring. The plugin:
11
+
12
+ - Automatically handles language dependencies
13
+ - Supports HTML entity decoding
14
+ - Can add line numbers
15
+ - Works seamlessly with Markdown code blocks
16
+ - Supports all Prism.js languages
11
17
 
12
18
  ## Requirements
13
19
 
14
- + Node `>= 14.x.x`
15
- + NPM `>= 8.x.x`
16
- + Metalsmith `>= v2.4.x`
20
+ - Node `>= 18.x.x`
21
+ - NPM `>= 9.x.x`
22
+ - Metalsmith `>= v2.6.x`
23
+
24
+ ## Quick Start
17
25
 
26
+ 1. Install the plugin
27
+ 2. Add Prism CSS to your page
28
+ 3. Add language classes to your code blocks
29
+ 4. Configure the plugin in your Metalsmith build
18
30
 
31
+ Example using all features:
32
+
33
+ ```javascript
34
+ metalsmith(__dirname).use(
35
+ prism({
36
+ decode: true, // Decode HTML entities
37
+ lineNumbers: true, // Show line numbers
38
+ preLoad: ['java'], // Pre-load language dependencies
39
+ })
40
+ );
41
+ ```
19
42
 
20
43
  ## Installation
21
44
 
22
45
  NPM:
46
+
23
47
  ```bash
24
48
  npm install metalsmith-prism --save-dev
25
49
  ```
26
50
 
27
51
  Yarn:
52
+
28
53
  ```bash
29
54
  yarn add metalsmith-prism
30
55
  ```
31
56
 
32
57
  ## Usage
33
58
 
34
- ### Add Prism styles to page header.
59
+ ### Add Prism styles to page header.
35
60
 
36
- If the `linenumbers` option is set to `true`, `prism-line-numbers.css` must be added to the page.
61
+ If the `linenumbers` option is set to `true`, `prism-line-numbers.css` must be added to the page.
37
62
 
38
63
  The css files can be downloaded from the [Prism website](https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript) or [use a CDN](https://prismjs.com/#basic-usage-cdn). Please refer to the [Prism documentation](https://prismjs.com/index.html) for details.
39
64
 
40
65
  ```html
41
- <link href="/assets/prism.css" rel="stylesheet" />
42
- <link href="/assets/prism-line-numbers.css" rel="stylesheet" />
66
+ <link href="/assets/prism.css" rel="stylesheet" /> <link href="/assets/prism-line-numbers.css" rel="stylesheet" />
43
67
  ```
44
68
 
45
69
  ### Add language definition to code block
@@ -54,9 +78,7 @@ The css files can be downloaded from the [Prism website](https://prismjs.com/dow
54
78
  const metalsmith = require('metalsmith');
55
79
  const prism = require('metalsmith-prism');
56
80
 
57
- metalsmith(__dirname)
58
- .use(prism())
59
- .build();
81
+ metalsmith(__dirname).use(prism()).build();
60
82
  ```
61
83
 
62
84
  ### To use with Markdown code blocks rendered by [@metalsmith/markdown](https://github.com/metalsmith/markdown)
@@ -66,14 +88,13 @@ const metalsmith = require('metalsmith');
66
88
  const markdown = require('@metalsmith/markdown');
67
89
  const prism = require('metalsmith-prism');
68
90
 
69
- metalsmith(__dirname)
70
- .use(markdown())
71
- .use(prism())
72
- .build();
91
+ metalsmith(__dirname).use(markdown()).use(prism()).build();
73
92
  ```
74
93
 
75
94
  ## Language support
76
95
 
96
+ The plugin default language support includes: markup, css, clike, javascript and php.
97
+
77
98
  Supports all programming languages that have a corresponding Prism.js component file. Component files are found in the [Prism.js `components` directory](https://github.com/PrismJS/prism/tree/master/components).
78
99
 
79
100
  ## Options
@@ -83,21 +104,23 @@ Supports all programming languages that have a corresponding Prism.js component
83
104
  Always decode the html entities when processing language of type `markup`
84
105
 
85
106
  ```js
86
- Metalsmith(__dirname)
87
- .use(prism({
88
- decode: true
89
- }))
107
+ Metalsmith(__dirname).use(
108
+ prism({
109
+ decode: true,
110
+ })
111
+ );
90
112
  ```
91
113
 
92
114
  **lineNumbers (optional)**
93
115
 
94
- Adds the additional HTML markup so line numbers can be added via the line-numbers CSS.
116
+ Adds the additional HTML markup so line numbers can be added via the line-numbers CSS.
95
117
 
96
118
  ```javascript
97
- Metalsmith(__dirname)
98
- .use(metalsmithPrism({
99
- lineNumbers: true
100
- }))
119
+ Metalsmith(__dirname).use(
120
+ metalsmithPrism({
121
+ lineNumbers: true,
122
+ })
123
+ );
101
124
  ```
102
125
 
103
126
  **preLoad (optional)**
@@ -107,11 +130,13 @@ Pre-loads language component(s), such that each language component registers its
107
130
  Useful for loading syntax that extends other language components that are not automatically registered by Prism
108
131
 
109
132
  ```javascript
110
- Metalsmith(__dirname)
111
- .use(prism({
112
- preLoad: ["java", "scala"]
113
- }))
133
+ Metalsmith(__dirname).use(
134
+ prism({
135
+ preLoad: ['java', 'scala'],
136
+ })
137
+ );
114
138
  ```
139
+
115
140
  ## Debug
116
141
 
117
142
  To enable debug logs, set the `DEBUG` environment variable to `metalsmith-prism`:
@@ -142,16 +167,11 @@ Add `metalsmith-prism` key to your `metalsmith.json` plugins key
142
167
  }
143
168
  }
144
169
  ```
145
- ## Credits
146
-
147
- [Robert McGuinness]( https://github.com/robmcguinness) - for the initial implementation of the plugin.
148
-
149
170
 
171
+ ## Credits
150
172
 
173
+ [Robert McGuinness](https://github.com/robmcguinness) - for the initial implementation of the plugin.
151
174
 
152
175
  ## License
153
176
 
154
177
  Code released under [the MIT license](https://github.com/wernerglinka/metalsmith-prism/blob/main/LICENSE).
155
-
156
-
157
-
package/lib/index.js CHANGED
@@ -1,71 +1,63 @@
1
- 'use strict';
1
+ import { load } from 'cheerio';
2
+ import { extname } from 'path';
3
+ import Prism from 'prismjs';
4
+ import loadLanguages from 'prismjs/components/index.js';
5
+ import he from 'he';
2
6
 
3
- const cheerio = require( 'cheerio' );
4
- const debug = require( 'debug' )( 'metalsmith-prism' );
5
- const extname = require( 'path' ).extname;
6
- const languages = require( 'prismjs' ).languages;
7
- const Prism = require( 'prismjs' );
7
+ // Import languages from Prism's default export
8
+ const { languages } = Prism;
8
9
 
9
- const loadLanguages = require( 'prismjs/components/' );
10
+ // Preload PHP
10
11
  loadLanguages( [ 'php' ] );
11
12
 
12
- const he = require( 'he' );
13
-
13
+ /**
14
+ * Check if a file is HTML
15
+ * @param {string} filePath
16
+ * @returns {boolean}
17
+ */
14
18
  const isHTMLFile = ( filePath ) => {
15
19
  return /\.html|\.htm/.test( extname( filePath ) );
16
20
  };
17
21
 
22
+ /**
23
+ * @typedef Options
24
+ * @property {boolean} [decode=false] - Whether to decode HTML entities
25
+ * @property {boolean} [lineNumbers=false] - Whether to add line numbers
26
+ * @property {string[]} [preLoad=[]] - Languages to preload
27
+ */
18
28
 
19
29
  /**
20
30
  * Metalsmith plugin to highlight code syntax with PrismJS
21
31
  *
22
- * @param {Object} options
23
- * @returns
32
+ * @param {Options} [options]
33
+ * @returns {import('metalsmith').Plugin}
24
34
  */
25
-
26
- module.exports = ( options ) => {
27
-
28
- options = options || {};
29
-
35
+ function metalsmithPrism( options = {} ) {
30
36
  if ( options.preLoad ) {
31
- //list of available languages: https://github.com/PrismJS/prism/tree/master/components
32
37
  options.preLoad.forEach( ( language ) => {
33
38
  try {
34
- require( `prismjs/components/prism-${ language }.js` );
39
+ loadLanguages( [ language ] );
35
40
  } catch ( e ) {
36
- /* eslint no-console: 0 */
37
- console.warn( `Failed to preload prism syntax: ${ language } !` );
41
+ console.warn( `Failed to preload prism syntax: ${ language }!` );
38
42
  }
39
43
  } );
40
44
  }
41
45
 
42
46
  /**
43
- * requireLanguage
44
47
  * Require optional language package
45
- *
46
- * @param {*} language
48
+ * @param {string} language
47
49
  */
48
50
  function requireLanguage( language ) {
49
51
  if ( !languages[ language ] ) {
50
52
  try {
51
- require( `prismjs/components/prism-${ language }.js` );
53
+ loadLanguages( [ language ] );
52
54
  } catch ( e ) {
53
- /* eslint no-console: 0 */
54
- console.warn( `Failed to load prism syntax: ${ language } !` );
55
+ console.warn( `Failed to load prism syntax: ${ language }!` );
55
56
  }
56
57
  }
57
58
  }
58
59
 
59
-
60
- /**
61
- * Prism hook "after-tokenize" used to add html for line numbers
62
- * Neccessary as we don't have a browser
63
- *
64
- * Sources:
65
- * https://github.com/PrismJS/prism/blob/master/plugins/line-numbers/prism-line-numbers.js#L109
66
- * https://stackoverflow.com/questions/59508413/static-html-generation-with-prismjs-how-to-enable-line-numbers
67
- *
68
- */
60
+ // Set up line numbers
69
61
  const NEW_LINE_EXP = /\n(?!$)/g;
70
62
  let lineNumbersWrapper;
71
63
 
@@ -73,22 +65,19 @@ module.exports = ( options ) => {
73
65
  const match = env.code.match( NEW_LINE_EXP );
74
66
  const linesNum = match ? match.length + 1 : 1;
75
67
  const lines = new Array( linesNum + 1 ).join( '<span></span>' );
76
-
77
68
  lineNumbersWrapper = `<span aria-hidden="true" class="line-numbers-rows">${ lines }</span>`;
78
69
  } );
79
70
 
80
71
  return function( files, metalsmith, done ) {
81
-
82
72
  setImmediate( done );
83
73
 
84
74
  Object.keys( files ).forEach( file => {
85
-
86
75
  if ( !isHTMLFile( file ) ) {
87
76
  return;
88
77
  }
89
78
 
90
79
  const contents = files[ file ].contents.toString();
91
- const $ = cheerio.load( contents, { decodeEntities: false }, true );
80
+ const $ = load( contents, { decodeEntities: false } );
92
81
  let highlighted = false;
93
82
  const code = $( 'code' );
94
83
 
@@ -99,10 +88,9 @@ module.exports = ( options ) => {
99
88
 
100
89
  const className = $this.attr( 'class' ) || '';
101
90
  const targets = className.split( 'language-' );
102
- let addLineNmbers = false;
91
+ let addLineNumbers = false;
103
92
 
104
93
  if ( targets.length > 1 ) {
105
-
106
94
  const $pre = $this.parent( 'pre' );
107
95
 
108
96
  if ( $pre ) {
@@ -110,9 +98,8 @@ module.exports = ( options ) => {
110
98
  $pre.addClass( className );
111
99
 
112
100
  if ( options.lineNumbers ) {
113
- debug( 'adding line numbers' );
114
101
  $pre.addClass( 'line-numbers' );
115
- addLineNmbers = true;
102
+ addLineNumbers = true;
116
103
  }
117
104
  }
118
105
 
@@ -123,10 +110,13 @@ module.exports = ( options ) => {
123
110
  if ( !languages[ language ] ) {
124
111
  language = 'markup';
125
112
  }
126
- const html = ( language === 'markup' && !options.decode ) ? $this.html() : he.decode( $this.html() );
127
- const highlightedCode = Prism.highlight( html, Prism.languages[ language ] );
128
- $this.html( addLineNmbers ? highlightedCode + lineNumbersWrapper : highlightedCode );
129
113
 
114
+ const html = ( language === 'markup' && !options.decode )
115
+ ? $this.html()
116
+ : he.decode( $this.html() );
117
+
118
+ const highlightedCode = Prism.highlight( html, languages[ language ] );
119
+ $this.html( addLineNumbers ? highlightedCode + lineNumbersWrapper : highlightedCode );
130
120
  }
131
121
  } );
132
122
 
@@ -135,4 +125,6 @@ module.exports = ( options ) => {
135
125
  }
136
126
  } );
137
127
  };
138
- };
128
+ }
129
+
130
+ export default metalsmithPrism;
package/package.json CHANGED
@@ -1,10 +1,12 @@
1
1
  {
2
2
  "name": "metalsmith-prism",
3
- "version": "4.3.0",
3
+ "version": "5.0.1",
4
4
  "description": "Syntax highlighting for Metalsmith HTML templates using Prism.js",
5
+ "type": "module",
5
6
  "main": "lib/index.js",
7
+ "exports": "./lib/index.js",
6
8
  "engines": {
7
- "node": ">= 14.0.0"
9
+ "node": ">= 18.0.0"
8
10
  },
9
11
  "scripts": {
10
12
  "preversion": "npm run test",
@@ -39,9 +41,8 @@
39
41
  "prismjs": "^1.29.0"
40
42
  },
41
43
  "devDependencies": {
42
- "babel-eslint": "^7.2.3",
43
44
  "chai": "^5.1.2",
44
- "eslint": "^9.14.0",
45
+ "eslint": "^9.15.0",
45
46
  "eslint-config-prettier": "^9.1.0",
46
47
  "eslint-plugin-prettier": "^5.2.1",
47
48
  "mocha": "^10.8.2",