精简markd编辑器
parent
b52c95f210
commit
c6a0cfbcef
|
@ -1,99 +0,0 @@
|
||||||
/**
|
|
||||||
* 基础拓展
|
|
||||||
* @author yutent<yutent.io@gmail.com>
|
|
||||||
* @date 2020/10/14 17:52:44
|
|
||||||
*/
|
|
||||||
|
|
||||||
const PLACEHOLDER = '在此输入文本'
|
|
||||||
|
|
||||||
function trim(str, sign) {
|
|
||||||
return str.replace(new RegExp('^' + sign + '|' + sign + '$', 'g'), '')
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
header() {
|
|
||||||
this.$refs.header.classList.add('fadein')
|
|
||||||
},
|
|
||||||
|
|
||||||
h(level) {
|
|
||||||
var wrap = this.selection(true) || PLACEHOLDER
|
|
||||||
wrap = wrap.replace(/^(#+ )?/, '#'.repeat(level) + ' ')
|
|
||||||
this.insert(wrap, true)
|
|
||||||
},
|
|
||||||
|
|
||||||
quote() {
|
|
||||||
var wrap = this.selection(true) || PLACEHOLDER
|
|
||||||
wrap = wrap.replace(/^(>+ )?/, '> ')
|
|
||||||
|
|
||||||
this.insert(wrap, true)
|
|
||||||
},
|
|
||||||
|
|
||||||
bold() {
|
|
||||||
var wrap = this.selection() || PLACEHOLDER
|
|
||||||
var unwrap = trim(wrap, '\\*\\*')
|
|
||||||
wrap = wrap === unwrap ? `**${wrap}**` : unwrap
|
|
||||||
this.insert(wrap, true)
|
|
||||||
},
|
|
||||||
|
|
||||||
italic() {
|
|
||||||
var wrap = this.selection() || PLACEHOLDER
|
|
||||||
var unwrap = trim(wrap, '_')
|
|
||||||
wrap = wrap === unwrap ? `_${wrap}_` : unwrap
|
|
||||||
this.insert(wrap, true)
|
|
||||||
},
|
|
||||||
|
|
||||||
through() {
|
|
||||||
var wrap = this.selection() || PLACEHOLDER
|
|
||||||
var unwrap = trim(wrap, '~~')
|
|
||||||
wrap = wrap === unwrap ? `~~${wrap}~~` : unwrap
|
|
||||||
this.insert(wrap, true)
|
|
||||||
},
|
|
||||||
|
|
||||||
list() {
|
|
||||||
var wrap = this.selection(true) || PLACEHOLDER
|
|
||||||
|
|
||||||
wrap = wrap.replace(/^([+\-*] )?/, '+ ')
|
|
||||||
this.insert(wrap, true)
|
|
||||||
},
|
|
||||||
|
|
||||||
order() {
|
|
||||||
var wrap = this.selection(true) || PLACEHOLDER
|
|
||||||
|
|
||||||
wrap = wrap.replace(/^(\d+\. )?/, '1. ')
|
|
||||||
this.insert(wrap, true)
|
|
||||||
},
|
|
||||||
|
|
||||||
line() {
|
|
||||||
this.insert('\n\n---\n\n', false)
|
|
||||||
},
|
|
||||||
|
|
||||||
code() {
|
|
||||||
var wrap = this.selection() || PLACEHOLDER
|
|
||||||
var unwrap = trim(wrap, '`')
|
|
||||||
wrap = wrap === unwrap ? `\`${wrap}\`` : unwrap
|
|
||||||
this.insert(wrap, true)
|
|
||||||
},
|
|
||||||
|
|
||||||
codeblock() {
|
|
||||||
this.insert('\n```language\n\n```\n')
|
|
||||||
},
|
|
||||||
|
|
||||||
table() {
|
|
||||||
this.$refs.table.classList.add('fadein')
|
|
||||||
},
|
|
||||||
|
|
||||||
link() {
|
|
||||||
this.$refs.link.classList.add('fadein')
|
|
||||||
},
|
|
||||||
|
|
||||||
fullscreen() {
|
|
||||||
this.classList.toggle('fullscreen')
|
|
||||||
},
|
|
||||||
preview() {
|
|
||||||
this.previewEnabled = !this.previewEnabled
|
|
||||||
this.$refs.view.classList.toggle('active')
|
|
||||||
if (this.previewEnabled) {
|
|
||||||
this.$refs.view.code = this.value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -4,6 +4,8 @@
|
||||||
* @date 2020/10/12 18:23:23
|
* @date 2020/10/12 18:23:23
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
const PLACEHOLDER = '在此输入文本'
|
||||||
|
|
||||||
const ELEMS = {
|
const ELEMS = {
|
||||||
a: function (str, attr, inner) {
|
a: function (str, attr, inner) {
|
||||||
let href = attr.match(attrExp('href'))
|
let href = attr.match(attrExp('href'))
|
||||||
|
@ -82,6 +84,10 @@ export const DEFAULT_TOOLS = [
|
||||||
|
|
||||||
const LI_EXP = /<(ul|ol)>(?:(?!<ul|<ol)[\s\S])*?<\/\1>/gi
|
const LI_EXP = /<(ul|ol)>(?:(?!<ul|<ol)[\s\S])*?<\/\1>/gi
|
||||||
|
|
||||||
|
function trim(str, sign) {
|
||||||
|
return str.replace(new RegExp('^' + sign + '|' + sign + '$', 'g'), '')
|
||||||
|
}
|
||||||
|
|
||||||
// html标签的属性正则
|
// html标签的属性正则
|
||||||
function attrExp(field, flag = 'i') {
|
function attrExp(field, flag = 'i') {
|
||||||
return new RegExp(field + '\\s?=\\s?["\']?([^"\']*)["\']?', flag)
|
return new RegExp(field + '\\s?=\\s?["\']?([^"\']*)["\']?', flag)
|
||||||
|
@ -187,3 +193,91 @@ export function html2md(str) {
|
||||||
})
|
})
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const Addon = {
|
||||||
|
header() {
|
||||||
|
this.$refs.header.classList.add('fadein')
|
||||||
|
},
|
||||||
|
|
||||||
|
h(level) {
|
||||||
|
var wrap = this.selection(true) || PLACEHOLDER
|
||||||
|
wrap = wrap.replace(/^(#+ )?/, '#'.repeat(level) + ' ')
|
||||||
|
this.insert(wrap, true)
|
||||||
|
},
|
||||||
|
|
||||||
|
quote() {
|
||||||
|
var wrap = this.selection(true) || PLACEHOLDER
|
||||||
|
wrap = wrap.replace(/^(>+ )?/, '> ')
|
||||||
|
|
||||||
|
this.insert(wrap, true)
|
||||||
|
},
|
||||||
|
|
||||||
|
bold() {
|
||||||
|
var wrap = this.selection() || PLACEHOLDER
|
||||||
|
var unwrap = trim(wrap, '\\*\\*')
|
||||||
|
wrap = wrap === unwrap ? `**${wrap}**` : unwrap
|
||||||
|
this.insert(wrap, true)
|
||||||
|
},
|
||||||
|
|
||||||
|
italic() {
|
||||||
|
var wrap = this.selection() || PLACEHOLDER
|
||||||
|
var unwrap = trim(wrap, '_')
|
||||||
|
wrap = wrap === unwrap ? `_${wrap}_` : unwrap
|
||||||
|
this.insert(wrap, true)
|
||||||
|
},
|
||||||
|
|
||||||
|
through() {
|
||||||
|
var wrap = this.selection() || PLACEHOLDER
|
||||||
|
var unwrap = trim(wrap, '~~')
|
||||||
|
wrap = wrap === unwrap ? `~~${wrap}~~` : unwrap
|
||||||
|
this.insert(wrap, true)
|
||||||
|
},
|
||||||
|
|
||||||
|
list() {
|
||||||
|
var wrap = this.selection(true) || PLACEHOLDER
|
||||||
|
|
||||||
|
wrap = wrap.replace(/^([+\-*] )?/, '+ ')
|
||||||
|
this.insert(wrap, true)
|
||||||
|
},
|
||||||
|
|
||||||
|
order() {
|
||||||
|
var wrap = this.selection(true) || PLACEHOLDER
|
||||||
|
|
||||||
|
wrap = wrap.replace(/^(\d+\. )?/, '1. ')
|
||||||
|
this.insert(wrap, true)
|
||||||
|
},
|
||||||
|
|
||||||
|
line() {
|
||||||
|
this.insert('\n\n---\n\n', false)
|
||||||
|
},
|
||||||
|
|
||||||
|
code() {
|
||||||
|
var wrap = this.selection() || PLACEHOLDER
|
||||||
|
var unwrap = trim(wrap, '`')
|
||||||
|
wrap = wrap === unwrap ? `\`${wrap}\`` : unwrap
|
||||||
|
this.insert(wrap, true)
|
||||||
|
},
|
||||||
|
|
||||||
|
codeblock() {
|
||||||
|
this.insert('\n```language\n\n```\n')
|
||||||
|
},
|
||||||
|
|
||||||
|
table() {
|
||||||
|
this.$refs.table.classList.add('fadein')
|
||||||
|
},
|
||||||
|
|
||||||
|
link() {
|
||||||
|
this.$refs.link.classList.add('fadein')
|
||||||
|
},
|
||||||
|
|
||||||
|
fullscreen() {
|
||||||
|
this.classList.toggle('fullscreen')
|
||||||
|
},
|
||||||
|
preview() {
|
||||||
|
this.previewEnabled = !this.previewEnabled
|
||||||
|
this.$refs.view.classList.toggle('active')
|
||||||
|
if (this.previewEnabled) {
|
||||||
|
this.$refs.view.code = this.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -6,44 +6,22 @@
|
||||||
|
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
raw,
|
|
||||||
html,
|
html,
|
||||||
Component,
|
Component,
|
||||||
range,
|
range,
|
||||||
bind,
|
|
||||||
unbind,
|
|
||||||
nextTick,
|
nextTick,
|
||||||
styleMap,
|
|
||||||
classMap,
|
classMap,
|
||||||
outsideClick,
|
outsideClick,
|
||||||
clearOutsideClick
|
clearOutsideClick
|
||||||
} from 'wkit'
|
} from 'wkit'
|
||||||
|
|
||||||
import { DEFAULT_TOOLS, html2md } from './helper.js'
|
import '../markd/index.js'
|
||||||
import Addon from './addon.js'
|
|
||||||
import markd from '../markd/index.js'
|
|
||||||
|
|
||||||
import '../form/input.js'
|
import '../form/input.js'
|
||||||
import '../form/button.js'
|
import '../form/button.js'
|
||||||
import '../code/index.js'
|
|
||||||
|
|
||||||
|
import { DEFAULT_TOOLS, html2md, Addon } from './helper.js'
|
||||||
import ICONS from './svg.js'
|
import ICONS from './svg.js'
|
||||||
|
|
||||||
const COLORS = [
|
|
||||||
'#f3f5fb',
|
|
||||||
'#dae1e9',
|
|
||||||
'#62778d',
|
|
||||||
'#58d68d',
|
|
||||||
'#3fc2a7',
|
|
||||||
'#52a3de',
|
|
||||||
'#ac61ce',
|
|
||||||
'#ffb618',
|
|
||||||
'#e67e22',
|
|
||||||
'#ff5061',
|
|
||||||
'#ff0000',
|
|
||||||
'#000000'
|
|
||||||
]
|
|
||||||
|
|
||||||
// 获取一维数组转二维的行
|
// 获取一维数组转二维的行
|
||||||
function getY(i) {
|
function getY(i) {
|
||||||
return (i / 9) >> 0
|
return (i / 9) >> 0
|
||||||
|
@ -377,13 +355,10 @@ class MEditor extends Component {
|
||||||
#gridx = 0
|
#gridx = 0
|
||||||
#gridy = 0
|
#gridy = 0
|
||||||
|
|
||||||
#select = null
|
|
||||||
|
|
||||||
previewEnabled = false
|
previewEnabled = false
|
||||||
|
|
||||||
#hideLayers() {
|
#hideLayers() {
|
||||||
this.$refs.header.classList.remove('fadein')
|
this.$refs.header.classList.remove('fadein')
|
||||||
// this.$refs.color.classList.remove('fadein')
|
|
||||||
this.$refs.link.classList.remove('fadein')
|
this.$refs.link.classList.remove('fadein')
|
||||||
this.$refs.table.classList.remove('fadein')
|
this.$refs.table.classList.remove('fadein')
|
||||||
}
|
}
|
||||||
|
@ -807,12 +782,15 @@ class MEditor extends Component {
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.#fixedPadding()
|
this.#fixedPadding()
|
||||||
|
this._clickoutsideFn = outsideClick(this, _ => this.#hideLayers())
|
||||||
|
|
||||||
this.__observer = new ResizeObserver(this.#fixedPadding.bind(this))
|
this.__observer = new ResizeObserver(this.#fixedPadding.bind(this))
|
||||||
this.__observer.observe(this)
|
this.__observer.observe(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
unmounted() {
|
unmounted() {
|
||||||
this.__observer?.disconnect()
|
this.__observer?.disconnect()
|
||||||
|
clearOutsideClick(this._clickoutsideFn)
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -846,6 +824,7 @@ class MEditor extends Component {
|
||||||
spellcheck="false"
|
spellcheck="false"
|
||||||
:readOnly=${this.readOnly}
|
:readOnly=${this.readOnly}
|
||||||
:disabled=${this.disabled}
|
:disabled=${this.disabled}
|
||||||
|
@click=${this.#hideLayers}
|
||||||
@keydown=${this.#handleKeydown}
|
@keydown=${this.#handleKeydown}
|
||||||
@paste.prevent=${this.#handlePaste}
|
@paste.prevent=${this.#handlePaste}
|
||||||
@input=${this.#updatePreview}
|
@input=${this.#updatePreview}
|
||||||
|
|
Loading…
Reference in New Issue