marktext/src/muya/lib/parser/marked/parser.js
Felix Häusler 270d33f6c8 fix: update list item lexer and parser (#803)
* fix: CommonMark 264

* fix: muya list behavior
2019-03-27 19:51:46 +08:00

208 lines
4.6 KiB
JavaScript

import Renderer from './renderer'
import InlineLexer from './inlineLexer'
import Slugger from './slugger'
import TextRenderer from './textRenderer'
import defaultOptions from './options'
/**
* Parsing & Compiling
*/
function Parser (options) {
this.tokens = []
this.token = null
this.options = options || defaultOptions
this.options.renderer = this.options.renderer || new Renderer()
this.renderer = this.options.renderer
this.renderer.options = this.options
this.slugger = new Slugger()
}
/**
* Parse Loop
*/
Parser.prototype.parse = function (src) {
this.inline = new InlineLexer(src.links, this.options)
// use an InlineLexer with a TextRenderer to extract pure text
this.inlineText = new InlineLexer(
src.links,
Object.assign({}, this.options, {renderer: new TextRenderer()})
)
this.tokens = src.reverse()
let out = ''
while (this.next()) {
out += this.tok()
}
return out
}
/**
* Next Token
*/
Parser.prototype.next = function () {
this.token = this.tokens.pop()
return this.token
}
/**
* Preview Next Token
*/
Parser.prototype.peek = function () {
return this.tokens[this.tokens.length - 1] || 0
}
/**
* Parse Text Tokens
*/
Parser.prototype.parseText = function () {
let body = this.token.text
while (this.peek().type === 'text') {
body += '\n' + this.next().text
}
return this.inline.output(body)
}
/**
* Parse Current Token
*/
Parser.prototype.tok = function () {
switch (this.token.type) {
case 'frontmatter': {
return this.renderer.frontmatter(this.token.text)
}
case 'space': {
return ''
}
case 'hr': {
return this.renderer.hr()
}
case 'heading': {
return this.renderer.heading(
this.inline.output(this.token.text),
this.token.depth,
unescape(this.inlineText.output(this.token.text)),
this.slugger,
this.token.headingStyle
)
}
case 'multiplemath': {
const { text } = this.token
return this.renderer.multiplemath(text)
}
case 'code': {
const { codeBlockStyle, text, lang, escaped } = this.token
return this.renderer.code(text, lang, escaped, codeBlockStyle)
}
case 'table': {
let header = ''
let body = ''
let i
let row
let cell
let j
// header
cell = ''
for (i = 0; i < this.token.header.length; i++) {
cell += this.renderer.tablecell(
this.inline.output(this.token.header[i]), {
header: true,
align: this.token.align[i]
}
)
}
header += this.renderer.tablerow(cell)
for (i = 0; i < this.token.cells.length; i++) {
row = this.token.cells[i]
cell = ''
for (j = 0; j < row.length; j++) {
cell += this.renderer.tablecell(
this.inline.output(row[j]), {
header: false,
align: this.token.align[j]
}
)
}
body += this.renderer.tablerow(cell)
}
return this.renderer.table(header, body)
}
case 'blockquote_start': {
let body = ''
while (this.next().type !== 'blockquote_end') {
body += this.tok()
}
return this.renderer.blockquote(body)
}
case 'list_start': {
let body = ''
let taskList = false
const { ordered, start } = this.token
while (this.next().type !== 'list_end') {
if (this.token.checked !== undefined) {
taskList = true
}
body += this.tok()
}
return this.renderer.list(body, ordered, start, taskList)
}
case 'list_item_start': {
let body = ''
const { checked } = this.token
while (this.next().type !== 'list_item_end') {
body += this.token.type === 'text' ? this.parseText() : this.tok()
}
return this.renderer.listitem(body, checked)
}
case 'loose_item_start': {
let body = ''
const { checked } = this.token
while (this.next().type !== 'list_item_end') {
body += this.tok()
}
return this.renderer.listitem(body, checked)
}
case 'html': {
// TODO parse inline content if parameter markdown=1
return this.renderer.html(this.token.text)
}
case 'paragraph': {
return this.renderer.paragraph(this.inline.output(this.token.text))
}
case 'text': {
return this.renderer.paragraph(this.parseText())
}
default: {
let errMsg = 'Token with "' + this.token.type + '" type was not found.'
if (this.options.silent) {
console.error(errMsg)
} else {
throw new Error(errMsg)
}
}
}
}
export default Parser