得鹿梦鱼 得鹿梦鱼

marked

marked 使用了单例模式
marked 提供了一个插件式开发的基座,

function marked{}const markedInstance = new Marked;marked.use =function ...args: MarkedExtension[]{    markedInstance.use...args;}

use 方法

class Marked {    constructor...args: MarkedExtension[]{        this.use...args    }    use...args: MarkedExtension[] {        const extensions: MarkedOptions['extensions'] = this.defaults.extensions  { renderers: {}, childTokens: {} };        args.forEachpack => {            const opts = { ...pack } as MarkedOptions;            opts.async = this.defaults.async  opts.async  false;            ifpack.extensions{                pack.extensions.forEachext => {                    if !ext.name {                        throw new Error'extension name required';                    }                    if"renderer" in ext{                        const prevRenderer = extensions.renderers[ext.name];                        ifprevRenderer{                           extensions.renderers[ext.name] = function...args{                                let ret = ext.renderer.applythis, args;                                ifret === false{                                    ret = prevRenderer.applythis, args;                                }                                return ret;                            }                        } else {                            extensions.renderers[ext.name] = ext.renderer                        }                    }                }            }        }    }}

parse 文档解析处理

  1. 词法分析可以分为2中类型,一种是仅有行内的规则,一种是包含块级规则的
  2. 如果hooks存在,则优先从hooks中获取词法分析函数
  3. 如果是异步的则返回promise

执行顺序

  1. 优先执行钩子函数中的pregrocess
  2. 进行词法分析Lexer
  3. 对词法分析后的token执行钩子函数中的processAllTokens
  4. 对词法分析后的token执行walkTokens函数处理
  5. 进行语法解析parse
  6. 对语法分析后的结果进行钩子中的postprocess函数
class Marked {    parse = this.parseMarkdowntrue;    parseInline = this.parseMarkdownfalse;    private parseMarkdownblockType: boolean{        type overloadedParse = {            src: string, options: MarkedOptions & { async: true }: Promise<string>;            src: string, options: MarkedOptions & { async: false }: string;            src: string, options?: MarkedOptions  null: string  Promise<string>;        };        const parse: overloadedParse = src: string, options: MarkedOptions  null: any => {            const origOpt = { ...options };            const opt = { ...this.defaults, ...origOpt };            const throwError = this.onError!!opt.silent, !!opt.async;            if this.defaults.async === true && origOpt.async === false {                return throwErrornew Error'marked: The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise.';            }            if typeof src === 'undefined'  src === null {                return throwErrornew Error'marked: input parameter is undefined or null';            }            if typeof src !== 'string' {                return throwErrornew Error'marked: input parameter is of type '                + Object.prototype.toString.callsrc + ', string expected';            }                        if opt.hooks {                opt.hooks.options = opt;                opt.hooks.block = blockType;            }            const lexer = opt.hooks ? opt.hooks.provideLexer : blockType ? _Lexer.lex : _Lexer.lexInline;            const parser = opt.hooks ? opt.hooks.provideParser : blockType ? _Parser.parse : _Parser.parseInline;            if opt.async {                return Promise.resolveopt.hooks ? opt.hooks.preprocesssrc : src                .thensrc => lexersrc, opt                .thentokens => opt.hooks ? opt.hooks.processAllTokenstokens : tokens                .thentokens => opt.walkTokens ? Promise.allthis.walkTokenstokens, opt.walkTokens.then => tokens : tokens                .thentokens => parsertokens, opt                .thenhtml => opt.hooks ? opt.hooks.postprocesshtml : html                .catchthrowError;            }            try {                if opt.hooks {                src = opt.hooks.preprocesssrc as string;                }                let tokens = lexersrc, opt;                if opt.hooks {                tokens = opt.hooks.processAllTokenstokens;                }                if opt.walkTokens {                this.walkTokenstokens, opt.walkTokens;                }                let html = parsertokens, opt;                if opt.hooks {                html = opt.hooks.postprocesshtml as string;                }                return html;            } catch e {                return throwErrore as Error;            }        }        return parse;    }    private onErrorsilent: boolean, async: boolean {        return e: Error: string  Promise<string> => {        e.message += '\nPlease report this to https://github.com/markedjs/marked.';        if silent {            const msg = '<p>An error occurred:</p><pre>'            + escapee.message + '', true            + '</pre>';            if async {                return Promise.resolvemsg;            }            return msg;        }        if async {            return Promise.rejecte;        }            throw e;        };    }}