UNPKG

remix-nlux

Version:

Remix IDE NLUX integration. Remix IDE is the leading IDE for building and deploying smart contracts on Ethereum. NLUX is a JavaScript and React library for building conversational AI experiences.

304 lines (281 loc) 11.8 kB
import {_defaults} from './defaults'; import {unescape} from './helpers'; import type {MarkedOptions} from './MarkedOptions'; import {_Renderer} from './Renderer'; import {_TextRenderer} from './TextRenderer'; import type {Token, Tokens} from './Tokens'; /** * Parsing & Compiling */ export class _Parser { options: MarkedOptions; renderer: _Renderer; textRenderer: _TextRenderer; constructor(options?: MarkedOptions) { this.options = options || _defaults; this.options.renderer = this.options.renderer || new _Renderer(); this.renderer = this.options.renderer; this.renderer.options = this.options; this.textRenderer = new _TextRenderer(); } /** * Static Parse Method */ static parse(tokens: Token[], options?: MarkedOptions) { const parser = new _Parser(options); return parser.parse(tokens); } /** * Static Parse Inline Method */ static parseInline(tokens: Token[], options?: MarkedOptions) { const parser = new _Parser(options); return parser.parseInline(tokens); } /** * Parse Loop */ parse(tokens: Token[], top = true): string { let out = ''; for (let i = 0; i < tokens.length; i++) { const token = tokens[i]; // Run any renderer extensions if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[token.type]) { const genericToken = token as Tokens.Generic; const ret = this.options.extensions.renderers[genericToken.type].call({parser: this}, genericToken); if (ret !== false || ![ 'space', 'hr', 'heading', 'code', 'table', 'blockquote', 'list', 'html', 'paragraph', 'text', ].includes(genericToken.type)) { out += ret || ''; continue; } } switch (token.type) { case 'space': { continue; } case 'hr': { out += this.renderer.hr(); continue; } case 'heading': { const headingToken = token as Tokens.Heading; out += this.renderer.heading( this.parseInline(headingToken.tokens), headingToken.depth, unescape(this.parseInline(headingToken.tokens, this.textRenderer)), ); continue; } case 'code': { const codeToken = token as Tokens.Code; out += this.renderer.code(codeToken.text, codeToken.lang, !!codeToken.escaped, ); continue; } case 'table': { const tableToken = token as Tokens.Table; let header = ''; // header let cell = ''; for (let j = 0; j < tableToken.header.length; j++) { cell += this.renderer.tablecell( this.parseInline(tableToken.header[j].tokens), {header: true, align: tableToken.align[j]}, ); } header += this.renderer.tablerow(cell); let body = ''; for (let j = 0; j < tableToken.rows.length; j++) { const row = tableToken.rows[j]; cell = ''; for (let k = 0; k < row.length; k++) { cell += this.renderer.tablecell( this.parseInline(row[k].tokens), {header: false, align: tableToken.align[k]}, ); } body += this.renderer.tablerow(cell); } out += this.renderer.table(header, body); continue; } case 'blockquote': { const blockquoteToken = token as Tokens.Blockquote; const body = this.parse(blockquoteToken.tokens); out += this.renderer.blockquote(body); continue; } case 'list': { const listToken = token as Tokens.List; const ordered = listToken.ordered; const start = listToken.start; const loose = listToken.loose; let body = ''; for (let j = 0; j < listToken.items.length; j++) { const item = listToken.items[j]; const checked = item.checked; const task = item.task; let itemBody = ''; if (item.task) { const checkbox = this.renderer.checkbox(!!checked); if (loose) { if (item.tokens.length > 0 && item.tokens[0].type === 'paragraph') { item.tokens[0].text = checkbox + ' ' + item.tokens[0].text; if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') { item.tokens[0].tokens[0].text = checkbox + ' ' + item.tokens[0].tokens[0].text; } } else { item.tokens.unshift({ type: 'text', text: checkbox + ' ', } as Tokens.Text); } } else { itemBody += checkbox + ' '; } } itemBody += this.parse(item.tokens, loose); body += this.renderer.listitem(itemBody, task, !!checked); } out += this.renderer.list(body, ordered, start); continue; } case 'html': { const htmlToken = token as Tokens.HTML; out += this.renderer.html(htmlToken.text, htmlToken.block); continue; } case 'paragraph': { const paragraphToken = token as Tokens.Paragraph; out += this.renderer.paragraph(this.parseInline(paragraphToken.tokens)); continue; } case 'text': { let textToken = token as Tokens.Text; let body = textToken.tokens ? this.parseInline(textToken.tokens) : textToken.text; while (i + 1 < tokens.length && tokens[i + 1].type === 'text') { textToken = tokens[++i] as Tokens.Text; body += '\n' + (textToken.tokens ? this.parseInline(textToken.tokens) : textToken.text); } out += top ? this.renderer.paragraph(body) : body; continue; } default: { const errMsg = 'Token with "' + token.type + '" type was not found.'; if (this.options.silent) { console.error(errMsg); return ''; } else { throw new Error(errMsg); } } } } return out; } /** * Parse Inline Tokens */ parseInline(tokens: Token[], renderer?: _Renderer | _TextRenderer): string { renderer = renderer || this.renderer; let out = ''; for (let i = 0; i < tokens.length; i++) { const token = tokens[i]; // Run any renderer extensions if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[token.type]) { const ret = this.options.extensions.renderers[token.type].call({parser: this}, token); if (ret !== false || ![ 'escape', 'html', 'link', 'image', 'strong', 'em', 'codespan', 'br', 'del', 'text', ].includes(token.type)) { out += ret || ''; continue; } } switch (token.type) { case 'escape': { const escapeToken = token as Tokens.Escape; out += renderer.text(escapeToken.text); break; } case 'html': { const tagToken = token as Tokens.Tag; out += renderer.html(tagToken.text); break; } case 'link': { const linkToken = token as Tokens.Link; out += renderer.link(linkToken.href, linkToken.title, this.parseInline(linkToken.tokens, renderer)); break; } case 'image': { const imageToken = token as Tokens.Image; out += renderer.image(imageToken.href, imageToken.title, imageToken.text); break; } case 'strong': { const strongToken = token as Tokens.Strong; out += renderer.strong(this.parseInline(strongToken.tokens, renderer)); break; } case 'em': { const emToken = token as Tokens.Em; out += renderer.em(this.parseInline(emToken.tokens, renderer)); break; } case 'codespan': { const codespanToken = token as Tokens.Codespan; out += renderer.codespan(codespanToken.text); break; } case 'br': { out += renderer.br(); break; } case 'del': { const delToken = token as Tokens.Del; out += renderer.del(this.parseInline(delToken.tokens, renderer)); break; } case 'text': { const textToken = token as Tokens.Text; out += renderer.text(textToken.text); break; } default: { const errMsg = 'Token with "' + token.type + '" type was not found.'; if (this.options.silent) { console.error(errMsg); return ''; } else { throw new Error(errMsg); } } } } return out; } }