diff --git a/docs/css/table-styles.css b/docs/css/table-styles.css new file mode 100644 index 0000000000..7ebae0be12 --- /dev/null +++ b/docs/css/table-styles.css @@ -0,0 +1,65 @@ +/* Markdown Table Styles */ +.markdown-table { + border-collapse: collapse; + width: 100%; + margin: 1em 0; + font-size: 14px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + border-radius: 8px; + overflow: hidden; +} + +.markdown-table th { + background: linear-gradient(135deg, #4a90e2 0%, #357abd 100%); + color: white; + font-weight: bold; + text-align: center; + padding: 12px 8px; + border: none; +} + +.markdown-table td { + padding: 12px 8px; + text-align: center; + border: 1px solid #e0e0e0; +} + +.markdown-table tr:nth-child(even) { + background-color: #f8f9fa; +} + +.markdown-table tr:nth-child(odd) { + background-color: #ffffff; +} + +.markdown-table tr:hover { + background-color: #e3f2fd; + transition: background-color 0.2s ease; +} + +.markdown-table tbody tr:last-child td { + border-bottom: none; +} + +/* Responsive Design */ +@media (max-width: 768px) { + .markdown-table { + font-size: 12px; + } + + .markdown-table th, + .markdown-table td { + padding: 8px 4px; + } +} + +@media (max-width: 480px) { + .markdown-table { + font-size: 11px; + } + + .markdown-table th, + .markdown-table td { + padding: 6px 2px; + } +} \ No newline at end of file diff --git a/docs/demo/index.html b/docs/demo/index.html index 1011fdc924..59f3875a81 100644 --- a/docs/demo/index.html +++ b/docs/demo/index.html @@ -5,13 +5,12 @@ Marked Demo - - + -

Marked Demo


Daring Fireball (pedantic) Demo -
Loading...
@@ -92,7 +77,6 @@

You'll need to enable Javascript to use this tool.

- diff --git a/docs/demo/worker.js b/docs/demo/worker.js index 106dfeaf3f..2ed0c6c8b2 100644 --- a/docs/demo/worker.js +++ b/docs/demo/worker.js @@ -1,3 +1,49 @@ +const tableExtension = { + renderer: { + table(token) { + let header = ''; + + // header + let cell = ''; + for (let j = 0; j < token.header.length; j++) { + cell += this.tablecell(token.header[j]); + } + header += this.tablerow({ text: cell }); + + let body = ''; + for (let j = 0; j < token.rows.length; j++) { + const row = token.rows[j]; + + cell = ''; + for (let k = 0; k < row.length; k++) { + cell += this.tablecell(row[k]); + } + + body += this.tablerow({ text: cell }); + } + if (body) body = `${body}`; + + return '\n' + + '\n' + + header + + '\n' + + body + + '
\n'; + }, + tablerow({ text }) { + return `\n${text}\n`; + }, + tablecell(token) { + const content = this.parser.parseInline(token.tokens); + const type = token.header ? 'th' : 'td'; + const tag = token.align + ? `<${type} align="${token.align}">` + : `<${type}>`; + return tag + content + `\n`; + }, + }, +}; + const versionCache = {}; let currentVersion; @@ -62,6 +108,10 @@ function parse(e) { } case 'parse': { const marked = versionCache[currentVersion]; + // Use table extension for local version + if (currentVersion === '../') { + marked.use(tableExtension); + } // marked 0.0.1 had tokens array as the second parameter of lexer and no options const options = currentVersion.endsWith('@0.0.1') ? [] : mergeOptions(e.data.options); const startTime = new Date(); diff --git a/src/rules.ts b/src/rules.ts index 0eb338b46b..a8e3930a05 100644 --- a/src/rules.ts +++ b/src/rules.ts @@ -67,12 +67,12 @@ export const other = { spaceLine: /^ +$/gm, notSpaceStart: /^\S*/, endingNewline: /\n$/, - listItemRegex: (bull: string) => new RegExp(`^( {0,3}${bull})((?:[\t ][^\\n]*)?(?:\\n|$))`), - nextBulletRegex: (indent: number) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ \t][^\\n]*)?(?:\\n|$))`), - hrRegex: (indent: number) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`), - fencesBeginRegex: (indent: number) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:\`\`\`|~~~)`), - headingBeginRegex: (indent: number) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}#`), - htmlBeginRegex: (indent: number) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}<(?:[a-z].*>|!--)`, 'i'), + listItemRegex: (bull: string) => new RegExp(`^( {0,4}${bull})((?:[\t ][^\\n]*)?(?:\\n|$))`), + nextBulletRegex: (indent: number) => /^ {0,4}(?:[*+-]|\d{1,9}[.)])((?:[ \t][^\n]*)?(?:\n|$))/, + hrRegex: (indent: number) => /^ {0,4}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/, + fencesBeginRegex: (indent: number) => /^ {0,4}(?:```|~~~)/, + headingBeginRegex: (indent: number) => /^ {0,4}#/, + htmlBeginRegex: (indent: number) => /^ {0,4}<(?:[a-z].*>|!--)/i, }; /** @@ -112,7 +112,7 @@ const def = edit(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: + .replace('title', /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/) .getRegex(); -const list = edit(/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/) +const list = edit(/^( {0,4}bull)([ \t][^\n]+?)?(?:\n|$)/) .replace(/bull/g, bullet) .getRegex(); diff --git a/src/tableExtension.ts b/src/tableExtension.ts new file mode 100644 index 0000000000..8ca1102030 --- /dev/null +++ b/src/tableExtension.ts @@ -0,0 +1,48 @@ +import type { MarkedExtension } from './MarkedOptions.ts'; +import type { Tokens } from './Tokens.ts'; + +export const tableExtension: MarkedExtension = { + renderer: { + table(token: Tokens.Table): string { + let header = ''; + + // header + let cell = ''; + for (let j = 0; j < token.header.length; j++) { + cell += this.tablecell(token.header[j]); + } + header += this.tablerow({ text: cell }); + + let body = ''; + for (let j = 0; j < token.rows.length; j++) { + const row = token.rows[j]; + + cell = ''; + for (let k = 0; k < row.length; k++) { + cell += this.tablecell(row[k]); + } + + body += this.tablerow({ text: cell }); + } + if (body) body = `${body}`; + + return '\n' + + '\n' + + header + + '\n' + + body + + '
\n'; + }, + tablerow({ text }: Tokens.TableRow): string { + return `\n${text}\n`; + }, + tablecell(token: Tokens.TableCell): string { + const content = this.parser.parseInline(token.tokens); + const type = token.header ? 'th' : 'td'; + const tag = token.align + ? `<${type} align="${token.align}">` + : `<${type}>`; + return tag + content + `\n`; + }, + }, +}; diff --git a/test-bullet-issue.js b/test-bullet-issue.js new file mode 100644 index 0000000000..e595ed9827 --- /dev/null +++ b/test-bullet-issue.js @@ -0,0 +1,30 @@ +// Test case for issue #2832 - bullet rendering with 4-space indentation +import { marked } from './lib/marked.esm.js'; + +const testCases = [ + { + name: 'Empty nested item with 4-space indentation', + markdown: `- title + - desc + -`, + }, + { + name: 'Empty nested item with 2-space indentation', + markdown: `- title + - desc + -`, + }, +]; + +testCases.forEach((testCase) => { + console.log(`\n=== ${testCase.name} ===`); + console.log('Input:'); + console.log(JSON.stringify(testCase.markdown)); + console.log('\nOutput:'); + try { + const result = marked.parse(testCase.markdown); + console.log(result); + } catch(error) { + console.error('Error:', error.message); + } +});