精简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
|
||||
*/
|
||||
|
||||
const PLACEHOLDER = '在此输入文本'
|
||||
|
||||
const ELEMS = {
|
||||
a: function (str, attr, inner) {
|
||||
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
|
||||
|
||||
function trim(str, sign) {
|
||||
return str.replace(new RegExp('^' + sign + '|' + sign + '$', 'g'), '')
|
||||
}
|
||||
|
||||
// html标签的属性正则
|
||||
function attrExp(field, flag = 'i') {
|
||||
return new RegExp(field + '\\s?=\\s?["\']?([^"\']*)["\']?', flag)
|
||||
|
@ -187,3 +193,91 @@ export function html2md(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 {
|
||||
css,
|
||||
raw,
|
||||
html,
|
||||
Component,
|
||||
range,
|
||||
bind,
|
||||
unbind,
|
||||
nextTick,
|
||||
styleMap,
|
||||
classMap,
|
||||
outsideClick,
|
||||
clearOutsideClick
|
||||
} from 'wkit'
|
||||
|
||||
import { DEFAULT_TOOLS, html2md } from './helper.js'
|
||||
import Addon from './addon.js'
|
||||
import markd from '../markd/index.js'
|
||||
|
||||
import '../markd/index.js'
|
||||
import '../form/input.js'
|
||||
import '../form/button.js'
|
||||
import '../code/index.js'
|
||||
|
||||
import { DEFAULT_TOOLS, html2md, Addon } from './helper.js'
|
||||
import ICONS from './svg.js'
|
||||
|
||||
const COLORS = [
|
||||
'#f3f5fb',
|
||||
'#dae1e9',
|
||||
'#62778d',
|
||||
'#58d68d',
|
||||
'#3fc2a7',
|
||||
'#52a3de',
|
||||
'#ac61ce',
|
||||
'#ffb618',
|
||||
'#e67e22',
|
||||
'#ff5061',
|
||||
'#ff0000',
|
||||
'#000000'
|
||||
]
|
||||
|
||||
// 获取一维数组转二维的行
|
||||
function getY(i) {
|
||||
return (i / 9) >> 0
|
||||
|
@ -377,13 +355,10 @@ class MEditor extends Component {
|
|||
#gridx = 0
|
||||
#gridy = 0
|
||||
|
||||
#select = null
|
||||
|
||||
previewEnabled = false
|
||||
|
||||
#hideLayers() {
|
||||
this.$refs.header.classList.remove('fadein')
|
||||
// this.$refs.color.classList.remove('fadein')
|
||||
this.$refs.link.classList.remove('fadein')
|
||||
this.$refs.table.classList.remove('fadein')
|
||||
}
|
||||
|
@ -807,12 +782,15 @@ class MEditor extends Component {
|
|||
|
||||
mounted() {
|
||||
this.#fixedPadding()
|
||||
this._clickoutsideFn = outsideClick(this, _ => this.#hideLayers())
|
||||
|
||||
this.__observer = new ResizeObserver(this.#fixedPadding.bind(this))
|
||||
this.__observer.observe(this)
|
||||
}
|
||||
|
||||
unmounted() {
|
||||
this.__observer?.disconnect()
|
||||
clearOutsideClick(this._clickoutsideFn)
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -846,6 +824,7 @@ class MEditor extends Component {
|
|||
spellcheck="false"
|
||||
:readOnly=${this.readOnly}
|
||||
:disabled=${this.disabled}
|
||||
@click=${this.#hideLayers}
|
||||
@keydown=${this.#handleKeydown}
|
||||
@paste.prevent=${this.#handlePaste}
|
||||
@input=${this.#updatePreview}
|
||||
|
|
Loading…
Reference in New Issue