metalsmith-prism 5.0.2 → 5.0.4
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.
- package/README.md +51 -19
- package/lib/index.cjs +93 -74
- package/lib/index.cjs.map +1 -1
- package/lib/index.js +200 -0
- package/lib/index.js.map +1 -0
- package/lib/index.modern.js +7 -2
- package/lib/index.modern.js.map +1 -1
- package/package.json +24 -17
- package/src/index.js +126 -106
package/README.md
CHANGED
|
@@ -1,32 +1,35 @@
|
|
|
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. Now with full dual module support for both **ESM** and **CommonJS** environments.
|
|
4
4
|
|
|
5
|
-
[![
|
|
6
|
-
[![
|
|
7
|
-
[![
|
|
8
|
-
[![
|
|
5
|
+
[![metalsmith:plugin][metalsmith-badge]][metalsmith-url]
|
|
6
|
+
[![npm: version][npm-badge]][npm-url]
|
|
7
|
+
[![license: MIT][license-badge]][license-url]
|
|
8
|
+
[![coverage][coverage-badge]][coverage-url]
|
|
9
|
+
[![ESM/CommonJS][modules-badge]][npm-url]
|
|
9
10
|
|
|
10
11
|
## Dual Module Support (ESM and CommonJS)
|
|
11
12
|
|
|
12
|
-
This plugin supports both ESM and CommonJS environments:
|
|
13
|
+
This plugin supports both ESM and CommonJS environments with no configuration needed:
|
|
13
14
|
|
|
14
15
|
- ESM: `import prism from 'metalsmith-prism'`
|
|
15
16
|
- CommonJS: `const prism = require('metalsmith-prism')`
|
|
16
17
|
|
|
18
|
+
The package detects your environment automatically and provides the appropriate module format. This makes it compatible with both modern ESM projects and legacy CommonJS codebases.
|
|
19
|
+
|
|
17
20
|
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:
|
|
18
21
|
|
|
22
|
+
- Supports both ESM and CommonJS environments
|
|
19
23
|
- Automatically handles language dependencies
|
|
20
24
|
- Supports HTML entity decoding
|
|
21
25
|
- Can add line numbers
|
|
22
26
|
- Works seamlessly with Markdown code blocks
|
|
23
|
-
- Supports all Prism.js
|
|
27
|
+
- Supports all Prism.js language
|
|
24
28
|
|
|
25
29
|
## Requirements
|
|
26
30
|
|
|
27
|
-
- Node `>= 18.
|
|
28
|
-
-
|
|
29
|
-
- Metalsmith `>= v2.6.x`
|
|
31
|
+
- Node `>= 18.0.0`
|
|
32
|
+
- Metalsmith `>= v2.6.0`
|
|
30
33
|
|
|
31
34
|
## Quick Start
|
|
32
35
|
|
|
@@ -42,7 +45,7 @@ metalsmith(__dirname).use(
|
|
|
42
45
|
prism({
|
|
43
46
|
decode: true, // Decode HTML entities
|
|
44
47
|
lineNumbers: true, // Show line numbers
|
|
45
|
-
preLoad: ['java']
|
|
48
|
+
preLoad: ['java'] // Pre-load language dependencies
|
|
46
49
|
})
|
|
47
50
|
);
|
|
48
51
|
```
|
|
@@ -82,6 +85,7 @@ The css files can be downloaded from the [Prism website](https://prismjs.com/dow
|
|
|
82
85
|
### Add `metalsmith-prism` plugin to metalsmith
|
|
83
86
|
|
|
84
87
|
**ESM:**
|
|
88
|
+
|
|
85
89
|
```js
|
|
86
90
|
import Metalsmith from 'metalsmith';
|
|
87
91
|
import prism from 'metalsmith-prism';
|
|
@@ -90,6 +94,7 @@ Metalsmith(__dirname).use(prism()).build();
|
|
|
90
94
|
```
|
|
91
95
|
|
|
92
96
|
**CommonJS:**
|
|
97
|
+
|
|
93
98
|
```js
|
|
94
99
|
const Metalsmith = require('metalsmith');
|
|
95
100
|
const prism = require('metalsmith-prism');
|
|
@@ -100,6 +105,7 @@ Metalsmith(__dirname).use(prism()).build();
|
|
|
100
105
|
### To use with Markdown code blocks rendered by [@metalsmith/markdown](https://github.com/metalsmith/markdown)
|
|
101
106
|
|
|
102
107
|
**ESM:**
|
|
108
|
+
|
|
103
109
|
```js
|
|
104
110
|
import Metalsmith from 'metalsmith';
|
|
105
111
|
import markdown from '@metalsmith/markdown';
|
|
@@ -109,6 +115,7 @@ Metalsmith(__dirname).use(markdown()).use(prism()).build();
|
|
|
109
115
|
```
|
|
110
116
|
|
|
111
117
|
**CommonJS:**
|
|
118
|
+
|
|
112
119
|
```js
|
|
113
120
|
const Metalsmith = require('metalsmith');
|
|
114
121
|
const markdown = require('@metalsmith/markdown');
|
|
@@ -132,7 +139,7 @@ Always decode the html entities when processing language of type `markup`
|
|
|
132
139
|
```js
|
|
133
140
|
Metalsmith(__dirname).use(
|
|
134
141
|
prism({
|
|
135
|
-
decode: true
|
|
142
|
+
decode: true
|
|
136
143
|
})
|
|
137
144
|
);
|
|
138
145
|
```
|
|
@@ -143,8 +150,8 @@ Adds the additional HTML markup so line numbers can be added via the line-number
|
|
|
143
150
|
|
|
144
151
|
```javascript
|
|
145
152
|
Metalsmith(__dirname).use(
|
|
146
|
-
|
|
147
|
-
lineNumbers: true
|
|
153
|
+
prism({
|
|
154
|
+
lineNumbers: true
|
|
148
155
|
})
|
|
149
156
|
);
|
|
150
157
|
```
|
|
@@ -158,7 +165,7 @@ Useful for loading syntax that extends other language components that are not au
|
|
|
158
165
|
```javascript
|
|
159
166
|
Metalsmith(__dirname).use(
|
|
160
167
|
prism({
|
|
161
|
-
preLoad: ['java', 'scala']
|
|
168
|
+
preLoad: ['java', 'scala']
|
|
162
169
|
})
|
|
163
170
|
);
|
|
164
171
|
```
|
|
@@ -169,14 +176,20 @@ To enable debug logs, set the `DEBUG` environment variable to `metalsmith-prism`
|
|
|
169
176
|
|
|
170
177
|
Linux/Mac:
|
|
171
178
|
|
|
172
|
-
```
|
|
173
|
-
DEBUG=metalsmith-prism
|
|
179
|
+
```bash
|
|
180
|
+
DEBUG=metalsmith-prism npm test
|
|
174
181
|
```
|
|
175
182
|
|
|
176
183
|
Windows:
|
|
177
184
|
|
|
185
|
+
```bash
|
|
186
|
+
set "DEBUG=metalsmith-prism" && npm test
|
|
178
187
|
```
|
|
179
|
-
|
|
188
|
+
|
|
189
|
+
Or use the test:debug script:
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
npm run test:debug
|
|
180
193
|
```
|
|
181
194
|
|
|
182
195
|
## CLI Usage
|
|
@@ -194,10 +207,29 @@ Add `metalsmith-prism` key to your `metalsmith.json` plugins key
|
|
|
194
207
|
}
|
|
195
208
|
```
|
|
196
209
|
|
|
210
|
+
## Test Coverage
|
|
211
|
+
|
|
212
|
+
This project maintains high statement and line coverage for the source code. Coverage is verified during the release process using the c8 coverage tool.
|
|
213
|
+
|
|
197
214
|
## Credits
|
|
198
215
|
|
|
199
|
-
[Robert McGuinness](https://github.com/robmcguinness) - for the initial implementation of the plugin.
|
|
216
|
+
- [Robert McGuinness](https://github.com/robmcguinness) - for the initial implementation of the plugin.
|
|
217
|
+
- [Werner Glinka](https://github.com/wernerglinka) - current maintainer.
|
|
200
218
|
|
|
201
219
|
## License
|
|
202
220
|
|
|
203
221
|
Code released under [the MIT license](https://github.com/wernerglinka/metalsmith-prism/blob/main/LICENSE).
|
|
222
|
+
|
|
223
|
+
[coverage-badge]: https://img.shields.io/badge/coverage-94%25-brightgreen
|
|
224
|
+
[coverage-url]: #test-coverage
|
|
225
|
+
[modules-badge]: https://img.shields.io/badge/modules-ESM%2FCJS-blue
|
|
226
|
+
[npm-url]: https://npmjs.org/package/metalsmith-prism
|
|
227
|
+
[npm-badge]: https://img.shields.io/npm/v/metalsmith-prism.svg
|
|
228
|
+
[npm-url]: https://www.npmjs.com/package/metalsmith-prism
|
|
229
|
+
[metalsmith-badge]: https://img.shields.io/badge/metalsmith-plugin-green.svg?longCache=true
|
|
230
|
+
[metalsmith-url]: https://metalsmith.io
|
|
231
|
+
[license-badge]: https://img.shields.io/github/license/wernerglinka/metalsmith-prism
|
|
232
|
+
[license-url]: LICENSE
|
|
233
|
+
[coverage-badge]: https://img.shields.io/badge/test%20coverage-98%25-brightgreen
|
|
234
|
+
[coverage-url]: #test-coverage
|
|
235
|
+
[modules-badge]: https://img.shields.io/badge/modules-ESM%2FCJS-blue
|
package/lib/index.cjs
CHANGED
|
@@ -28,7 +28,7 @@ const {
|
|
|
28
28
|
*/
|
|
29
29
|
const isHTMLFile = filePath => {
|
|
30
30
|
const extension = path.extname(filePath).toLowerCase();
|
|
31
|
-
return
|
|
31
|
+
return ['.html', '.htm'].includes(extension);
|
|
32
32
|
};
|
|
33
33
|
|
|
34
34
|
/**
|
|
@@ -40,7 +40,7 @@ const isHTMLFile = filePath => {
|
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
42
|
* Metalsmith plugin to highlight code syntax with PrismJS
|
|
43
|
-
*
|
|
43
|
+
*
|
|
44
44
|
* This plugin finds all code blocks in HTML files that have language-* classes
|
|
45
45
|
* and applies Prism.js syntax highlighting to them. It can also add line numbers
|
|
46
46
|
* and handle HTML entity decoding.
|
|
@@ -53,7 +53,7 @@ const isHTMLFile = filePath => {
|
|
|
53
53
|
* @example
|
|
54
54
|
* // Basic usage
|
|
55
55
|
* metalsmith.use(prism());
|
|
56
|
-
*
|
|
56
|
+
*
|
|
57
57
|
* // With options
|
|
58
58
|
* metalsmith.use(prism({
|
|
59
59
|
* decode: true,
|
|
@@ -61,7 +61,15 @@ const isHTMLFile = filePath => {
|
|
|
61
61
|
* preLoad: ['java', 'scala']
|
|
62
62
|
* }));
|
|
63
63
|
*/
|
|
64
|
-
|
|
64
|
+
const metalsmithPrism = (options = {}) => {
|
|
65
|
+
// Create a new options object with defaults
|
|
66
|
+
const opts = {
|
|
67
|
+
decode: false,
|
|
68
|
+
lineNumbers: false,
|
|
69
|
+
preLoad: [],
|
|
70
|
+
...options
|
|
71
|
+
};
|
|
72
|
+
|
|
65
73
|
// Track loaded languages to avoid duplicate loading
|
|
66
74
|
const loadedLanguages = new Set();
|
|
67
75
|
|
|
@@ -73,9 +81,9 @@ function metalsmithPrism(options = {}) {
|
|
|
73
81
|
} catch (e) {
|
|
74
82
|
debug('Failed to load PHP:', e);
|
|
75
83
|
}
|
|
76
|
-
if (
|
|
77
|
-
debug('Preloading languages:',
|
|
78
|
-
|
|
84
|
+
if (opts.preLoad && opts.preLoad.length) {
|
|
85
|
+
debug('Preloading languages:', opts.preLoad);
|
|
86
|
+
opts.preLoad.forEach(language => {
|
|
79
87
|
if (!loadedLanguages.has(language)) {
|
|
80
88
|
try {
|
|
81
89
|
loadLanguages__default["default"]([language]);
|
|
@@ -94,27 +102,30 @@ function metalsmithPrism(options = {}) {
|
|
|
94
102
|
/**
|
|
95
103
|
* Require optional language package
|
|
96
104
|
* @param {string} language
|
|
105
|
+
* @param {Set} loadedLanguages
|
|
97
106
|
*/
|
|
98
|
-
|
|
99
|
-
if (
|
|
100
|
-
debug(`
|
|
101
|
-
|
|
102
|
-
loadLanguages__default["default"]([language]);
|
|
103
|
-
loadedLanguages.add(language);
|
|
104
|
-
debug(`Successfully loaded language: ${language}`);
|
|
105
|
-
} catch (e) {
|
|
106
|
-
console.warn(`Failed to load prism syntax: ${language}!`, e);
|
|
107
|
-
debug(`Error loading language ${language}:`, e);
|
|
108
|
-
}
|
|
107
|
+
const requireLanguage = (language, loadedLanguages) => {
|
|
108
|
+
if (loadedLanguages.has(language) || languages[language]) {
|
|
109
|
+
debug(`Language ${language} already available, skipping load`);
|
|
110
|
+
return;
|
|
109
111
|
}
|
|
110
|
-
|
|
112
|
+
debug(`Loading language on-demand: ${language}`);
|
|
113
|
+
try {
|
|
114
|
+
loadLanguages__default["default"]([language]);
|
|
115
|
+
loadedLanguages.add(language);
|
|
116
|
+
debug(`Successfully loaded language: ${language}`);
|
|
117
|
+
} catch (e) {
|
|
118
|
+
console.warn(`Failed to load prism syntax: ${language}!`, e);
|
|
119
|
+
debug(`Error loading language ${language}:`, e);
|
|
120
|
+
}
|
|
121
|
+
};
|
|
111
122
|
|
|
112
123
|
// Set up line numbers functionality
|
|
113
124
|
const NEW_LINE_EXP = /\n(?!$)/g;
|
|
114
125
|
let lineNumbersWrapper;
|
|
115
126
|
|
|
116
127
|
// Only set up the hook if line numbers are requested
|
|
117
|
-
if (
|
|
128
|
+
if (opts.lineNumbers) {
|
|
118
129
|
debug('Setting up line numbers hook');
|
|
119
130
|
Prism__default["default"].hooks.add('after-tokenize', env => {
|
|
120
131
|
const match = env.code.match(NEW_LINE_EXP);
|
|
@@ -124,67 +135,75 @@ function metalsmithPrism(options = {}) {
|
|
|
124
135
|
lineNumbersWrapper = `<span aria-hidden="true" class="line-numbers-rows">${lines}</span>`;
|
|
125
136
|
});
|
|
126
137
|
}
|
|
127
|
-
return
|
|
138
|
+
return (files, metalsmith, done) => {
|
|
128
139
|
debug('Starting metalsmith-prism plugin');
|
|
129
|
-
debug('Options:',
|
|
140
|
+
debug('Options:', opts);
|
|
141
|
+
|
|
142
|
+
// Call done asynchronously to avoid blocking
|
|
130
143
|
setImmediate(done);
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
144
|
+
try {
|
|
145
|
+
Object.keys(files).forEach(file => {
|
|
146
|
+
if (!isHTMLFile(file)) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
debug(`Processing HTML file: ${file}`);
|
|
150
|
+
const contents = files[file].contents.toString();
|
|
151
|
+
const $ = cheerio.load(contents, {
|
|
152
|
+
decodeEntities: false
|
|
153
|
+
});
|
|
154
|
+
let highlighted = false;
|
|
155
|
+
const code = $('code');
|
|
156
|
+
if (!code.length) {
|
|
157
|
+
debug(`No code blocks found in ${file}`);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
debug(`Found ${code.length} code blocks in ${file}`);
|
|
161
|
+
code.each(function () {
|
|
162
|
+
const $this = $(this);
|
|
163
|
+
const className = $this.attr('class') || '';
|
|
164
|
+
const targets = className.split('language-');
|
|
165
|
+
let addLineNumbers = false;
|
|
166
|
+
if (targets.length > 1) {
|
|
167
|
+
const $pre = $this.parent('pre');
|
|
168
|
+
if ($pre) {
|
|
169
|
+
// Copy className to <pre> container
|
|
170
|
+
$pre.addClass(className);
|
|
171
|
+
if (opts.lineNumbers) {
|
|
172
|
+
$pre.addClass('line-numbers');
|
|
173
|
+
addLineNumbers = true;
|
|
174
|
+
debug('Adding line numbers');
|
|
175
|
+
}
|
|
161
176
|
}
|
|
177
|
+
highlighted = true;
|
|
178
|
+
let language = targets[1];
|
|
179
|
+
debug(`Detected language: ${language}`);
|
|
180
|
+
requireLanguage(language, loadedLanguages);
|
|
181
|
+
if (!languages[language]) {
|
|
182
|
+
debug(`Language ${language} not available, falling back to markup`);
|
|
183
|
+
language = 'markup';
|
|
184
|
+
}
|
|
185
|
+
const html = language === 'markup' && !opts.decode ? $this.html() : he__default["default"].decode($this.html());
|
|
186
|
+
debug(`HTML decoding ${opts.decode ? 'applied' : 'not applied'} for language ${language}`);
|
|
187
|
+
debug(`Highlighting code with language: ${language}`);
|
|
188
|
+
const highlightedCode = Prism__default["default"].highlight(html, languages[language]);
|
|
189
|
+
$this.html(addLineNumbers ? highlightedCode + lineNumbersWrapper : highlightedCode);
|
|
162
190
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
debug(`
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
language = 'markup';
|
|
170
|
-
}
|
|
171
|
-
const html = language === 'markup' && !options.decode ? $this.html() : he__default["default"].decode($this.html());
|
|
172
|
-
debug(`HTML decoding ${options.decode ? 'applied' : 'not applied'} for language ${language}`);
|
|
173
|
-
debug(`Highlighting code with language: ${language}`);
|
|
174
|
-
const highlightedCode = Prism__default["default"].highlight(html, languages[language]);
|
|
175
|
-
$this.html(addLineNumbers ? highlightedCode + lineNumbersWrapper : highlightedCode);
|
|
191
|
+
});
|
|
192
|
+
if (highlighted) {
|
|
193
|
+
debug(`Updating contents of ${file} with highlighted code`);
|
|
194
|
+
files[file].contents = Buffer.from($.html());
|
|
195
|
+
} else {
|
|
196
|
+
debug(`No code was highlighted in ${file}`);
|
|
176
197
|
}
|
|
177
198
|
});
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
});
|
|
185
|
-
debug('Completed metalsmith-prism plugin');
|
|
199
|
+
debug('Completed metalsmith-prism plugin');
|
|
200
|
+
} catch (error) {
|
|
201
|
+
debug('Error in metalsmith-prism plugin:', error);
|
|
202
|
+
// We can't call done(error) here because done has already been called
|
|
203
|
+
console.error('Error processing files:', error);
|
|
204
|
+
}
|
|
186
205
|
};
|
|
187
|
-
}
|
|
206
|
+
};
|
|
188
207
|
|
|
189
208
|
module.exports = metalsmithPrism;
|
|
190
209
|
//# sourceMappingURL=index.cjs.map
|
package/lib/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/index.js"],"sourcesContent":["import { load } from 'cheerio';\nimport { extname } from 'path';\nimport Prism from 'prismjs';\nimport loadLanguages from 'prismjs/components/index.js';\nimport he from 'he';\nimport debugLib from 'debug';\n\nconst debug = debugLib('metalsmith-prism');\n\n// Import languages from Prism's default export\nconst { languages } = Prism;\n\n/**\n * Check if a file is HTML based on its extension\n * @param {string} filePath - Path to the file\n * @returns {boolean} - True if the file has an HTML extension\n */\nconst isHTMLFile = (filePath) => {\n const extension = extname(filePath).toLowerCase();\n return extension === '.html' || extension === '.htm';\n};\n\n/**\n * @typedef Options\n * @property {boolean} [decode=false] - Whether to decode HTML entities\n * @property {boolean} [lineNumbers=false] - Whether to add line numbers\n * @property {string[]} [preLoad=[]] - Languages to preload\n */\n\n/**\n * Metalsmith plugin to highlight code syntax with PrismJS\n * \n * This plugin finds all code blocks in HTML files that have language-* classes\n * and applies Prism.js syntax highlighting to them. It can also add line numbers\n * and handle HTML entity decoding.\n *\n * @param {Options} [options] - Configuration options\n * @param {boolean} [options.decode=false] - Whether to decode HTML entities in code blocks\n * @param {boolean} [options.lineNumbers=false] - Whether to add line numbers to code blocks\n * @param {string[]} [options.preLoad=[]] - Languages to preload before processing\n * @returns {import('metalsmith').Plugin} - A metalsmith plugin function\n * @example\n * // Basic usage\n * metalsmith.use(prism());\n * \n * // With options\n * metalsmith.use(prism({\n * decode: true,\n * lineNumbers: true,\n * preLoad: ['java', 'scala']\n * }));\n */\nfunction metalsmithPrism(options = {}) {\n // Track loaded languages to avoid duplicate loading\n const loadedLanguages = new Set();\n \n // Always load PHP by default\n debug('Loading PHP by default');\n try {\n loadLanguages(['php']);\n loadedLanguages.add('php');\n } catch (e) {\n debug('Failed to load PHP:', e);\n }\n \n if (options.preLoad) {\n debug('Preloading languages:', options.preLoad);\n options.preLoad.forEach((language) => {\n if (!loadedLanguages.has(language)) {\n try {\n loadLanguages([language]);\n loadedLanguages.add(language);\n debug(`Successfully preloaded language: ${language}`);\n } catch (e) {\n console.warn(`Failed to preload prism syntax: ${language}!`, e);\n debug(`Error preloading language ${language}:`, e);\n }\n } else {\n debug(`Language ${language} already loaded, skipping`);\n }\n });\n }\n\n /**\n * Require optional language package\n * @param {string} language\n */\n function requireLanguage(language) {\n if (!loadedLanguages.has(language) && !languages[language]) {\n debug(`Loading language on-demand: ${language}`);\n try {\n loadLanguages([language]);\n loadedLanguages.add(language);\n debug(`Successfully loaded language: ${language}`);\n } catch (e) {\n console.warn(`Failed to load prism syntax: ${language}!`, e);\n debug(`Error loading language ${language}:`, e);\n }\n }\n }\n\n // Set up line numbers functionality\n const NEW_LINE_EXP = /\\n(?!$)/g;\n let lineNumbersWrapper;\n\n // Only set up the hook if line numbers are requested\n if (options.lineNumbers) {\n debug('Setting up line numbers hook');\n Prism.hooks.add('after-tokenize', (env) => {\n const match = env.code.match(NEW_LINE_EXP);\n const linesNum = match ? match.length + 1 : 1;\n debug(`Counted ${linesNum} lines for line numbers`);\n const lines = new Array(linesNum + 1).join('<span></span>');\n lineNumbersWrapper = `<span aria-hidden=\"true\" class=\"line-numbers-rows\">${lines}</span>`;\n });\n }\n\n return function (files, metalsmith, done) {\n debug('Starting metalsmith-prism plugin');\n debug('Options:', options);\n \n setImmediate(done);\n\n Object.keys(files).forEach((file) => {\n if (!isHTMLFile(file)) {\n return;\n }\n\n debug(`Processing HTML file: ${file}`);\n const contents = files[file].contents.toString();\n const $ = load(contents, { decodeEntities: false });\n let highlighted = false;\n const code = $('code');\n\n if (!code.length) {\n debug(`No code blocks found in ${file}`);\n return;\n }\n \n debug(`Found ${code.length} code blocks in ${file}`);\n\n code.each(function () {\n const $this = $(this);\n\n const className = $this.attr('class') || '';\n const targets = className.split('language-');\n let addLineNumbers = false;\n\n if (targets.length > 1) {\n const $pre = $this.parent('pre');\n\n if ($pre) {\n // Copy className to <pre> container\n $pre.addClass(className);\n\n if (options.lineNumbers) {\n $pre.addClass('line-numbers');\n addLineNumbers = true;\n debug('Adding line numbers');\n }\n }\n\n highlighted = true;\n let language = targets[1];\n debug(`Detected language: ${language}`);\n requireLanguage(language);\n\n if (!languages[language]) {\n debug(`Language ${language} not available, falling back to markup`);\n language = 'markup';\n }\n\n const html = language === 'markup' && !options.decode ? $this.html() : he.decode($this.html());\n debug(`HTML decoding ${options.decode ? 'applied' : 'not applied'} for language ${language}`);\n\n debug(`Highlighting code with language: ${language}`);\n const highlightedCode = Prism.highlight(html, languages[language]);\n $this.html(addLineNumbers ? highlightedCode + lineNumbersWrapper : highlightedCode);\n }\n });\n\n if (highlighted) {\n debug(`Updating contents of ${file} with highlighted code`);\n files[file].contents = Buffer.from($.html());\n } else {\n debug(`No code was highlighted in ${file}`);\n }\n });\n \n debug('Completed metalsmith-prism plugin');\n };\n}\n\nexport { metalsmithPrism as default };"],"names":["debug","debugLib","languages","Prism","isHTMLFile","filePath","extension","extname","toLowerCase","metalsmithPrism","options","loadedLanguages","Set","loadLanguages","add","e","preLoad","forEach","language","has","console","warn","requireLanguage","NEW_LINE_EXP","lineNumbersWrapper","lineNumbers","hooks","env","match","code","linesNum","length","lines","Array","join","files","metalsmith","done","setImmediate","Object","keys","file","contents","toString","$","load","decodeEntities","highlighted","each","$this","className","attr","targets","split","addLineNumbers","$pre","parent","addClass","html","decode","he","highlightedCode","highlight","Buffer","from"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/index.js"],"sourcesContent":["import { load } from 'cheerio';\nimport { extname } from 'path';\nimport Prism from 'prismjs';\nimport loadLanguages from 'prismjs/components/index.js';\nimport he from 'he';\nimport debugLib from 'debug';\n\nconst debug = debugLib( 'metalsmith-prism' );\n\n// Import languages from Prism's default export\nconst { languages } = Prism;\n\n/**\n * Check if a file is HTML based on its extension\n * @param {string} filePath - Path to the file\n * @returns {boolean} - True if the file has an HTML extension\n */\nconst isHTMLFile = ( filePath ) => {\n const extension = extname( filePath ).toLowerCase();\n return [ '.html', '.htm' ].includes( extension );\n};\n\n/**\n * @typedef Options\n * @property {boolean} [decode=false] - Whether to decode HTML entities\n * @property {boolean} [lineNumbers=false] - Whether to add line numbers\n * @property {string[]} [preLoad=[]] - Languages to preload\n */\n\n/**\n * Metalsmith plugin to highlight code syntax with PrismJS\n *\n * This plugin finds all code blocks in HTML files that have language-* classes\n * and applies Prism.js syntax highlighting to them. It can also add line numbers\n * and handle HTML entity decoding.\n *\n * @param {Options} [options] - Configuration options\n * @param {boolean} [options.decode=false] - Whether to decode HTML entities in code blocks\n * @param {boolean} [options.lineNumbers=false] - Whether to add line numbers to code blocks\n * @param {string[]} [options.preLoad=[]] - Languages to preload before processing\n * @returns {import('metalsmith').Plugin} - A metalsmith plugin function\n * @example\n * // Basic usage\n * metalsmith.use(prism());\n *\n * // With options\n * metalsmith.use(prism({\n * decode: true,\n * lineNumbers: true,\n * preLoad: ['java', 'scala']\n * }));\n */\nconst metalsmithPrism = ( options = {} ) => {\n // Create a new options object with defaults\n const opts = {\n decode: false,\n lineNumbers: false,\n preLoad: [],\n ...options\n };\n\n // Track loaded languages to avoid duplicate loading\n const loadedLanguages = new Set();\n\n // Always load PHP by default\n debug( 'Loading PHP by default' );\n try {\n loadLanguages( [ 'php' ] );\n loadedLanguages.add( 'php' );\n } catch ( e ) {\n debug( 'Failed to load PHP:', e );\n }\n\n if ( opts.preLoad && opts.preLoad.length ) {\n debug( 'Preloading languages:', opts.preLoad );\n opts.preLoad.forEach( ( language ) => {\n if ( !loadedLanguages.has( language ) ) {\n try {\n loadLanguages( [ language ] );\n loadedLanguages.add( language );\n debug( `Successfully preloaded language: ${ language }` );\n } catch ( e ) {\n console.warn( `Failed to preload prism syntax: ${ language }!`, e );\n debug( `Error preloading language ${ language }:`, e );\n }\n } else {\n debug( `Language ${ language } already loaded, skipping` );\n }\n } );\n }\n\n /**\n * Require optional language package\n * @param {string} language\n * @param {Set} loadedLanguages\n */\n const requireLanguage = ( language, loadedLanguages ) => {\n if ( loadedLanguages.has( language ) || languages[ language ] ) {\n debug( `Language ${ language } already available, skipping load` );\n return;\n }\n\n debug( `Loading language on-demand: ${ language }` );\n try {\n loadLanguages( [ language ] );\n loadedLanguages.add( language );\n debug( `Successfully loaded language: ${ language }` );\n } catch ( e ) {\n console.warn( `Failed to load prism syntax: ${ language }!`, e );\n debug( `Error loading language ${ language }:`, e );\n }\n };\n\n // Set up line numbers functionality\n const NEW_LINE_EXP = /\\n(?!$)/g;\n let lineNumbersWrapper;\n\n // Only set up the hook if line numbers are requested\n if ( opts.lineNumbers ) {\n debug( 'Setting up line numbers hook' );\n Prism.hooks.add( 'after-tokenize', ( env ) => {\n const match = env.code.match( NEW_LINE_EXP );\n const linesNum = match ? match.length + 1 : 1;\n debug( `Counted ${ linesNum } lines for line numbers` );\n const lines = new Array( linesNum + 1 ).join( '<span></span>' );\n lineNumbersWrapper = `<span aria-hidden=\"true\" class=\"line-numbers-rows\">${ lines }</span>`;\n } );\n }\n\n return ( files, metalsmith, done ) => {\n debug( 'Starting metalsmith-prism plugin' );\n debug( 'Options:', opts );\n\n // Call done asynchronously to avoid blocking\n setImmediate( done );\n\n try {\n Object.keys( files ).forEach( ( file ) => {\n if ( !isHTMLFile( file ) ) {\n return;\n }\n\n debug( `Processing HTML file: ${ file }` );\n const contents = files[ file ].contents.toString();\n const $ = load( contents, { decodeEntities: false } );\n let highlighted = false;\n const code = $( 'code' );\n\n if ( !code.length ) {\n debug( `No code blocks found in ${ file }` );\n return;\n }\n\n debug( `Found ${ code.length } code blocks in ${ file }` );\n\n code.each( function() {\n const $this = $( this );\n\n const className = $this.attr( 'class' ) || '';\n const targets = className.split( 'language-' );\n let addLineNumbers = false;\n\n if ( targets.length > 1 ) {\n const $pre = $this.parent( 'pre' );\n\n if ( $pre ) {\n // Copy className to <pre> container\n $pre.addClass( className );\n\n if ( opts.lineNumbers ) {\n $pre.addClass( 'line-numbers' );\n addLineNumbers = true;\n debug( 'Adding line numbers' );\n }\n }\n\n highlighted = true;\n let language = targets[ 1 ];\n debug( `Detected language: ${ language }` );\n requireLanguage( language, loadedLanguages );\n\n if ( !languages[ language ] ) {\n debug( `Language ${ language } not available, falling back to markup` );\n language = 'markup';\n }\n\n const html = language === 'markup' && !opts.decode ? $this.html() : he.decode( $this.html() );\n debug( `HTML decoding ${ opts.decode ? 'applied' : 'not applied' } for language ${ language }` );\n\n debug( `Highlighting code with language: ${ language }` );\n const highlightedCode = Prism.highlight( html, languages[ language ] );\n $this.html( addLineNumbers ? highlightedCode + lineNumbersWrapper : highlightedCode );\n }\n } );\n\n if ( highlighted ) {\n debug( `Updating contents of ${ file } with highlighted code` );\n files[ file ].contents = Buffer.from( $.html() );\n } else {\n debug( `No code was highlighted in ${ file }` );\n }\n } );\n\n debug( 'Completed metalsmith-prism plugin' );\n } catch ( error ) {\n debug( 'Error in metalsmith-prism plugin:', error );\n // We can't call done(error) here because done has already been called\n console.error( 'Error processing files:', error );\n }\n };\n};\n\n// ESM export\nexport default metalsmithPrism;\n"],"names":["debug","debugLib","languages","Prism","isHTMLFile","filePath","extension","extname","toLowerCase","includes","metalsmithPrism","options","opts","decode","lineNumbers","preLoad","loadedLanguages","Set","loadLanguages","add","e","length","forEach","language","has","console","warn","requireLanguage","NEW_LINE_EXP","lineNumbersWrapper","hooks","env","match","code","linesNum","lines","Array","join","files","metalsmith","done","setImmediate","Object","keys","file","contents","toString","$","load","decodeEntities","highlighted","each","$this","className","attr","targets","split","addLineNumbers","$pre","parent","addClass","html","he","highlightedCode","highlight","Buffer","from","error"],"mappings":"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"}
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
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';
|
|
6
|
+
import debugLib from 'debug';
|
|
7
|
+
|
|
8
|
+
const debug = debugLib('metalsmith-prism');
|
|
9
|
+
|
|
10
|
+
// Import languages from Prism's default export
|
|
11
|
+
const {
|
|
12
|
+
languages
|
|
13
|
+
} = Prism;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Check if a file is HTML based on its extension
|
|
17
|
+
* @param {string} filePath - Path to the file
|
|
18
|
+
* @returns {boolean} - True if the file has an HTML extension
|
|
19
|
+
*/
|
|
20
|
+
const isHTMLFile = filePath => {
|
|
21
|
+
const extension = extname(filePath).toLowerCase();
|
|
22
|
+
return ['.html', '.htm'].includes(extension);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @typedef Options
|
|
27
|
+
* @property {boolean} [decode=false] - Whether to decode HTML entities
|
|
28
|
+
* @property {boolean} [lineNumbers=false] - Whether to add line numbers
|
|
29
|
+
* @property {string[]} [preLoad=[]] - Languages to preload
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Metalsmith plugin to highlight code syntax with PrismJS
|
|
34
|
+
*
|
|
35
|
+
* This plugin finds all code blocks in HTML files that have language-* classes
|
|
36
|
+
* and applies Prism.js syntax highlighting to them. It can also add line numbers
|
|
37
|
+
* and handle HTML entity decoding.
|
|
38
|
+
*
|
|
39
|
+
* @param {Options} [options] - Configuration options
|
|
40
|
+
* @param {boolean} [options.decode=false] - Whether to decode HTML entities in code blocks
|
|
41
|
+
* @param {boolean} [options.lineNumbers=false] - Whether to add line numbers to code blocks
|
|
42
|
+
* @param {string[]} [options.preLoad=[]] - Languages to preload before processing
|
|
43
|
+
* @returns {import('metalsmith').Plugin} - A metalsmith plugin function
|
|
44
|
+
* @example
|
|
45
|
+
* // Basic usage
|
|
46
|
+
* metalsmith.use(prism());
|
|
47
|
+
*
|
|
48
|
+
* // With options
|
|
49
|
+
* metalsmith.use(prism({
|
|
50
|
+
* decode: true,
|
|
51
|
+
* lineNumbers: true,
|
|
52
|
+
* preLoad: ['java', 'scala']
|
|
53
|
+
* }));
|
|
54
|
+
*/
|
|
55
|
+
const metalsmithPrism = (options = {}) => {
|
|
56
|
+
// Create a new options object with defaults
|
|
57
|
+
const opts = {
|
|
58
|
+
decode: false,
|
|
59
|
+
lineNumbers: false,
|
|
60
|
+
preLoad: [],
|
|
61
|
+
...options
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// Track loaded languages to avoid duplicate loading
|
|
65
|
+
const loadedLanguages = new Set();
|
|
66
|
+
|
|
67
|
+
// Always load PHP by default
|
|
68
|
+
debug('Loading PHP by default');
|
|
69
|
+
try {
|
|
70
|
+
loadLanguages(['php']);
|
|
71
|
+
loadedLanguages.add('php');
|
|
72
|
+
} catch (e) {
|
|
73
|
+
debug('Failed to load PHP:', e);
|
|
74
|
+
}
|
|
75
|
+
if (opts.preLoad && opts.preLoad.length) {
|
|
76
|
+
debug('Preloading languages:', opts.preLoad);
|
|
77
|
+
opts.preLoad.forEach(language => {
|
|
78
|
+
if (!loadedLanguages.has(language)) {
|
|
79
|
+
try {
|
|
80
|
+
loadLanguages([language]);
|
|
81
|
+
loadedLanguages.add(language);
|
|
82
|
+
debug(`Successfully preloaded language: ${language}`);
|
|
83
|
+
} catch (e) {
|
|
84
|
+
console.warn(`Failed to preload prism syntax: ${language}!`, e);
|
|
85
|
+
debug(`Error preloading language ${language}:`, e);
|
|
86
|
+
}
|
|
87
|
+
} else {
|
|
88
|
+
debug(`Language ${language} already loaded, skipping`);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Require optional language package
|
|
95
|
+
* @param {string} language
|
|
96
|
+
* @param {Set} loadedLanguages
|
|
97
|
+
*/
|
|
98
|
+
const requireLanguage = (language, loadedLanguages) => {
|
|
99
|
+
if (loadedLanguages.has(language) || languages[language]) {
|
|
100
|
+
debug(`Language ${language} already available, skipping load`);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
debug(`Loading language on-demand: ${language}`);
|
|
104
|
+
try {
|
|
105
|
+
loadLanguages([language]);
|
|
106
|
+
loadedLanguages.add(language);
|
|
107
|
+
debug(`Successfully loaded language: ${language}`);
|
|
108
|
+
} catch (e) {
|
|
109
|
+
console.warn(`Failed to load prism syntax: ${language}!`, e);
|
|
110
|
+
debug(`Error loading language ${language}:`, e);
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// Set up line numbers functionality
|
|
115
|
+
const NEW_LINE_EXP = /\n(?!$)/g;
|
|
116
|
+
let lineNumbersWrapper;
|
|
117
|
+
|
|
118
|
+
// Only set up the hook if line numbers are requested
|
|
119
|
+
if (opts.lineNumbers) {
|
|
120
|
+
debug('Setting up line numbers hook');
|
|
121
|
+
Prism.hooks.add('after-tokenize', env => {
|
|
122
|
+
const match = env.code.match(NEW_LINE_EXP);
|
|
123
|
+
const linesNum = match ? match.length + 1 : 1;
|
|
124
|
+
debug(`Counted ${linesNum} lines for line numbers`);
|
|
125
|
+
const lines = new Array(linesNum + 1).join('<span></span>');
|
|
126
|
+
lineNumbersWrapper = `<span aria-hidden="true" class="line-numbers-rows">${lines}</span>`;
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
return (files, metalsmith, done) => {
|
|
130
|
+
debug('Starting metalsmith-prism plugin');
|
|
131
|
+
debug('Options:', opts);
|
|
132
|
+
|
|
133
|
+
// Call done asynchronously to avoid blocking
|
|
134
|
+
setImmediate(done);
|
|
135
|
+
try {
|
|
136
|
+
Object.keys(files).forEach(file => {
|
|
137
|
+
if (!isHTMLFile(file)) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
debug(`Processing HTML file: ${file}`);
|
|
141
|
+
const contents = files[file].contents.toString();
|
|
142
|
+
const $ = load(contents, {
|
|
143
|
+
decodeEntities: false
|
|
144
|
+
});
|
|
145
|
+
let highlighted = false;
|
|
146
|
+
const code = $('code');
|
|
147
|
+
if (!code.length) {
|
|
148
|
+
debug(`No code blocks found in ${file}`);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
debug(`Found ${code.length} code blocks in ${file}`);
|
|
152
|
+
code.each(function () {
|
|
153
|
+
const $this = $(this);
|
|
154
|
+
const className = $this.attr('class') || '';
|
|
155
|
+
const targets = className.split('language-');
|
|
156
|
+
let addLineNumbers = false;
|
|
157
|
+
if (targets.length > 1) {
|
|
158
|
+
const $pre = $this.parent('pre');
|
|
159
|
+
if ($pre) {
|
|
160
|
+
// Copy className to <pre> container
|
|
161
|
+
$pre.addClass(className);
|
|
162
|
+
if (opts.lineNumbers) {
|
|
163
|
+
$pre.addClass('line-numbers');
|
|
164
|
+
addLineNumbers = true;
|
|
165
|
+
debug('Adding line numbers');
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
highlighted = true;
|
|
169
|
+
let language = targets[1];
|
|
170
|
+
debug(`Detected language: ${language}`);
|
|
171
|
+
requireLanguage(language, loadedLanguages);
|
|
172
|
+
if (!languages[language]) {
|
|
173
|
+
debug(`Language ${language} not available, falling back to markup`);
|
|
174
|
+
language = 'markup';
|
|
175
|
+
}
|
|
176
|
+
const html = language === 'markup' && !opts.decode ? $this.html() : he.decode($this.html());
|
|
177
|
+
debug(`HTML decoding ${opts.decode ? 'applied' : 'not applied'} for language ${language}`);
|
|
178
|
+
debug(`Highlighting code with language: ${language}`);
|
|
179
|
+
const highlightedCode = Prism.highlight(html, languages[language]);
|
|
180
|
+
$this.html(addLineNumbers ? highlightedCode + lineNumbersWrapper : highlightedCode);
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
if (highlighted) {
|
|
184
|
+
debug(`Updating contents of ${file} with highlighted code`);
|
|
185
|
+
files[file].contents = Buffer.from($.html());
|
|
186
|
+
} else {
|
|
187
|
+
debug(`No code was highlighted in ${file}`);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
debug('Completed metalsmith-prism plugin');
|
|
191
|
+
} catch (error) {
|
|
192
|
+
debug('Error in metalsmith-prism plugin:', error);
|
|
193
|
+
// We can't call done(error) here because done has already been called
|
|
194
|
+
console.error('Error processing files:', error);
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
export { metalsmithPrism as default };
|
|
200
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/index.js"],"sourcesContent":["import { load } from 'cheerio';\nimport { extname } from 'path';\nimport Prism from 'prismjs';\nimport loadLanguages from 'prismjs/components/index.js';\nimport he from 'he';\nimport debugLib from 'debug';\n\nconst debug = debugLib( 'metalsmith-prism' );\n\n// Import languages from Prism's default export\nconst { languages } = Prism;\n\n/**\n * Check if a file is HTML based on its extension\n * @param {string} filePath - Path to the file\n * @returns {boolean} - True if the file has an HTML extension\n */\nconst isHTMLFile = ( filePath ) => {\n const extension = extname( filePath ).toLowerCase();\n return [ '.html', '.htm' ].includes( extension );\n};\n\n/**\n * @typedef Options\n * @property {boolean} [decode=false] - Whether to decode HTML entities\n * @property {boolean} [lineNumbers=false] - Whether to add line numbers\n * @property {string[]} [preLoad=[]] - Languages to preload\n */\n\n/**\n * Metalsmith plugin to highlight code syntax with PrismJS\n *\n * This plugin finds all code blocks in HTML files that have language-* classes\n * and applies Prism.js syntax highlighting to them. It can also add line numbers\n * and handle HTML entity decoding.\n *\n * @param {Options} [options] - Configuration options\n * @param {boolean} [options.decode=false] - Whether to decode HTML entities in code blocks\n * @param {boolean} [options.lineNumbers=false] - Whether to add line numbers to code blocks\n * @param {string[]} [options.preLoad=[]] - Languages to preload before processing\n * @returns {import('metalsmith').Plugin} - A metalsmith plugin function\n * @example\n * // Basic usage\n * metalsmith.use(prism());\n *\n * // With options\n * metalsmith.use(prism({\n * decode: true,\n * lineNumbers: true,\n * preLoad: ['java', 'scala']\n * }));\n */\nconst metalsmithPrism = ( options = {} ) => {\n // Create a new options object with defaults\n const opts = {\n decode: false,\n lineNumbers: false,\n preLoad: [],\n ...options\n };\n\n // Track loaded languages to avoid duplicate loading\n const loadedLanguages = new Set();\n\n // Always load PHP by default\n debug( 'Loading PHP by default' );\n try {\n loadLanguages( [ 'php' ] );\n loadedLanguages.add( 'php' );\n } catch ( e ) {\n debug( 'Failed to load PHP:', e );\n }\n\n if ( opts.preLoad && opts.preLoad.length ) {\n debug( 'Preloading languages:', opts.preLoad );\n opts.preLoad.forEach( ( language ) => {\n if ( !loadedLanguages.has( language ) ) {\n try {\n loadLanguages( [ language ] );\n loadedLanguages.add( language );\n debug( `Successfully preloaded language: ${ language }` );\n } catch ( e ) {\n console.warn( `Failed to preload prism syntax: ${ language }!`, e );\n debug( `Error preloading language ${ language }:`, e );\n }\n } else {\n debug( `Language ${ language } already loaded, skipping` );\n }\n } );\n }\n\n /**\n * Require optional language package\n * @param {string} language\n * @param {Set} loadedLanguages\n */\n const requireLanguage = ( language, loadedLanguages ) => {\n if ( loadedLanguages.has( language ) || languages[ language ] ) {\n debug( `Language ${ language } already available, skipping load` );\n return;\n }\n\n debug( `Loading language on-demand: ${ language }` );\n try {\n loadLanguages( [ language ] );\n loadedLanguages.add( language );\n debug( `Successfully loaded language: ${ language }` );\n } catch ( e ) {\n console.warn( `Failed to load prism syntax: ${ language }!`, e );\n debug( `Error loading language ${ language }:`, e );\n }\n };\n\n // Set up line numbers functionality\n const NEW_LINE_EXP = /\\n(?!$)/g;\n let lineNumbersWrapper;\n\n // Only set up the hook if line numbers are requested\n if ( opts.lineNumbers ) {\n debug( 'Setting up line numbers hook' );\n Prism.hooks.add( 'after-tokenize', ( env ) => {\n const match = env.code.match( NEW_LINE_EXP );\n const linesNum = match ? match.length + 1 : 1;\n debug( `Counted ${ linesNum } lines for line numbers` );\n const lines = new Array( linesNum + 1 ).join( '<span></span>' );\n lineNumbersWrapper = `<span aria-hidden=\"true\" class=\"line-numbers-rows\">${ lines }</span>`;\n } );\n }\n\n return ( files, metalsmith, done ) => {\n debug( 'Starting metalsmith-prism plugin' );\n debug( 'Options:', opts );\n\n // Call done asynchronously to avoid blocking\n setImmediate( done );\n\n try {\n Object.keys( files ).forEach( ( file ) => {\n if ( !isHTMLFile( file ) ) {\n return;\n }\n\n debug( `Processing HTML file: ${ file }` );\n const contents = files[ file ].contents.toString();\n const $ = load( contents, { decodeEntities: false } );\n let highlighted = false;\n const code = $( 'code' );\n\n if ( !code.length ) {\n debug( `No code blocks found in ${ file }` );\n return;\n }\n\n debug( `Found ${ code.length } code blocks in ${ file }` );\n\n code.each( function() {\n const $this = $( this );\n\n const className = $this.attr( 'class' ) || '';\n const targets = className.split( 'language-' );\n let addLineNumbers = false;\n\n if ( targets.length > 1 ) {\n const $pre = $this.parent( 'pre' );\n\n if ( $pre ) {\n // Copy className to <pre> container\n $pre.addClass( className );\n\n if ( opts.lineNumbers ) {\n $pre.addClass( 'line-numbers' );\n addLineNumbers = true;\n debug( 'Adding line numbers' );\n }\n }\n\n highlighted = true;\n let language = targets[ 1 ];\n debug( `Detected language: ${ language }` );\n requireLanguage( language, loadedLanguages );\n\n if ( !languages[ language ] ) {\n debug( `Language ${ language } not available, falling back to markup` );\n language = 'markup';\n }\n\n const html = language === 'markup' && !opts.decode ? $this.html() : he.decode( $this.html() );\n debug( `HTML decoding ${ opts.decode ? 'applied' : 'not applied' } for language ${ language }` );\n\n debug( `Highlighting code with language: ${ language }` );\n const highlightedCode = Prism.highlight( html, languages[ language ] );\n $this.html( addLineNumbers ? highlightedCode + lineNumbersWrapper : highlightedCode );\n }\n } );\n\n if ( highlighted ) {\n debug( `Updating contents of ${ file } with highlighted code` );\n files[ file ].contents = Buffer.from( $.html() );\n } else {\n debug( `No code was highlighted in ${ file }` );\n }\n } );\n\n debug( 'Completed metalsmith-prism plugin' );\n } catch ( error ) {\n debug( 'Error in metalsmith-prism plugin:', error );\n // We can't call done(error) here because done has already been called\n console.error( 'Error processing files:', error );\n }\n };\n};\n\n// ESM export\nexport default metalsmithPrism;\n"],"names":["debug","debugLib","languages","Prism","isHTMLFile","filePath","extension","extname","toLowerCase","includes","metalsmithPrism","options","opts","decode","lineNumbers","preLoad","loadedLanguages","Set","loadLanguages","add","e","length","forEach","language","has","console","warn","requireLanguage","NEW_LINE_EXP","lineNumbersWrapper","hooks","env","match","code","linesNum","lines","Array","join","files","metalsmith","done","setImmediate","Object","keys","file","contents","toString","$","load","decodeEntities","highlighted","each","$this","className","attr","targets","split","addLineNumbers","$pre","parent","addClass","html","he","highlightedCode","highlight","Buffer","from","error"],"mappings":"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"}
|
package/lib/index.modern.js
CHANGED
|
@@ -31,7 +31,7 @@ const isHTMLFile = filePath => {
|
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
33
|
* Metalsmith plugin to highlight code syntax with PrismJS
|
|
34
|
-
*
|
|
34
|
+
*
|
|
35
35
|
* This plugin finds all code blocks in HTML files that have language-* classes
|
|
36
36
|
* and applies Prism.js syntax highlighting to them. It can also add line numbers
|
|
37
37
|
* and handle HTML entity decoding.
|
|
@@ -44,7 +44,7 @@ const isHTMLFile = filePath => {
|
|
|
44
44
|
* @example
|
|
45
45
|
* // Basic usage
|
|
46
46
|
* metalsmith.use(prism());
|
|
47
|
-
*
|
|
47
|
+
*
|
|
48
48
|
* // With options
|
|
49
49
|
* metalsmith.use(prism({
|
|
50
50
|
* decode: true,
|
|
@@ -177,5 +177,10 @@ function metalsmithPrism(options = {}) {
|
|
|
177
177
|
};
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
+
// CommonJS export compatibility
|
|
181
|
+
if (typeof module !== 'undefined') {
|
|
182
|
+
module.exports = metalsmithPrism;
|
|
183
|
+
}
|
|
184
|
+
|
|
180
185
|
export { metalsmithPrism as default };
|
|
181
186
|
//# sourceMappingURL=index.modern.js.map
|
package/lib/index.modern.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.modern.js","sources":["../src/index.js"],"sourcesContent":["import { load } from 'cheerio';\nimport { extname } from 'path';\nimport Prism from 'prismjs';\nimport loadLanguages from 'prismjs/components/index.js';\nimport he from 'he';\nimport debugLib from 'debug';\n\nconst debug = debugLib('metalsmith-prism');\n\n// Import languages from Prism's default export\nconst { languages } = Prism;\n\n/**\n * Check if a file is HTML based on its extension\n * @param {string} filePath - Path to the file\n * @returns {boolean} - True if the file has an HTML extension\n */\nconst isHTMLFile = (filePath) => {\n const extension = extname(filePath).toLowerCase();\n return extension === '.html' || extension === '.htm';\n};\n\n/**\n * @typedef Options\n * @property {boolean} [decode=false] - Whether to decode HTML entities\n * @property {boolean} [lineNumbers=false] - Whether to add line numbers\n * @property {string[]} [preLoad=[]] - Languages to preload\n */\n\n/**\n * Metalsmith plugin to highlight code syntax with PrismJS\n * \n * This plugin finds all code blocks in HTML files that have language-* classes\n * and applies Prism.js syntax highlighting to them. It can also add line numbers\n * and handle HTML entity decoding.\n *\n * @param {Options} [options] - Configuration options\n * @param {boolean} [options.decode=false] - Whether to decode HTML entities in code blocks\n * @param {boolean} [options.lineNumbers=false] - Whether to add line numbers to code blocks\n * @param {string[]} [options.preLoad=[]] - Languages to preload before processing\n * @returns {import('metalsmith').Plugin} - A metalsmith plugin function\n * @example\n * // Basic usage\n * metalsmith.use(prism());\n * \n * // With options\n * metalsmith.use(prism({\n * decode: true,\n * lineNumbers: true,\n * preLoad: ['java', 'scala']\n * }));\n */\nfunction metalsmithPrism(options = {}) {\n // Track loaded languages to avoid duplicate loading\n const loadedLanguages = new Set();\n \n // Always load PHP by default\n debug('Loading PHP by default');\n try {\n loadLanguages(['php']);\n loadedLanguages.add('php');\n } catch (e) {\n debug('Failed to load PHP:', e);\n }\n \n if (options.preLoad) {\n debug('Preloading languages:', options.preLoad);\n options.preLoad.forEach((language) => {\n if (!loadedLanguages.has(language)) {\n try {\n loadLanguages([language]);\n loadedLanguages.add(language);\n debug(`Successfully preloaded language: ${language}`);\n } catch (e) {\n console.warn(`Failed to preload prism syntax: ${language}!`, e);\n debug(`Error preloading language ${language}:`, e);\n }\n } else {\n debug(`Language ${language} already loaded, skipping`);\n }\n });\n }\n\n /**\n * Require optional language package\n * @param {string} language\n */\n function requireLanguage(language) {\n if (!loadedLanguages.has(language) && !languages[language]) {\n debug(`Loading language on-demand: ${language}`);\n try {\n loadLanguages([language]);\n loadedLanguages.add(language);\n debug(`Successfully loaded language: ${language}`);\n } catch (e) {\n console.warn(`Failed to load prism syntax: ${language}!`, e);\n debug(`Error loading language ${language}:`, e);\n }\n }\n }\n\n // Set up line numbers functionality\n const NEW_LINE_EXP = /\\n(?!$)/g;\n let lineNumbersWrapper;\n\n // Only set up the hook if line numbers are requested\n if (options.lineNumbers) {\n debug('Setting up line numbers hook');\n Prism.hooks.add('after-tokenize', (env) => {\n const match = env.code.match(NEW_LINE_EXP);\n const linesNum = match ? match.length + 1 : 1;\n debug(`Counted ${linesNum} lines for line numbers`);\n const lines = new Array(linesNum + 1).join('<span></span>');\n lineNumbersWrapper = `<span aria-hidden=\"true\" class=\"line-numbers-rows\">${lines}</span>`;\n });\n }\n\n return function (files, metalsmith, done) {\n debug('Starting metalsmith-prism plugin');\n debug('Options:', options);\n \n setImmediate(done);\n\n Object.keys(files).forEach((file) => {\n if (!isHTMLFile(file)) {\n return;\n }\n\n debug(`Processing HTML file: ${file}`);\n const contents = files[file].contents.toString();\n const $ = load(contents, { decodeEntities: false });\n let highlighted = false;\n const code = $('code');\n\n if (!code.length) {\n debug(`No code blocks found in ${file}`);\n return;\n }\n \n debug(`Found ${code.length} code blocks in ${file}`);\n\n code.each(function () {\n const $this = $(this);\n\n const className = $this.attr('class') || '';\n const targets = className.split('language-');\n let addLineNumbers = false;\n\n if (targets.length > 1) {\n const $pre = $this.parent('pre');\n\n if ($pre) {\n // Copy className to <pre> container\n $pre.addClass(className);\n\n if (options.lineNumbers) {\n $pre.addClass('line-numbers');\n addLineNumbers = true;\n debug('Adding line numbers');\n }\n }\n\n highlighted = true;\n let language = targets[1];\n debug(`Detected language: ${language}`);\n requireLanguage(language);\n\n if (!languages[language]) {\n debug(`Language ${language} not available, falling back to markup`);\n language = 'markup';\n }\n\n const html = language === 'markup' && !options.decode ? $this.html() : he.decode($this.html());\n debug(`HTML decoding ${options.decode ? 'applied' : 'not applied'} for language ${language}`);\n\n debug(`Highlighting code with language: ${language}`);\n const highlightedCode = Prism.highlight(html, languages[language]);\n $this.html(addLineNumbers ? highlightedCode + lineNumbersWrapper : highlightedCode);\n }\n });\n\n if (highlighted) {\n debug(`Updating contents of ${file} with highlighted code`);\n files[file].contents = Buffer.from($.html());\n } else {\n debug(`No code was highlighted in ${file}`);\n }\n });\n \n debug('Completed metalsmith-prism plugin');\n };\n}\n\nexport { metalsmithPrism as default };"],"names":["debug","debugLib","languages","Prism","isHTMLFile","filePath","extension","extname","toLowerCase","metalsmithPrism","options","loadedLanguages","Set","loadLanguages","add","e","preLoad","forEach","language","has","console","warn","requireLanguage","NEW_LINE_EXP","lineNumbersWrapper","lineNumbers","hooks","env","match","code","linesNum","length","lines","Array","join","files","metalsmith","done","setImmediate","Object","keys","file","contents","toString","$","load","decodeEntities","highlighted","each","$this","className","attr","targets","split","addLineNumbers","$pre","parent","addClass","html","decode","he","highlightedCode","highlight","Buffer","from"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.modern.js","sources":["../src/index.js"],"sourcesContent":["import { load } from 'cheerio';\nimport { extname } from 'path';\nimport Prism from 'prismjs';\nimport loadLanguages from 'prismjs/components/index.js';\nimport he from 'he';\nimport debugLib from 'debug';\n\nconst debug = debugLib('metalsmith-prism');\n\n// Import languages from Prism's default export\nconst { languages } = Prism;\n\n/**\n * Check if a file is HTML based on its extension\n * @param {string} filePath - Path to the file\n * @returns {boolean} - True if the file has an HTML extension\n */\nconst isHTMLFile = (filePath) => {\n const extension = extname(filePath).toLowerCase();\n return extension === '.html' || extension === '.htm';\n};\n\n/**\n * @typedef Options\n * @property {boolean} [decode=false] - Whether to decode HTML entities\n * @property {boolean} [lineNumbers=false] - Whether to add line numbers\n * @property {string[]} [preLoad=[]] - Languages to preload\n */\n\n/**\n * Metalsmith plugin to highlight code syntax with PrismJS\n *\n * This plugin finds all code blocks in HTML files that have language-* classes\n * and applies Prism.js syntax highlighting to them. It can also add line numbers\n * and handle HTML entity decoding.\n *\n * @param {Options} [options] - Configuration options\n * @param {boolean} [options.decode=false] - Whether to decode HTML entities in code blocks\n * @param {boolean} [options.lineNumbers=false] - Whether to add line numbers to code blocks\n * @param {string[]} [options.preLoad=[]] - Languages to preload before processing\n * @returns {import('metalsmith').Plugin} - A metalsmith plugin function\n * @example\n * // Basic usage\n * metalsmith.use(prism());\n *\n * // With options\n * metalsmith.use(prism({\n * decode: true,\n * lineNumbers: true,\n * preLoad: ['java', 'scala']\n * }));\n */\nfunction metalsmithPrism(options = {}) {\n // Track loaded languages to avoid duplicate loading\n const loadedLanguages = new Set();\n\n // Always load PHP by default\n debug('Loading PHP by default');\n try {\n loadLanguages(['php']);\n loadedLanguages.add('php');\n } catch (e) {\n debug('Failed to load PHP:', e);\n }\n\n if (options.preLoad) {\n debug('Preloading languages:', options.preLoad);\n options.preLoad.forEach((language) => {\n if (!loadedLanguages.has(language)) {\n try {\n loadLanguages([language]);\n loadedLanguages.add(language);\n debug(`Successfully preloaded language: ${language}`);\n } catch (e) {\n console.warn(`Failed to preload prism syntax: ${language}!`, e);\n debug(`Error preloading language ${language}:`, e);\n }\n } else {\n debug(`Language ${language} already loaded, skipping`);\n }\n });\n }\n\n /**\n * Require optional language package\n * @param {string} language\n */\n function requireLanguage(language) {\n if (!loadedLanguages.has(language) && !languages[language]) {\n debug(`Loading language on-demand: ${language}`);\n try {\n loadLanguages([language]);\n loadedLanguages.add(language);\n debug(`Successfully loaded language: ${language}`);\n } catch (e) {\n console.warn(`Failed to load prism syntax: ${language}!`, e);\n debug(`Error loading language ${language}:`, e);\n }\n }\n }\n\n // Set up line numbers functionality\n const NEW_LINE_EXP = /\\n(?!$)/g;\n let lineNumbersWrapper;\n\n // Only set up the hook if line numbers are requested\n if (options.lineNumbers) {\n debug('Setting up line numbers hook');\n Prism.hooks.add('after-tokenize', (env) => {\n const match = env.code.match(NEW_LINE_EXP);\n const linesNum = match ? match.length + 1 : 1;\n debug(`Counted ${linesNum} lines for line numbers`);\n const lines = new Array(linesNum + 1).join('<span></span>');\n lineNumbersWrapper = `<span aria-hidden=\"true\" class=\"line-numbers-rows\">${lines}</span>`;\n });\n }\n\n return function (files, metalsmith, done) {\n debug('Starting metalsmith-prism plugin');\n debug('Options:', options);\n\n setImmediate(done);\n\n Object.keys(files).forEach((file) => {\n if (!isHTMLFile(file)) {\n return;\n }\n\n debug(`Processing HTML file: ${file}`);\n const contents = files[file].contents.toString();\n const $ = load(contents, { decodeEntities: false });\n let highlighted = false;\n const code = $('code');\n\n if (!code.length) {\n debug(`No code blocks found in ${file}`);\n return;\n }\n\n debug(`Found ${code.length} code blocks in ${file}`);\n\n code.each(function () {\n const $this = $(this);\n\n const className = $this.attr('class') || '';\n const targets = className.split('language-');\n let addLineNumbers = false;\n\n if (targets.length > 1) {\n const $pre = $this.parent('pre');\n\n if ($pre) {\n // Copy className to <pre> container\n $pre.addClass(className);\n\n if (options.lineNumbers) {\n $pre.addClass('line-numbers');\n addLineNumbers = true;\n debug('Adding line numbers');\n }\n }\n\n highlighted = true;\n let language = targets[1];\n debug(`Detected language: ${language}`);\n requireLanguage(language);\n\n if (!languages[language]) {\n debug(`Language ${language} not available, falling back to markup`);\n language = 'markup';\n }\n\n const html = language === 'markup' && !options.decode ? $this.html() : he.decode($this.html());\n debug(`HTML decoding ${options.decode ? 'applied' : 'not applied'} for language ${language}`);\n\n debug(`Highlighting code with language: ${language}`);\n const highlightedCode = Prism.highlight(html, languages[language]);\n $this.html(addLineNumbers ? highlightedCode + lineNumbersWrapper : highlightedCode);\n }\n });\n\n if (highlighted) {\n debug(`Updating contents of ${file} with highlighted code`);\n files[file].contents = Buffer.from($.html());\n } else {\n debug(`No code was highlighted in ${file}`);\n }\n });\n\n debug('Completed metalsmith-prism plugin');\n };\n}\n\n// ESM export\nexport { metalsmithPrism as default };\n\n// CommonJS export compatibility\nif (typeof module !== 'undefined') {\n module.exports = metalsmithPrism;\n}\n"],"names":["debug","debugLib","languages","Prism","isHTMLFile","filePath","extension","extname","toLowerCase","metalsmithPrism","options","loadedLanguages","Set","loadLanguages","add","e","preLoad","forEach","language","has","console","warn","requireLanguage","NEW_LINE_EXP","lineNumbersWrapper","lineNumbers","hooks","env","match","code","linesNum","length","lines","Array","join","files","metalsmith","done","setImmediate","Object","keys","file","contents","toString","$","load","decodeEntities","highlighted","each","$this","className","attr","targets","split","addLineNumbers","$pre","parent","addClass","html","decode","he","highlightedCode","highlight","Buffer","from","module","exports"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,30 +1,37 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "metalsmith-prism",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.4",
|
|
4
4
|
"description": "Syntax highlighting for Metalsmith HTML templates using Prism.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.cjs",
|
|
7
|
-
"module": "./lib/index.
|
|
7
|
+
"module": "./lib/index.js",
|
|
8
8
|
"exports": {
|
|
9
|
-
"import": "./lib/index.
|
|
10
|
-
"require": "./lib/index.cjs"
|
|
9
|
+
"import": "./lib/index.js",
|
|
10
|
+
"require": "./lib/index.cjs",
|
|
11
|
+
"default": "./lib/index.js"
|
|
11
12
|
},
|
|
12
13
|
"engines": {
|
|
13
14
|
"node": ">= 18.0.0"
|
|
14
15
|
},
|
|
15
16
|
"scripts": {
|
|
16
|
-
"coverage": "npm test && c8 report --reporter=text-lcov > ./coverage.info",
|
|
17
17
|
"build": "microbundle --entry src/index.js --output lib/index.js --target node -f esm,cjs --strict --generateTypes=false",
|
|
18
|
-
"
|
|
19
|
-
"
|
|
18
|
+
"changelog": "auto-changelog -u --commit-limit false --ignore-commit-pattern '^((dev|chore|ci):|Release)'",
|
|
19
|
+
"coverage": "npm test && c8 report --reporter=text-lcov > ./coverage.info",
|
|
20
|
+
"format": "prettier --write \"**/*.{yml,md,json}\"",
|
|
20
21
|
"format:check": "prettier --list-different \"**/*.{yml,md,js,json}\"",
|
|
21
22
|
"lint": "eslint --fix .",
|
|
22
23
|
"lint:check": "eslint --fix-dry-run .",
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
24
|
+
"format-and-lint": "npm run format && npm run lint",
|
|
25
|
+
"prepublishOnly": "npm run build",
|
|
26
|
+
"update-coverage": "node scripts/update-coverage-badge.js",
|
|
27
|
+
"prerelease": "npm run update-coverage && git add README.md && git commit -m \"Update coverage badge in README\" || true",
|
|
28
|
+
"release": "npm run build && GITHUB_TOKEN=$(grep GITHUB_TOKEN .env | cut -d '=' -f2) ./node_modules/.bin/release-it . ",
|
|
29
|
+
"release:check": "npm run lint:check && npm run build && GITHUB_TOKEN=$(grep GITHUB_TOKEN .env | cut -d '=' -f2) ./node_modules/.bin/release-it . --dry-run",
|
|
30
|
+
"test": "c8 --include=src/**/*.js mocha 'test/index.js' 'test/cjs.test.cjs' 'test/comprehensive.mjs' 'test/additional.mjs' -t 15000",
|
|
31
|
+
"test:esm": "c8 --include=src/**/*.js mocha 'test/index.js' 'test/comprehensive.mjs' 'test/additional.mjs' -t 15000",
|
|
32
|
+
"test:cjs": "c8 --include=src/**/*.js mocha test/cjs.test.cjs -t 15000",
|
|
33
|
+
"test:e2e": "serve -l 3000 test/fixtures",
|
|
34
|
+
"depcheck": "depcheck"
|
|
28
35
|
},
|
|
29
36
|
"repository": {
|
|
30
37
|
"type": "git",
|
|
@@ -50,7 +57,7 @@
|
|
|
50
57
|
"dependencies": {
|
|
51
58
|
"cheerio": "^1.0.0",
|
|
52
59
|
"debug": "^4.4.0",
|
|
53
|
-
"dotenv": "^16.
|
|
60
|
+
"dotenv": "^16.5.0",
|
|
54
61
|
"he": "^1.2.0",
|
|
55
62
|
"metalsmith": "^2.6.3",
|
|
56
63
|
"prismjs": "^1.30.0"
|
|
@@ -59,13 +66,13 @@
|
|
|
59
66
|
"auto-changelog": "^2.5.0",
|
|
60
67
|
"c8": "^10.1.3",
|
|
61
68
|
"chai": "^5.2.0",
|
|
62
|
-
"eslint": "^9.
|
|
63
|
-
"eslint-config-prettier": "^10.1.
|
|
64
|
-
"eslint-plugin-prettier": "^5.2.
|
|
69
|
+
"eslint": "^9.25.1",
|
|
70
|
+
"eslint-config-prettier": "^10.1.2",
|
|
71
|
+
"eslint-plugin-prettier": "^5.2.6",
|
|
65
72
|
"globals": "^16.0.0",
|
|
66
73
|
"microbundle": "^0.15.1",
|
|
67
74
|
"mocha": "^11.1.0",
|
|
68
75
|
"prettier": "^3.5.3",
|
|
69
|
-
"release-it": "^
|
|
76
|
+
"release-it": "^19.0.1"
|
|
70
77
|
}
|
|
71
78
|
}
|
package/src/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import loadLanguages from 'prismjs/components/index.js';
|
|
|
5
5
|
import he from 'he';
|
|
6
6
|
import debugLib from 'debug';
|
|
7
7
|
|
|
8
|
-
const debug = debugLib('metalsmith-prism');
|
|
8
|
+
const debug = debugLib( 'metalsmith-prism' );
|
|
9
9
|
|
|
10
10
|
// Import languages from Prism's default export
|
|
11
11
|
const { languages } = Prism;
|
|
@@ -15,9 +15,9 @@ const { languages } = Prism;
|
|
|
15
15
|
* @param {string} filePath - Path to the file
|
|
16
16
|
* @returns {boolean} - True if the file has an HTML extension
|
|
17
17
|
*/
|
|
18
|
-
const isHTMLFile = (filePath) => {
|
|
19
|
-
const extension = extname(filePath).toLowerCase();
|
|
20
|
-
return
|
|
18
|
+
const isHTMLFile = ( filePath ) => {
|
|
19
|
+
const extension = extname( filePath ).toLowerCase();
|
|
20
|
+
return [ '.html', '.htm' ].includes( extension );
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
/**
|
|
@@ -29,7 +29,7 @@ const isHTMLFile = (filePath) => {
|
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* Metalsmith plugin to highlight code syntax with PrismJS
|
|
32
|
-
*
|
|
32
|
+
*
|
|
33
33
|
* This plugin finds all code blocks in HTML files that have language-* classes
|
|
34
34
|
* and applies Prism.js syntax highlighting to them. It can also add line numbers
|
|
35
35
|
* and handle HTML entity decoding.
|
|
@@ -42,7 +42,7 @@ const isHTMLFile = (filePath) => {
|
|
|
42
42
|
* @example
|
|
43
43
|
* // Basic usage
|
|
44
44
|
* metalsmith.use(prism());
|
|
45
|
-
*
|
|
45
|
+
*
|
|
46
46
|
* // With options
|
|
47
47
|
* metalsmith.use(prism({
|
|
48
48
|
* decode: true,
|
|
@@ -50,145 +50,165 @@ const isHTMLFile = (filePath) => {
|
|
|
50
50
|
* preLoad: ['java', 'scala']
|
|
51
51
|
* }));
|
|
52
52
|
*/
|
|
53
|
-
|
|
53
|
+
const metalsmithPrism = ( options = {} ) => {
|
|
54
|
+
// Create a new options object with defaults
|
|
55
|
+
const opts = {
|
|
56
|
+
decode: false,
|
|
57
|
+
lineNumbers: false,
|
|
58
|
+
preLoad: [],
|
|
59
|
+
...options
|
|
60
|
+
};
|
|
61
|
+
|
|
54
62
|
// Track loaded languages to avoid duplicate loading
|
|
55
63
|
const loadedLanguages = new Set();
|
|
56
|
-
|
|
64
|
+
|
|
57
65
|
// Always load PHP by default
|
|
58
|
-
debug('Loading PHP by default');
|
|
66
|
+
debug( 'Loading PHP by default' );
|
|
59
67
|
try {
|
|
60
|
-
loadLanguages(['php']);
|
|
61
|
-
loadedLanguages.add('php');
|
|
62
|
-
} catch (e) {
|
|
63
|
-
debug('Failed to load PHP:', e);
|
|
68
|
+
loadLanguages( [ 'php' ] );
|
|
69
|
+
loadedLanguages.add( 'php' );
|
|
70
|
+
} catch ( e ) {
|
|
71
|
+
debug( 'Failed to load PHP:', e );
|
|
64
72
|
}
|
|
65
|
-
|
|
66
|
-
if (
|
|
67
|
-
debug('Preloading languages:',
|
|
68
|
-
|
|
69
|
-
if (!loadedLanguages.has(language)) {
|
|
73
|
+
|
|
74
|
+
if ( opts.preLoad && opts.preLoad.length ) {
|
|
75
|
+
debug( 'Preloading languages:', opts.preLoad );
|
|
76
|
+
opts.preLoad.forEach( ( language ) => {
|
|
77
|
+
if ( !loadedLanguages.has( language ) ) {
|
|
70
78
|
try {
|
|
71
|
-
loadLanguages([language]);
|
|
72
|
-
loadedLanguages.add(language);
|
|
73
|
-
debug(`Successfully preloaded language: ${language}`);
|
|
74
|
-
} catch (e) {
|
|
75
|
-
console.warn(`Failed to preload prism syntax: ${language}!`, e);
|
|
76
|
-
debug(`Error preloading language ${language}:`, e);
|
|
79
|
+
loadLanguages( [ language ] );
|
|
80
|
+
loadedLanguages.add( language );
|
|
81
|
+
debug( `Successfully preloaded language: ${ language }` );
|
|
82
|
+
} catch ( e ) {
|
|
83
|
+
console.warn( `Failed to preload prism syntax: ${ language }!`, e );
|
|
84
|
+
debug( `Error preloading language ${ language }:`, e );
|
|
77
85
|
}
|
|
78
86
|
} else {
|
|
79
|
-
debug(`Language ${language} already loaded, skipping`);
|
|
87
|
+
debug( `Language ${ language } already loaded, skipping` );
|
|
80
88
|
}
|
|
81
|
-
});
|
|
89
|
+
} );
|
|
82
90
|
}
|
|
83
91
|
|
|
84
92
|
/**
|
|
85
93
|
* Require optional language package
|
|
86
94
|
* @param {string} language
|
|
95
|
+
* @param {Set} loadedLanguages
|
|
87
96
|
*/
|
|
88
|
-
|
|
89
|
-
if (
|
|
90
|
-
debug(`
|
|
91
|
-
|
|
92
|
-
loadLanguages([language]);
|
|
93
|
-
loadedLanguages.add(language);
|
|
94
|
-
debug(`Successfully loaded language: ${language}`);
|
|
95
|
-
} catch (e) {
|
|
96
|
-
console.warn(`Failed to load prism syntax: ${language}!`, e);
|
|
97
|
-
debug(`Error loading language ${language}:`, e);
|
|
98
|
-
}
|
|
97
|
+
const requireLanguage = ( language, loadedLanguages ) => {
|
|
98
|
+
if ( loadedLanguages.has( language ) || languages[ language ] ) {
|
|
99
|
+
debug( `Language ${ language } already available, skipping load` );
|
|
100
|
+
return;
|
|
99
101
|
}
|
|
100
|
-
|
|
102
|
+
|
|
103
|
+
debug( `Loading language on-demand: ${ language }` );
|
|
104
|
+
try {
|
|
105
|
+
loadLanguages( [ language ] );
|
|
106
|
+
loadedLanguages.add( language );
|
|
107
|
+
debug( `Successfully loaded language: ${ language }` );
|
|
108
|
+
} catch ( e ) {
|
|
109
|
+
console.warn( `Failed to load prism syntax: ${ language }!`, e );
|
|
110
|
+
debug( `Error loading language ${ language }:`, e );
|
|
111
|
+
}
|
|
112
|
+
};
|
|
101
113
|
|
|
102
114
|
// Set up line numbers functionality
|
|
103
115
|
const NEW_LINE_EXP = /\n(?!$)/g;
|
|
104
116
|
let lineNumbersWrapper;
|
|
105
117
|
|
|
106
118
|
// Only set up the hook if line numbers are requested
|
|
107
|
-
if (
|
|
108
|
-
debug('Setting up line numbers hook');
|
|
109
|
-
Prism.hooks.add('after-tokenize', (env) => {
|
|
110
|
-
const match = env.code.match(NEW_LINE_EXP);
|
|
119
|
+
if ( opts.lineNumbers ) {
|
|
120
|
+
debug( 'Setting up line numbers hook' );
|
|
121
|
+
Prism.hooks.add( 'after-tokenize', ( env ) => {
|
|
122
|
+
const match = env.code.match( NEW_LINE_EXP );
|
|
111
123
|
const linesNum = match ? match.length + 1 : 1;
|
|
112
|
-
debug(`Counted ${linesNum} lines for line numbers`);
|
|
113
|
-
const lines = new Array(linesNum + 1).join('<span></span>');
|
|
114
|
-
lineNumbersWrapper = `<span aria-hidden="true" class="line-numbers-rows">${lines}</span>`;
|
|
115
|
-
});
|
|
124
|
+
debug( `Counted ${ linesNum } lines for line numbers` );
|
|
125
|
+
const lines = new Array( linesNum + 1 ).join( '<span></span>' );
|
|
126
|
+
lineNumbersWrapper = `<span aria-hidden="true" class="line-numbers-rows">${ lines }</span>`;
|
|
127
|
+
} );
|
|
116
128
|
}
|
|
117
129
|
|
|
118
|
-
return
|
|
119
|
-
debug('Starting metalsmith-prism plugin');
|
|
120
|
-
debug('Options:',
|
|
121
|
-
|
|
122
|
-
setImmediate(done);
|
|
130
|
+
return ( files, metalsmith, done ) => {
|
|
131
|
+
debug( 'Starting metalsmith-prism plugin' );
|
|
132
|
+
debug( 'Options:', opts );
|
|
123
133
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
134
|
+
// Call done asynchronously to avoid blocking
|
|
135
|
+
setImmediate( done );
|
|
136
|
+
|
|
137
|
+
try {
|
|
138
|
+
Object.keys( files ).forEach( ( file ) => {
|
|
139
|
+
if ( !isHTMLFile( file ) ) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
128
142
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
143
|
+
debug( `Processing HTML file: ${ file }` );
|
|
144
|
+
const contents = files[ file ].contents.toString();
|
|
145
|
+
const $ = load( contents, { decodeEntities: false } );
|
|
146
|
+
let highlighted = false;
|
|
147
|
+
const code = $( 'code' );
|
|
134
148
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
149
|
+
if ( !code.length ) {
|
|
150
|
+
debug( `No code blocks found in ${ file }` );
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
debug( `Found ${ code.length } code blocks in ${ file }` );
|
|
141
155
|
|
|
142
|
-
|
|
143
|
-
|
|
156
|
+
code.each( function() {
|
|
157
|
+
const $this = $( this );
|
|
144
158
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
159
|
+
const className = $this.attr( 'class' ) || '';
|
|
160
|
+
const targets = className.split( 'language-' );
|
|
161
|
+
let addLineNumbers = false;
|
|
148
162
|
|
|
149
|
-
|
|
150
|
-
|
|
163
|
+
if ( targets.length > 1 ) {
|
|
164
|
+
const $pre = $this.parent( 'pre' );
|
|
151
165
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
166
|
+
if ( $pre ) {
|
|
167
|
+
// Copy className to <pre> container
|
|
168
|
+
$pre.addClass( className );
|
|
155
169
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
170
|
+
if ( opts.lineNumbers ) {
|
|
171
|
+
$pre.addClass( 'line-numbers' );
|
|
172
|
+
addLineNumbers = true;
|
|
173
|
+
debug( 'Adding line numbers' );
|
|
174
|
+
}
|
|
160
175
|
}
|
|
161
|
-
}
|
|
162
176
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
177
|
+
highlighted = true;
|
|
178
|
+
let language = targets[ 1 ];
|
|
179
|
+
debug( `Detected language: ${ language }` );
|
|
180
|
+
requireLanguage( language, loadedLanguages );
|
|
167
181
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
182
|
+
if ( !languages[ language ] ) {
|
|
183
|
+
debug( `Language ${ language } not available, falling back to markup` );
|
|
184
|
+
language = 'markup';
|
|
185
|
+
}
|
|
172
186
|
|
|
173
|
-
|
|
174
|
-
|
|
187
|
+
const html = language === 'markup' && !opts.decode ? $this.html() : he.decode( $this.html() );
|
|
188
|
+
debug( `HTML decoding ${ opts.decode ? 'applied' : 'not applied' } for language ${ language }` );
|
|
175
189
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
190
|
+
debug( `Highlighting code with language: ${ language }` );
|
|
191
|
+
const highlightedCode = Prism.highlight( html, languages[ language ] );
|
|
192
|
+
$this.html( addLineNumbers ? highlightedCode + lineNumbersWrapper : highlightedCode );
|
|
193
|
+
}
|
|
194
|
+
} );
|
|
195
|
+
|
|
196
|
+
if ( highlighted ) {
|
|
197
|
+
debug( `Updating contents of ${ file } with highlighted code` );
|
|
198
|
+
files[ file ].contents = Buffer.from( $.html() );
|
|
199
|
+
} else {
|
|
200
|
+
debug( `No code was highlighted in ${ file }` );
|
|
179
201
|
}
|
|
180
|
-
});
|
|
202
|
+
} );
|
|
181
203
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
debug('Completed metalsmith-prism plugin');
|
|
204
|
+
debug( 'Completed metalsmith-prism plugin' );
|
|
205
|
+
} catch ( error ) {
|
|
206
|
+
debug( 'Error in metalsmith-prism plugin:', error );
|
|
207
|
+
// We can't call done(error) here because done has already been called
|
|
208
|
+
console.error( 'Error processing files:', error );
|
|
209
|
+
}
|
|
191
210
|
};
|
|
192
|
-
}
|
|
211
|
+
};
|
|
193
212
|
|
|
194
|
-
|
|
213
|
+
// ESM export
|
|
214
|
+
export default metalsmithPrism;
|