@ant-design/x-markdown
Version:
placeholder for @ant-design/x-markdown
114 lines (113 loc) • 3.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
exports.escapeHtml = escapeHtml;
exports.other = void 0;
var _marked = require("marked");
const other = exports.other = {
escapeTestNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,
escapeTest: /[&<>"']/,
notSpaceStart: /^\S*/,
endingNewline: /\n$/,
escapeReplace: /[&<>"']/g,
escapeReplaceNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g,
completeFencedCode: /^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})(?:[^\n]*)(?:\n|$)([\s\S]*?)(?:\n|$) {0,3}\1[~`]* *\n/
};
const escapeReplacements = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
};
const getEscapeReplacement = ch => escapeReplacements[ch];
function escapeHtml(html, encode) {
if (encode) {
if (other.escapeTest.test(html)) {
return html.replace(other.escapeReplace, getEscapeReplacement);
}
} else {
if (other.escapeTestNoEncode.test(html)) {
return html.replace(other.escapeReplaceNoEncode, getEscapeReplacement);
}
}
return html;
}
class Parser {
options;
markdownInstance;
constructor(options = {}) {
const {
markedConfig = {}
} = options;
this.options = options;
this.markdownInstance = new _marked.Marked();
this.configureLinkRenderer();
this.configureParagraphRenderer();
this.configureCodeRenderer();
// user config at last
this.markdownInstance.use(markedConfig);
}
configureLinkRenderer() {
if (!this.options.openLinksInNewTab) return;
const renderer = {
link({
href,
title,
tokens
}) {
const text = this.parser.parseInline(tokens);
const titleAttr = title ? ` title="${title}"` : '';
return `<a href="${href}"${titleAttr} target="_blank" rel="noopener noreferrer">${text}</a>`;
}
};
this.markdownInstance.use({
renderer
});
}
configureParagraphRenderer() {
const {
paragraphTag
} = this.options;
if (!paragraphTag) return;
const renderer = {
paragraph({
tokens
}) {
return `<${paragraphTag}>${this.parser.parseInline(tokens)}</${paragraphTag}>\n`;
}
};
this.markdownInstance.use({
renderer
});
}
configureCodeRenderer() {
const renderer = {
code({
text,
raw,
lang,
escaped,
codeBlockStyle
}) {
const langString = (lang || '').match(other.notSpaceStart)?.[0];
const code = `${text.replace(other.endingNewline, '')}\n`;
const isIndentedCode = codeBlockStyle === 'indented';
// if code is indented, it's done because it has no end tag
const streamStatus = isIndentedCode || other.completeFencedCode.test(raw) ? 'done' : 'loading';
const escapedCode = escaped ? code : escapeHtml(code, true);
const classAttr = langString ? ` class="language-${escapeHtml(langString)}"` : '';
return `<pre><code data-block="true" data-state="${streamStatus}"${classAttr}>${escapedCode}</code></pre>\n`;
}
};
this.markdownInstance.use({
renderer
});
}
parse(content) {
return this.markdownInstance.parse(content);
}
}
var _default = exports.default = Parser;