l0bsterssg

node.js static responsive blog post generator
Log | Files | Refs | README

marked.js (6029B)


      1 const Lexer = require('./Lexer.js');
      2 const Parser = require('./Parser.js');
      3 const Tokenizer = require('./Tokenizer.js');
      4 const Renderer = require('./Renderer.js');
      5 const TextRenderer = require('./TextRenderer.js');
      6 const Slugger = require('./Slugger.js');
      7 const {
      8   merge,
      9   checkSanitizeDeprecation,
     10   escape
     11 } = require('./helpers.js');
     12 const {
     13   getDefaults,
     14   changeDefaults,
     15   defaults
     16 } = require('./defaults.js');
     17 
     18 /**
     19  * Marked
     20  */
     21 function marked(src, opt, callback) {
     22   // throw error in case of non string input
     23   if (typeof src === 'undefined' || src === null) {
     24     throw new Error('marked(): input parameter is undefined or null');
     25   }
     26   if (typeof src !== 'string') {
     27     throw new Error('marked(): input parameter is of type '
     28       + Object.prototype.toString.call(src) + ', string expected');
     29   }
     30 
     31   if (typeof opt === 'function') {
     32     callback = opt;
     33     opt = null;
     34   }
     35 
     36   opt = merge({}, marked.defaults, opt || {});
     37   checkSanitizeDeprecation(opt);
     38 
     39   if (callback) {
     40     const highlight = opt.highlight;
     41     let tokens;
     42 
     43     try {
     44       tokens = Lexer.lex(src, opt);
     45     } catch (e) {
     46       return callback(e);
     47     }
     48 
     49     const done = function(err) {
     50       let out;
     51 
     52       if (!err) {
     53         try {
     54           out = Parser.parse(tokens, opt);
     55         } catch (e) {
     56           err = e;
     57         }
     58       }
     59 
     60       opt.highlight = highlight;
     61 
     62       return err
     63         ? callback(err)
     64         : callback(null, out);
     65     };
     66 
     67     if (!highlight || highlight.length < 3) {
     68       return done();
     69     }
     70 
     71     delete opt.highlight;
     72 
     73     if (!tokens.length) return done();
     74 
     75     let pending = 0;
     76     marked.walkTokens(tokens, function(token) {
     77       if (token.type === 'code') {
     78         pending++;
     79         setTimeout(() => {
     80           highlight(token.text, token.lang, function(err, code) {
     81             if (err) {
     82               return done(err);
     83             }
     84             if (code != null && code !== token.text) {
     85               token.text = code;
     86               token.escaped = true;
     87             }
     88 
     89             pending--;
     90             if (pending === 0) {
     91               done();
     92             }
     93           });
     94         }, 0);
     95       }
     96     });
     97 
     98     if (pending === 0) {
     99       done();
    100     }
    101 
    102     return;
    103   }
    104 
    105   try {
    106     const tokens = Lexer.lex(src, opt);
    107     if (opt.walkTokens) {
    108       marked.walkTokens(tokens, opt.walkTokens);
    109     }
    110     return Parser.parse(tokens, opt);
    111   } catch (e) {
    112     e.message += '\nPlease report this to https://github.com/markedjs/marked.';
    113     if (opt.silent) {
    114       return '<p>An error occurred:</p><pre>'
    115         + escape(e.message + '', true)
    116         + '</pre>';
    117     }
    118     throw e;
    119   }
    120 }
    121 
    122 /**
    123  * Options
    124  */
    125 
    126 marked.options =
    127 marked.setOptions = function(opt) {
    128   merge(marked.defaults, opt);
    129   changeDefaults(marked.defaults);
    130   return marked;
    131 };
    132 
    133 marked.getDefaults = getDefaults;
    134 
    135 marked.defaults = defaults;
    136 
    137 /**
    138  * Use Extension
    139  */
    140 
    141 marked.use = function(extension) {
    142   const opts = merge({}, extension);
    143   if (extension.renderer) {
    144     const renderer = marked.defaults.renderer || new Renderer();
    145     for (const prop in extension.renderer) {
    146       const prevRenderer = renderer[prop];
    147       renderer[prop] = (...args) => {
    148         let ret = extension.renderer[prop].apply(renderer, args);
    149         if (ret === false) {
    150           ret = prevRenderer.apply(renderer, args);
    151         }
    152         return ret;
    153       };
    154     }
    155     opts.renderer = renderer;
    156   }
    157   if (extension.tokenizer) {
    158     const tokenizer = marked.defaults.tokenizer || new Tokenizer();
    159     for (const prop in extension.tokenizer) {
    160       const prevTokenizer = tokenizer[prop];
    161       tokenizer[prop] = (...args) => {
    162         let ret = extension.tokenizer[prop].apply(tokenizer, args);
    163         if (ret === false) {
    164           ret = prevTokenizer.apply(tokenizer, args);
    165         }
    166         return ret;
    167       };
    168     }
    169     opts.tokenizer = tokenizer;
    170   }
    171   if (extension.walkTokens) {
    172     const walkTokens = marked.defaults.walkTokens;
    173     opts.walkTokens = (token) => {
    174       extension.walkTokens(token);
    175       if (walkTokens) {
    176         walkTokens(token);
    177       }
    178     };
    179   }
    180   marked.setOptions(opts);
    181 };
    182 
    183 /**
    184  * Run callback for every token
    185  */
    186 
    187 marked.walkTokens = function(tokens, callback) {
    188   for (const token of tokens) {
    189     callback(token);
    190     switch (token.type) {
    191       case 'table': {
    192         for (const cell of token.tokens.header) {
    193           marked.walkTokens(cell, callback);
    194         }
    195         for (const row of token.tokens.cells) {
    196           for (const cell of row) {
    197             marked.walkTokens(cell, callback);
    198           }
    199         }
    200         break;
    201       }
    202       case 'list': {
    203         marked.walkTokens(token.items, callback);
    204         break;
    205       }
    206       default: {
    207         if (token.tokens) {
    208           marked.walkTokens(token.tokens, callback);
    209         }
    210       }
    211     }
    212   }
    213 };
    214 
    215 /**
    216  * Parse Inline
    217  */
    218 marked.parseInline = function(src, opt) {
    219   // throw error in case of non string input
    220   if (typeof src === 'undefined' || src === null) {
    221     throw new Error('marked.parseInline(): input parameter is undefined or null');
    222   }
    223   if (typeof src !== 'string') {
    224     throw new Error('marked.parseInline(): input parameter is of type '
    225       + Object.prototype.toString.call(src) + ', string expected');
    226   }
    227 
    228   opt = merge({}, marked.defaults, opt || {});
    229   checkSanitizeDeprecation(opt);
    230 
    231   try {
    232     const tokens = Lexer.lexInline(src, opt);
    233     if (opt.walkTokens) {
    234       marked.walkTokens(tokens, opt.walkTokens);
    235     }
    236     return Parser.parseInline(tokens, opt);
    237   } catch (e) {
    238     e.message += '\nPlease report this to https://github.com/markedjs/marked.';
    239     if (opt.silent) {
    240       return '<p>An error occurred:</p><pre>'
    241         + escape(e.message + '', true)
    242         + '</pre>';
    243     }
    244     throw e;
    245   }
    246 };
    247 
    248 /**
    249  * Expose
    250  */
    251 
    252 marked.Parser = Parser;
    253 marked.parser = Parser.parse;
    254 
    255 marked.Renderer = Renderer;
    256 marked.TextRenderer = TextRenderer;
    257 
    258 marked.Lexer = Lexer;
    259 marked.lexer = Lexer.lex;
    260 
    261 marked.Tokenizer = Tokenizer;
    262 
    263 marked.Slugger = Slugger;
    264 
    265 marked.parse = marked;
    266 
    267 module.exports = marked;