vnote/src/data/extra/web/js/turndown.js
Le Tan a4a5dea3d7 fixes
* MarkdownViewWindow: add switch for code block line number
* MarkodwnViewWindow: fix Turndown <style> issue
* MarkdownViewWindow: add config for overridding MathJax script
* SortDialog: fix sorting issue of date
* FramelessMainWindow: fix StayOnTop issue
2022-01-10 20:06:45 +08:00

119 lines
3.6 KiB
JavaScript

// Convert HTML to Markdown.
class TurndownConverter {
constructor(p_adapter) {
this.adapter = p_adapter;
turndownPluginGfm.options.autoHead = true;
this.ts = new TurndownService({headingStyle: 'atx',
bulletListMarker: '*',
emDelimiter: '*',
hr: '***',
codeBlockStyle: 'fenced',
blankReplacement: function(content, node) {
if (node.nodeName == 'SPAN') {
return content;
}
return node.isBlock ? '\n\n' : ''
}});
this.ts.use(turndownPluginGfm.gfm);
// TODO: verify and copy several rules from VNote 2.0.
// No <head> and <style> parse.
this.ts.remove(['head', 'style']);
this.fixMark();
this.fixParagraph();
}
turndown(p_html) {
let markdown = this.ts.turndown(p_html);
return markdown;
}
// Trim a string into 3 parts: leading spaces, content, trailing spaces.
trimString(p_str) {
let result = { leadingSpaces: '',
content: '',
trailingSpaces: ''
};
if (!p_str) {
return result;
}
let lRe = /^\s+/;
let ret = lRe.exec(p_str);
if (ret) {
result.leadingSpaces = ret[0];
if (result.leadingSpaces.length == p_str.length) {
return result;
}
}
let tRe = /\s+$/;
ret = tRe.exec(p_str);
if (ret) {
result.trailingSpaces = ret[0];
}
result.content = p_str.slice(result.leadingSpaces.length, p_str.length - result.trailingSpaces.length);
return result;
};
fixMark() {
this.ts.addRule('mark', {
filter: 'mark',
replacement: function(content, node, options) {
if (!content) {
return '';
}
return '<mark>' + content + '</mark>';
}
});
}
fixParagraph() {
this.ts.addRule('paragraph', {
filter: 'p',
replacement: function(content) {
// Replace leading spaces with &nbsp; to avoid being parsed as code block.
let lRe = /^\s+/;
let ret = lRe.exec(content);
if (ret) {
let leadingSpaces = ret[0];
if (leadingSpaces.length > 3) {
content = '&nbsp;'.repeat(leadingSpaces.length) + content.slice(leadingSpaces.length);
}
}
return '\n\n' + content + '\n\n'
}
});
}
fixImage() {
this.ts.addRule('img_fix', {
filter: 'img',
replacement: function (content, node) {
let alt = node.alt || '';
if (/[\r\n\[\]]/g.test(alt)) {
alt= '';
}
let src = node.getAttribute('src') || '';
let title = node.title || '';
if (/[\r\n\)"]/g.test(title)) {
title = '';
}
let titlePart = title ? ' "' + title + '"' : '';
return src ? '![' + alt + ']' + '(' + src + titlePart + ')' : ''
}
});
}
}