add metadata

This commit is contained in:
Estevão Soares dos Santos 2022-04-21 03:06:44 +01:00
parent c48801d8fa
commit a82a51d147
2 changed files with 84 additions and 21 deletions

View File

@ -27,7 +27,7 @@ Note:
This object holds the text captured by the subparser. The properties of this object
are different for each subparser.
Properties whose name starts with `_` are readonly.
**Properties whose name starts with `_` are readonly**.
Example:
@ -214,3 +214,15 @@ These events are always guaranteed to be called, regardless of options or circum
### blockquote
####
### metadata
## Common pitfalls
### Infinite loop
If you pass the input as output in a `onCapture` event, you might trigger an infinite loop.

View File

@ -8,11 +8,50 @@ showdown.subParser('makehtml.metadata', function (text, options, globals) {
return text;
}
text = globals.converter._dispatch('makehtml.metadata.before', text, options, globals).getText();
let startEvent = new showdown.Event('makehtml.metadata.onStart', text);
startEvent
.setOutput(text)
._setGlobals(globals)
._setOptions(options);
startEvent = globals.converter.dispatch(startEvent);
text = startEvent.output;
/**
* @param {RegExp} pattern
* @param {string} wholeMatch
* @param {string} format
* @param {string} content
* @returns {string}
*/
function parseMetadataContents (pattern, wholeMatch, format, content) {
let otp;
let captureStartEvent = new showdown.Event('makehtml.metadata.onCapture', content);
captureStartEvent
.setOutput(null)
._setGlobals(globals)
._setOptions(options)
.setRegexp(pattern)
.setMatches({
_wholeMatch: wholeMatch,
format: format,
content: content
})
.setAttributes({});
captureStartEvent = globals.converter.dispatch(captureStartEvent);
format = captureStartEvent.matches.format;
content = captureStartEvent.matches.content;
// if something was passed as output, it will be used as output
if (captureStartEvent.output && captureStartEvent.output !== '') {
otp = captureStartEvent.output;
} else {
otp = '¨M';
}
function parseMetadataContents (content) {
// raw is raw so it's not changed in any way
globals.metadata.raw = content;
globals.metadata.format = format;
// escape chars forbidden in html attributes
// double quotes
@ -20,35 +59,47 @@ showdown.subParser('makehtml.metadata', function (text, options, globals) {
// ampersand first
.replace(/&/g, '&')
// double quotes
.replace(/"/g, '"');
.replace(/"/g, '"')
// Restore dollar signs and tremas
content = content
.replace(/¨D/g, '$$')
.replace(/¨T/g, '¨');
.replace(/¨T/g, '¨')
// replace multiple spaces
.replace(/\n {4}/g, ' ');
content = content.replace(/\n {4}/g, ' ');
content.replace(/^([\S ]+): +([\s\S]+?)$/gm, function (wm, key, value) {
globals.metadata.parsed[key] = value;
return '';
});
let beforeHashEvent = new showdown.Event('makehtml.metadata.onHash', otp);
beforeHashEvent
.setOutput(otp)
._setGlobals(globals)
._setOptions(options);
beforeHashEvent = globals.converter.dispatch(beforeHashEvent);
otp = beforeHashEvent.output;
if (!otp) {
otp = '¨M';
}
return otp;
}
text = text.replace(/^\s*«««+\s*(\S*?)\n([\s\S]+?)\n»»»+\s*\n/, function (wholematch, format, content) {
parseMetadataContents(content);
return '¨M';
// 1. Metadata with «««»»» delimiters
const rgx1 = /^\s*«««+\s*(\S*?)\n([\s\S]+?)\n»»»+\s*\n/;
text = text.replace(rgx1, function (wholeMatch, format, content) {
return parseMetadataContents(rgx1, wholeMatch, format, content);
});
text = text.replace(/^\s*---+\s*(\S*?)\n([\s\S]+?)\n---+\s*\n/, function (wholematch, format, content) {
if (format) {
globals.metadata.format = format;
}
parseMetadataContents(content);
return '¨M';
// 2. Metadata with YAML delimiters
const rgx2 = /^\s*---+\s*(\S*?)\n([\s\S]+?)\n---+\s*\n/;
text = text.replace(rgx2, function (wholeMatch, format, content) {
return parseMetadataContents(rgx1, wholeMatch, format, content);
});
text = text.replace(/¨M/g, '');
text = globals.converter._dispatch('makehtml.metadata.after', text, options, globals).getText();
return text;
let afterEvent = new showdown.Event('makehtml.metadata.onEnd', text);
afterEvent
.setOutput(text)
._setGlobals(globals)
._setOptions(options);
afterEvent = globals.converter.dispatch(afterEvent);
return afterEvent.output;
});