From 2c2278dbe1933cf72f323ae6e144a3d096af2cde Mon Sep 17 00:00:00 2001 From: olaven Date: Fri, 28 Feb 2020 23:47:53 +0100 Subject: [PATCH 1/3] fixed ~25 compile errors --- main.ts | 124 ++++++++++++++++++++++++++++----------------------- main_test.ts | 4 +- 2 files changed, 70 insertions(+), 58 deletions(-) diff --git a/main.ts b/main.ts index a23c159..fffd565 100644 --- a/main.ts +++ b/main.ts @@ -111,12 +111,13 @@ interface Link { title: string; } -type TokensList = Token[] & { +type TokensList = [] & Token[] & { links: { [key: string]: { href: string; title: string; } } }; + type Token = Tokens.Space | Tokens.Code @@ -132,7 +133,10 @@ type Token = | Tokens.ListEnd | Tokens.Paragraph | Tokens.HTML - | Tokens.Text; + | Tokens.Text + | Tokens.ListStart; + +type AlignPosition = "center" | "left" | "right" | null namespace Tokens { export interface Space { @@ -155,7 +159,7 @@ namespace Tokens { export interface Table { type: 'table'; header: string[]; - align: Array<'center' | 'left' | 'right' | null>; + align: Array; cells: string[][]; } @@ -353,13 +357,15 @@ class Lexer { constructor(options?: MarkedOptions) { this.tokens = [] as TokensList; this.tokens.links = Object.create(null); - this.options = options || marked.defaults; + + + this.options = options || (marked.defaults as unknown as MarkedOptions); this.rules = block.normal; - if (this.options.pedantic) { + if (this.options?.pedantic) { this.rules = block.pedantic; - } else if (this.options.gfm) { - if (this.options.tables) { + } else if (this.options?.gfm) { + if (this.options?.tables) { this.rules = block.tables; } else { this.rules = block.gfm; @@ -421,9 +427,9 @@ class Lexer { cap = cap[0].replace(/^ {4}/gm, ''); this.tokens.push({ type: 'code', - text: !this.options.pedantic + text: !this.options?.pedantic ? rtrim(cap, '\n') - : cap + : cap }); continue; } @@ -453,29 +459,29 @@ class Lexer { // table no leading pipe (gfm) if (top && (cap = this.rules.nptable.exec(src))) { item = { - type: 'table', + type: 'table' as 'table', header: splitCells(cap[1].replace(/^ *| *\| *$/g, '')), align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), cells: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : [] - }; + } as Tokens.Table; if (item.header.length === item.align.length) { src = src.substring(cap[0].length); for (i = 0; i < item.align.length; i++) { - if (/^ *-+: *$/.test(item.align[i])) { + if (/^ *-+: *$/.test(item.align[i] as string)) { item.align[i] = 'right'; - } else if (/^ *:-+: *$/.test(item.align[i])) { + } else if (/^ *:-+: *$/.test(item.align[i] as string)) { item.align[i] = 'center'; - } else if (/^ *:-+ *$/.test(item.align[i])) { + } else if (/^ *:-+ *$/.test(item.align[i] as string)) { item.align[i] = 'left'; } else { item.align[i] = null; } } - for (i = 0; i < item.cells.length; i++) { - item.cells[i] = splitCells(item.cells[i], item.header.length); + for (i = 0; i < item.cells.length; i++) { //NOTE: risky conversion with toString? -@olaven + item.cells[i] = splitCells(item.cells[i].toString(), item.header.length); } this.tokens.push(item); @@ -528,7 +534,8 @@ class Lexer { loose: false }; - this.tokens.push(listStart); + + this.tokens.push(listStart as Tokens.ListStart); // Get each top-level item. cap = cap[0].match(this.rules.item); @@ -550,7 +557,7 @@ class Lexer { // list item contains. Hacky. if (~item.indexOf('\n ')) { space -= item.length; - item = !this.options.pedantic + item = !this.options?.pedantic ? item.replace(new RegExp(`^ {1,${space}}`, 'gm'), '') : item.replace(/^ {1,4}/gm, ''); } @@ -560,7 +567,7 @@ class Lexer { if (i !== l - 1) { b = block.bullet.exec(cap[i + 1])[0]; if (bull.length > 1 ? b.length === 1 - : (b.length > 1 || (this.options.smartLists && b !== bull))) { + : (b.length > 1 || (this.options?.smartLists && b !== bull))) { src = cap.slice(i + 1).join('\n') + src; i = l - 1; } @@ -592,7 +599,8 @@ class Lexer { task: istask, checked: ischecked, loose - }; + } as unknown as Tokens.ListStart; + listItems.push(t); this.tokens.push(t); @@ -609,7 +617,7 @@ class Lexer { l = listItems.length; i = 0; for (; i < l; i++) { - listItems[i].loose = true; + (listItems[i] as any).loose = true; } } @@ -624,10 +632,10 @@ class Lexer { if (cap = this.rules.html.exec(src)) { src = src.substring(cap[0].length); this.tokens.push({ - type: this.options.sanitize + type: this.options?.sanitize ? 'paragraph' : 'html', - pre: !this.options.sanitizer + pre: !this.options?.sanitizer && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'), text: cap[0] } as Token); @@ -651,7 +659,7 @@ class Lexer { // table (gfm) if (top && (cap = this.rules.table.exec(src))) { item = { - type: 'table', + type: 'table' as 'table', header: splitCells(cap[1].replace(/^ *| *\| *$/g, '')), align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), cells: cap[3] ? cap[3].replace(/(?: *\| *)?\n$/, '').split('\n') : [] @@ -857,9 +865,9 @@ class InlineLexer { }; static escapes = - (text?: string) => text ? text.replace(InlineLexer.rules._escapes, '$1') : text; + (text: string): string => text ? text.replace(InlineLexer.rules._escapes, '$1') : text; - options: MarkedOptions; + options: MarkedOptions | undefined; links: {[key: string]: Link}; rules: Rules; renderer: any; @@ -867,20 +875,20 @@ class InlineLexer { inRawBlock: any; constructor(links: {[key: string]: Link}, options?: MarkedOptions) { - this.options = options || marked.defaults; + this.options = options; this.links = links; this.rules = inline.normal; - this.renderer = this.options.renderer || new Renderer(); + this.renderer = this.options?.renderer || new Renderer(); this.renderer.options = this.options; if (!this.links) { throw new Error('Tokens array requires a `links` property.'); } - if (this.options.pedantic) { + if (this.options?.pedantic) { this.rules = inline.pedantic; - } else if (this.options.gfm) { - if (this.options.breaks) { + } else if (this.options?.gfm) { + if (this.options?.breaks) { this.rules = inline.breaks; } else { this.rules = inline.gfm; @@ -923,9 +931,9 @@ class InlineLexer { } src = src.substring(cap[0].length); - out += this.options.sanitize - ? this.options.sanitizer - ? this.options.sanitizer(cap[0]) + out += this.options?.sanitize + ? this.options?.sanitizer + ? this.options?.sanitizer(cap[0]) : escape(cap[0]) : cap[0]; continue; @@ -936,7 +944,7 @@ class InlineLexer { src = src.substring(cap[0].length); this.inLink = true; href = cap[2]; - if (this.options.pedantic) { + if (this.options?.pedantic) { link = /^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(href); if (link) { @@ -1083,7 +1091,7 @@ class InlineLexer { */ smartypants(text: string) { - if (!this.options.smartypants) return text; + if (!this.options?.smartypants) return text; return text // em-dashes .replace(/---/g, '\u2014') @@ -1106,7 +1114,7 @@ class InlineLexer { */ mangle(text: string) { - if (!this.options.mangle) return text; + if (!this.options?.mangle) return text; let out = ''; const l = text.length; let i = 0; @@ -1132,13 +1140,15 @@ class Renderer { options: MarkedOptions; constructor(options?: MarkedOptions) { - this.options = options || marked.defaults; + this.options = options || (marked.defaults as unknown as MarkedOptions); } code(code: string, infostring: string, escaped: boolean) { - const lang = (infostring || '').match(/\S*/)[0]; - if (this.options.highlight) { - const out = this.options.highlight(code, lang); + const lang = infostring.match(/\S*/)[0]; + + + if (this.options?.highlight) { + const out = this.options?.highlight(code, lang); if (out != null && out !== code) { escaped = true; code = out; @@ -1149,7 +1159,7 @@ class Renderer { return `
${escaped ? code : escape(code, true)}
`; } - return `
${escaped ? code : escape(code, true)}
\n`; + return `
${escaped ? code : escape(code, true)}
\n`; } blockquote(quote: string) { @@ -1161,15 +1171,15 @@ class Renderer { } heading(text: string, level: number, raw: string, slugger?: Slugger) { - if (this.options.headerIds) { - return `${text}\n`; + if (this.options?.headerIds) { + return `${text}\n`; } // ignore IDs return `${text}\n`; } hr() { - return this.options.xhtml ? '
\n' : '
\n'; + return this.options?.xhtml ? '
\n' : '
\n'; } list(body: string, ordered: boolean, start: number) { @@ -1183,7 +1193,7 @@ class Renderer { } checkbox(checked: boolean) { - return ` `; + return ` `; } paragraph(text: string) { @@ -1222,7 +1232,7 @@ class Renderer { } br() { - return this.options.xhtml ? '
' : '
'; + return this.options?.xhtml ? '
' : '
'; } del(text: string) { @@ -1230,7 +1240,7 @@ class Renderer { } link(href: string, title: string, text: string) { - href = cleanUrl(this.options.sanitize, this.options.baseUrl, href); + href = cleanUrl(this.options?.sanitize, this.options?.baseUrl, href); if (href === null) { return text; } @@ -1243,7 +1253,7 @@ class Renderer { } image(href: string, title: string, text: string) { - href = cleanUrl(this.options.sanitize, this.options.baseUrl, href); + href = cleanUrl(this.options?.sanitize, this.options?.baseUrl, href); if (href === null) { return text; } @@ -1252,7 +1262,7 @@ class Renderer { if (title) { out += ` title="${title}"`; } - out += this.options.xhtml ? '/>' : '>'; + out += this.options?.xhtml ? '/>' : '>'; return out; } @@ -1307,8 +1317,8 @@ class Parser { this.tokens = []; this.token = null; this.options = options || marked.defaults; - this.options.renderer = this.options.renderer || new Renderer(); - this.renderer = this.options.renderer; + this.options?.renderer = this.options?.renderer || new Renderer(); + this.renderer = this.options?.renderer; this.renderer.options = this.options; this.slugger = new Slugger(); } @@ -1469,7 +1479,7 @@ class Parser { } default: { const errMsg = `Token with "${this.token.type}" type was not found.`; - if (this.options.silent) { + if (this.options?.silent) { console.log(errMsg); } else { throw new Error(errMsg); @@ -1665,7 +1675,7 @@ function splitCells(tableRow: string, count?: number) { if (cells.length > count) { cells.splice(count); } else { - while (cells.length < count) cells.push(''); + while (count && cells.length < count) cells.push(''); } for (; i < cells.length; i++) { @@ -1707,7 +1717,7 @@ type MarkedCallback = (error: any | undefined, parseResult?: string) => void; * Marked */ function marked(src: string): string; -function marked(src: string, optOrCallback: MarkedOptions | MarkedCallback) +function marked(src: string, optOrCallback: MarkedOptions | MarkedCallback): void; function marked(src: string, optOrCallback?: MarkedOptions | MarkedCallback, callback?: MarkedCallback): string | void { // throw error in case of non string input if (typeof src === 'undefined' || src === null) { @@ -1790,10 +1800,12 @@ function marked(src: string, optOrCallback?: MarkedOptions | MarkedCallback, cal } try { if (opt) opt = merge({}, marked.defaults, opt); + //@ts-ignore return Parser.parse(Lexer.lex(src, opt), opt); } catch (e) { e.message += '\nPlease report this to https://github.com/markedjs/marked.'; - if ((opt || marked.defaults).silent) { + //@ts-ignore + if (opt || (marked.defaults).silent) { return `

An error occurred:

${escape(`${e.message}`, true)}
`; } throw e; diff --git a/main_test.ts b/main_test.ts index 6419256..af5baad 100644 --- a/main_test.ts +++ b/main_test.ts @@ -1,6 +1,6 @@ import marked from "./main.ts"; -import { test, runTests } from "https://deno.land/std@v0.3.2/testing/mod.ts"; -import { assert } from "https://deno.land/std@v0.3.2/testing/asserts.ts"; +import { test, runTests } from "https://deno.land/std/testing/asserts_test.ts"; +import { assert } from "https://deno.land/std/testing/runner_test.ts"; test({ name: "[Marked] Test heading ID functionality - add id attribute by default", From 9ff7e40c0e12775291845f28c5ea788fb0767772 Mon Sep 17 00:00:00 2001 From: olaven Date: Sat, 29 Feb 2020 13:15:36 +0100 Subject: [PATCH 2/3] compiles and passes on Deno 0.3.4 --- main.ts | 62 +++++++++++++++++++++++++++++++--------------------- main_test.ts | 7 +++--- 2 files changed, 41 insertions(+), 28 deletions(-) diff --git a/main.ts b/main.ts index fffd565..1e9f109 100644 --- a/main.ts +++ b/main.ts @@ -346,7 +346,7 @@ class Lexer { /** * Static Lex Method */ - static lex(src: string, options?: MarkedOptions) { + static lex(src: string, options?: MarkedOptions): TokensList { const lexer = new Lexer(options); return lexer.lex(src); }; @@ -460,7 +460,7 @@ class Lexer { if (top && (cap = this.rules.nptable.exec(src))) { item = { type: 'table' as 'table', - header: splitCells(cap[1].replace(/^ *| *\| *$/g, '')), + header: splitCells(cap[1].replace(/^ *| *\| *$/g, ''), 0),//NOTE: "0" added by me, check this if code does not work. Used to be nothing -> compile error //@olaven align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), cells: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : [] } as Tokens.Table; @@ -660,7 +660,7 @@ class Lexer { if (top && (cap = this.rules.table.exec(src))) { item = { type: 'table' as 'table', - header: splitCells(cap[1].replace(/^ *| *\| *$/g, '')), + header: splitCells(cap[1].replace(/^ *| *\| *$/g, ''), 0), //NOTE: "0" added by me, check this if code does not work. Used to be nothing -> compile error //@olaven align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), cells: cap[3] ? cap[3].replace(/(?: *\| *)?\n$/, '').split('\n') : [] }; @@ -1144,9 +1144,10 @@ class Renderer { } code(code: string, infostring: string, escaped: boolean) { + + //@ts-ignore: may be null const lang = infostring.match(/\S*/)[0]; - - + if (this.options?.highlight) { const out = this.options?.highlight(code, lang); if (out != null && out !== code) { @@ -1170,9 +1171,9 @@ class Renderer { return html; } - heading(text: string, level: number, raw: string, slugger?: Slugger) { + heading(text: string, level: number, raw: string, slugger: Slugger) { if (this.options?.headerIds) { - return `${text}\n`; + return `${text}\n`; } // ignore IDs return `${text}\n`; @@ -1210,6 +1211,7 @@ class Renderer { return `\n${content}\n`; } + //@ts-ignore tablecell(content: string, {header, align}) { const type = header ? 'th' : 'td'; const tag = align @@ -1240,7 +1242,7 @@ class Renderer { } link(href: string, title: string, text: string) { - href = cleanUrl(this.options?.sanitize, this.options?.baseUrl, href); + href = cleanUrl(this.options.sanitize as boolean, this.options.baseUrl!, href) as string; if (href === null) { return text; } @@ -1253,7 +1255,7 @@ class Renderer { } image(href: string, title: string, text: string) { - href = cleanUrl(this.options?.sanitize, this.options?.baseUrl, href); + href = cleanUrl(this.options.sanitize!, this.options.baseUrl!, href) as string; if (href === null) { return text; } @@ -1316,8 +1318,8 @@ class Parser { constructor(options?: MarkedOptions) { this.tokens = []; this.token = null; - this.options = options || marked.defaults; - this.options?.renderer = this.options?.renderer || new Renderer(); + this.options = options || (marked.defaults as unknown as MarkedOptions); + this.options.renderer = this.options?.renderer || new Renderer(); this.renderer = this.options?.renderer; this.renderer.options = this.options; this.slugger = new Slugger(); @@ -1550,7 +1552,7 @@ escape.replacements = { '>': '>', '"': '"', "'": ''' -}; +} as any; escape.escapeTestNoEncode = /[<>"']|&(?!#?\w+;)/; escape.escapeReplaceNoEncode = /[<>"']|&(?!#?\w+;)/g; @@ -1569,11 +1571,11 @@ function unescape(html: string) { }); } -function edit(regex, opt?: string) { +function edit(regex: any, opt?: string) { regex = regex.source || regex; opt = opt || ''; return { - replace(name, val) { + replace(name: any, val: any) { val = val.source || val; val = val.replace(/(^|[^\[])\^/g, '$1'); regex = regex.replace(name, val); @@ -1585,7 +1587,7 @@ function edit(regex, opt?: string) { }; } -function cleanUrl(sanitize: boolean, base: string, href: string) { +function cleanUrl(sanitize: boolean, base: string, href: string): string | null { if (sanitize) { try { var prot = decodeURIComponent(unescape(href)) @@ -1630,13 +1632,13 @@ function resolveUrl(base: string, href: string) { return base + href; } } -var baseUrls = {}; +var baseUrls: any = {} var originIndependentUrl = /^$|^[a-z][a-z0-9+.-]*:|^[?#]/i; function noop() {} noop.exec = noop; -function merge(obj, ...args: {[key: string]: any}[]) { +function merge(obj: any, ...args: {[key: string]: any}[]) { let i = 0; let target; let key; @@ -1653,7 +1655,7 @@ function merge(obj, ...args: {[key: string]: any}[]) { return obj; } -function splitCells(tableRow: string, count?: number) { +function splitCells(tableRow: string, count: number) { // ensure that every cell-delimiting pipe has a space // before it to distinguish it from an escaped pipe const row = tableRow.replace(/\|/g, (match, offset, str) => { @@ -1727,24 +1729,26 @@ function marked(src: string, optOrCallback?: MarkedOptions | MarkedCallback, cal throw new Error(`marked(): input parameter is of type ${Object.prototype.toString.call(src)}, string expected`); } - let opt: MarkedOptions; + let opt: MarkedOptions; // | null; if (callback || typeof optOrCallback === "function") { + if (!callback) { callback = optOrCallback as MarkedCallback; - opt = null; + //opt = null; } opt = merge({}, marked.defaults, optOrCallback || {}) as MarkedOptions; const highlight = opt.highlight; let tokens: TokensList; - let pending; + let pending: number; let i = 0; try { tokens = Lexer.lex(src, opt); } catch (e) { + return callback(e); } @@ -1752,8 +1756,9 @@ function marked(src: string, optOrCallback?: MarkedOptions | MarkedCallback, cal const done = (err?: any) => { if (err) { - opt.highlight = highlight; - return callback(err); + if (opt) opt.highlight = highlight; + //@ts-ignore: callback not always defined + callback(err) } let out; @@ -1766,8 +1771,11 @@ function marked(src: string, optOrCallback?: MarkedOptions | MarkedCallback, cal opt.highlight = highlight; + //@ts-ignore: callback not always defined return err + //@ts-ignore: callback not always defined ? callback(err) + //@ts-ignore: callback not always defined : callback(null, out); }; @@ -1780,11 +1788,14 @@ function marked(src: string, optOrCallback?: MarkedOptions | MarkedCallback, cal if (!pending) return done(); for (; i < tokens.length; i++) { - (token => { + (t => { + + const token = (t as Token); //TODO: why is array not already correctly typed? //@olaven if (token.type !== 'code') { return --pending || done(); } - return highlight(token.text, token.lang, (err, code) => { + + return highlight(token.text, token.lang!, (err: any, code: string) => { if (err) return done(err); if (code == null || code === token.text) { return --pending || done(); @@ -1799,6 +1810,7 @@ function marked(src: string, optOrCallback?: MarkedOptions | MarkedCallback, cal return; } try { + //@ts-ignore: is defined in scope, but TS complains //@olaven if (opt) opt = merge({}, marked.defaults, opt); //@ts-ignore return Parser.parse(Lexer.lex(src, opt), opt); diff --git a/main_test.ts b/main_test.ts index af5baad..cc3402a 100644 --- a/main_test.ts +++ b/main_test.ts @@ -1,6 +1,6 @@ import marked from "./main.ts"; -import { test, runTests } from "https://deno.land/std/testing/asserts_test.ts"; -import { assert } from "https://deno.land/std/testing/runner_test.ts"; +import { assert } from "https://deno.land/std/testing/asserts.ts"; +const { test, runTests } = Deno; test({ name: "[Marked] Test heading ID functionality - add id attribute by default", @@ -17,6 +17,7 @@ test({ "[Marked] Test heading ID functionality - NOT add id attribute when options set false", fn() { var renderer = new marked.Renderer({ headerIds: false }); + //@ts-ignore: slugger is not passed var header = renderer.heading("test", 1, "test"); assert(header === "

test

\n"); } @@ -94,7 +95,7 @@ test({ '[Marked] Test paragraph token type - should use the "paragraph" type on top level', fn() { const md = "A Paragraph.\n\n> A blockquote\n\n- list item\n"; - const tokens = marked.lexer(md); + const tokens = marked.lexer(md) as any; assert(tokens[0].type === "paragraph"); assert(tokens[3].type === "paragraph"); assert(tokens[7].type === "text"); From ebc4446b3e3c3802b45b2c4c4d2a89ef73efef31 Mon Sep 17 00:00:00 2001 From: olaven Date: Mon, 2 Mar 2020 19:51:59 +0100 Subject: [PATCH 3/3] addressed feedback --- main.ts | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/main.ts b/main.ts index 1e9f109..a89e9e3 100644 --- a/main.ts +++ b/main.ts @@ -352,7 +352,7 @@ class Lexer { }; tokens: TokensList; - options?: MarkedOptions; + options: MarkedOptions; rules: Rules; constructor(options?: MarkedOptions) { this.tokens = [] as TokensList; @@ -362,10 +362,10 @@ class Lexer { this.options = options || (marked.defaults as unknown as MarkedOptions); this.rules = block.normal; - if (this.options?.pedantic) { + if (this.options.pedantic) { this.rules = block.pedantic; } else if (this.options?.gfm) { - if (this.options?.tables) { + if (this.options.tables) { this.rules = block.tables; } else { this.rules = block.gfm; @@ -427,7 +427,7 @@ class Lexer { cap = cap[0].replace(/^ {4}/gm, ''); this.tokens.push({ type: 'code', - text: !this.options?.pedantic + text: !this.options.pedantic ? rtrim(cap, '\n') : cap }); @@ -460,7 +460,7 @@ class Lexer { if (top && (cap = this.rules.nptable.exec(src))) { item = { type: 'table' as 'table', - header: splitCells(cap[1].replace(/^ *| *\| *$/g, ''), 0),//NOTE: "0" added by me, check this if code does not work. Used to be nothing -> compile error //@olaven + header: splitCells(cap[1].replace(/^ *| *\| *$/g, '')), align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), cells: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : [] } as Tokens.Table; @@ -480,7 +480,7 @@ class Lexer { } } - for (i = 0; i < item.cells.length; i++) { //NOTE: risky conversion with toString? -@olaven + for (i = 0; i < item.cells.length; i++) { item.cells[i] = splitCells(item.cells[i].toString(), item.header.length); } @@ -550,6 +550,7 @@ class Lexer { // Remove the list item's bullet // so it is seen as the next token. + space = item.length; item = item.replace(/^ *([*+-]|\d+\.) */, ''); @@ -557,7 +558,7 @@ class Lexer { // list item contains. Hacky. if (~item.indexOf('\n ')) { space -= item.length; - item = !this.options?.pedantic + item = !this.options.pedantic ? item.replace(new RegExp(`^ {1,${space}}`, 'gm'), '') : item.replace(/^ {1,4}/gm, ''); } @@ -567,7 +568,7 @@ class Lexer { if (i !== l - 1) { b = block.bullet.exec(cap[i + 1])[0]; if (bull.length > 1 ? b.length === 1 - : (b.length > 1 || (this.options?.smartLists && b !== bull))) { + : (b.length > 1 || (this.options.smartLists && b !== bull))) { src = cap.slice(i + 1).join('\n') + src; i = l - 1; } @@ -660,7 +661,7 @@ class Lexer { if (top && (cap = this.rules.table.exec(src))) { item = { type: 'table' as 'table', - header: splitCells(cap[1].replace(/^ *| *\| *$/g, ''), 0), //NOTE: "0" added by me, check this if code does not work. Used to be nothing -> compile error //@olaven + header: splitCells(cap[1].replace(/^ *| *\| *$/g, '')), align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), cells: cap[3] ? cap[3].replace(/(?: *\| *)?\n$/, '').split('\n') : [] }; @@ -875,7 +876,7 @@ class InlineLexer { inRawBlock: any; constructor(links: {[key: string]: Link}, options?: MarkedOptions) { - this.options = options; + this.options = options || (marked.defaults as unknown as MarkedOptions); this.links = links; this.rules = inline.normal; this.renderer = this.options?.renderer || new Renderer(); @@ -1655,7 +1656,7 @@ function merge(obj: any, ...args: {[key: string]: any}[]) { return obj; } -function splitCells(tableRow: string, count: number) { +function splitCells(tableRow: string, count: number | undefined = undefined) { // ensure that every cell-delimiting pipe has a space // before it to distinguish it from an escaped pipe const row = tableRow.replace(/\|/g, (match, offset, str) => { @@ -1674,7 +1675,7 @@ function splitCells(tableRow: string, count: number) { const cells = row.split(/ \|/); let i = 0; - if (cells.length > count) { + if (count && cells.length > count) { cells.splice(count); } else { while (count && cells.length < count) cells.push(''); @@ -1790,7 +1791,7 @@ function marked(src: string, optOrCallback?: MarkedOptions | MarkedCallback, cal for (; i < tokens.length; i++) { (t => { - const token = (t as Token); //TODO: why is array not already correctly typed? //@olaven + const token = (t as Token); if (token.type !== 'code') { return --pending || done(); } @@ -1810,7 +1811,7 @@ function marked(src: string, optOrCallback?: MarkedOptions | MarkedCallback, cal return; } try { - //@ts-ignore: is defined in scope, but TS complains //@olaven + //@ts-ignore: is defined in scope, but TS complains if (opt) opt = merge({}, marked.defaults, opt); //@ts-ignore return Parser.parse(Lexer.lex(src, opt), opt);