Skip to content
This repository has been archived by the owner on Mar 23, 2023. It is now read-only.

Commit

Permalink
First working version
Browse files Browse the repository at this point in the history
  • Loading branch information
fortes committed Sep 29, 2014
1 parent bd8da29 commit 710a689
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 1 deletion.
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
# metalsmith-code-highlight

Finds content with `<code>` elements and highlights it using [HighlightJS](https://highlightjs.org/).
Finds content with `<code>` elements and highlights it using [HighlightJS](https://github.com/isagalaev/highlight.js).

## Configuration

Supports the [Highlight.js options](http://highlightjs.readthedocs.org/en/latest/api.html#configure-options):

* `tabReplace`
* `useBR`
* `classPrefix`
* `languages`

## Alternatives

Expand Down
82 changes: 82 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
var domino = require('domino'),
highlight = require('highlight.js');

var window, document, container;

var HTML_FILENAME_REGEXP = /\.html$/,
CODE_LANGUAGE_REGEXP = /(?:^|\w)lang-(.+)(?:$|\w)/;

/**
* @param {!HTMLElement} element
* @return {?string} Null if not found
*/
var getLanguage = function(element) {
var match;

if (element.className) {
match = element.className.match(CODE_LANGUAGE_REGEXP);

if (match) {
return match[1];
}
}
return null;
};

/**
* @param {!string} html
* @return {!string} New HTML with code highlighted
*/
var highlightFile = function(html) {
var i, len, codeBlocks, codeBlock, lang, result;

// Parse HTML into DOM
window = window || domino.createWindow('');
document = window.document;
container = document.createElement('div');

container.innerHTML = html;

codeBlocks = container.querySelectorAll('code');
for(i = 0, len = codeBlocks.length; i < len; i++) {
codeBlock = codeBlocks[i];
lang = getLanguage(codeBlock);

if (lang) {
result = highlight.highlight(lang, codeBlock.innerHTML, true);
}
else {
result = highlight.highlightAuto(codeBlock.innerHTML);
if (result.language) {
codeBlock.classList.add('lang-' + result.language);
}
}

codeBlock.innerHTML = result.value;
}

return container.innerHTML;
};

module.exports = function(options) {
highlight.configure(options);

/**
* @param {Object} files
* @param {Metalsmith} metalsmith
* @param {Function} done
*/
return function(files, metalsmith, done) {
var file, data;
for (file in files) {
if (HTML_FILENAME_REGEXP.test(file)) {
data = files[file];
data.contents = new Buffer(
highlightFile(data.contents.toString())
);
}
}

setImmediate(done);
}
}
28 changes: 28 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "metalsmith-code-highlight",
"version": "0.0.1",
"description": "Metalsmith plugin for adding syntax highlighting to code within posts",
"main": "index.js",
"scripts": {
"test": "node test.js"
},
"repository": {
"type": "git",
"url": "https://github.com/fortes/metalsmith-code-highlight.git"
},
"keywords": [
"metalsmith",
"syntax",
"highlight"
],
"author": "Filipe Fortes",
"license": "ISC",
"bugs": {
"url": "https://github.com/fortes/metalsmith-code-highlight/issues"
},
"homepage": "https://github.com/fortes/metalsmith-code-highlight",
"dependencies": {
"domino": "^1.0.18",
"highlight.js": "^8.2.0"
}
}
48 changes: 48 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
var assert = require('assert'),
metalsmithCodeHighlight = require('./index');

var files = {
'bogus.jpg': {
contents: new Buffer('<code class=lang-js>// Hi</code>')
},
'code.html': {
contents: new Buffer('<code class=lang-js>// Hi</code>')
},
'double.html': {
contents: new Buffer(
'<p>Hello there.</p>' +
'<p>Inline <code class=lang-js>document.all</code></p>' +
'<pre><code>' +
'\nrequire "fs"\nconsole.log fs.readFileSync "/etc/passwd"' +
'</code></pre>'
)
}
}

var plugin = metalsmithCodeHighlight();

plugin(files, {}, function(err) {
assert.equal(
files['code.html'].contents.toString(),
'<code class="lang-js"><span class="hljs-comment">// Hi</span></code>'
)

assert.equal(
files['double.html'].contents.toString(),
('<p>Hello there.</p><p>Inline <code class="lang-js">' +
'<span class="hljs-built_in">document</span>.all</code></p>' +
'<pre><code class="lang-coffeescript">\n' +
'<span class="hljs-built_in">require</span> ' +
'<span class="hljs-string">"fs"</span>\n' +
'<span class="hljs-built_in">console</span>.log fs.readFileSync ' +
'<span class="hljs-string">"/etc/passwd"</span></code></pre>')
)

// Don't touch non-HTML files
assert.equal(
files['bogus.jpg'].contents.toString(),
'<code class=lang-js>// Hi</code>'
)

console.log("All tests passed");
});

0 comments on commit 710a689

Please sign in to comment.