mirror of
https://github.com/showdownjs/showdown.git
synced 2024-03-22 13:30:55 +08:00
refactor codeblock to new event system
This commit is contained in:
parent
997adada9d
commit
954e065193
|
@ -74,11 +74,14 @@ Usually you would want to use this event if you wish to modify the subparser beh
|
|||
of the subparser.
|
||||
|
||||
**IMPORTANT NOTE**: Extensions listening to onCapture event should try to AVOID changing the output property.
|
||||
Instead, they should modify the values of the matches and attributes arrays. This is because
|
||||
the **output property takes precedence over the matches array**, which means 2 very important things:
|
||||
Instead, they should modify the values of the matches and attributes objects. This is because
|
||||
the **output property takes precedence over the matches objects** and **prevents showdown to call other subparsers**
|
||||
inside the captured fragment.This means 3 very important things:
|
||||
|
||||
1. If something is passed as the output property, any changes to the matches array will be ignored.
|
||||
2. Point 1 includes other extensions that listen to the same event.
|
||||
1. If something is passed as the output property, any changes to the matches and attributes objects will be ignored.
|
||||
2. Changes made by other extensions to the matches or attributes objects will also be ignored
|
||||
3. Showdown will not call other subparsers, such as encode code or span gamut in the text fragment, which may lead to
|
||||
weird results.
|
||||
|
||||
```javascript
|
||||
// showdown extension 1 that is listening to makehtml.blockquote.onCapture
|
||||
|
|
|
@ -61,6 +61,22 @@ showdown.helper.isUndefined = function (value) {
|
|||
return typeof value === 'undefined';
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if value is an object (excluding arrays)
|
||||
* @param {*} value
|
||||
* @returns {boolean}
|
||||
*/
|
||||
showdown.helper.isObject = function (value) {
|
||||
'use strict';
|
||||
return (
|
||||
typeof value === 'object' &&
|
||||
!Array.isArray(value) &&
|
||||
value !== null
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* ForEach helper function
|
||||
* Iterates over Arrays and Objects (own properties only)
|
||||
|
@ -551,6 +567,24 @@ showdown.helper.cloneObject = function (obj, deep) {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Populate attributes in output text
|
||||
* @param {string} text
|
||||
* @param {{}} attributes
|
||||
* @returns {string}
|
||||
*/
|
||||
showdown.helper._populateAttributes = function (attributes) {
|
||||
let text = '';
|
||||
if (attributes && showdown.helper.isObject(attributes)) {
|
||||
for (let attr in attributes) {
|
||||
if (attributes.hasOwnProperty(attr)) {
|
||||
text += ' ' + attr + '=' + attributes[attr];
|
||||
}
|
||||
}
|
||||
}
|
||||
return text;
|
||||
};
|
||||
|
||||
showdown.helper.Event = class {
|
||||
|
||||
/**
|
||||
|
|
|
@ -75,13 +75,7 @@ showdown.subParser('makehtml.blockQuotes', function (text, options, globals) {
|
|||
return pre;
|
||||
});
|
||||
attributes = captureStartEvent.attributes;
|
||||
otp = '<blockquote';
|
||||
for (let attr in attributes) {
|
||||
if (attributes.hasOwnProperty(attr)) {
|
||||
otp += ' ' + attr + '=' + attributes[attr];
|
||||
}
|
||||
}
|
||||
otp += '>\n' + bq + '\n</blockquote>';
|
||||
otp = '<blockquote' + showdown.helper._populateAttributes(attributes) + '>\n' + bq + '\n</blockquote>';
|
||||
}
|
||||
|
||||
let beforeHashEvent = new showdown.helper.Event('makehtml.blockQuotes.onHash', otp);
|
||||
|
|
|
@ -65,24 +65,8 @@ showdown.subParser('makehtml.codeBlocks', function (text, options, globals) {
|
|||
|
||||
otp = '<pre><code>';
|
||||
if (!showdown.helper.isUndefined(attributes)) {
|
||||
otp = '<pre';
|
||||
if (!showdown.helper.isUndefined(attributes.pre)) {
|
||||
for (let preAttr in attributes.pre) {
|
||||
if (attributes.hasOwnProperty(preAttr)) {
|
||||
otp += ' ' + preAttr + '=' + attributes[preAttr];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
otp += '><code';
|
||||
if (!showdown.helper.isUndefined(attributes.code)) {
|
||||
for (let codeAttr in attributes.code) {
|
||||
if (attributes.hasOwnProperty(codeAttr)) {
|
||||
otp += ' ' + codeAttr + '=' + attributes[codeAttr];
|
||||
}
|
||||
}
|
||||
}
|
||||
otp += '>';
|
||||
otp = '<pre' + showdown.helper._populateAttributes(attributes.pre) + '>';
|
||||
otp += '<code' + showdown.helper._populateAttributes(attributes.code) + '>';
|
||||
}
|
||||
if (options.omitExtraWLInCodeBlocks) {
|
||||
end = '';
|
||||
|
|
|
@ -26,23 +26,69 @@
|
|||
showdown.subParser('makehtml.codeSpans', function (text, options, globals) {
|
||||
'use strict';
|
||||
|
||||
text = globals.converter._dispatch('makehtml.codeSpans.before', text, options, globals).getText();
|
||||
let startEvent = new showdown.helper.Event('makehtml.codeSpans.onStart', text);
|
||||
startEvent
|
||||
.setOutput(text)
|
||||
._setGlobals(globals)
|
||||
._setOptions(options);
|
||||
|
||||
if (typeof (text) === 'undefined') {
|
||||
startEvent = globals.converter.dispatch(startEvent);
|
||||
|
||||
text = startEvent.output;
|
||||
|
||||
if (showdown.helper.isUndefined((text))) {
|
||||
text = '';
|
||||
}
|
||||
text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,
|
||||
function (wholeMatch, m1, m2, m3) {
|
||||
var c = m3;
|
||||
|
||||
let pattern = /(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm;
|
||||
|
||||
text = text.replace(pattern,
|
||||
function (wholeMatch, m1, m2, c) {
|
||||
let otp,
|
||||
attributes = {};
|
||||
|
||||
c = c.replace(/^([ \t]*)/g, ''); // leading whitespace
|
||||
c = c.replace(/[ \t]*$/g, ''); // trailing whitespace
|
||||
c = showdown.subParser('makehtml.encodeCode')(c, options, globals);
|
||||
c = m1 + '<code>' + c + '</code>';
|
||||
c = showdown.subParser('makehtml.hashHTMLSpans')(c, options, globals);
|
||||
return c;
|
||||
|
||||
let captureStartEvent = new showdown.helper.Event('makehtml.codeSpans.onCapture', c);
|
||||
captureStartEvent
|
||||
.setOutput(null)
|
||||
._setGlobals(globals)
|
||||
._setOptions(options)
|
||||
.setRegexp(pattern)
|
||||
.setMatches({
|
||||
code: c
|
||||
})
|
||||
.setAttributes({});
|
||||
captureStartEvent = globals.converter.dispatch(captureStartEvent);
|
||||
|
||||
// if something was passed as output, it takes precedence
|
||||
// and will be used as output
|
||||
if (captureStartEvent.output && captureStartEvent.output !== '') {
|
||||
otp = m1 + captureStartEvent.output;
|
||||
} else {
|
||||
c = captureStartEvent.matches.code;
|
||||
c = showdown.subParser('makehtml.encodeCode')(c, options, globals);
|
||||
otp = m1 + '<code' + showdown.helper._populateAttributes(attributes) + '>' + c + '</code>';
|
||||
}
|
||||
|
||||
let beforeHashEvent = new showdown.helper.Event('makehtml.codeSpans.onHash', otp);
|
||||
beforeHashEvent
|
||||
.setOutput(otp)
|
||||
._setGlobals(globals)
|
||||
._setOptions(options);
|
||||
|
||||
beforeHashEvent = globals.converter.dispatch(beforeHashEvent);
|
||||
otp = beforeHashEvent.output;
|
||||
return showdown.subParser('makehtml.hashHTMLSpans')(otp, options, globals);
|
||||
}
|
||||
);
|
||||
|
||||
text = globals.converter._dispatch('makehtml.codeSpans.after', text, options, globals).getText();
|
||||
return text;
|
||||
let afterEvent = new showdown.helper.Event('makehtml.codeSpans.onEnd', text);
|
||||
afterEvent
|
||||
.setOutput(text)
|
||||
._setGlobals(globals)
|
||||
._setOptions(options);
|
||||
|
||||
return afterEvent.output;
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue
Block a user