metalsmith-prism 5.0.2 → 5.0.5
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 +133 -22
- package/lib/index.cjs +128 -109
- package/lib/index.cjs.map +1 -1
- package/lib/index.js +201 -0
- package/lib/index.js.map +1 -0
- package/package.json +38 -26
- package/lib/index.modern.js +0 -181
- package/lib/index.modern.js.map +0 -1
- package/src/index.js +0 -194
package/README.md
CHANGED
|
@@ -1,32 +1,36 @@
|
|
|
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]
|
|
10
|
+
[](https://snyk.io/test/npm/metalsmith-prism)
|
|
9
11
|
|
|
10
12
|
## Dual Module Support (ESM and CommonJS)
|
|
11
13
|
|
|
12
|
-
This plugin supports both ESM and CommonJS environments:
|
|
14
|
+
This plugin supports both ESM and CommonJS environments with no configuration needed:
|
|
13
15
|
|
|
14
16
|
- ESM: `import prism from 'metalsmith-prism'`
|
|
15
17
|
- CommonJS: `const prism = require('metalsmith-prism')`
|
|
16
18
|
|
|
19
|
+
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.
|
|
20
|
+
|
|
17
21
|
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
22
|
|
|
23
|
+
- Supports both ESM and CommonJS environments
|
|
19
24
|
- Automatically handles language dependencies
|
|
20
25
|
- Supports HTML entity decoding
|
|
21
26
|
- Can add line numbers
|
|
22
27
|
- Works seamlessly with Markdown code blocks
|
|
23
|
-
- Supports all Prism.js
|
|
28
|
+
- Supports all Prism.js language
|
|
24
29
|
|
|
25
30
|
## Requirements
|
|
26
31
|
|
|
27
|
-
- Node `>= 18.
|
|
28
|
-
-
|
|
29
|
-
- Metalsmith `>= v2.6.x`
|
|
32
|
+
- Node `>= 18.0.0`
|
|
33
|
+
- Metalsmith `>= v2.6.0`
|
|
30
34
|
|
|
31
35
|
## Quick Start
|
|
32
36
|
|
|
@@ -42,7 +46,7 @@ metalsmith(__dirname).use(
|
|
|
42
46
|
prism({
|
|
43
47
|
decode: true, // Decode HTML entities
|
|
44
48
|
lineNumbers: true, // Show line numbers
|
|
45
|
-
preLoad: ['java']
|
|
49
|
+
preLoad: ['java'] // Pre-load language dependencies
|
|
46
50
|
})
|
|
47
51
|
);
|
|
48
52
|
```
|
|
@@ -82,6 +86,7 @@ The css files can be downloaded from the [Prism website](https://prismjs.com/dow
|
|
|
82
86
|
### Add `metalsmith-prism` plugin to metalsmith
|
|
83
87
|
|
|
84
88
|
**ESM:**
|
|
89
|
+
|
|
85
90
|
```js
|
|
86
91
|
import Metalsmith from 'metalsmith';
|
|
87
92
|
import prism from 'metalsmith-prism';
|
|
@@ -90,6 +95,7 @@ Metalsmith(__dirname).use(prism()).build();
|
|
|
90
95
|
```
|
|
91
96
|
|
|
92
97
|
**CommonJS:**
|
|
98
|
+
|
|
93
99
|
```js
|
|
94
100
|
const Metalsmith = require('metalsmith');
|
|
95
101
|
const prism = require('metalsmith-prism');
|
|
@@ -100,6 +106,7 @@ Metalsmith(__dirname).use(prism()).build();
|
|
|
100
106
|
### To use with Markdown code blocks rendered by [@metalsmith/markdown](https://github.com/metalsmith/markdown)
|
|
101
107
|
|
|
102
108
|
**ESM:**
|
|
109
|
+
|
|
103
110
|
```js
|
|
104
111
|
import Metalsmith from 'metalsmith';
|
|
105
112
|
import markdown from '@metalsmith/markdown';
|
|
@@ -109,6 +116,7 @@ Metalsmith(__dirname).use(markdown()).use(prism()).build();
|
|
|
109
116
|
```
|
|
110
117
|
|
|
111
118
|
**CommonJS:**
|
|
119
|
+
|
|
112
120
|
```js
|
|
113
121
|
const Metalsmith = require('metalsmith');
|
|
114
122
|
const markdown = require('@metalsmith/markdown');
|
|
@@ -132,7 +140,7 @@ Always decode the html entities when processing language of type `markup`
|
|
|
132
140
|
```js
|
|
133
141
|
Metalsmith(__dirname).use(
|
|
134
142
|
prism({
|
|
135
|
-
decode: true
|
|
143
|
+
decode: true
|
|
136
144
|
})
|
|
137
145
|
);
|
|
138
146
|
```
|
|
@@ -143,8 +151,8 @@ Adds the additional HTML markup so line numbers can be added via the line-number
|
|
|
143
151
|
|
|
144
152
|
```javascript
|
|
145
153
|
Metalsmith(__dirname).use(
|
|
146
|
-
|
|
147
|
-
lineNumbers: true
|
|
154
|
+
prism({
|
|
155
|
+
lineNumbers: true
|
|
148
156
|
})
|
|
149
157
|
);
|
|
150
158
|
```
|
|
@@ -158,25 +166,113 @@ Useful for loading syntax that extends other language components that are not au
|
|
|
158
166
|
```javascript
|
|
159
167
|
Metalsmith(__dirname).use(
|
|
160
168
|
prism({
|
|
161
|
-
preLoad: ['java', 'scala']
|
|
169
|
+
preLoad: ['java', 'scala']
|
|
162
170
|
})
|
|
163
171
|
);
|
|
164
172
|
```
|
|
165
173
|
|
|
166
|
-
##
|
|
174
|
+
## Examples
|
|
175
|
+
|
|
176
|
+
### Basic Usage
|
|
177
|
+
|
|
178
|
+
Transform a simple code block with JavaScript:
|
|
179
|
+
|
|
180
|
+
**Input HTML:**
|
|
181
|
+
|
|
182
|
+
```html
|
|
183
|
+
<pre><code class="language-javascript">
|
|
184
|
+
const greeting = 'Hello, World!';
|
|
185
|
+
console.log(greeting);
|
|
186
|
+
</code></pre>
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Output HTML (with syntax highlighting):**
|
|
190
|
+
|
|
191
|
+
```html
|
|
192
|
+
<pre class="language-javascript"><code class="language-javascript">
|
|
193
|
+
<span class="token keyword">const</span> greeting <span class="token operator">=</span> <span class="token string">'Hello, World!'</span><span class="token punctuation">;</span>
|
|
194
|
+
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>greeting<span class="token punctuation">)</span><span class="token punctuation">;</span>
|
|
195
|
+
</code></pre>
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### With Line Numbers
|
|
199
|
+
|
|
200
|
+
Enable line numbers for longer code examples:
|
|
201
|
+
|
|
202
|
+
```javascript
|
|
203
|
+
metalsmith(__dirname)
|
|
204
|
+
.use(
|
|
205
|
+
prism({
|
|
206
|
+
lineNumbers: true
|
|
207
|
+
})
|
|
208
|
+
)
|
|
209
|
+
.build();
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
This adds the `line-numbers` class and line number markup to your code blocks.
|
|
213
|
+
|
|
214
|
+
### Working with Markdown
|
|
167
215
|
|
|
168
|
-
|
|
216
|
+
When using with @metalsmith/markdown, code blocks in markdown files are automatically processed:
|
|
169
217
|
|
|
170
|
-
|
|
218
|
+
**Markdown file:**
|
|
171
219
|
|
|
220
|
+
````markdown
|
|
221
|
+
```python
|
|
222
|
+
def fibonacci(n):
|
|
223
|
+
if n <= 1:
|
|
224
|
+
return n
|
|
225
|
+
return fibonacci(n-1) + fibonacci(n-2)
|
|
172
226
|
```
|
|
173
|
-
|
|
227
|
+
````
|
|
228
|
+
|
|
229
|
+
**Build configuration:**
|
|
230
|
+
|
|
231
|
+
```javascript
|
|
232
|
+
metalsmith(__dirname)
|
|
233
|
+
.use(markdown())
|
|
234
|
+
.use(
|
|
235
|
+
prism({
|
|
236
|
+
preLoad: ['python'] // Ensure Python support is loaded
|
|
237
|
+
})
|
|
238
|
+
)
|
|
239
|
+
.build();
|
|
174
240
|
```
|
|
175
241
|
|
|
176
|
-
|
|
242
|
+
### Preloading Languages
|
|
177
243
|
|
|
244
|
+
For better performance with known languages, preload them:
|
|
245
|
+
|
|
246
|
+
```javascript
|
|
247
|
+
metalsmith(__dirname)
|
|
248
|
+
.use(
|
|
249
|
+
prism({
|
|
250
|
+
preLoad: ['python', 'ruby', 'go', 'rust']
|
|
251
|
+
})
|
|
252
|
+
)
|
|
253
|
+
.build();
|
|
178
254
|
```
|
|
179
|
-
|
|
255
|
+
|
|
256
|
+
### Handling Special Characters
|
|
257
|
+
|
|
258
|
+
For code with HTML entities, use the decode option:
|
|
259
|
+
|
|
260
|
+
```javascript
|
|
261
|
+
metalsmith(__dirname)
|
|
262
|
+
.use(
|
|
263
|
+
prism({
|
|
264
|
+
decode: true // Properly handle <, >, & etc.
|
|
265
|
+
})
|
|
266
|
+
)
|
|
267
|
+
.build();
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## Debug
|
|
271
|
+
|
|
272
|
+
To enable debug logs, set the DEBUG environment variable to metalsmith-prism\*:
|
|
273
|
+
|
|
274
|
+
```bash
|
|
275
|
+
metalsmith.env('DEBUG', 'metalsmith-prism*');
|
|
180
276
|
```
|
|
181
277
|
|
|
182
278
|
## CLI Usage
|
|
@@ -194,10 +290,25 @@ Add `metalsmith-prism` key to your `metalsmith.json` plugins key
|
|
|
194
290
|
}
|
|
195
291
|
```
|
|
196
292
|
|
|
293
|
+
## Test Coverage
|
|
294
|
+
|
|
295
|
+
This project maintains high statement and line coverage for the source code. Coverage is verified during the release process using the c8 coverage tool.
|
|
296
|
+
|
|
197
297
|
## Credits
|
|
198
298
|
|
|
199
|
-
[Robert McGuinness](https://github.com/robmcguinness) - for the initial implementation of the plugin.
|
|
299
|
+
- [Robert McGuinness](https://github.com/robmcguinness) - for the initial implementation of the plugin.
|
|
300
|
+
- [Werner Glinka](https://github.com/wernerglinka) - current maintainer.
|
|
200
301
|
|
|
201
302
|
## License
|
|
202
303
|
|
|
203
304
|
Code released under [the MIT license](https://github.com/wernerglinka/metalsmith-prism/blob/main/LICENSE).
|
|
305
|
+
|
|
306
|
+
[metalsmith-badge]: https://img.shields.io/badge/metalsmith-plugin-green.svg?longCache=true
|
|
307
|
+
[metalsmith-url]: https://metalsmith.io
|
|
308
|
+
[npm-badge]: https://img.shields.io/npm/v/metalsmith-prism.svg
|
|
309
|
+
[npm-url]: https://www.npmjs.com/package/metalsmith-prism
|
|
310
|
+
[license-badge]: https://img.shields.io/github/license/wernerglinka/metalsmith-prism
|
|
311
|
+
[license-url]: LICENSE
|
|
312
|
+
[coverage-badge]: https://img.shields.io/badge/test%20coverage-94%25-brightgreen
|
|
313
|
+
[coverage-url]: #test-coverage
|
|
314
|
+
[modules-badge]: https://img.shields.io/badge/modules-ESM%2FCJS-blue
|
package/lib/index.cjs
CHANGED
|
@@ -5,16 +5,12 @@ var path = require('path');
|
|
|
5
5
|
var Prism = require('prismjs');
|
|
6
6
|
var loadLanguages = require('prismjs/components/index.js');
|
|
7
7
|
var he = require('he');
|
|
8
|
-
var debugLib = require('debug');
|
|
9
8
|
|
|
10
9
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
11
10
|
|
|
12
11
|
var Prism__default = /*#__PURE__*/_interopDefaultLegacy(Prism);
|
|
13
12
|
var loadLanguages__default = /*#__PURE__*/_interopDefaultLegacy(loadLanguages);
|
|
14
13
|
var he__default = /*#__PURE__*/_interopDefaultLegacy(he);
|
|
15
|
-
var debugLib__default = /*#__PURE__*/_interopDefaultLegacy(debugLib);
|
|
16
|
-
|
|
17
|
-
const debug = debugLib__default["default"]('metalsmith-prism');
|
|
18
14
|
|
|
19
15
|
// Import languages from Prism's default export
|
|
20
16
|
const {
|
|
@@ -28,7 +24,7 @@ const {
|
|
|
28
24
|
*/
|
|
29
25
|
const isHTMLFile = filePath => {
|
|
30
26
|
const extension = path.extname(filePath).toLowerCase();
|
|
31
|
-
return
|
|
27
|
+
return ['.html', '.htm'].includes(extension);
|
|
32
28
|
};
|
|
33
29
|
|
|
34
30
|
/**
|
|
@@ -40,7 +36,7 @@ const isHTMLFile = filePath => {
|
|
|
40
36
|
|
|
41
37
|
/**
|
|
42
38
|
* Metalsmith plugin to highlight code syntax with PrismJS
|
|
43
|
-
*
|
|
39
|
+
*
|
|
44
40
|
* This plugin finds all code blocks in HTML files that have language-* classes
|
|
45
41
|
* and applies Prism.js syntax highlighting to them. It can also add line numbers
|
|
46
42
|
* and handle HTML entity decoding.
|
|
@@ -53,7 +49,7 @@ const isHTMLFile = filePath => {
|
|
|
53
49
|
* @example
|
|
54
50
|
* // Basic usage
|
|
55
51
|
* metalsmith.use(prism());
|
|
56
|
-
*
|
|
52
|
+
*
|
|
57
53
|
* // With options
|
|
58
54
|
* metalsmith.use(prism({
|
|
59
55
|
* decode: true,
|
|
@@ -61,42 +57,65 @@ const isHTMLFile = filePath => {
|
|
|
61
57
|
* preLoad: ['java', 'scala']
|
|
62
58
|
* }));
|
|
63
59
|
*/
|
|
64
|
-
|
|
60
|
+
const metalsmithPrism = (options = {}) => {
|
|
61
|
+
// Create a new options object with defaults
|
|
62
|
+
const opts = {
|
|
63
|
+
decode: false,
|
|
64
|
+
lineNumbers: false,
|
|
65
|
+
preLoad: [],
|
|
66
|
+
...options
|
|
67
|
+
};
|
|
68
|
+
|
|
65
69
|
// Track loaded languages to avoid duplicate loading
|
|
66
70
|
const loadedLanguages = new Set();
|
|
67
71
|
|
|
68
|
-
//
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
debug('
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
72
|
+
// Set up line numbers functionality
|
|
73
|
+
const NEW_LINE_EXP = /\n(?!$)/g;
|
|
74
|
+
let lineNumbersWrapper;
|
|
75
|
+
return (files, metalsmith, done) => {
|
|
76
|
+
// Get debug instance from metalsmith
|
|
77
|
+
const debug = metalsmith.debug('metalsmith-prism');
|
|
78
|
+
debug('Starting metalsmith-prism plugin');
|
|
79
|
+
debug('Options:', opts);
|
|
80
|
+
|
|
81
|
+
// Always load PHP by default
|
|
82
|
+
debug('Loading PHP by default');
|
|
83
|
+
try {
|
|
84
|
+
loadLanguages__default["default"](['php']);
|
|
85
|
+
loadedLanguages.add('php');
|
|
86
|
+
} catch (e) {
|
|
87
|
+
debug('Failed to load PHP:', e);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Preload languages if specified
|
|
91
|
+
if (opts.preLoad && opts.preLoad.length) {
|
|
92
|
+
debug('Preloading languages:', opts.preLoad);
|
|
93
|
+
opts.preLoad.forEach(language => {
|
|
94
|
+
if (!loadedLanguages.has(language)) {
|
|
95
|
+
try {
|
|
96
|
+
loadLanguages__default["default"]([language]);
|
|
97
|
+
loadedLanguages.add(language);
|
|
98
|
+
debug(`Successfully preloaded language: ${language}`);
|
|
99
|
+
} catch (e) {
|
|
100
|
+
console.warn(`Failed to preload prism syntax: ${language}!`, e);
|
|
101
|
+
debug(`Error preloading language ${language}:`, e);
|
|
102
|
+
}
|
|
103
|
+
} else {
|
|
104
|
+
debug(`Language ${language} already loaded, skipping`);
|
|
87
105
|
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
}
|
|
106
|
+
});
|
|
107
|
+
}
|
|
93
108
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
109
|
+
/**
|
|
110
|
+
* Require optional language package
|
|
111
|
+
* @param {string} language
|
|
112
|
+
* @param {Set} loadedLanguages
|
|
113
|
+
*/
|
|
114
|
+
const requireLanguage = (language, loadedLanguages) => {
|
|
115
|
+
if (loadedLanguages.has(language) || languages[language]) {
|
|
116
|
+
debug(`Language ${language} already available, skipping load`);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
100
119
|
debug(`Loading language on-demand: ${language}`);
|
|
101
120
|
try {
|
|
102
121
|
loadLanguages__default["default"]([language]);
|
|
@@ -106,85 +125,85 @@ function metalsmithPrism(options = {}) {
|
|
|
106
125
|
console.warn(`Failed to load prism syntax: ${language}!`, e);
|
|
107
126
|
debug(`Error loading language ${language}:`, e);
|
|
108
127
|
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
128
|
+
};
|
|
111
129
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
130
|
+
// Only set up the hook if line numbers are requested
|
|
131
|
+
if (opts.lineNumbers) {
|
|
132
|
+
debug('Setting up line numbers hook');
|
|
133
|
+
Prism__default["default"].hooks.add('after-tokenize', env => {
|
|
134
|
+
const match = env.code.match(NEW_LINE_EXP);
|
|
135
|
+
const linesNum = match ? match.length + 1 : 1;
|
|
136
|
+
debug(`Counted ${linesNum} lines for line numbers`);
|
|
137
|
+
const lines = new Array(linesNum + 1).join('<span></span>');
|
|
138
|
+
lineNumbersWrapper = `<span aria-hidden="true" class="line-numbers-rows">${lines}</span>`;
|
|
139
|
+
});
|
|
140
|
+
}
|
|
115
141
|
|
|
116
|
-
|
|
117
|
-
if (options.lineNumbers) {
|
|
118
|
-
debug('Setting up line numbers hook');
|
|
119
|
-
Prism__default["default"].hooks.add('after-tokenize', env => {
|
|
120
|
-
const match = env.code.match(NEW_LINE_EXP);
|
|
121
|
-
const linesNum = match ? match.length + 1 : 1;
|
|
122
|
-
debug(`Counted ${linesNum} lines for line numbers`);
|
|
123
|
-
const lines = new Array(linesNum + 1).join('<span></span>');
|
|
124
|
-
lineNumbersWrapper = `<span aria-hidden="true" class="line-numbers-rows">${lines}</span>`;
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
return function (files, metalsmith, done) {
|
|
128
|
-
debug('Starting metalsmith-prism plugin');
|
|
129
|
-
debug('Options:', options);
|
|
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('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":";;;;;;;;;;;;;;;;AAOA,MAAMA,KAAK,GAAGC,4BAAQ,CAAC,kBAAkB,CAAC,CAAA;;AAE1C;AACA,MAAM;AAAEC,EAAAA,SAAAA;AAAU,CAAC,GAAGC,yBAAK,CAAA;;AAE3B;AACA;AACA;AACA;AACA;AACA,MAAMC,UAAU,GAAIC,QAAQ,IAAK;EAC/B,MAAMC,SAAS,GAAGC,YAAO,CAACF,QAAQ,CAAC,CAACG,WAAW,EAAE,CAAA;AACjD,EAAA,OAAOF,SAAS,KAAK,OAAO,IAAIA,SAAS,KAAK,MAAM,CAAA;AACtD,CAAC,CAAA;;AAED;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASG,eAAeA,CAACC,OAAO,GAAG,EAAE,EAAE;AACrC;AACA,EAAA,MAAMC,eAAe,GAAG,IAAIC,GAAG,EAAE,CAAA;;AAEjC;EACAZ,KAAK,CAAC,wBAAwB,CAAC,CAAA;EAC/B,IAAI;AACFa,IAAAA,iCAAa,CAAC,CAAC,KAAK,CAAC,CAAC,CAAA;AACtBF,IAAAA,eAAe,CAACG,GAAG,CAAC,KAAK,CAAC,CAAA;GAC3B,CAAC,OAAOC,CAAC,EAAE;AACVf,IAAAA,KAAK,CAAC,qBAAqB,EAAEe,CAAC,CAAC,CAAA;AACjC,GAAA;EAEA,IAAIL,OAAO,CAACM,OAAO,EAAE;AACnBhB,IAAAA,KAAK,CAAC,uBAAuB,EAAEU,OAAO,CAACM,OAAO,CAAC,CAAA;AAC/CN,IAAAA,OAAO,CAACM,OAAO,CAACC,OAAO,CAAEC,QAAQ,IAAK;AACpC,MAAA,IAAI,CAACP,eAAe,CAACQ,GAAG,CAACD,QAAQ,CAAC,EAAE;QAClC,IAAI;AACFL,UAAAA,iCAAa,CAAC,CAACK,QAAQ,CAAC,CAAC,CAAA;AACzBP,UAAAA,eAAe,CAACG,GAAG,CAACI,QAAQ,CAAC,CAAA;AAC7BlB,UAAAA,KAAK,CAAC,CAAA,iCAAA,EAAoCkB,QAAQ,CAAA,CAAE,CAAC,CAAA;SACtD,CAAC,OAAOH,CAAC,EAAE;UACVK,OAAO,CAACC,IAAI,CAAC,CAAA,gCAAA,EAAmCH,QAAQ,CAAG,CAAA,CAAA,EAAEH,CAAC,CAAC,CAAA;AAC/Df,UAAAA,KAAK,CAAC,CAA6BkB,0BAAAA,EAAAA,QAAQ,CAAG,CAAA,CAAA,EAAEH,CAAC,CAAC,CAAA;AACpD,SAAA;AACF,OAAC,MAAM;AACLf,QAAAA,KAAK,CAAC,CAAA,SAAA,EAAYkB,QAAQ,CAAA,yBAAA,CAA2B,CAAC,CAAA;AACxD,OAAA;AACF,KAAC,CAAC,CAAA;AACJ,GAAA;;AAEA;AACF;AACA;AACA;EACE,SAASI,eAAeA,CAACJ,QAAQ,EAAE;AACjC,IAAA,IAAI,CAACP,eAAe,CAACQ,GAAG,CAACD,QAAQ,CAAC,IAAI,CAAChB,SAAS,CAACgB,QAAQ,CAAC,EAAE;AAC1DlB,MAAAA,KAAK,CAAC,CAAA,4BAAA,EAA+BkB,QAAQ,CAAA,CAAE,CAAC,CAAA;MAChD,IAAI;AACFL,QAAAA,iCAAa,CAAC,CAACK,QAAQ,CAAC,CAAC,CAAA;AACzBP,QAAAA,eAAe,CAACG,GAAG,CAACI,QAAQ,CAAC,CAAA;AAC7BlB,QAAAA,KAAK,CAAC,CAAA,8BAAA,EAAiCkB,QAAQ,CAAA,CAAE,CAAC,CAAA;OACnD,CAAC,OAAOH,CAAC,EAAE;QACVK,OAAO,CAACC,IAAI,CAAC,CAAA,6BAAA,EAAgCH,QAAQ,CAAG,CAAA,CAAA,EAAEH,CAAC,CAAC,CAAA;AAC5Df,QAAAA,KAAK,CAAC,CAA0BkB,uBAAAA,EAAAA,QAAQ,CAAG,CAAA,CAAA,EAAEH,CAAC,CAAC,CAAA;AACjD,OAAA;AACF,KAAA;AACF,GAAA;;AAEA;EACA,MAAMQ,YAAY,GAAG,UAAU,CAAA;AAC/B,EAAA,IAAIC,kBAAkB,CAAA;;AAEtB;EACA,IAAId,OAAO,CAACe,WAAW,EAAE;IACvBzB,KAAK,CAAC,8BAA8B,CAAC,CAAA;IACrCG,yBAAK,CAACuB,KAAK,CAACZ,GAAG,CAAC,gBAAgB,EAAGa,GAAG,IAAK;MACzC,MAAMC,KAAK,GAAGD,GAAG,CAACE,IAAI,CAACD,KAAK,CAACL,YAAY,CAAC,CAAA;MAC1C,MAAMO,QAAQ,GAAGF,KAAK,GAAGA,KAAK,CAACG,MAAM,GAAG,CAAC,GAAG,CAAC,CAAA;AAC7C/B,MAAAA,KAAK,CAAC,CAAA,QAAA,EAAW8B,QAAQ,CAAA,uBAAA,CAAyB,CAAC,CAAA;AACnD,MAAA,MAAME,KAAK,GAAG,IAAIC,KAAK,CAACH,QAAQ,GAAG,CAAC,CAAC,CAACI,IAAI,CAAC,eAAe,CAAC,CAAA;MAC3DV,kBAAkB,GAAG,CAAsDQ,mDAAAA,EAAAA,KAAK,CAAS,OAAA,CAAA,CAAA;AAC3F,KAAC,CAAC,CAAA;AACJ,GAAA;AAEA,EAAA,OAAO,UAAUG,KAAK,EAAEC,UAAU,EAAEC,IAAI,EAAE;IACxCrC,KAAK,CAAC,kCAAkC,CAAC,CAAA;AACzCA,IAAAA,KAAK,CAAC,UAAU,EAAEU,OAAO,CAAC,CAAA;IAE1B4B,YAAY,CAACD,IAAI,CAAC,CAAA;IAElBE,MAAM,CAACC,IAAI,CAACL,KAAK,CAAC,CAAClB,OAAO,CAAEwB,IAAI,IAAK;AACnC,MAAA,IAAI,CAACrC,UAAU,CAACqC,IAAI,CAAC,EAAE;AACrB,QAAA,OAAA;AACF,OAAA;AAEAzC,MAAAA,KAAK,CAAC,CAAA,sBAAA,EAAyByC,IAAI,CAAA,CAAE,CAAC,CAAA;MACtC,MAAMC,QAAQ,GAAGP,KAAK,CAACM,IAAI,CAAC,CAACC,QAAQ,CAACC,QAAQ,EAAE,CAAA;AAChD,MAAA,MAAMC,CAAC,GAAGC,YAAI,CAACH,QAAQ,EAAE;AAAEI,QAAAA,cAAc,EAAE,KAAA;AAAM,OAAC,CAAC,CAAA;MACnD,IAAIC,WAAW,GAAG,KAAK,CAAA;AACvB,MAAA,MAAMlB,IAAI,GAAGe,CAAC,CAAC,MAAM,CAAC,CAAA;AAEtB,MAAA,IAAI,CAACf,IAAI,CAACE,MAAM,EAAE;AAChB/B,QAAAA,KAAK,CAAC,CAAA,wBAAA,EAA2ByC,IAAI,CAAA,CAAE,CAAC,CAAA;AACxC,QAAA,OAAA;AACF,OAAA;MAEAzC,KAAK,CAAC,SAAS6B,IAAI,CAACE,MAAM,CAAmBU,gBAAAA,EAAAA,IAAI,EAAE,CAAC,CAAA;MAEpDZ,IAAI,CAACmB,IAAI,CAAC,YAAY;AACpB,QAAA,MAAMC,KAAK,GAAGL,CAAC,CAAC,IAAI,CAAC,CAAA;QAErB,MAAMM,SAAS,GAAGD,KAAK,CAACE,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAA;AAC3C,QAAA,MAAMC,OAAO,GAAGF,SAAS,CAACG,KAAK,CAAC,WAAW,CAAC,CAAA;QAC5C,IAAIC,cAAc,GAAG,KAAK,CAAA;AAE1B,QAAA,IAAIF,OAAO,CAACrB,MAAM,GAAG,CAAC,EAAE;AACtB,UAAA,MAAMwB,IAAI,GAAGN,KAAK,CAACO,MAAM,CAAC,KAAK,CAAC,CAAA;AAEhC,UAAA,IAAID,IAAI,EAAE;AACR;AACAA,YAAAA,IAAI,CAACE,QAAQ,CAACP,SAAS,CAAC,CAAA;YAExB,IAAIxC,OAAO,CAACe,WAAW,EAAE;AACvB8B,cAAAA,IAAI,CAACE,QAAQ,CAAC,cAAc,CAAC,CAAA;AAC7BH,cAAAA,cAAc,GAAG,IAAI,CAAA;cACrBtD,KAAK,CAAC,qBAAqB,CAAC,CAAA;AAC9B,aAAA;AACF,WAAA;AAEA+C,UAAAA,WAAW,GAAG,IAAI,CAAA;AAClB,UAAA,IAAI7B,QAAQ,GAAGkC,OAAO,CAAC,CAAC,CAAC,CAAA;AACzBpD,UAAAA,KAAK,CAAC,CAAA,mBAAA,EAAsBkB,QAAQ,CAAA,CAAE,CAAC,CAAA;UACvCI,eAAe,CAACJ,QAAQ,CAAC,CAAA;AAEzB,UAAA,IAAI,CAAChB,SAAS,CAACgB,QAAQ,CAAC,EAAE;AACxBlB,YAAAA,KAAK,CAAC,CAAA,SAAA,EAAYkB,QAAQ,CAAA,sCAAA,CAAwC,CAAC,CAAA;AACnEA,YAAAA,QAAQ,GAAG,QAAQ,CAAA;AACrB,WAAA;UAEA,MAAMwC,IAAI,GAAGxC,QAAQ,KAAK,QAAQ,IAAI,CAACR,OAAO,CAACiD,MAAM,GAAGV,KAAK,CAACS,IAAI,EAAE,GAAGE,sBAAE,CAACD,MAAM,CAACV,KAAK,CAACS,IAAI,EAAE,CAAC,CAAA;AAC9F1D,UAAAA,KAAK,CAAC,CAAA,cAAA,EAAiBU,OAAO,CAACiD,MAAM,GAAG,SAAS,GAAG,aAAa,CAAA,cAAA,EAAiBzC,QAAQ,CAAA,CAAE,CAAC,CAAA;AAE7FlB,UAAAA,KAAK,CAAC,CAAA,iCAAA,EAAoCkB,QAAQ,CAAA,CAAE,CAAC,CAAA;AACrD,UAAA,MAAM2C,eAAe,GAAG1D,yBAAK,CAAC2D,SAAS,CAACJ,IAAI,EAAExD,SAAS,CAACgB,QAAQ,CAAC,CAAC,CAAA;UAClE+B,KAAK,CAACS,IAAI,CAACJ,cAAc,GAAGO,eAAe,GAAGrC,kBAAkB,GAAGqC,eAAe,CAAC,CAAA;AACrF,SAAA;AACF,OAAC,CAAC,CAAA;AAEF,MAAA,IAAId,WAAW,EAAE;AACf/C,QAAAA,KAAK,CAAC,CAAA,qBAAA,EAAwByC,IAAI,CAAA,sBAAA,CAAwB,CAAC,CAAA;AAC3DN,QAAAA,KAAK,CAACM,IAAI,CAAC,CAACC,QAAQ,GAAGqB,MAAM,CAACC,IAAI,CAACpB,CAAC,CAACc,IAAI,EAAE,CAAC,CAAA;AAC9C,OAAC,MAAM;AACL1D,QAAAA,KAAK,CAAC,CAAA,2BAAA,EAA8ByC,IAAI,CAAA,CAAE,CAAC,CAAA;AAC7C,OAAA;AACF,KAAC,CAAC,CAAA;IAEFzC,KAAK,CAAC,mCAAmC,CAAC,CAAA;GAC3C,CAAA;AACH;;;;"}
|
|
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';\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 // Set up line numbers functionality\n const NEW_LINE_EXP = /\\n(?!$)/g;\n let lineNumbersWrapper;\n\n return (files, metalsmith, done) => {\n // Get debug instance from metalsmith\n const debug = metalsmith.debug('metalsmith-prism');\n \n debug('Starting metalsmith-prism plugin');\n debug('Options:', opts);\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 // Preload languages if specified\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 // 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 // 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('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":["languages","Prism","isHTMLFile","filePath","extension","extname","toLowerCase","includes","metalsmithPrism","options","opts","decode","lineNumbers","preLoad","loadedLanguages","Set","NEW_LINE_EXP","lineNumbersWrapper","files","metalsmith","done","debug","loadLanguages","add","e","length","forEach","language","has","console","warn","requireLanguage","hooks","env","match","code","linesNum","lines","Array","join","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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"}
|