mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 13:59:52 +08:00

* 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
119 lines
3.6 KiB
JavaScript
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 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 = ' '.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 + ')' : ''
|
|
}
|
|
});
|
|
}
|
|
}
|