mirror of
https://github.com/showdownjs/showdown.git
synced 2024-03-22 13:30:55 +08:00
hard line break implementation
This commit is contained in:
parent
6e6af3cc03
commit
cd293fb61a
|
@ -55,6 +55,8 @@ showdown.subParser('makehtml.codeSpan', function (text, options, globals) {
|
||||||
|
|
||||||
c = c.replace(/^([ \t]*)/g, ''); // leading whitespace
|
c = c.replace(/^([ \t]*)/g, ''); // leading whitespace
|
||||||
c = c.replace(/[ \t]*$/g, ''); // trailing whitespace
|
c = c.replace(/[ \t]*$/g, ''); // trailing whitespace
|
||||||
|
// remove newlines
|
||||||
|
c = c.replace(/\n/, ' ');
|
||||||
|
|
||||||
let captureStartEvent = new showdown.Event('makehtml.codeSpan.onCapture', c);
|
let captureStartEvent = new showdown.Event('makehtml.codeSpan.onCapture', c);
|
||||||
captureStartEvent
|
captureStartEvent
|
||||||
|
|
|
@ -85,18 +85,23 @@ showdown.subParser('makehtml.emphasisAndStrong', function (text, options, global
|
||||||
if (showdown.helper.isUndefined(attributes.strong)) {
|
if (showdown.helper.isUndefined(attributes.strong)) {
|
||||||
attributes.strong = {};
|
attributes.strong = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (tags) {
|
switch (tags) {
|
||||||
case '<em>':
|
case '<em>':
|
||||||
otp = '<em' + showdown.helper._populateAttributes(attributes.em) + '>' + txt + '</em>';
|
otp = '<em' + showdown.helper._populateAttributes(attributes.em) + '>' +
|
||||||
|
showdown.subParser('makehtml.hardLineBreaks')(txt, options, globals) +
|
||||||
|
'</em>';
|
||||||
break;
|
break;
|
||||||
case '<strong>':
|
case '<strong>':
|
||||||
otp = '<strong' + showdown.helper._populateAttributes(attributes.strong) + '>' + txt + '</strong>';
|
otp = '<strong' + showdown.helper._populateAttributes(attributes.strong) + '>' +
|
||||||
|
showdown.subParser('makehtml.hardLineBreaks')(txt, options, globals) +
|
||||||
|
'</strong>';
|
||||||
break;
|
break;
|
||||||
case '<strong><em>':
|
case '<strong><em>':
|
||||||
otp = '<strong' + showdown.helper._populateAttributes(attributes.strong) + '>' +
|
otp = '<strong' + showdown.helper._populateAttributes(attributes.strong) + '>' +
|
||||||
'<em' + showdown.helper._populateAttributes(attributes.em) + '>' +
|
'<em' + showdown.helper._populateAttributes(attributes.em) + '>' +
|
||||||
txt +
|
showdown.subParser('makehtml.hardLineBreaks')(txt, options, globals) +
|
||||||
'</em>' +
|
'</em>' +
|
||||||
'</strong>';
|
'</strong>';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -109,10 +114,11 @@ showdown.subParser('makehtml.emphasisAndStrong', function (text, options, global
|
||||||
._setOptions(options);
|
._setOptions(options);
|
||||||
beforeHashEvent = globals.converter.dispatch(beforeHashEvent);
|
beforeHashEvent = globals.converter.dispatch(beforeHashEvent);
|
||||||
otp = beforeHashEvent.output;
|
otp = beforeHashEvent.output;
|
||||||
|
otp = showdown.subParser('makehtml.hashHTMLSpans')(otp, options, globals);
|
||||||
return otp;
|
return otp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// it's faster to have 3 separate regexes for each case than have just one
|
// it's faster to have separate regexes for each case than have just one
|
||||||
// because of backtracking, in some cases, it could lead to an exponential effect
|
// because of backtracking, in some cases, it could lead to an exponential effect
|
||||||
// called "catastrophic backtrace". Ominous!
|
// called "catastrophic backtrace". Ominous!
|
||||||
const lmwuStrongEmRegex = /\b___(\S[\s\S]*?)___\b/g,
|
const lmwuStrongEmRegex = /\b___(\S[\s\S]*?)___\b/g,
|
||||||
|
|
|
@ -42,7 +42,6 @@ showdown.subParser('makehtml.githubCodeBlock', function (text, options, globals)
|
||||||
});
|
});
|
||||||
|
|
||||||
text = text.replace(emptyBlockRegex, function (wholeMatch, delim, language) {
|
text = text.replace(emptyBlockRegex, function (wholeMatch, delim, language) {
|
||||||
console.log('|', wholeMatch, '|>');
|
|
||||||
return parse(emptyBlockRegex, wholeMatch, delim, language, '');
|
return parse(emptyBlockRegex, wholeMatch, delim, language, '');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
32
src/subParsers/makehtml/hardLineBreaks.js
Normal file
32
src/subParsers/makehtml/hardLineBreaks.js
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
////
|
||||||
|
// makehtml/emphasisAndStrong.js
|
||||||
|
// Copyright (c) 2022 ShowdownJS
|
||||||
|
//
|
||||||
|
// Transforms MD emphasis and strong into `<em>` and `<strong>` html entities
|
||||||
|
//
|
||||||
|
// Markdown treats asterisks (*) and underscores (_) as indicators of emphasis.
|
||||||
|
// Text wrapped with one * or _ will be wrapped with an HTML <em> tag;
|
||||||
|
// double *’s or _’s will be wrapped with an HTML <strong> tag
|
||||||
|
//
|
||||||
|
// ***Author:***
|
||||||
|
// - Estêvão Soares dos Santos (Tivie) <https://github.com/tivie>
|
||||||
|
////
|
||||||
|
|
||||||
|
showdown.subParser('makehtml.hardLineBreaks', function (text, options) {
|
||||||
|
|
||||||
|
// Do hard breaks
|
||||||
|
if (options.simpleLineBreaks) {
|
||||||
|
// GFM style hard breaks
|
||||||
|
// only add line breaks if the text does not contain a block (special case for lists)
|
||||||
|
if (!/\n\n¨K/.test(text)) {
|
||||||
|
text = text.replace(/\n+/gm, '<br />\n');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Vanilla hard breaks
|
||||||
|
text = text.replace(/ +\n/g, '<br />\n');
|
||||||
|
}
|
||||||
|
text = text.replace(/\\\n/g, '<br />\n');
|
||||||
|
|
||||||
|
return text;
|
||||||
|
|
||||||
|
});
|
|
@ -168,7 +168,6 @@ showdown.subParser('makehtml.heading', function (text, options, globals) {
|
||||||
}
|
}
|
||||||
|
|
||||||
nPrepend = showdown.subParser('makehtml.blockGamut')(multilineText, options, globals, 'makehtml.heading');
|
nPrepend = showdown.subParser('makehtml.blockGamut')(multilineText, options, globals, 'makehtml.heading');
|
||||||
//console.log(nPrepend);
|
|
||||||
if (nPrepend !== multilineText) {
|
if (nPrepend !== multilineText) {
|
||||||
// we found a block, so it should take precedence
|
// we found a block, so it should take precedence
|
||||||
prepend += nPrepend;
|
prepend += nPrepend;
|
||||||
|
@ -192,7 +191,7 @@ showdown.subParser('makehtml.heading', function (text, options, globals) {
|
||||||
|
|
||||||
function parseHeader (pattern, wholeMatch, headingText, headingLevel, headingId) {
|
function parseHeader (pattern, wholeMatch, headingText, headingLevel, headingId) {
|
||||||
let captureStartEvent = new showdown.Event('makehtml.heading.onCapture', headingText),
|
let captureStartEvent = new showdown.Event('makehtml.heading.onCapture', headingText),
|
||||||
otp;
|
otp;
|
||||||
|
|
||||||
captureStartEvent
|
captureStartEvent
|
||||||
.setOutput(null)
|
.setOutput(null)
|
||||||
|
@ -215,7 +214,7 @@ showdown.subParser('makehtml.heading', function (text, options, globals) {
|
||||||
} else {
|
} else {
|
||||||
headingText = captureStartEvent.matches.heading;
|
headingText = captureStartEvent.matches.heading;
|
||||||
let spanGamut = showdown.subParser('makehtml.spanGamut')(headingText, options, globals),
|
let spanGamut = showdown.subParser('makehtml.spanGamut')(headingText, options, globals),
|
||||||
attributes = captureStartEvent.attributes;
|
attributes = captureStartEvent.attributes;
|
||||||
otp = '<h' + headingLevel + showdown.helper._populateAttributes(attributes) + '>' + spanGamut + '</h' + headingLevel + '>';
|
otp = '<h' + headingLevel + showdown.helper._populateAttributes(attributes) + '>' + spanGamut + '</h' + headingLevel + '>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,17 +34,7 @@ showdown.subParser('makehtml.spanGamut', function (text, options, globals) {
|
||||||
// now we encode amps and angles
|
// now we encode amps and angles
|
||||||
text = showdown.subParser('makehtml.encodeAmpsAndAngles')(text, options, globals);
|
text = showdown.subParser('makehtml.encodeAmpsAndAngles')(text, options, globals);
|
||||||
|
|
||||||
// Do hard breaks
|
text = showdown.subParser('makehtml.hardLineBreaks')(text, options, globals);
|
||||||
if (options.simpleLineBreaks) {
|
|
||||||
// GFM style hard breaks
|
|
||||||
// only add line breaks if the text does not contain a block (special case for lists)
|
|
||||||
if (!/\n\n¨K/.test(text)) {
|
|
||||||
text = text.replace(/\n+/g, '<br />\n');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Vanilla hard breaks
|
|
||||||
text = text.replace(/ +\n/g, '<br />\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
let afterEvent = new showdown.Event('makehtml.spanGamut.onEnd', text);
|
let afterEvent = new showdown.Event('makehtml.spanGamut.onEnd', text);
|
||||||
afterEvent
|
afterEvent
|
||||||
|
|
|
@ -33,7 +33,9 @@ showdown.subParser('makehtml.strikethrough', function (text, options, globals) {
|
||||||
if (captureStartEvent.output && captureStartEvent.output !== '') {
|
if (captureStartEvent.output && captureStartEvent.output !== '') {
|
||||||
otp = captureStartEvent.output;
|
otp = captureStartEvent.output;
|
||||||
} else {
|
} else {
|
||||||
otp = '<del' + showdown.helper._populateAttributes(captureStartEvent.attributes) + '>' + txt + '</del>';
|
otp = '<del' + showdown.helper._populateAttributes(captureStartEvent.attributes) + '>' +
|
||||||
|
showdown.subParser('makehtml.hardLineBreaks')(txt, options, globals) +
|
||||||
|
'</del>';
|
||||||
}
|
}
|
||||||
|
|
||||||
let beforeHashEvent = new showdown.Event('makehtml.strikethrough.onHash', otp);
|
let beforeHashEvent = new showdown.Event('makehtml.strikethrough.onHash', otp);
|
||||||
|
|
|
@ -74,7 +74,9 @@ showdown.subParser('makehtml.underline', function (text, options, globals) {
|
||||||
if (captureStartEvent.output && captureStartEvent.output !== '') {
|
if (captureStartEvent.output && captureStartEvent.output !== '') {
|
||||||
otp = captureStartEvent.output;
|
otp = captureStartEvent.output;
|
||||||
} else {
|
} else {
|
||||||
otp = '<u' + showdown.helper._populateAttributes(captureStartEvent.attributes) + '>' + txt + '</u>';
|
otp = '<u' + showdown.helper._populateAttributes(captureStartEvent.attributes) + '>' +
|
||||||
|
showdown.subParser('makehtml.hardLineBreaks')(txt, options, globals) +
|
||||||
|
'</u>';
|
||||||
}
|
}
|
||||||
let beforeHashEvent = new showdown.Event('makehtml.underline.onHash', otp);
|
let beforeHashEvent = new showdown.Event('makehtml.underline.onHash', otp);
|
||||||
beforeHashEvent
|
beforeHashEvent
|
||||||
|
|
|
@ -26,6 +26,7 @@ describe('makeHtml() commonmark testsuite', function () {
|
||||||
case 'Thematic breaks_43': // malformed input of test case
|
case 'Thematic breaks_43': // malformed input of test case
|
||||||
case 'Thematic breaks_61': // hr inside lists does not make sense
|
case 'Thematic breaks_61': // hr inside lists does not make sense
|
||||||
case 'Fenced code blocks_146': // as of date, github doesn't support this so we don't either
|
case 'Fenced code blocks_146': // as of date, github doesn't support this so we don't either
|
||||||
|
//case 'Raw HTML_619': // breaks prettifier so the test fails
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case 'Setext headings_91': //it's failing because the testcase converts " to " even though it's not supposed to
|
case 'Setext headings_91': //it's failing because the testcase converts " to " even though it's not supposed to
|
||||||
|
@ -40,6 +41,10 @@ describe('makeHtml() commonmark testsuite', function () {
|
||||||
case 'Fenced code blocks_144': // we use different classes to mark languages in fenced code blocks
|
case 'Fenced code blocks_144': // we use different classes to mark languages in fenced code blocks
|
||||||
testsuite[section][i].expected = testsuite[section][i].expected.replace('language-;', '; language-;');
|
testsuite[section][i].expected = testsuite[section][i].expected.replace('language-;', '; language-;');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'Hard line breaks_638':
|
||||||
|
console.log(testsuite[section][i].input);
|
||||||
|
|
||||||
}
|
}
|
||||||
it(name, assertion(testsuite[section][i], converter, true));
|
it(name, assertion(testsuite[section][i], converter, true));
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,8 +112,14 @@
|
||||||
|
|
||||||
//prettify
|
//prettify
|
||||||
if (prettify) {
|
if (prettify) {
|
||||||
testCase.expected = htmlPrettify(testCase.expected);
|
try {
|
||||||
testCase.actual = htmlPrettify(testCase.actual);
|
testCase.expected = htmlPrettify(testCase.expected);
|
||||||
|
testCase.actual = htmlPrettify(testCase.actual);
|
||||||
|
} catch (e) {
|
||||||
|
// some weird html in testcase breaks prettifier so we skip it and do some manual stuff
|
||||||
|
testCase.expected = testCase.expected.trim().replace('\n', '');
|
||||||
|
testCase.actual = testCase.actual.trim().replace('\n', '');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user