UNPKG

@connectv/marked

Version:
94 lines 4.43 kB
import { InlineLexer, TextRenderer, Slugger } from 'marked'; import { InlineProcessor } from './inline'; import { fill } from './defaults'; import { unescape } from './util/unescape'; export class Parser { constructor(options) { this.tokens = []; this.slugger = new Slugger(); this.options = fill(options || {}); } parse(tokens, renderer) { this.renderer = renderer; this.inline = new InlineProcessor(tokens, renderer, this.options); this.inlineText = new InlineLexer(tokens.links, { renderer: new TextRenderer() }); this.tokens = tokens.reverse(); const res = renderer.create("fragment", null); while (this.next()) renderer.render(this.tok()).on(res); return res; } next() { const _next = this.tokens.pop(); if (_next) this.token = _next; return _next; } safeNext() { const _next = this.next(); if (!_next) /* istanbul ignore next */ throw new Error('Unexpected end of stream'); return _next; } peek() { return this.tokens[this.tokens.length - 1]; } parseText() { let body = this.token.text || ''; while (this.peek().type === 'text') /* istanbul ignore next */ body += '\n' + this.next().text; return this.inline.process(body); } tok() { const renderer = this.renderer; switch (this.token.type) { case 'space': return this.options.Space ? renderer.create(this.options.Space, null) : renderer.create("fragment", null); case 'hr': return renderer.create(this.options.Hr, null); case 'heading': const slug = this.slugger.slug(unescape(this.inlineText.output(this.token.text))); return renderer.create(this.options.Heading, { depth: this.token.depth, slug: slug }, this.inline.process(this.token.text)); case 'code': return renderer.create(this.options.Code, { lang: this.token.lang || '' }, this.token.text); case 'table': { const header = this.token.header.map((cell, i) => renderer.create(this.options.TableHeaderCell, { align: this.token.align[i] }, this.inline.process(cell))); const body = this.token.cells.map(row => renderer.create(this.options.TableRow, null, row.map((cell, j) => renderer.create(this.options.TableCell, { align: this.token.align[j] }, this.inline.process(cell))))); return renderer.create(this.options.Table, { header: header, body: body }); } case 'blockquote_start': { const body = renderer.create("fragment", null); while (this.safeNext().type !== 'blockquote_end') renderer.render(this.tok()).on(body); return renderer.create(this.options.BlockQuote, null, body); } case 'list_start': { const body = renderer.create("fragment", null); const ordered = this.token.ordered; while (this.safeNext().type !== 'list_end') renderer.render(this.tok()).on(body); return renderer.create(this.options.List, { ordered: ordered }, body); } case 'list_item_start': { const body = renderer.create("fragment", null); const loose = this.token.loose; while (this.safeNext().type !== 'list_item_end') { if (!loose && this.token.type === 'text') renderer.render(renderer.create("fragment", null, this.parseText())).on(body); else renderer.render(this.tok()).on(body); } return renderer.create(this.options.ListItem, null, body); } case 'html': return renderer.create(this.options.Html, { content: this.token.text }); case 'paragraph': return renderer.create(this.options.Paragraph, null, this.inline.process(this.token.text)); case 'text': return renderer.create(this.options.Paragraph, null, this.parseText()); default: /* istanbul ignore next */ throw new Error('Unrecognized Token:: ' + this.token.type); } } } //# sourceMappingURL=parser.js.map