metalsmith-prism 5.0.4 → 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 +96 -17
- package/lib/index.cjs +64 -64
- package/lib/index.cjs.map +1 -1
- package/lib/index.js +64 -63
- package/lib/index.js.map +1 -1
- package/package.json +28 -23
- package/lib/index.modern.js +0 -186
- package/lib/index.modern.js.map +0 -1
- package/src/index.js +0 -214
package/README.md
CHANGED
|
@@ -7,6 +7,7 @@ A Metalsmith plugin that **adds Prism specific HTML markup** to code sections fo
|
|
|
7
7
|
[![license: MIT][license-badge]][license-url]
|
|
8
8
|
[![coverage][coverage-badge]][coverage-url]
|
|
9
9
|
[![ESM/CommonJS][modules-badge]][npm-url]
|
|
10
|
+
[](https://snyk.io/test/npm/metalsmith-prism)
|
|
10
11
|
|
|
11
12
|
## Dual Module Support (ESM and CommonJS)
|
|
12
13
|
|
|
@@ -170,26 +171,108 @@ Metalsmith(__dirname).use(
|
|
|
170
171
|
);
|
|
171
172
|
```
|
|
172
173
|
|
|
173
|
-
##
|
|
174
|
+
## Examples
|
|
174
175
|
|
|
175
|
-
|
|
176
|
+
### Basic Usage
|
|
176
177
|
|
|
177
|
-
|
|
178
|
+
Transform a simple code block with JavaScript:
|
|
178
179
|
|
|
179
|
-
|
|
180
|
-
|
|
180
|
+
**Input HTML:**
|
|
181
|
+
|
|
182
|
+
```html
|
|
183
|
+
<pre><code class="language-javascript">
|
|
184
|
+
const greeting = 'Hello, World!';
|
|
185
|
+
console.log(greeting);
|
|
186
|
+
</code></pre>
|
|
181
187
|
```
|
|
182
188
|
|
|
183
|
-
|
|
189
|
+
**Output HTML (with syntax highlighting):**
|
|
184
190
|
|
|
185
|
-
```
|
|
186
|
-
|
|
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
|
|
215
|
+
|
|
216
|
+
When using with @metalsmith/markdown, code blocks in markdown files are automatically processed:
|
|
217
|
+
|
|
218
|
+
**Markdown file:**
|
|
219
|
+
|
|
220
|
+
````markdown
|
|
221
|
+
```python
|
|
222
|
+
def fibonacci(n):
|
|
223
|
+
if n <= 1:
|
|
224
|
+
return n
|
|
225
|
+
return fibonacci(n-1) + fibonacci(n-2)
|
|
187
226
|
```
|
|
227
|
+
````
|
|
228
|
+
|
|
229
|
+
**Build configuration:**
|
|
188
230
|
|
|
189
|
-
|
|
231
|
+
```javascript
|
|
232
|
+
metalsmith(__dirname)
|
|
233
|
+
.use(markdown())
|
|
234
|
+
.use(
|
|
235
|
+
prism({
|
|
236
|
+
preLoad: ['python'] // Ensure Python support is loaded
|
|
237
|
+
})
|
|
238
|
+
)
|
|
239
|
+
.build();
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Preloading Languages
|
|
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();
|
|
254
|
+
```
|
|
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\*:
|
|
190
273
|
|
|
191
274
|
```bash
|
|
192
|
-
|
|
275
|
+
metalsmith.env('DEBUG', 'metalsmith-prism*');
|
|
193
276
|
```
|
|
194
277
|
|
|
195
278
|
## CLI Usage
|
|
@@ -220,16 +303,12 @@ This project maintains high statement and line coverage for the source code. Cov
|
|
|
220
303
|
|
|
221
304
|
Code released under [the MIT license](https://github.com/wernerglinka/metalsmith-prism/blob/main/LICENSE).
|
|
222
305
|
|
|
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
306
|
[metalsmith-badge]: https://img.shields.io/badge/metalsmith-plugin-green.svg?longCache=true
|
|
230
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
|
|
231
310
|
[license-badge]: https://img.shields.io/github/license/wernerglinka/metalsmith-prism
|
|
232
311
|
[license-url]: LICENSE
|
|
233
|
-
[coverage-badge]: https://img.shields.io/badge/test%20coverage-
|
|
312
|
+
[coverage-badge]: https://img.shields.io/badge/test%20coverage-94%25-brightgreen
|
|
234
313
|
[coverage-url]: #test-coverage
|
|
235
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 {
|
|
@@ -73,72 +69,76 @@ const metalsmithPrism = (options = {}) => {
|
|
|
73
69
|
// Track loaded languages to avoid duplicate loading
|
|
74
70
|
const loadedLanguages = new Set();
|
|
75
71
|
|
|
76
|
-
// Always load PHP by default
|
|
77
|
-
debug('Loading PHP by default');
|
|
78
|
-
try {
|
|
79
|
-
loadLanguages__default["default"](['php']);
|
|
80
|
-
loadedLanguages.add('php');
|
|
81
|
-
} catch (e) {
|
|
82
|
-
debug('Failed to load PHP:', e);
|
|
83
|
-
}
|
|
84
|
-
if (opts.preLoad && opts.preLoad.length) {
|
|
85
|
-
debug('Preloading languages:', opts.preLoad);
|
|
86
|
-
opts.preLoad.forEach(language => {
|
|
87
|
-
if (!loadedLanguages.has(language)) {
|
|
88
|
-
try {
|
|
89
|
-
loadLanguages__default["default"]([language]);
|
|
90
|
-
loadedLanguages.add(language);
|
|
91
|
-
debug(`Successfully preloaded language: ${language}`);
|
|
92
|
-
} catch (e) {
|
|
93
|
-
console.warn(`Failed to preload prism syntax: ${language}!`, e);
|
|
94
|
-
debug(`Error preloading language ${language}:`, e);
|
|
95
|
-
}
|
|
96
|
-
} else {
|
|
97
|
-
debug(`Language ${language} already loaded, skipping`);
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Require optional language package
|
|
104
|
-
* @param {string} language
|
|
105
|
-
* @param {Set} loadedLanguages
|
|
106
|
-
*/
|
|
107
|
-
const requireLanguage = (language, loadedLanguages) => {
|
|
108
|
-
if (loadedLanguages.has(language) || languages[language]) {
|
|
109
|
-
debug(`Language ${language} already available, skipping load`);
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
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
|
-
};
|
|
122
|
-
|
|
123
72
|
// Set up line numbers functionality
|
|
124
73
|
const NEW_LINE_EXP = /\n(?!$)/g;
|
|
125
74
|
let lineNumbersWrapper;
|
|
126
|
-
|
|
127
|
-
// Only set up the hook if line numbers are requested
|
|
128
|
-
if (opts.lineNumbers) {
|
|
129
|
-
debug('Setting up line numbers hook');
|
|
130
|
-
Prism__default["default"].hooks.add('after-tokenize', env => {
|
|
131
|
-
const match = env.code.match(NEW_LINE_EXP);
|
|
132
|
-
const linesNum = match ? match.length + 1 : 1;
|
|
133
|
-
debug(`Counted ${linesNum} lines for line numbers`);
|
|
134
|
-
const lines = new Array(linesNum + 1).join('<span></span>');
|
|
135
|
-
lineNumbersWrapper = `<span aria-hidden="true" class="line-numbers-rows">${lines}</span>`;
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
75
|
return (files, metalsmith, done) => {
|
|
76
|
+
// Get debug instance from metalsmith
|
|
77
|
+
const debug = metalsmith.debug('metalsmith-prism');
|
|
139
78
|
debug('Starting metalsmith-prism plugin');
|
|
140
79
|
debug('Options:', opts);
|
|
141
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`);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
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
|
+
}
|
|
119
|
+
debug(`Loading language on-demand: ${language}`);
|
|
120
|
+
try {
|
|
121
|
+
loadLanguages__default["default"]([language]);
|
|
122
|
+
loadedLanguages.add(language);
|
|
123
|
+
debug(`Successfully loaded language: ${language}`);
|
|
124
|
+
} catch (e) {
|
|
125
|
+
console.warn(`Failed to load prism syntax: ${language}!`, e);
|
|
126
|
+
debug(`Error loading language ${language}:`, e);
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
|
|
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
|
+
}
|
|
141
|
+
|
|
142
142
|
// Call done asynchronously to avoid blocking
|
|
143
143
|
setImmediate(done);
|
|
144
144
|
try {
|
|
@@ -198,7 +198,7 @@ const metalsmithPrism = (options = {}) => {
|
|
|
198
198
|
});
|
|
199
199
|
debug('Completed metalsmith-prism plugin');
|
|
200
200
|
} catch (error) {
|
|
201
|
-
debug('Error in metalsmith-prism plugin:', error);
|
|
201
|
+
debug.error('Error in metalsmith-prism plugin:', error);
|
|
202
202
|
// We can't call done(error) here because done has already been called
|
|
203
203
|
console.error('Error processing files:', error);
|
|
204
204
|
}
|
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 [ '.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":";;;;;;;;;;;;;;;;AAOA,MAAMA,KAAK,GAAGC,4BAAQ,CAAE,kBAAmB,CAAC,CAAA;;AAE5C;AACA,MAAM;AAAEC,EAAAA,SAAAA;AAAU,CAAC,GAAGC,yBAAK,CAAA;;AAE3B;AACA;AACA;AACA;AACA;AACA,MAAMC,UAAU,GAAKC,QAAQ,IAAM;EACjC,MAAMC,SAAS,GAAGC,YAAO,CAAEF,QAAS,CAAC,CAACG,WAAW,EAAE,CAAA;EACnD,OAAO,CAAE,OAAO,EAAE,MAAM,CAAE,CAACC,QAAQ,CAAEH,SAAU,CAAC,CAAA;AAClD,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,MAAMI,eAAe,GAAGA,CAAEC,OAAO,GAAG,EAAE,KAAM;AAC1C;AACA,EAAA,MAAMC,IAAI,GAAG;AACXC,IAAAA,MAAM,EAAE,KAAK;AACbC,IAAAA,WAAW,EAAE,KAAK;AAClBC,IAAAA,OAAO,EAAE,EAAE;IACX,GAAGJ,OAAAA;GACJ,CAAA;;AAED;AACA,EAAA,MAAMK,eAAe,GAAG,IAAIC,GAAG,EAAE,CAAA;;AAEjC;EACAjB,KAAK,CAAE,wBAAyB,CAAC,CAAA;EACjC,IAAI;AACFkB,IAAAA,iCAAa,CAAE,CAAE,KAAK,CAAG,CAAC,CAAA;AAC1BF,IAAAA,eAAe,CAACG,GAAG,CAAE,KAAM,CAAC,CAAA;GAC7B,CAAC,OAAQC,CAAC,EAAG;AACZpB,IAAAA,KAAK,CAAE,qBAAqB,EAAEoB,CAAE,CAAC,CAAA;AACnC,GAAA;EAEA,IAAKR,IAAI,CAACG,OAAO,IAAIH,IAAI,CAACG,OAAO,CAACM,MAAM,EAAG;AACzCrB,IAAAA,KAAK,CAAE,uBAAuB,EAAEY,IAAI,CAACG,OAAQ,CAAC,CAAA;AAC9CH,IAAAA,IAAI,CAACG,OAAO,CAACO,OAAO,CAAIC,QAAQ,IAAM;AACpC,MAAA,IAAK,CAACP,eAAe,CAACQ,GAAG,CAAED,QAAS,CAAC,EAAG;QACtC,IAAI;AACFL,UAAAA,iCAAa,CAAE,CAAEK,QAAQ,CAAG,CAAC,CAAA;AAC7BP,UAAAA,eAAe,CAACG,GAAG,CAAEI,QAAS,CAAC,CAAA;AAC/BvB,UAAAA,KAAK,CAAE,CAAA,iCAAA,EAAqCuB,QAAQ,CAAA,CAAI,CAAC,CAAA;SAC1D,CAAC,OAAQH,CAAC,EAAG;UACZK,OAAO,CAACC,IAAI,CAAE,CAAA,gCAAA,EAAoCH,QAAQ,CAAI,CAAA,CAAA,EAAEH,CAAE,CAAC,CAAA;AACnEpB,UAAAA,KAAK,CAAE,CAA8BuB,0BAAAA,EAAAA,QAAQ,CAAI,CAAA,CAAA,EAAEH,CAAE,CAAC,CAAA;AACxD,SAAA;AACF,OAAC,MAAM;AACLpB,QAAAA,KAAK,CAAE,CAAA,SAAA,EAAauB,QAAQ,CAAA,yBAAA,CAA6B,CAAC,CAAA;AAC5D,OAAA;AACF,KAAE,CAAC,CAAA;AACL,GAAA;;AAEA;AACF;AACA;AACA;AACA;AACE,EAAA,MAAMI,eAAe,GAAGA,CAAEJ,QAAQ,EAAEP,eAAe,KAAM;IACvD,IAAKA,eAAe,CAACQ,GAAG,CAAED,QAAS,CAAC,IAAIrB,SAAS,CAAEqB,QAAQ,CAAE,EAAG;AAC9DvB,MAAAA,KAAK,CAAE,CAAA,SAAA,EAAauB,QAAQ,CAAA,iCAAA,CAAqC,CAAC,CAAA;AAClE,MAAA,OAAA;AACF,KAAA;AAEAvB,IAAAA,KAAK,CAAE,CAAA,4BAAA,EAAgCuB,QAAQ,CAAA,CAAI,CAAC,CAAA;IACpD,IAAI;AACFL,MAAAA,iCAAa,CAAE,CAAEK,QAAQ,CAAG,CAAC,CAAA;AAC7BP,MAAAA,eAAe,CAACG,GAAG,CAAEI,QAAS,CAAC,CAAA;AAC/BvB,MAAAA,KAAK,CAAE,CAAA,8BAAA,EAAkCuB,QAAQ,CAAA,CAAI,CAAC,CAAA;KACvD,CAAC,OAAQH,CAAC,EAAG;MACZK,OAAO,CAACC,IAAI,CAAE,CAAA,6BAAA,EAAiCH,QAAQ,CAAI,CAAA,CAAA,EAAEH,CAAE,CAAC,CAAA;AAChEpB,MAAAA,KAAK,CAAE,CAA2BuB,uBAAAA,EAAAA,QAAQ,CAAI,CAAA,CAAA,EAAEH,CAAE,CAAC,CAAA;AACrD,KAAA;GACD,CAAA;;AAED;EACA,MAAMQ,YAAY,GAAG,UAAU,CAAA;AAC/B,EAAA,IAAIC,kBAAkB,CAAA;;AAEtB;EACA,IAAKjB,IAAI,CAACE,WAAW,EAAG;IACtBd,KAAK,CAAE,8BAA+B,CAAC,CAAA;IACvCG,yBAAK,CAAC2B,KAAK,CAACX,GAAG,CAAE,gBAAgB,EAAIY,GAAG,IAAM;MAC5C,MAAMC,KAAK,GAAGD,GAAG,CAACE,IAAI,CAACD,KAAK,CAAEJ,YAAa,CAAC,CAAA;MAC5C,MAAMM,QAAQ,GAAGF,KAAK,GAAGA,KAAK,CAACX,MAAM,GAAG,CAAC,GAAG,CAAC,CAAA;AAC7CrB,MAAAA,KAAK,CAAE,CAAA,QAAA,EAAYkC,QAAQ,CAAA,uBAAA,CAA2B,CAAC,CAAA;AACvD,MAAA,MAAMC,KAAK,GAAG,IAAIC,KAAK,CAAEF,QAAQ,GAAG,CAAE,CAAC,CAACG,IAAI,CAAE,eAAgB,CAAC,CAAA;MAC/DR,kBAAkB,GAAG,CAAuDM,mDAAAA,EAAAA,KAAK,CAAU,OAAA,CAAA,CAAA;AAC7F,KAAE,CAAC,CAAA;AACL,GAAA;AAEA,EAAA,OAAO,CAAEG,KAAK,EAAEC,UAAU,EAAEC,IAAI,KAAM;IACpCxC,KAAK,CAAE,kCAAmC,CAAC,CAAA;AAC3CA,IAAAA,KAAK,CAAE,UAAU,EAAEY,IAAK,CAAC,CAAA;;AAEzB;IACA6B,YAAY,CAAED,IAAK,CAAC,CAAA;IAEpB,IAAI;MACFE,MAAM,CAACC,IAAI,CAAEL,KAAM,CAAC,CAAChB,OAAO,CAAIsB,IAAI,IAAM;AACxC,QAAA,IAAK,CAACxC,UAAU,CAAEwC,IAAK,CAAC,EAAG;AACzB,UAAA,OAAA;AACF,SAAA;AAEA5C,QAAAA,KAAK,CAAE,CAAA,sBAAA,EAA0B4C,IAAI,CAAA,CAAI,CAAC,CAAA;QAC1C,MAAMC,QAAQ,GAAGP,KAAK,CAAEM,IAAI,CAAE,CAACC,QAAQ,CAACC,QAAQ,EAAE,CAAA;AAClD,QAAA,MAAMC,CAAC,GAAGC,YAAI,CAAEH,QAAQ,EAAE;AAAEI,UAAAA,cAAc,EAAE,KAAA;AAAM,SAAE,CAAC,CAAA;QACrD,IAAIC,WAAW,GAAG,KAAK,CAAA;AACvB,QAAA,MAAMjB,IAAI,GAAGc,CAAC,CAAE,MAAO,CAAC,CAAA;AAExB,QAAA,IAAK,CAACd,IAAI,CAACZ,MAAM,EAAG;AAClBrB,UAAAA,KAAK,CAAE,CAAA,wBAAA,EAA4B4C,IAAI,CAAA,CAAI,CAAC,CAAA;AAC5C,UAAA,OAAA;AACF,SAAA;QAEA5C,KAAK,CAAE,SAAUiC,IAAI,CAACZ,MAAM,CAAqBuB,gBAAAA,EAAAA,IAAI,EAAI,CAAC,CAAA;QAE1DX,IAAI,CAACkB,IAAI,CAAE,YAAW;AACpB,UAAA,MAAMC,KAAK,GAAGL,CAAC,CAAE,IAAK,CAAC,CAAA;UAEvB,MAAMM,SAAS,GAAGD,KAAK,CAACE,IAAI,CAAE,OAAQ,CAAC,IAAI,EAAE,CAAA;AAC7C,UAAA,MAAMC,OAAO,GAAGF,SAAS,CAACG,KAAK,CAAE,WAAY,CAAC,CAAA;UAC9C,IAAIC,cAAc,GAAG,KAAK,CAAA;AAE1B,UAAA,IAAKF,OAAO,CAAClC,MAAM,GAAG,CAAC,EAAG;AACxB,YAAA,MAAMqC,IAAI,GAAGN,KAAK,CAACO,MAAM,CAAE,KAAM,CAAC,CAAA;AAElC,YAAA,IAAKD,IAAI,EAAG;AACV;AACAA,cAAAA,IAAI,CAACE,QAAQ,CAAEP,SAAU,CAAC,CAAA;cAE1B,IAAKzC,IAAI,CAACE,WAAW,EAAG;AACtB4C,gBAAAA,IAAI,CAACE,QAAQ,CAAE,cAAe,CAAC,CAAA;AAC/BH,gBAAAA,cAAc,GAAG,IAAI,CAAA;gBACrBzD,KAAK,CAAE,qBAAsB,CAAC,CAAA;AAChC,eAAA;AACF,aAAA;AAEAkD,YAAAA,WAAW,GAAG,IAAI,CAAA;AAClB,YAAA,IAAI3B,QAAQ,GAAGgC,OAAO,CAAE,CAAC,CAAE,CAAA;AAC3BvD,YAAAA,KAAK,CAAE,CAAA,mBAAA,EAAuBuB,QAAQ,CAAA,CAAI,CAAC,CAAA;AAC3CI,YAAAA,eAAe,CAAEJ,QAAQ,EAAEP,eAAgB,CAAC,CAAA;AAE5C,YAAA,IAAK,CAACd,SAAS,CAAEqB,QAAQ,CAAE,EAAG;AAC5BvB,cAAAA,KAAK,CAAE,CAAA,SAAA,EAAauB,QAAQ,CAAA,sCAAA,CAA0C,CAAC,CAAA;AACvEA,cAAAA,QAAQ,GAAG,QAAQ,CAAA;AACrB,aAAA;YAEA,MAAMsC,IAAI,GAAGtC,QAAQ,KAAK,QAAQ,IAAI,CAACX,IAAI,CAACC,MAAM,GAAGuC,KAAK,CAACS,IAAI,EAAE,GAAGC,sBAAE,CAACjD,MAAM,CAAEuC,KAAK,CAACS,IAAI,EAAG,CAAC,CAAA;AAC7F7D,YAAAA,KAAK,CAAE,CAAA,cAAA,EAAkBY,IAAI,CAACC,MAAM,GAAG,SAAS,GAAG,aAAa,CAAA,cAAA,EAAmBU,QAAQ,CAAA,CAAI,CAAC,CAAA;AAEhGvB,YAAAA,KAAK,CAAE,CAAA,iCAAA,EAAqCuB,QAAQ,CAAA,CAAI,CAAC,CAAA;AACzD,YAAA,MAAMwC,eAAe,GAAG5D,yBAAK,CAAC6D,SAAS,CAAEH,IAAI,EAAE3D,SAAS,CAAEqB,QAAQ,CAAG,CAAC,CAAA;YACtE6B,KAAK,CAACS,IAAI,CAAEJ,cAAc,GAAGM,eAAe,GAAGlC,kBAAkB,GAAGkC,eAAgB,CAAC,CAAA;AACvF,WAAA;AACF,SAAE,CAAC,CAAA;AAEH,QAAA,IAAKb,WAAW,EAAG;AACjBlD,UAAAA,KAAK,CAAE,CAAA,qBAAA,EAAyB4C,IAAI,CAAA,sBAAA,CAA0B,CAAC,CAAA;AAC/DN,UAAAA,KAAK,CAAEM,IAAI,CAAE,CAACC,QAAQ,GAAGoB,MAAM,CAACC,IAAI,CAAEnB,CAAC,CAACc,IAAI,EAAG,CAAC,CAAA;AAClD,SAAC,MAAM;AACL7D,UAAAA,KAAK,CAAE,CAAA,2BAAA,EAA+B4C,IAAI,CAAA,CAAI,CAAC,CAAA;AACjD,SAAA;AACF,OAAE,CAAC,CAAA;MAEH5C,KAAK,CAAE,mCAAoC,CAAC,CAAA;KAC7C,CAAC,OAAQmE,KAAK,EAAG;AAChBnE,MAAAA,KAAK,CAAE,mCAAmC,EAAEmE,KAAM,CAAC,CAAA;AACnD;AACA1C,MAAAA,OAAO,CAAC0C,KAAK,CAAE,yBAAyB,EAAEA,KAAM,CAAC,CAAA;AACnD,KAAA;GACD,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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"}
|
package/lib/index.js
CHANGED
|
@@ -3,9 +3,6 @@ import { extname } from 'path';
|
|
|
3
3
|
import Prism from 'prismjs';
|
|
4
4
|
import loadLanguages from 'prismjs/components/index.js';
|
|
5
5
|
import he from 'he';
|
|
6
|
-
import debugLib from 'debug';
|
|
7
|
-
|
|
8
|
-
const debug = debugLib('metalsmith-prism');
|
|
9
6
|
|
|
10
7
|
// Import languages from Prism's default export
|
|
11
8
|
const {
|
|
@@ -64,72 +61,76 @@ const metalsmithPrism = (options = {}) => {
|
|
|
64
61
|
// Track loaded languages to avoid duplicate loading
|
|
65
62
|
const loadedLanguages = new Set();
|
|
66
63
|
|
|
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
64
|
// Set up line numbers functionality
|
|
115
65
|
const NEW_LINE_EXP = /\n(?!$)/g;
|
|
116
66
|
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
67
|
return (files, metalsmith, done) => {
|
|
68
|
+
// Get debug instance from metalsmith
|
|
69
|
+
const debug = metalsmith.debug('metalsmith-prism');
|
|
130
70
|
debug('Starting metalsmith-prism plugin');
|
|
131
71
|
debug('Options:', opts);
|
|
132
72
|
|
|
73
|
+
// Always load PHP by default
|
|
74
|
+
debug('Loading PHP by default');
|
|
75
|
+
try {
|
|
76
|
+
loadLanguages(['php']);
|
|
77
|
+
loadedLanguages.add('php');
|
|
78
|
+
} catch (e) {
|
|
79
|
+
debug('Failed to load PHP:', e);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Preload languages if specified
|
|
83
|
+
if (opts.preLoad && opts.preLoad.length) {
|
|
84
|
+
debug('Preloading languages:', opts.preLoad);
|
|
85
|
+
opts.preLoad.forEach(language => {
|
|
86
|
+
if (!loadedLanguages.has(language)) {
|
|
87
|
+
try {
|
|
88
|
+
loadLanguages([language]);
|
|
89
|
+
loadedLanguages.add(language);
|
|
90
|
+
debug(`Successfully preloaded language: ${language}`);
|
|
91
|
+
} catch (e) {
|
|
92
|
+
console.warn(`Failed to preload prism syntax: ${language}!`, e);
|
|
93
|
+
debug(`Error preloading language ${language}:`, e);
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
debug(`Language ${language} already loaded, skipping`);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Require optional language package
|
|
103
|
+
* @param {string} language
|
|
104
|
+
* @param {Set} loadedLanguages
|
|
105
|
+
*/
|
|
106
|
+
const requireLanguage = (language, loadedLanguages) => {
|
|
107
|
+
if (loadedLanguages.has(language) || languages[language]) {
|
|
108
|
+
debug(`Language ${language} already available, skipping load`);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
debug(`Loading language on-demand: ${language}`);
|
|
112
|
+
try {
|
|
113
|
+
loadLanguages([language]);
|
|
114
|
+
loadedLanguages.add(language);
|
|
115
|
+
debug(`Successfully loaded language: ${language}`);
|
|
116
|
+
} catch (e) {
|
|
117
|
+
console.warn(`Failed to load prism syntax: ${language}!`, e);
|
|
118
|
+
debug(`Error loading language ${language}:`, e);
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
// Only set up the hook if line numbers are requested
|
|
123
|
+
if (opts.lineNumbers) {
|
|
124
|
+
debug('Setting up line numbers hook');
|
|
125
|
+
Prism.hooks.add('after-tokenize', env => {
|
|
126
|
+
const match = env.code.match(NEW_LINE_EXP);
|
|
127
|
+
const linesNum = match ? match.length + 1 : 1;
|
|
128
|
+
debug(`Counted ${linesNum} lines for line numbers`);
|
|
129
|
+
const lines = new Array(linesNum + 1).join('<span></span>');
|
|
130
|
+
lineNumbersWrapper = `<span aria-hidden="true" class="line-numbers-rows">${lines}</span>`;
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
133
134
|
// Call done asynchronously to avoid blocking
|
|
134
135
|
setImmediate(done);
|
|
135
136
|
try {
|
|
@@ -189,7 +190,7 @@ const metalsmithPrism = (options = {}) => {
|
|
|
189
190
|
});
|
|
190
191
|
debug('Completed metalsmith-prism plugin');
|
|
191
192
|
} catch (error) {
|
|
192
|
-
debug('Error in metalsmith-prism plugin:', error);
|
|
193
|
+
debug.error('Error in metalsmith-prism plugin:', error);
|
|
193
194
|
// We can't call done(error) here because done has already been called
|
|
194
195
|
console.error('Error processing files:', error);
|
|
195
196
|
}
|
package/lib/index.js.map
CHANGED
|
@@ -1 +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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"}
|
|
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';\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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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "metalsmith-prism",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.5",
|
|
4
4
|
"description": "Syntax highlighting for Metalsmith HTML templates using Prism.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.cjs",
|
|
@@ -16,21 +16,21 @@
|
|
|
16
16
|
"scripts": {
|
|
17
17
|
"build": "microbundle --entry src/index.js --output lib/index.js --target node -f esm,cjs --strict --generateTypes=false",
|
|
18
18
|
"changelog": "auto-changelog -u --commit-limit false --ignore-commit-pattern '^((dev|chore|ci):|Release)'",
|
|
19
|
-
"coverage": "
|
|
20
|
-
"format": "prettier --write \"**/*.{yml,md,json}\"",
|
|
19
|
+
"coverage": "c8 --include=src/**/*.js --reporter=lcov --reporter=text-summary mocha 'test/index.js' 'test/cjs.test.cjs' 'test/comprehensive.mjs' 'test/additional.mjs' -t 15000",
|
|
20
|
+
"format": "prettier --write \"**/*.{yml,md,js,json}\"",
|
|
21
21
|
"format:check": "prettier --list-different \"**/*.{yml,md,js,json}\"",
|
|
22
22
|
"lint": "eslint --fix .",
|
|
23
23
|
"lint:check": "eslint --fix-dry-run .",
|
|
24
|
-
"format-and-lint": "npm run format && npm run lint",
|
|
25
24
|
"prepublishOnly": "npm run build",
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"release": "
|
|
29
|
-
"release:check": "npm run lint:check && npm run build &&
|
|
25
|
+
"release:patch": "./scripts/release.sh patch --ci",
|
|
26
|
+
"release:minor": "./scripts/release.sh minor --ci",
|
|
27
|
+
"release:major": "./scripts/release.sh major --ci",
|
|
28
|
+
"release:check": "npm run lint:check && npm run build && release-it --dry-run",
|
|
30
29
|
"test": "c8 --include=src/**/*.js mocha 'test/index.js' 'test/cjs.test.cjs' 'test/comprehensive.mjs' 'test/additional.mjs' -t 15000",
|
|
30
|
+
"test:coverage": "c8 npm test",
|
|
31
|
+
"test:unit": "mocha 'test/unit/**/*.js' -t 5000",
|
|
31
32
|
"test:esm": "c8 --include=src/**/*.js mocha 'test/index.js' 'test/comprehensive.mjs' 'test/additional.mjs' -t 15000",
|
|
32
33
|
"test:cjs": "c8 --include=src/**/*.js mocha test/cjs.test.cjs -t 15000",
|
|
33
|
-
"test:e2e": "serve -l 3000 test/fixtures",
|
|
34
34
|
"depcheck": "depcheck"
|
|
35
35
|
},
|
|
36
36
|
"repository": {
|
|
@@ -39,14 +39,15 @@
|
|
|
39
39
|
},
|
|
40
40
|
"keywords": [
|
|
41
41
|
"metalsmith",
|
|
42
|
+
"metalsmith-plugin",
|
|
42
43
|
"prismjs",
|
|
43
44
|
"syntax",
|
|
44
45
|
"highlighting"
|
|
45
46
|
],
|
|
46
47
|
"files": [
|
|
47
|
-
"src",
|
|
48
48
|
"lib",
|
|
49
|
-
"README.md"
|
|
49
|
+
"README.md",
|
|
50
|
+
"LICENSE"
|
|
50
51
|
],
|
|
51
52
|
"author": "Werner Glinka <werner@glinka.co>",
|
|
52
53
|
"license": "MIT",
|
|
@@ -55,24 +56,28 @@
|
|
|
55
56
|
},
|
|
56
57
|
"homepage": "https://github.com/wernerglinka/metalsmith-prism",
|
|
57
58
|
"dependencies": {
|
|
58
|
-
"cheerio": "
|
|
59
|
-
"debug": "^4.4.0",
|
|
60
|
-
"dotenv": "^16.5.0",
|
|
59
|
+
"cheerio": "1.1.2",
|
|
61
60
|
"he": "^1.2.0",
|
|
62
|
-
"metalsmith": "^2.
|
|
61
|
+
"metalsmith": "^2.5.0",
|
|
63
62
|
"prismjs": "^1.30.0"
|
|
64
63
|
},
|
|
65
64
|
"devDependencies": {
|
|
66
65
|
"auto-changelog": "^2.5.0",
|
|
67
66
|
"c8": "^10.1.3",
|
|
68
|
-
"chai": "
|
|
69
|
-
"eslint": "
|
|
70
|
-
"eslint-config-prettier": "
|
|
71
|
-
"eslint-plugin-prettier": "
|
|
72
|
-
"globals": "
|
|
67
|
+
"chai": "5.2.1",
|
|
68
|
+
"eslint": "9.32.0",
|
|
69
|
+
"eslint-config-prettier": "10.1.8",
|
|
70
|
+
"eslint-plugin-prettier": "5.5.3",
|
|
71
|
+
"globals": "16.3.0",
|
|
73
72
|
"microbundle": "^0.15.1",
|
|
74
|
-
"mocha": "
|
|
75
|
-
"prettier": "
|
|
76
|
-
"release-it": "
|
|
73
|
+
"mocha": "11.7.1",
|
|
74
|
+
"prettier": "3.6.2",
|
|
75
|
+
"release-it": "19.0.4"
|
|
76
|
+
},
|
|
77
|
+
"peerDependencies": {
|
|
78
|
+
"metalsmith": "^2.5.0"
|
|
79
|
+
},
|
|
80
|
+
"publishConfig": {
|
|
81
|
+
"access": "public"
|
|
77
82
|
}
|
|
78
83
|
}
|
package/lib/index.modern.js
DELETED
|
@@ -1,186 +0,0 @@
|
|
|
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 extension === '.html' || extension === '.htm';
|
|
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
|
-
function metalsmithPrism(options = {}) {
|
|
56
|
-
// Track loaded languages to avoid duplicate loading
|
|
57
|
-
const loadedLanguages = new Set();
|
|
58
|
-
|
|
59
|
-
// Always load PHP by default
|
|
60
|
-
debug('Loading PHP by default');
|
|
61
|
-
try {
|
|
62
|
-
loadLanguages(['php']);
|
|
63
|
-
loadedLanguages.add('php');
|
|
64
|
-
} catch (e) {
|
|
65
|
-
debug('Failed to load PHP:', e);
|
|
66
|
-
}
|
|
67
|
-
if (options.preLoad) {
|
|
68
|
-
debug('Preloading languages:', options.preLoad);
|
|
69
|
-
options.preLoad.forEach(language => {
|
|
70
|
-
if (!loadedLanguages.has(language)) {
|
|
71
|
-
try {
|
|
72
|
-
loadLanguages([language]);
|
|
73
|
-
loadedLanguages.add(language);
|
|
74
|
-
debug(`Successfully preloaded language: ${language}`);
|
|
75
|
-
} catch (e) {
|
|
76
|
-
console.warn(`Failed to preload prism syntax: ${language}!`, e);
|
|
77
|
-
debug(`Error preloading language ${language}:`, e);
|
|
78
|
-
}
|
|
79
|
-
} else {
|
|
80
|
-
debug(`Language ${language} already loaded, skipping`);
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Require optional language package
|
|
87
|
-
* @param {string} language
|
|
88
|
-
*/
|
|
89
|
-
function requireLanguage(language) {
|
|
90
|
-
if (!loadedLanguages.has(language) && !languages[language]) {
|
|
91
|
-
debug(`Loading language on-demand: ${language}`);
|
|
92
|
-
try {
|
|
93
|
-
loadLanguages([language]);
|
|
94
|
-
loadedLanguages.add(language);
|
|
95
|
-
debug(`Successfully loaded language: ${language}`);
|
|
96
|
-
} catch (e) {
|
|
97
|
-
console.warn(`Failed to load prism syntax: ${language}!`, e);
|
|
98
|
-
debug(`Error loading language ${language}:`, e);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Set up line numbers functionality
|
|
104
|
-
const NEW_LINE_EXP = /\n(?!$)/g;
|
|
105
|
-
let lineNumbersWrapper;
|
|
106
|
-
|
|
107
|
-
// Only set up the hook if line numbers are requested
|
|
108
|
-
if (options.lineNumbers) {
|
|
109
|
-
debug('Setting up line numbers hook');
|
|
110
|
-
Prism.hooks.add('after-tokenize', env => {
|
|
111
|
-
const match = env.code.match(NEW_LINE_EXP);
|
|
112
|
-
const linesNum = match ? match.length + 1 : 1;
|
|
113
|
-
debug(`Counted ${linesNum} lines for line numbers`);
|
|
114
|
-
const lines = new Array(linesNum + 1).join('<span></span>');
|
|
115
|
-
lineNumbersWrapper = `<span aria-hidden="true" class="line-numbers-rows">${lines}</span>`;
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
return function (files, metalsmith, done) {
|
|
119
|
-
debug('Starting metalsmith-prism plugin');
|
|
120
|
-
debug('Options:', options);
|
|
121
|
-
setImmediate(done);
|
|
122
|
-
Object.keys(files).forEach(file => {
|
|
123
|
-
if (!isHTMLFile(file)) {
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
debug(`Processing HTML file: ${file}`);
|
|
127
|
-
const contents = files[file].contents.toString();
|
|
128
|
-
const $ = load(contents, {
|
|
129
|
-
decodeEntities: false
|
|
130
|
-
});
|
|
131
|
-
let highlighted = false;
|
|
132
|
-
const code = $('code');
|
|
133
|
-
if (!code.length) {
|
|
134
|
-
debug(`No code blocks found in ${file}`);
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
debug(`Found ${code.length} code blocks in ${file}`);
|
|
138
|
-
code.each(function () {
|
|
139
|
-
const $this = $(this);
|
|
140
|
-
const className = $this.attr('class') || '';
|
|
141
|
-
const targets = className.split('language-');
|
|
142
|
-
let addLineNumbers = false;
|
|
143
|
-
if (targets.length > 1) {
|
|
144
|
-
const $pre = $this.parent('pre');
|
|
145
|
-
if ($pre) {
|
|
146
|
-
// Copy className to <pre> container
|
|
147
|
-
$pre.addClass(className);
|
|
148
|
-
if (options.lineNumbers) {
|
|
149
|
-
$pre.addClass('line-numbers');
|
|
150
|
-
addLineNumbers = true;
|
|
151
|
-
debug('Adding line numbers');
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
highlighted = true;
|
|
155
|
-
let language = targets[1];
|
|
156
|
-
debug(`Detected language: ${language}`);
|
|
157
|
-
requireLanguage(language);
|
|
158
|
-
if (!languages[language]) {
|
|
159
|
-
debug(`Language ${language} not available, falling back to markup`);
|
|
160
|
-
language = 'markup';
|
|
161
|
-
}
|
|
162
|
-
const html = language === 'markup' && !options.decode ? $this.html() : he.decode($this.html());
|
|
163
|
-
debug(`HTML decoding ${options.decode ? 'applied' : 'not applied'} for language ${language}`);
|
|
164
|
-
debug(`Highlighting code with language: ${language}`);
|
|
165
|
-
const highlightedCode = Prism.highlight(html, languages[language]);
|
|
166
|
-
$this.html(addLineNumbers ? highlightedCode + lineNumbersWrapper : highlightedCode);
|
|
167
|
-
}
|
|
168
|
-
});
|
|
169
|
-
if (highlighted) {
|
|
170
|
-
debug(`Updating contents of ${file} with highlighted code`);
|
|
171
|
-
files[file].contents = Buffer.from($.html());
|
|
172
|
-
} else {
|
|
173
|
-
debug(`No code was highlighted in ${file}`);
|
|
174
|
-
}
|
|
175
|
-
});
|
|
176
|
-
debug('Completed metalsmith-prism plugin');
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// CommonJS export compatibility
|
|
181
|
-
if (typeof module !== 'undefined') {
|
|
182
|
-
module.exports = metalsmithPrism;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
export { metalsmithPrism as default };
|
|
186
|
-
//# sourceMappingURL=index.modern.js.map
|
package/lib/index.modern.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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":";;;;;;;AAOA,MAAMA,KAAK,GAAGC,QAAQ,CAAC,kBAAkB,CAAC,CAAA;;AAE1C;AACA,MAAM;AAAEC,EAAAA,SAAAA;AAAU,CAAC,GAAGC,KAAK,CAAA;;AAE3B;AACA;AACA;AACA;AACA;AACA,MAAMC,UAAU,GAAIC,QAAQ,IAAK;EAC/B,MAAMC,SAAS,GAAGC,OAAO,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,aAAa,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,aAAa,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,aAAa,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,KAAK,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,IAAI,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,EAAE,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,KAAK,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,CAAA;;AAKA;AACA,IAAI,OAAOiE,MAAM,KAAK,WAAW,EAAE;EACjCA,MAAM,CAACC,OAAO,GAAGzD,eAAe,CAAA;AAClC;;;;"}
|
package/src/index.js
DELETED
|
@@ -1,214 +0,0 @@
|
|
|
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 { languages } = Prism;
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Check if a file is HTML based on its extension
|
|
15
|
-
* @param {string} filePath - Path to the file
|
|
16
|
-
* @returns {boolean} - True if the file has an HTML extension
|
|
17
|
-
*/
|
|
18
|
-
const isHTMLFile = ( filePath ) => {
|
|
19
|
-
const extension = extname( filePath ).toLowerCase();
|
|
20
|
-
return [ '.html', '.htm' ].includes( extension );
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* @typedef Options
|
|
25
|
-
* @property {boolean} [decode=false] - Whether to decode HTML entities
|
|
26
|
-
* @property {boolean} [lineNumbers=false] - Whether to add line numbers
|
|
27
|
-
* @property {string[]} [preLoad=[]] - Languages to preload
|
|
28
|
-
*/
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Metalsmith plugin to highlight code syntax with PrismJS
|
|
32
|
-
*
|
|
33
|
-
* This plugin finds all code blocks in HTML files that have language-* classes
|
|
34
|
-
* and applies Prism.js syntax highlighting to them. It can also add line numbers
|
|
35
|
-
* and handle HTML entity decoding.
|
|
36
|
-
*
|
|
37
|
-
* @param {Options} [options] - Configuration options
|
|
38
|
-
* @param {boolean} [options.decode=false] - Whether to decode HTML entities in code blocks
|
|
39
|
-
* @param {boolean} [options.lineNumbers=false] - Whether to add line numbers to code blocks
|
|
40
|
-
* @param {string[]} [options.preLoad=[]] - Languages to preload before processing
|
|
41
|
-
* @returns {import('metalsmith').Plugin} - A metalsmith plugin function
|
|
42
|
-
* @example
|
|
43
|
-
* // Basic usage
|
|
44
|
-
* metalsmith.use(prism());
|
|
45
|
-
*
|
|
46
|
-
* // With options
|
|
47
|
-
* metalsmith.use(prism({
|
|
48
|
-
* decode: true,
|
|
49
|
-
* lineNumbers: true,
|
|
50
|
-
* preLoad: ['java', 'scala']
|
|
51
|
-
* }));
|
|
52
|
-
*/
|
|
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
|
-
|
|
62
|
-
// Track loaded languages to avoid duplicate loading
|
|
63
|
-
const loadedLanguages = new Set();
|
|
64
|
-
|
|
65
|
-
// Always load PHP by default
|
|
66
|
-
debug( 'Loading PHP by default' );
|
|
67
|
-
try {
|
|
68
|
-
loadLanguages( [ 'php' ] );
|
|
69
|
-
loadedLanguages.add( 'php' );
|
|
70
|
-
} catch ( e ) {
|
|
71
|
-
debug( 'Failed to load PHP:', e );
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if ( opts.preLoad && opts.preLoad.length ) {
|
|
75
|
-
debug( 'Preloading languages:', opts.preLoad );
|
|
76
|
-
opts.preLoad.forEach( ( language ) => {
|
|
77
|
-
if ( !loadedLanguages.has( language ) ) {
|
|
78
|
-
try {
|
|
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 );
|
|
85
|
-
}
|
|
86
|
-
} else {
|
|
87
|
-
debug( `Language ${ language } already loaded, skipping` );
|
|
88
|
-
}
|
|
89
|
-
} );
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Require optional language package
|
|
94
|
-
* @param {string} language
|
|
95
|
-
* @param {Set} loadedLanguages
|
|
96
|
-
*/
|
|
97
|
-
const requireLanguage = ( language, loadedLanguages ) => {
|
|
98
|
-
if ( loadedLanguages.has( language ) || languages[ language ] ) {
|
|
99
|
-
debug( `Language ${ language } already available, skipping load` );
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
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
|
-
|
|
130
|
-
return ( files, metalsmith, done ) => {
|
|
131
|
-
debug( 'Starting metalsmith-prism plugin' );
|
|
132
|
-
debug( 'Options:', opts );
|
|
133
|
-
|
|
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
|
-
}
|
|
142
|
-
|
|
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' );
|
|
148
|
-
|
|
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 }` );
|
|
155
|
-
|
|
156
|
-
code.each( function() {
|
|
157
|
-
const $this = $( this );
|
|
158
|
-
|
|
159
|
-
const className = $this.attr( 'class' ) || '';
|
|
160
|
-
const targets = className.split( 'language-' );
|
|
161
|
-
let addLineNumbers = false;
|
|
162
|
-
|
|
163
|
-
if ( targets.length > 1 ) {
|
|
164
|
-
const $pre = $this.parent( 'pre' );
|
|
165
|
-
|
|
166
|
-
if ( $pre ) {
|
|
167
|
-
// Copy className to <pre> container
|
|
168
|
-
$pre.addClass( className );
|
|
169
|
-
|
|
170
|
-
if ( opts.lineNumbers ) {
|
|
171
|
-
$pre.addClass( 'line-numbers' );
|
|
172
|
-
addLineNumbers = true;
|
|
173
|
-
debug( 'Adding line numbers' );
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
highlighted = true;
|
|
178
|
-
let language = targets[ 1 ];
|
|
179
|
-
debug( `Detected language: ${ language }` );
|
|
180
|
-
requireLanguage( language, loadedLanguages );
|
|
181
|
-
|
|
182
|
-
if ( !languages[ language ] ) {
|
|
183
|
-
debug( `Language ${ language } not available, falling back to markup` );
|
|
184
|
-
language = 'markup';
|
|
185
|
-
}
|
|
186
|
-
|
|
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 }` );
|
|
189
|
-
|
|
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 }` );
|
|
201
|
-
}
|
|
202
|
-
} );
|
|
203
|
-
|
|
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
|
-
}
|
|
210
|
-
};
|
|
211
|
-
};
|
|
212
|
-
|
|
213
|
-
// ESM export
|
|
214
|
-
export default metalsmithPrism;
|