Defite
3/19/2016 - 6:04 AM

Hexo lib/utli/highlight.js without elements I don't need like tables and above all accepting standard highlightjs themes

Hexo lib/utli/highlight.js without elements I don't need like tables and above all accepting standard highlightjs themes

/*
  Adaption of Hexo's hexo\node_modules\hexo-util\lib\util\highlight.js
  
  original code highlighter uses <figure> and <table>s as gutter. Had some validation issues. Also did not accept
  standard higlightjs themes (https://github.com/isagalaev/highlight.js/tree/master/src/styles) which are now
  just drop in. 
  
  captions still require a tiny bit of css of your own because they're not standard in highlightjs. 
  
  I'm accompanying this by a tiny JS that adds .hljs to every pre tag that doesn't contain it, so it applies to 
  4-space code blocks too
  
  One day I should turn this into a hexo renderer...
*/
 
var hljs = require('highlight.js'),
    _ = require('lodash');
 
var alias = {
    js: 'javascript',
    jscript: 'javascript',
    html: 'xml',
    htm: 'xml',
    coffee: 'coffeescript',
    'coffee-script': 'coffeescript',
    yml: 'yaml',
    pl: 'perl',
    ru: 'ruby',
    rb: 'ruby',
    csharp: 'cs'
};
 
var keys = Object.keys(alias);
 
/**
 * Highlights a code block.
 *
 * See [highlight.js](http://highlightjs.org/)
 *
 * @method highlight
 * @param {String} str
 * @param {Object} [options]
 *   @param {Boolean} [options.gutter=true] Displays line numbers. Only available when `options.wrap` is true
 *   @param {Boolean} [options.wrap=true] Wraps code block with a table
 *   @param {Number} [options.first_line=1] The first line number
 *   @param {String} [options.lang] Language. Program will decide the language automatically if not defined.
 *   @param {String} [options.caption] Caption.
 *   @param {String} [options.tab] Tab replacement
 * @return {String}
 * @for util
 * @static
 */
 
module.exports = function(str, options) {
    options = _.extend({
        gutter: true,
        wrap: true,
        first_line: 1,
        lang: '',
        caption: '',
        tab: '3'
    }, options);
 
    if (options.tab) {
        str = str.replace(/\n(\t+)/g, function(match, tabs) {
            var result = '\n';
            for (var i = 0, len = tabs.length; i < len; i++) {
                result += options.tab;
            }
 
            return result;
        });
    }
	
    var compiled = '';
 
    if (!options.lang) {
        compiled = hljs.highlightAuto(str).value;
    } else if (options.lang === 'plain') {
        compiled = str;
    } else {
        var lang = options.lang.toLowerCase();
 
        if (keys.indexOf(lang) !== -1) lang = alias[lang];
 
        try {
            compiled = hljs.highlight(lang, str).value;
        } catch (e) {
            compiled = hljs.highlightAuto(str).value;
        }
    }
 
    if (!options.wrap) return compiled;
	
    var lines = compiled.split('\n');
    var output = '<pre class="hljs' + ((lang) ? ' ' + lang : '') + '"><code>';
    output += (options.caption ? '<div class="caption">' + options.caption + '</div>' : '');
    if (options.gutter) output += '<ol>';
 
    lines.forEach(function(item, i) {
		item = item.replace(' ', '&nbsp;');
        if (options.gutter)
            output += '<li>' + item + '</li>';
        else
            output += item
    });
    if (options.gutter) output += '</ol>';
    output += '</code></pre>';
    return output;
 
};