From c747c5577e5aeddbe24e15116b6fac57932eb68e Mon Sep 17 00:00:00 2001 From: David Bolack Date: Tue, 16 Jan 2024 02:01:55 -0600 Subject: [PATCH] Add PANdoc style lists ( using :: not : ) Includes new tests and fixes broken old tests --- shared/naturalcrit/markdown.js | 7 ++-- tests/markdown/marked-extensions.test.js | 51 ++++++++++++++++++------ 2 files changed, 42 insertions(+), 16 deletions(-) diff --git a/shared/naturalcrit/markdown.js b/shared/naturalcrit/markdown.js index c191c081f..8b54ece57 100644 --- a/shared/naturalcrit/markdown.js +++ b/shared/naturalcrit/markdown.js @@ -239,7 +239,7 @@ const definitionLists = { level : 'block', start(src) { return src.match(/^.*?::.*\n\n/m)?.index; }, // Hint to Marked.js to stop and check for a match tokenizer(src, tokens) { - const regex = /^([^\n:]*?)::(.*)(?:\n|$)/ym; + const regex = /^([^:\n]*?)[\n]?::(.*)(?:\n|$)/ym; let match; const endIndex = src.match(`\n\n`)?.index + 2; const allDefinitions = []; @@ -258,7 +258,6 @@ const definitionLists = { return; } const newDefinitions = match[2].split('::').filter((item)=>item).map((s)=>this.lexer.inlineTokens(s.trim())); - console.log(newDefinitions); if(newDefinitions?.length) { currentDefinition.dd.push(newDefinitions); } else { @@ -277,11 +276,13 @@ const definitionLists = { renderer(token) { let returnVal = `
`; token.definitions.forEach((def)=>{ - const dds = def.dd.map((ddef)=>{ + let dds = def.dd.map((ddef)=>{ return ddef.map((s)=>`
${this.parser.parseInline(s)}
`).join(''); }).join('\n'); + dds = dds.trim(); returnVal += `
${this.parser.parseInline(def.dt)}
${dds.indexOf('\n') > -1 ? '\n' : ''}${dds}\n`; }); + returnVal = returnVal.trim(); return `${returnVal}
`; } }; diff --git a/tests/markdown/marked-extensions.test.js b/tests/markdown/marked-extensions.test.js index 71bb47a30..814aea993 100644 --- a/tests/markdown/marked-extensions.test.js +++ b/tests/markdown/marked-extensions.test.js @@ -6,49 +6,74 @@ describe('Dictionary Terms', ()=>{ test('Single Definition', function() { const source = 'My term :: My First Definition\n\n'; const rendered = Markdown.render(source); - expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
My term
My First Definition
\n
'); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
My term
My First Definition
'); }); test('Two Definitions', function() { const source = 'My term :: My First Definition :: My Second Definition\n\n'; const rendered = Markdown.render(source); - expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
My term
My First Definition
My Second Definition
\n
'); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
My term
My First Definition
My Second Definition
'); }); test('Three Definitions', function() { const source = 'My term :: My First Definition :: My Second Definition :: My Third Definition\n\n'; const rendered = Markdown.render(source); - expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
My term
My First Definition
My Second Definition
My Third Definition
\n
'); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
My term
My First Definition
My Second Definition
My Third Definition
'); }); test('Multiline Definitions', function() { - const source = '**Example** :: V3 uses HTML *definition lists* to create "lists" with hanging indents.\n::Two::\nThree\n::Four\n\n'; + const source = '**Example** :: V3 uses HTML *definition lists* to create "lists" with hanging indents.\n::Two\n::Three\n::Four\n\n'; const rendered = Markdown.render(source); - expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
Example
\n
V3 uses HTML definition lists to create “lists” with hanging indents.
\n
TwoThree
\n
Four
\n
'); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
Example
\n
V3 uses HTML definition lists to create “lists” with hanging indents.
\n
Two
\n
Three
\n
Four
'); }); test('Multiple Definition Terms, single line, single definition', function() { - const source = 'Term 1::Definition of Term 1\nTerm 2::Definition of Term 2'; + const source = 'Term 1::Definition of Term 1\nTerm 2::Definition of Term 2\n\n'; const rendered = Markdown.render(source); - expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
Term 1
Definition of Term 1
Term 2>
Definition of Term 2
\n
'); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
Term 1
Definition of Term 1
\n
Term 2
Definition of Term 2
'); }); test('Multiple Definition Terms, single line, multiple definitions', function() { - const source = 'Term 1::Definition 1 of Term 1::Definition 2 of Term 1\nTerm 2::Definition 1 of Term 2::Definition 2 of Term 2'; + const source = 'Term 1::Definition 1 of Term 1::Definition 2 of Term 1\nTerm 2::Definition 1 of Term 2::Definition 2 of Term 2\n\n'; const rendered = Markdown.render(source); - expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
Term 1
Definition of Term 1
Term 2>
Definition of Term 2
\n
'); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
Term 1
Definition 1 of Term 1
Definition 2 of Term 1
\n
Term 2
Definition 1 of Term 2
Definition 2 of Term 2
'); }); test('Multiple Definition Terms, single definitions, multiple lines', function() { - const source = 'Term 1::Definition 1 of Term 1\n::Definition 2 of Term 1\nTerm 2::Definition of Term 2'; + const source = 'Term 1::Definition 1 of Term 1\n::Definition 2 of Term 1\nTerm 2::Definition of Term 2\n\n'; const rendered = Markdown.render(source); - expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
Term 1
Definition of Term 1
Term 2>
Definition of Term 2
\n
'); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
Term 1
\n
Definition 1 of Term 1
\n
Definition 2 of Term 1
\n
Term 2
Definition of Term 2
'); }); test('Multiple Definition Terms, multiple mixed-line definitions', function() { - const source = 'Term 1::Definition 1 of Term 1\n::Definition 2 of Term 1::Definition 3 of Term 1\nTerm 2::Definition of Term 2'; + const source = 'Term 1::Definition 1 of Term 1\n::Definition 2 of Term 1::Definition 3 of Term 1\nTerm 2::Definition of Term 2\n\n'; const rendered = Markdown.render(source); - expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
Term 1
Definition of Term 1
Term 2>
Definition of Term 2
\n
'); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
Term 1
\n
Definition 1 of Term 1
\n
Definition 2 of Term 1
Definition 3 of Term 1
\n
Term 2
Definition of Term 2
'); }); + test('PANdoc style list - Single Term, Single Definition', function() { + const source = 'Term 1\n::Definition 1\n\n'; + const rendered = Markdown.render(source); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
Term 1
Definition 1
'); + }); + + test('PANdoc style list - Single Term, Plural Definitions', function() { + const source = 'Term 1\n::Definition 1\n::Definition 2\n\n'; + const rendered = Markdown.render(source); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
Term 1
\n
Definition 1
\n
Definition 2
'); + }); + + test('PANdoc style list - Multiple Term, Single Definitions', function() { + const source = 'Term 1\n::Definition 1\nTerm 2\n::Definition 1\n\n'; + const rendered = Markdown.render(source); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
Term 1
Definition 1
\n
Term 2
Definition 1
'); + }); + + test('PANdoc style list - Multiple Term, Plural Definitions', function() { + const source = 'Term 1\n::Definition 1\n::Definition 2\nTerm 2\n::Definition 1\n::Definition 2\n\n'; + const rendered = Markdown.render(source); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
Term 1
\n
Definition 1
\n
Definition 2
\n
Term 2
\n
Definition 1
\n
Definition 2
'); + }); + + });