Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Multi-line Dictionary Definition (<dd>) rows. #3129

Merged
merged 62 commits into from
Mar 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
ce1ba82
Add Multi-line Dictionary Definition (<dd>) rows.
dbolacksn Nov 7, 2023
e6428a3
Update Editor highlighting for Definition Lists
dbolacksn Nov 8, 2023
d1152dc
Add Change log
dbolacksn Nov 8, 2023
1c5c21d
Merge branch 'master' into Extended_DD
calculuschild Nov 9, 2023
b561f69
Merge branch 'master' into Extended_DD
dbolacksn Nov 10, 2023
a6ecec4
Merge remote-tracking branch 'origin/Extended_DD' into Extended_DD
dbolacksn Nov 10, 2023
827fdd3
REmove a console message.
dbolacksn Nov 10, 2023
c78dcbf
Remove Line-break
dbolacksn Nov 11, 2023
0624f8a
Add basic tests for Dictionary lists.
dbolacksn Nov 22, 2023
eeba037
Merge branch 'master' into Extended_DD
dbolacksn Dec 6, 2023
96d9735
Updated and reworked to handle more definition*
dbolacksn Dec 21, 2023
dfd5b22
Merge branch 'master' into Extended_DD
dbolack-ab Dec 22, 2023
993ae29
Update editor pattern match for DLs
dbolacksn Jan 7, 2024
20b76bd
Fix issue when pattern matches a DD without DT
dbolacksn Jan 13, 2024
d076d6c
Update tests for previous changes.
dbolacksn Jan 14, 2024
4c2211c
Updated rendering to follow input line breaks
dbolacksn Jan 14, 2024
d09dc11
The remainder of the tests
dbolacksn Jan 14, 2024
0470d13
Add optimized NC logo
G-Ambatte Oct 1, 2023
fe0cfcb
New file was unnecessary
G-Ambatte Oct 1, 2023
c9c5176
Add Credits styling to 5ePHB theme
G-Ambatte Oct 1, 2023
2f383d5
Add HB Credit snippet
G-Ambatte Oct 1, 2023
d0ccc4a
Capitalize C in NaturalCrit.com
G-Ambatte Oct 1, 2023
0337761
Change the text to include URL link
G-Ambatte Oct 1, 2023
e56ff93
Add underline on hover to link in credit
G-Ambatte Oct 1, 2023
c0cabbb
Move Credits snippet to Blank
dbolacksn Jan 16, 2024
ce8cbba
Merge branch 'master' into Extended_DD
dbolacksn Jan 16, 2024
c747c55
Add PANdoc style lists ( using :: not : )
dbolacksn Jan 16, 2024
faba9f1
Merge branch 'master' into Extended_DD
dbolacksn Jan 19, 2024
7782e20
Merge branch 'master' into Extended_DD
dbolack-ab Jan 20, 2024
8ab2733
Merge branch 'master' of github.com:naturalcrit/homebrewery
dbolacksn Jan 26, 2024
46140e9
Merge branch 'master' into pr/3129
calculuschild Jan 30, 2024
e4324f3
Merge branch 'master' of github.com:naturalcrit/homebrewery
dbolacksn Jan 30, 2024
e1ad05e
Solve regression with monster template.
dbolacksn Jan 30, 2024
265e997
Merge branch 'master' of github.com:naturalcrit/homebrewery
dbolacksn Jan 31, 2024
29dc1e0
Merge branch 'master' into Extended_DD
dbolacksn Jan 31, 2024
283c2b5
Empty Tag multiline input
dbolacksn Feb 6, 2024
703e207
I think I have all the desired modes in place.
dbolacksn Feb 7, 2024
3ee9fe1
Update tests.
dbolacksn Feb 7, 2024
43b9f3d
Merge branch 'master' into Extended_DD
dbolack-ab Feb 7, 2024
13fbcd0
Improve Regex to permit DTs with a final :
dbolacksn Feb 7, 2024
ea320e0
Merge branch 'master' into Extended_DD
dbolack-ab Feb 8, 2024
f3148ed
Fix Syntax Highlighting
dbolacksn Feb 8, 2024
2b81c26
Working, but ugly
dbolacksn Feb 9, 2024
67b11d6
Small DD appending mode fix
dbolacksn Feb 9, 2024
84d5b26
Merge branch 'master' of github.com:naturalcrit/homebrewery
dbolacksn Feb 25, 2024
d1d28ac
Merge branch 'master' into Extended_DD
dbolacksn Feb 25, 2024
05f88df
Extended Definition List cleanup
dbolacksn Feb 25, 2024
3734c9e
Merge branch 'master' of github.com:naturalcrit/homebrewery
dbolacksn Mar 4, 2024
7f16da1
Merge branch 'master' into Extended_DD
dbolacksn Mar 4, 2024
15f95dd
Merge branch 'master' of github.com:naturalcrit/homebrewery
dbolacksn Mar 4, 2024
4f4b43f
Merge branch 'naturalcrit:master' into master
dbolacksn Mar 5, 2024
8c773ce
Merge branch 'master' of github.com:naturalcrit/homebrewery
dbolacksn Mar 7, 2024
8ab91c3
Merge branch 'master' of github.com:dbolacksn/homebrewery-broken
dbolacksn Mar 7, 2024
cd537f9
Merge branch 'master' into Extended_DD
dbolacksn Mar 7, 2024
f6c0b0d
Simplification of CSS
calculuschild Mar 8, 2024
e36a638
Add more tests
calculuschild Mar 9, 2024
ed6718e
Merge branch 'master' of github.com:naturalcrit/homebrewery
dbolacksn Mar 10, 2024
04e6f2e
Merge branch 'master' into Extended_DD
dbolacksn Mar 10, 2024
f3b17f4
Fix bad merge
dbolacksn Mar 10, 2024
d6aa013
Merge branch 'Extended_DD' of github.com:dbolacksn/homebrewery-broken…
dbolacksn Mar 10, 2024
d775623
More tests. Split into two extensions
calculuschild Mar 14, 2024
f37da19
lint
calculuschild Mar 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions client/homebrew/editor/editor.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -151,12 +151,19 @@ const Editor = createClass({

// definition lists
if(line.includes('::')){
const regex = /^([^\n]*?)::([^\n]*)(?:\n|$)/ym;
if(/^:*$/.test(line) == true){ return };
const regex = /^([^\n]*?:?\s?)(::[^\n]*)(?:\n|$)/ymd; // the `d` flag, for match indices, throws an ESLint error.
let match;
while ((match = regex.exec(line)) != null){
codeMirror.markText({ line: lineNumber, ch: line.indexOf(match[0]) }, { line: lineNumber, ch: line.indexOf(match[0]) + match[0].length }, { className: 'define' });
codeMirror.markText({ line: lineNumber, ch: line.indexOf(match[1]) }, { line: lineNumber, ch: line.indexOf(match[1]) + match[1].length }, { className: 'term' });
codeMirror.markText({ line: lineNumber, ch: line.indexOf(match[2]) }, { line: lineNumber, ch: line.indexOf(match[2]) + match[2].length }, { className: 'definition' });
codeMirror.markText({ line: lineNumber, ch: match.indices[0][0] }, { line: lineNumber, ch: match.indices[0][1] }, { className: 'dl-highlight' });
codeMirror.markText({ line: lineNumber, ch: match.indices[1][0] }, { line: lineNumber, ch: match.indices[1][1] }, { className: 'dt-highlight' });
codeMirror.markText({ line: lineNumber, ch: match.indices[2][0] }, { line: lineNumber, ch: match.indices[2][1] }, { className: 'dd-highlight' });
const ddIndex = match.indices[2][0];
let colons = /::/g;
let colonMatches = colons.exec(match[2]);
if(colonMatches !== null){
codeMirror.markText({ line: lineNumber, ch: colonMatches.index + ddIndex }, { line: lineNumber, ch: colonMatches.index + colonMatches[0].length + ddIndex }, { className: 'dl-colon-highlight'} )
}
}
}

Expand Down
10 changes: 10 additions & 0 deletions client/homebrew/editor/editor.less
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,16 @@
vertical-align : sub;
font-size : 0.9em;
}
.dl-highlight {
&.dl-colon-highlight {
font-weight : bold;
color : #949494;
background : #E5E5E5;
border-radius : 3px;
}
&.dt-highlight { color : rgb(96, 117, 143); }
&.dd-highlight { color : rgb(97, 57, 178); }
}
}

.brewJump {
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"test:mustache-syntax:inline": "jest '.*(mustache-syntax).*' -t '^Inline:.*' --verbose --noStackTrace",
"test:mustache-syntax:block": "jest '.*(mustache-syntax).*' -t '^Block:.*' --verbose --noStackTrace",
"test:mustache-syntax:injection": "jest '.*(mustache-syntax).*' -t '^Injection:.*' --verbose --noStackTrace",
"test:marked-extensions": "jest tests/markdown/marked-extensions.test.js --verbose --noStackTrace",
"test:route": "jest tests/routes/static-pages.test.js --verbose",
"phb": "node scripts/phb.js",
"prod": "set NODE_ENV=production && npm run build",
Expand Down
55 changes: 49 additions & 6 deletions shared/naturalcrit/markdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -294,10 +294,10 @@ const superSubScripts = {
}
};

const definitionLists = {
name : 'definitionLists',
const definitionListsInline = {
name : 'definitionListsInline',
level : 'block',
start(src) { return src.match(/^.*?::.*/m)?.index; }, // Hint to Marked.js to stop and check for a match
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]*)(?:\n|$)/ym;
let match;
Expand All @@ -312,7 +312,7 @@ const definitionLists = {
}
if(definitions.length) {
return {
type : 'definitionLists',
type : 'definitionListsInline',
raw : src.slice(0, endIndex),
definitions
};
Expand All @@ -321,11 +321,54 @@ const definitionLists = {
renderer(token) {
return `<dl>${token.definitions.reduce((html, def)=>{
return `${html}<dt>${this.parser.parseInline(def.dt)}</dt>`
+ `<dd>${this.parser.parseInline(def.dd)}</dd>\n`;
+ `<dd>${this.parser.parseInline(def.dd)}</dd>`;
}, '')}</dl>`;
}
};

const definitionListsMultiline = {
name : 'definitionListsMultiline',
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?(?!::)[^\n]+?(?=\n::))|\n::(.(?:.|\n)*?(?=(?:\n::)|(?:\n\n)|$))/y;
let match;
let endIndex = 0;
const definitions = [];
while (match = regex.exec(src)) {
if(match[1]) {
definitions.push({
dt : this.lexer.inlineTokens(match[1].trim()),
dds : []
});
}
if(match[2]) {
definitions[definitions.length - 1].dds.push(
this.lexer.inlineTokens(match[2].trim().replace(/\s/g, ' '))
);
}
endIndex = regex.lastIndex;
}
if(definitions.length) {
return {
type : 'definitionListsMultiline',
raw : src.slice(0, endIndex),
definitions
};
}
},
renderer(token) {
let returnVal = `<dl>`;
token.definitions.forEach((def)=>{
const dds = def.dds.map((s)=>{
return `\n<dd>${this.parser.parseInline(s).trim()}</dd>`;
}).join('');
returnVal += `<dt>${this.parser.parseInline(def.dt)}</dt>${dds}\n`;
});
returnVal = returnVal.trim();
return `${returnVal}</dl>`;
}
};

//v=====--------------------< Variable Handling >-------------------=====v// 242 lines
const replaceVar = function(input, hoist=false, allowUnresolved=false) {
Expand Down Expand Up @@ -572,7 +615,7 @@ function MarkedVariables() {
//^=====--------------------< Variable Handling >-------------------=====^//

Marked.use(MarkedVariables());
Marked.use({ extensions: [mustacheSpans, mustacheDivs, mustacheInjectInline, definitionLists, superSubScripts] });
Marked.use({ extensions: [mustacheSpans, mustacheDivs, mustacheInjectInline, definitionListsInline, definitionListsMultiline, superSubScripts] });
Marked.use(mustacheInjectBlock);
Marked.use({ renderer: renderer, tokenizer: tokenizer, mangle: false });
Marked.use(MarkedExtendedTables(), MarkedGFMHeadingId(), MarkedSmartypantsLite());
Expand Down
79 changes: 79 additions & 0 deletions tests/markdown/marked-extensions.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/* eslint-disable max-lines */

const Markdown = require('naturalcrit/markdown.js');

describe('Inline Definition Lists', ()=>{
test('No Term 1 Definition', function() {
const source = ':: My First Definition\n\n';
const rendered = Markdown.render(source).trim();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<dl><dt></dt><dd>My First Definition</dd></dl>');
});

test('Single Definition Term', function() {
const source = 'My term :: My First Definition\n\n';
const rendered = Markdown.render(source).trim();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<dl><dt>My term</dt><dd>My First Definition</dd></dl>');
});

test('Multiple Definition Terms', function() {
const source = 'Term 1::Definition of Term 1\nTerm 2::Definition of Term 2\n\n';
const rendered = Markdown.render(source).trim();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<dl><dt>Term 1</dt><dd>Definition of Term 1</dd><dt>Term 2</dt><dd>Definition of Term 2</dd></dl>');
});
});

describe('Multiline Definition Lists', ()=>{
test('Single Term, Single Definition', function() {
const source = 'Term 1\n::Definition 1\n\n';
const rendered = Markdown.render(source).trim();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<dl><dt>Term 1</dt>\n<dd>Definition 1</dd></dl>');
});

test('Single Term, Plural Definitions', function() {
const source = 'Term 1\n::Definition 1\n::Definition 2\n\n';
const rendered = Markdown.render(source).trim();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<dl><dt>Term 1</dt>\n<dd>Definition 1</dd>\n<dd>Definition 2</dd></dl>');
});

test('Multiple Term, Single Definitions', function() {
const source = 'Term 1\n::Definition 1\n\nTerm 2\n::Definition 1\n\n';
const rendered = Markdown.render(source).trim();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<dl><dt>Term 1</dt>\n<dd>Definition 1</dd>\n<dt>Term 2</dt>\n<dd>Definition 1</dd></dl>');
});

test('Multiple Term, Plural Definitions', function() {
const source = 'Term 1\n::Definition 1\n::Definition 2\n\nTerm 2\n::Definition 1\n::Definition 2\n\n';
const rendered = Markdown.render(source).trim();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<dl><dt>Term 1</dt>\n<dd>Definition 1</dd>\n<dd>Definition 2</dd>\n<dt>Term 2</dt>\n<dd>Definition 1</dd>\n<dd>Definition 2</dd></dl>');
});

test('Single Term, Single multi-line definition', function() {
const source = 'Term 1\n::Definition 1\nand more and\nmore and more\n\n';
const rendered = Markdown.render(source).trim();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<dl><dt>Term 1</dt>\n<dd>Definition 1 and more and more and more</dd></dl>');
});

test('Single Term, Plural multi-line definitions', function() {
const source = 'Term 1\n::Definition 1\nand more and more\n::Definition 2\nand more\nand more\n::Definition 3\n\n';
const rendered = Markdown.render(source).trim();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<dl><dt>Term 1</dt>\n<dd>Definition 1 and more and more</dd>\n<dd>Definition 2 and more and more</dd>\n<dd>Definition 3</dd></dl>');
});

test('Multiple Term, Single multi-line definition', function() {
const source = 'Term 1\n::Definition 1\nand more and more\n\nTerm 2\n::Definition 1\n::Definition 2\n\n';
const rendered = Markdown.render(source).trim();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<dl><dt>Term 1</dt>\n<dd>Definition 1 and more and more</dd>\n<dt>Term 2</dt>\n<dd>Definition 1</dd>\n<dd>Definition 2</dd></dl>');
});

test('Multiple Term, Single multi-line definition, followed by an inline dl', function() {
const source = 'Term 1\n::Definition 1\nand more and more\n\nTerm 2\n::Definition 1\n::Definition 2\n\n::Inline Definition (no term)';
const rendered = Markdown.render(source).trim();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<dl><dt>Term 1</dt>\n<dd>Definition 1 and more and more</dd>\n<dt>Term 2</dt>\n<dd>Definition 1</dd>\n<dd>Definition 2</dd></dl><dl><dt></dt><dd>Inline Definition (no term)</dd></dl>');
});

test('Multiple Term, Single multi-line definition, followed by paragraph', function() {
const source = 'Term 1\n::Definition 1\nand more and more\n\nTerm 2\n::Definition 1\n::Definition 2\n\nParagraph';
const rendered = Markdown.render(source).trim();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<dl><dt>Term 1</dt>\n<dd>Definition 1 and more and more</dd>\n<dt>Term 2</dt>\n<dd>Definition 1</dd>\n<dd>Definition 2</dd></dl><p>Paragraph</p>');
});
});