mirror of
https://github.com/mindoc-org/mindoc.git
synced 2025-12-19 10:58:32 +08:00
1、实现富文本编辑器
2、实现项目排序
This commit is contained in:
110
static/to-markdown/lib/gfm-converters.js
Normal file
110
static/to-markdown/lib/gfm-converters.js
Normal file
@@ -0,0 +1,110 @@
|
||||
'use strict'
|
||||
|
||||
function cell (content, node) {
|
||||
var index = Array.prototype.indexOf.call(node.parentNode.childNodes, node)
|
||||
var prefix = ' '
|
||||
if (index === 0) prefix = '| '
|
||||
return prefix + content + ' |'
|
||||
}
|
||||
|
||||
var highlightRegEx = /highlight highlight-(\S+)/
|
||||
|
||||
module.exports = [
|
||||
{
|
||||
filter: 'br',
|
||||
replacement: function () {
|
||||
return '\n'
|
||||
}
|
||||
},
|
||||
{
|
||||
filter: ['del', 's', 'strike'],
|
||||
replacement: function (content) {
|
||||
return '~~' + content + '~~'
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
filter: function (node) {
|
||||
return node.type === 'checkbox' && node.parentNode.nodeName === 'LI'
|
||||
},
|
||||
replacement: function (content, node) {
|
||||
return (node.checked ? '[x]' : '[ ]') + ' '
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
filter: ['th', 'td'],
|
||||
replacement: function (content, node) {
|
||||
return cell(content, node)
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
filter: 'tr',
|
||||
replacement: function (content, node) {
|
||||
var borderCells = ''
|
||||
var alignMap = { left: ':--', right: '--:', center: ':-:' }
|
||||
|
||||
if (node.parentNode.nodeName === 'THEAD') {
|
||||
for (var i = 0; i < node.childNodes.length; i++) {
|
||||
var align = node.childNodes[i].attributes.align
|
||||
var border = '---'
|
||||
|
||||
if (align) border = alignMap[align.value] || border
|
||||
|
||||
borderCells += cell(border, node.childNodes[i])
|
||||
}
|
||||
}
|
||||
return '\n' + content + (borderCells ? '\n' + borderCells : '')
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
filter: 'table',
|
||||
replacement: function (content) {
|
||||
return '\n\n' + content + '\n\n'
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
filter: ['thead', 'tbody', 'tfoot'],
|
||||
replacement: function (content) {
|
||||
return content
|
||||
}
|
||||
},
|
||||
|
||||
// Fenced code blocks
|
||||
{
|
||||
filter: function (node) {
|
||||
return node.nodeName === 'PRE' &&
|
||||
node.firstChild &&
|
||||
node.firstChild.nodeName === 'CODE'
|
||||
},
|
||||
replacement: function (content, node) {
|
||||
return '\n\n```\n' + node.firstChild.textContent + '\n```\n\n'
|
||||
}
|
||||
},
|
||||
|
||||
// Syntax-highlighted code blocks
|
||||
{
|
||||
filter: function (node) {
|
||||
return node.nodeName === 'PRE' &&
|
||||
node.parentNode.nodeName === 'DIV' &&
|
||||
highlightRegEx.test(node.parentNode.className)
|
||||
},
|
||||
replacement: function (content, node) {
|
||||
var language = node.parentNode.className.match(highlightRegEx)[1]
|
||||
return '\n\n```' + language + '\n' + node.textContent + '\n```\n\n'
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
filter: function (node) {
|
||||
return node.nodeName === 'DIV' &&
|
||||
highlightRegEx.test(node.className)
|
||||
},
|
||||
replacement: function (content) {
|
||||
return '\n\n' + content + '\n\n'
|
||||
}
|
||||
}
|
||||
]
|
||||
76
static/to-markdown/lib/html-parser.js
Normal file
76
static/to-markdown/lib/html-parser.js
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Set up window for Node.js
|
||||
*/
|
||||
|
||||
var _window = (typeof window !== 'undefined' ? window : this)
|
||||
|
||||
/*
|
||||
* Parsing HTML strings
|
||||
*/
|
||||
|
||||
function canParseHtmlNatively () {
|
||||
var Parser = _window.DOMParser
|
||||
var canParse = false
|
||||
|
||||
// Adapted from https://gist.github.com/1129031
|
||||
// Firefox/Opera/IE throw errors on unsupported types
|
||||
try {
|
||||
// WebKit returns null on unsupported types
|
||||
if (new Parser().parseFromString('', 'text/html')) {
|
||||
canParse = true
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
return canParse
|
||||
}
|
||||
|
||||
function createHtmlParser () {
|
||||
var Parser = function () {}
|
||||
|
||||
// For Node.js environments
|
||||
if (typeof document === 'undefined') {
|
||||
var jsdom = require('jsdom')
|
||||
Parser.prototype.parseFromString = function (string) {
|
||||
return jsdom.jsdom(string, {
|
||||
features: {
|
||||
FetchExternalResources: [],
|
||||
ProcessExternalResources: false
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
if (!shouldUseActiveX()) {
|
||||
Parser.prototype.parseFromString = function (string) {
|
||||
var doc = document.implementation.createHTMLDocument('')
|
||||
doc.open()
|
||||
doc.write(string)
|
||||
doc.close()
|
||||
return doc
|
||||
}
|
||||
} else {
|
||||
Parser.prototype.parseFromString = function (string) {
|
||||
var doc = new window.ActiveXObject('htmlfile')
|
||||
doc.designMode = 'on' // disable on-page scripts
|
||||
doc.open()
|
||||
doc.write(string)
|
||||
doc.close()
|
||||
return doc
|
||||
}
|
||||
}
|
||||
}
|
||||
return Parser
|
||||
}
|
||||
|
||||
function shouldUseActiveX () {
|
||||
var useActiveX = false
|
||||
|
||||
try {
|
||||
document.implementation.createHTMLDocument('').open()
|
||||
} catch (e) {
|
||||
if (window.ActiveXObject) useActiveX = true
|
||||
}
|
||||
|
||||
return useActiveX
|
||||
}
|
||||
|
||||
module.exports = canParseHtmlNatively() ? _window.DOMParser : createHtmlParser()
|
||||
151
static/to-markdown/lib/md-converters.js
Normal file
151
static/to-markdown/lib/md-converters.js
Normal file
@@ -0,0 +1,151 @@
|
||||
'use strict'
|
||||
|
||||
module.exports = [
|
||||
{
|
||||
filter: 'p',
|
||||
replacement: function (content) {
|
||||
return '\n\n' + content + '\n\n'
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
filter: 'br',
|
||||
replacement: function () {
|
||||
return ' \n'
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
filter: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'],
|
||||
replacement: function (content, node) {
|
||||
var hLevel = node.nodeName.charAt(1)
|
||||
var hPrefix = ''
|
||||
for (var i = 0; i < hLevel; i++) {
|
||||
hPrefix += '#'
|
||||
}
|
||||
return '\n\n' + hPrefix + ' ' + content + '\n\n'
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
filter: 'hr',
|
||||
replacement: function () {
|
||||
return '\n\n* * *\n\n'
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
filter: ['em', 'i'],
|
||||
replacement: function (content) {
|
||||
return '_' + content + '_'
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
filter: ['strong', 'b'],
|
||||
replacement: function (content) {
|
||||
return '**' + content + '**'
|
||||
}
|
||||
},
|
||||
|
||||
// Inline code
|
||||
{
|
||||
filter: function (node) {
|
||||
var hasSiblings = node.previousSibling || node.nextSibling
|
||||
var isCodeBlock = node.parentNode.nodeName === 'PRE' && !hasSiblings
|
||||
|
||||
return node.nodeName === 'CODE' && !isCodeBlock
|
||||
},
|
||||
replacement: function (content) {
|
||||
return '`' + content + '`'
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
filter: function (node) {
|
||||
return node.nodeName === 'A' && node.getAttribute('href')
|
||||
},
|
||||
replacement: function (content, node) {
|
||||
var titlePart = node.title ? ' "' + node.title + '"' : ''
|
||||
return '[' + content + '](' + node.getAttribute('href') + titlePart + ')'
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
filter: 'img',
|
||||
replacement: function (content, node) {
|
||||
var alt = node.alt || ''
|
||||
var src = node.getAttribute('src') || ''
|
||||
var title = node.title || ''
|
||||
var titlePart = title ? ' "' + title + '"' : ''
|
||||
return src ? '![' + alt + ']' + '(' + src + titlePart + ')' : ''
|
||||
}
|
||||
},
|
||||
|
||||
// Code blocks
|
||||
{
|
||||
filter: function (node) {
|
||||
return node.nodeName === 'PRE' && node.firstChild.nodeName === 'CODE'
|
||||
},
|
||||
replacement: function (content, node) {
|
||||
return '\n\n ' + node.firstChild.textContent.replace(/\n/g, '\n ') + '\n\n'
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
filter: 'blockquote',
|
||||
replacement: function (content) {
|
||||
content = content.trim()
|
||||
content = content.replace(/\n{3,}/g, '\n\n')
|
||||
content = content.replace(/^/gm, '> ')
|
||||
return '\n\n' + content + '\n\n'
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
filter: 'li',
|
||||
replacement: function (content, node) {
|
||||
content = content.replace(/^\s+/, '').replace(/\n/gm, '\n ')
|
||||
var prefix = '* '
|
||||
var parent = node.parentNode
|
||||
var index = Array.prototype.indexOf.call(parent.children, node) + 1
|
||||
|
||||
prefix = /ol/i.test(parent.nodeName) ? index + '. ' : '* '
|
||||
return prefix + content
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
filter: ['ul', 'ol'],
|
||||
replacement: function (content, node) {
|
||||
var strings = []
|
||||
for (var i = 0; i < node.childNodes.length; i++) {
|
||||
strings.push(node.childNodes[i]._replacement)
|
||||
}
|
||||
|
||||
if (/li/i.test(node.parentNode.nodeName)) {
|
||||
return '\n' + strings.join('\n')
|
||||
}
|
||||
return '\n\n' + strings.join('\n') + '\n\n'
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
filter: function (node) {
|
||||
return this.isBlock(node)
|
||||
},
|
||||
replacement: function (content, node) {
|
||||
return '\n\n' + this.outer(node, content) + '\n\n'
|
||||
}
|
||||
},
|
||||
|
||||
// Anything else!
|
||||
{
|
||||
filter: function () {
|
||||
return true
|
||||
},
|
||||
replacement: function (content, node) {
|
||||
return this.outer(node, content)
|
||||
}
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user