修复layer组件的回调及对shift属性的优化;移植meditor到新的框架
parent
8be3b9c70a
commit
d256f145cf
|
@ -4,7 +4,7 @@ $cpp: #651fff #7c4dff #6200ea;
|
||||||
$cb: #2196f3 #64b5f6 #1976d2;
|
$cb: #2196f3 #64b5f6 #1976d2;
|
||||||
$cr: #ff5722 #ff7043 #e64a19;
|
$cr: #ff5722 #ff7043 #e64a19;
|
||||||
$co: #ff9800 #ffa726 #f57c00;
|
$co: #ff9800 #ffa726 #f57c00;
|
||||||
$cp: #e7e8eb #ecf0f1 #bdc3c7;
|
$cp: #e7e8eb #ecf0f1 #d3d5db;
|
||||||
$cgr: #546e7a #607d8b #37474f;
|
$cgr: #546e7a #607d8b #37474f;
|
||||||
|
|
||||||
@mixin ts($c: all, $t: .2s, $m: ease-in-out){
|
@mixin ts($c: all, $t: .2s, $m: ease-in-out){
|
||||||
|
|
|
@ -182,8 +182,8 @@ class __layer__ {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted: function() {
|
mounted: function() {
|
||||||
if (typeof this.success === 'function') {
|
if (typeof this.props.success === 'function') {
|
||||||
this.success(_id)
|
this.props.success.call(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -216,7 +216,9 @@ class __layer__ {
|
||||||
layBox.classList.add('__' + state.shift)
|
layBox.classList.add('__' + state.shift)
|
||||||
} else {
|
} else {
|
||||||
for (let k in state.shift) {
|
for (let k in state.shift) {
|
||||||
layBox.style.cssText += `${k}: ${state.shift[k]};`
|
let val = state.shift[k]
|
||||||
|
val += isFinite(val) ? 'px' : ''
|
||||||
|
layBox.style.cssText += `${k}: ${val};`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,414 +1,438 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @authors yutent (yutent@doui.cc)
|
* @authors yutent (yutent@doui.cc)
|
||||||
* @date 2017-04-19 21:17:26
|
* @date 2017-04-19 21:17:26
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
"use strict";
|
'use strict'
|
||||||
|
|
||||||
|
define(['lib/layer/base', 'css!./attach'], function() {
|
||||||
|
var Uploader = function(url) {
|
||||||
|
this.url = url || ''
|
||||||
|
this.init()
|
||||||
|
}
|
||||||
|
|
||||||
define([
|
Uploader.prototype = {
|
||||||
'lib/layer/base',
|
init: function() {
|
||||||
'css!./attach'
|
this.xhr = new XMLHttpRequest()
|
||||||
], function(){
|
this.form = new FormData()
|
||||||
|
return this
|
||||||
var Uploader = function(url){
|
},
|
||||||
this.url = url || ''
|
field: function(key, val) {
|
||||||
this.init()
|
if (typeof key === 'object') {
|
||||||
}
|
for (var i in key) {
|
||||||
|
this.form.append(i, key[i])
|
||||||
Uploader.prototype = {
|
|
||||||
init: function(){
|
|
||||||
this.xhr = new XMLHttpRequest()
|
|
||||||
this.form = new FormData()
|
|
||||||
return this
|
|
||||||
},
|
|
||||||
field: function(key, val){
|
|
||||||
if(typeof key === 'object'){
|
|
||||||
for(var i in key){
|
|
||||||
this.form.append(i, key[i])
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
this.form.append(key, val)
|
|
||||||
}
|
|
||||||
return this
|
|
||||||
},
|
|
||||||
start: function(){
|
|
||||||
var _this = this
|
|
||||||
|
|
||||||
this.xhr.open('POST', this.url, true)
|
|
||||||
|
|
||||||
var startTime = Date.now()
|
|
||||||
|
|
||||||
this.xhr.upload.addEventListener('progress', function(evt){
|
|
||||||
|
|
||||||
if(evt.lengthComputable && _this.progress){
|
|
||||||
var res = Math.round(evt.loaded * 100 / evt.total)
|
|
||||||
_this.progress(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
}, false)
|
|
||||||
|
|
||||||
this.xhr.onreadystatechange = function(){
|
|
||||||
if(_this.xhr.readyState === 4){
|
|
||||||
if(_this.xhr.status >= 200 && _this.xhr.status < 205){
|
|
||||||
var res = _this.xhr.responseText
|
|
||||||
try{
|
|
||||||
res = JSON.parse(res)
|
|
||||||
}catch(err){}
|
|
||||||
_this.end && _this.end(res)
|
|
||||||
}else{
|
|
||||||
console.error(_this.xhr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.xhr.send(this.form)
|
|
||||||
|
|
||||||
},
|
|
||||||
onProgress: function(fn){
|
|
||||||
this.progress = fn
|
|
||||||
return this
|
|
||||||
},
|
|
||||||
onEnd: function(fn){
|
|
||||||
this.end = fn
|
|
||||||
return this
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
this.form.append(key, val)
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
start: function() {
|
||||||
|
var _this = this
|
||||||
|
|
||||||
|
this.xhr.open('POST', this.url, true)
|
||||||
|
|
||||||
|
var startTime = Date.now()
|
||||||
|
|
||||||
|
this.xhr.upload.addEventListener(
|
||||||
|
'progress',
|
||||||
|
function(evt) {
|
||||||
|
if (evt.lengthComputable && _this.progress) {
|
||||||
|
var res = Math.round(evt.loaded * 100 / evt.total)
|
||||||
|
_this.progress(res)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
false
|
||||||
|
)
|
||||||
|
|
||||||
|
this.xhr.onreadystatechange = function() {
|
||||||
|
if (_this.xhr.readyState === 4) {
|
||||||
|
if (_this.xhr.status >= 200 && _this.xhr.status < 205) {
|
||||||
|
var res = _this.xhr.responseText
|
||||||
|
try {
|
||||||
|
res = JSON.parse(res)
|
||||||
|
} catch (err) {}
|
||||||
|
_this.end && _this.end(res)
|
||||||
|
} else {
|
||||||
|
console.error(_this.xhr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.xhr.send(this.form)
|
||||||
|
},
|
||||||
|
onProgress: function(fn) {
|
||||||
|
this.progress = fn
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
onEnd: function(fn) {
|
||||||
|
this.end = fn
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function uploadScreenshot(vm, blob) {
|
||||||
|
var upload = new Uploader(vm.uploadUrl || ME.uploadUrl)
|
||||||
|
if (ME.beforeUpload) {
|
||||||
|
ME.beforeUpload(Date.now().toString(16) + '.jpg', function(qn) {
|
||||||
|
upload
|
||||||
|
.field('file', blob)
|
||||||
|
.field('token', qn.token)
|
||||||
|
.field('key', qn.key)
|
||||||
|
.onEnd(function(json) {
|
||||||
|
ME.insert(vm.$editor, '![截图](' + qn.url + ')')
|
||||||
|
})
|
||||||
|
.start()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
upload
|
||||||
|
.field('file', blob)
|
||||||
|
.onEnd(function(json) {
|
||||||
|
ME.insert(vm.$editor, '![截图](' + json.data.url + ')')
|
||||||
|
})
|
||||||
|
.start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var $init = function(vm) {
|
||||||
|
if (!vm.uploadUrl && !ME.uploadUrl) {
|
||||||
|
console.error(
|
||||||
|
'使用附件上传,必须先设置uploadUrl;\n可以给vm增加uploadUrl属性,也可以通过ME.uploadUrl设置'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (!vm.manageUrl && !ME.manageUrl) {
|
||||||
|
console.error(
|
||||||
|
'使用附件管理功能,必须先设置manageUrl;\n可以给vm增加manageUrl属性,也可以通过ME.manageUrl设置'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (!ME.maxSize) {
|
||||||
|
ME.maxSize = 4194304
|
||||||
|
}
|
||||||
|
|
||||||
|
vm.$editor.addEventListener('paste', function(ev) {
|
||||||
|
var txt = ev.clipboardData.getData('text/plain').trim(),
|
||||||
|
html = ev.clipboardData.getData('text/html').trim()
|
||||||
|
|
||||||
|
//文本类型直接默认处理
|
||||||
|
if (txt || html) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ev.clipboardData.items) {
|
||||||
|
var items = ev.clipboardData.items,
|
||||||
|
len = items.length,
|
||||||
|
blob = null
|
||||||
|
for (var i = 0, it; (it = items[i++]); ) {
|
||||||
|
if (it.type.indexOf('image') > -1) {
|
||||||
|
blob = it.getAsFile()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (blob !== null) {
|
||||||
|
layer.msg('截图处理中...')
|
||||||
|
// 压缩截图,避免文件过大
|
||||||
|
var reader = new FileReader()
|
||||||
|
reader.onload = function() {
|
||||||
|
var img = document.createElement('img'),
|
||||||
|
canvas = document.createElement('canvas')
|
||||||
|
|
||||||
|
img.onload = function() {
|
||||||
|
canvas.width = img.width
|
||||||
|
canvas.height = img.height
|
||||||
|
|
||||||
|
var ctx = canvas.getContext('2d')
|
||||||
|
ctx.clearRect(0, 0, canvas.width, canvas.height)
|
||||||
|
ctx.drawImage(this, 0, 0, canvas.width, canvas.height)
|
||||||
|
|
||||||
|
if (canvas.toBlob) {
|
||||||
|
canvas.toBlob(
|
||||||
|
function(obj) {
|
||||||
|
uploadScreenshot(vm, obj)
|
||||||
|
},
|
||||||
|
'image/jpeg',
|
||||||
|
0.8
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
var base64 = canvas.toDataURL('image/jpeg', 0.8),
|
||||||
|
buf = atob(base64.split(',')[1]),
|
||||||
|
arrBuf = new ArrayBuffer(buf.length),
|
||||||
|
intArr = new Uint8Array(arrBuf),
|
||||||
|
obj = null
|
||||||
|
|
||||||
|
for (var i = 0; i < buf.length; i++) {
|
||||||
|
intArr[i] = buf.charCodeAt(i)
|
||||||
|
}
|
||||||
|
obj = new Blob([intArr], { type: 'image/jpeg' })
|
||||||
|
uploadScreenshot(vm, obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
img.src = this.result
|
||||||
|
}
|
||||||
|
reader.readAsDataURL(blob)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ev.preventDefault()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
lang = {
|
||||||
|
image: ['远程图片', '图片管理', '图片描述', '图片地址'],
|
||||||
|
file: ['远程附件', '附件管理', '附件描述', '附件地址']
|
||||||
|
},
|
||||||
|
opened = false, //记录是否已经打开
|
||||||
|
openType = 'image', //打开类型, 图片/附件
|
||||||
|
cache = {
|
||||||
|
//缓存附件列表
|
||||||
|
image: [],
|
||||||
|
file: []
|
||||||
|
},
|
||||||
|
fixCont = function() {
|
||||||
|
return (
|
||||||
|
'<dl class="do-meditor-attach do-meditor-font">' +
|
||||||
|
'<dt class="tab-box" :drag="do-layer" data-limit="window">' +
|
||||||
|
'<span class="item" :class="active:tab === 1" :click="$switch(1)">' +
|
||||||
|
lang[openType][0] +
|
||||||
|
'</span>' +
|
||||||
|
'<span class="item" :class="active:tab === 2" :click="$switch(2)">本地上传</span>' +
|
||||||
|
'<span class="item" :class="active:tab === 3" :click="$switch(3)">' +
|
||||||
|
lang[openType][1] +
|
||||||
|
'</span>' +
|
||||||
|
'<a href="javascript:;" :click="no" class="action-close do-ui-font"></a>' +
|
||||||
|
'</dt>' +
|
||||||
|
'<dt class="cont-box">' +
|
||||||
|
'<div class="remote" :visible="tab === 1">' +
|
||||||
|
'<section class="section do-fn-cl input"><span class="label">' +
|
||||||
|
lang[openType][2] +
|
||||||
|
'</span>' +
|
||||||
|
'<input class="txt" :duplex="attachAlt" />' +
|
||||||
|
'</section>' +
|
||||||
|
'<section class="section do-fn-cl input"><span class="label">' +
|
||||||
|
lang[openType][3] +
|
||||||
|
'</span>' +
|
||||||
|
'<input class="txt" :duplex="attach" />' +
|
||||||
|
'</section>' +
|
||||||
|
'<section class="section do-fn-cl">' +
|
||||||
|
'<a href="javascript:;" class="submit" :click="$confirm">确定</a>' +
|
||||||
|
'</section>' +
|
||||||
|
'</div>' +
|
||||||
|
'<div class="local" :visible="tab === 2">' +
|
||||||
|
'<div class="select-file"><input id="meditor-attch" multiple :change="$change" type="file" class="hide" /><span class="file" :click="$select">选择文件</span><span class="tips">(上传大小限制:单文件最大 ' +
|
||||||
|
((ME.maxSize / 1048576).toFixed(2) - 0) +
|
||||||
|
'MB)</span></div>' +
|
||||||
|
'<ul class="upload-box">' +
|
||||||
|
'<li class="tr thead"><span class="td name">文件名</span><span class="td progress">上传进度</span><span class="td option">操作</span></li>' +
|
||||||
|
'<li class="tr" :repeat="uploadFile">' +
|
||||||
|
'<span class="td name" :text="el.name"></span>' +
|
||||||
|
'<span class="td progress" :html="el.progress"></span>' +
|
||||||
|
'<span class="td option"><a href="javascript:;" :click="$insert(el)">插入</a></span>' +
|
||||||
|
'</li>' +
|
||||||
|
'</ul>' +
|
||||||
|
'</div>' +
|
||||||
|
'<ul class="manager" :visible="tab === 3">' +
|
||||||
|
'<li class="item" :repeat="attachList" :click="$insert(el)">' +
|
||||||
|
'<span class="thumb" :html="el.thumb"></span>' +
|
||||||
|
'<p class="name" :attr-title="el.name" :text="el.name"></p>' +
|
||||||
|
'</li>' +
|
||||||
|
'</ul>' +
|
||||||
|
'</dt>' +
|
||||||
|
'</dl>'
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [uploadFile 文件上传]
|
||||||
|
* @param {[type]} files [文件列表]
|
||||||
|
* @param {[type]} vm [vm对象]
|
||||||
|
* @param {[type]} type [image/file]
|
||||||
|
*/
|
||||||
|
function uploadFile(files, vm) {
|
||||||
|
for (var i = 0, it; (it = files[i++]); ) {
|
||||||
|
if (
|
||||||
|
openType === 'image' &&
|
||||||
|
!/\.(jpg|jpeg|png|gif|bmp|webp|ico)$/.test(it.name)
|
||||||
|
) {
|
||||||
|
vm.uploadFile.push({
|
||||||
|
name: it.name,
|
||||||
|
progress: '<span class="red">0%(失败,不允许的文件类型)</span>',
|
||||||
|
url: ''
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (ME.maxSize > 0 && it.size > ME.maxSize) {
|
||||||
|
vm.uploadFile.push({
|
||||||
|
name: it.name,
|
||||||
|
progress: '<span class="red">0%(文件体积过大)</span>',
|
||||||
|
url: ''
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var fixName =
|
||||||
|
Date.now().toString(16) + it.name.slice(it.name.lastIndexOf('.'))
|
||||||
|
|
||||||
function uploadScreenshot(vm, blob){
|
var idx = vm.uploadFile.length,
|
||||||
var upload = new Uploader(vm.uploadUrl || ME.uploadUrl)
|
upload = new Uploader(vm.uploadUrl || ME.uploadUrl)
|
||||||
if(ME.beforeUpload){
|
|
||||||
ME.beforeUpload(Date.now().toString(16) + '.jpg', function(qn){
|
vm.uploadFile.push({ name: it.name, progress: '0%', url: '' })
|
||||||
upload.field('file', blob)
|
|
||||||
.field('token', qn.token)
|
upload.field('file', it)
|
||||||
.field('key', qn.key)
|
|
||||||
.onEnd(function(json){
|
if (ME.beforeUpload) {
|
||||||
ME.insert(vm.$editor, '![截图](' + qn.url + ')')
|
ME.beforeUpload(fixName, function(qn) {
|
||||||
})
|
upload
|
||||||
.start()
|
.field('token', qn.token)
|
||||||
|
.field('key', qn.key)
|
||||||
|
.onProgress(function(val) {
|
||||||
|
vm.uploadFile[idx].progress = val + '%'
|
||||||
})
|
})
|
||||||
}else{
|
.onEnd(function(json) {
|
||||||
upload.field('file', blob)
|
vm.uploadFile[idx].url = qn.url
|
||||||
.onEnd(function(json){
|
|
||||||
ME.insert(vm.$editor, '![截图](' + json.data.url + ')')
|
|
||||||
})
|
|
||||||
.start()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var $init = function(vm){
|
|
||||||
if(!vm.uploadUrl && !ME.uploadUrl){
|
|
||||||
console.error('使用附件上传,必须先设置uploadUrl;\n可以给vm增加uploadUrl属性,也可以通过ME.uploadUrl设置')
|
|
||||||
}
|
|
||||||
if(!vm.manageUrl && !ME.manageUrl){
|
|
||||||
console.error('使用附件管理功能,必须先设置manageUrl;\n可以给vm增加manageUrl属性,也可以通过ME.manageUrl设置')
|
|
||||||
}
|
|
||||||
if(!ME.maxSize){
|
|
||||||
ME.maxSize = 4194304
|
|
||||||
}
|
|
||||||
|
|
||||||
vm.$editor.addEventListener('paste', function(ev){
|
|
||||||
var txt = ev.clipboardData.getData('text/plain').trim(),
|
|
||||||
html = ev.clipboardData.getData('text/html').trim();
|
|
||||||
|
|
||||||
//文本类型直接默认处理
|
|
||||||
if(txt || html){
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ev.clipboardData.items){
|
|
||||||
var items = ev.clipboardData.items,
|
|
||||||
len = items.length,
|
|
||||||
blob = null;
|
|
||||||
for(var i = 0,it; it = items[i++];){
|
|
||||||
if(it.type.indexOf('image') > -1){
|
|
||||||
blob = it.getAsFile()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(blob !== null) {
|
|
||||||
layer.msg('截图处理中...')
|
|
||||||
// 压缩截图,避免文件过大
|
|
||||||
var reader = new FileReader()
|
|
||||||
reader.onload = function(){
|
|
||||||
var img = document.createElement('img'),
|
|
||||||
canvas = document.createElement('canvas')
|
|
||||||
|
|
||||||
img.onload = function(){
|
|
||||||
canvas.width = img.width
|
|
||||||
canvas.height = img.height
|
|
||||||
|
|
||||||
var ctx = canvas.getContext('2d')
|
|
||||||
ctx.clearRect(0,0, canvas.width, canvas.height)
|
|
||||||
ctx.drawImage(this, 0, 0, canvas.width, canvas.height)
|
|
||||||
|
|
||||||
|
|
||||||
if(canvas.toBlob){
|
|
||||||
canvas.toBlob(function(obj){
|
|
||||||
uploadScreenshot(vm, obj)
|
|
||||||
}, 'image/jpeg', 0.8)
|
|
||||||
}else{
|
|
||||||
var base64 = canvas.toDataURL('image/jpeg', 0.8),
|
|
||||||
buf = atob(base64.split(',')[1]),
|
|
||||||
arrBuf = new ArrayBuffer(buf.length),
|
|
||||||
intArr = new Uint8Array(arrBuf),
|
|
||||||
obj = null;
|
|
||||||
|
|
||||||
for(var i = 0; i < buf.length; i++){
|
|
||||||
intArr[i] = buf.charCodeAt(i)
|
|
||||||
}
|
|
||||||
obj = new Blob([intArr], {type: 'image/jpeg'})
|
|
||||||
uploadScreenshot(vm, obj)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
img.src = this.result
|
|
||||||
}
|
|
||||||
reader.readAsDataURL(blob)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ev.preventDefault()
|
|
||||||
})
|
})
|
||||||
},
|
.start()
|
||||||
lang = {
|
})
|
||||||
image: ['远程图片', '图片管理', '图片描述', '图片地址'],
|
} else {
|
||||||
file: ['远程附件', '附件管理', '附件描述', '附件地址']
|
upload
|
||||||
},
|
.onProgress(function(val) {
|
||||||
opened = false, //记录是否已经打开
|
vm.uploadFile[idx].progress = val + '%'
|
||||||
openType = 'image', //打开类型, 图片/附件
|
})
|
||||||
cache = { //缓存附件列表
|
.onEnd(function(json) {
|
||||||
image: [],
|
vm.uploadFile[idx].url = json.data.url
|
||||||
file: []
|
})
|
||||||
},
|
.start()
|
||||||
fixCont = function(){
|
}
|
||||||
return '<dl class="do-meditor-attach do-meditor-font">'
|
|
||||||
+ '<dt class="tab-box" :drag="do-layer" data-limit="window">'
|
|
||||||
+ '<span class="item" :class="active:tab === 1" :click="$switch(1)">' + lang[openType][0] +'</span>'
|
|
||||||
+ '<span class="item" :class="active:tab === 2" :click="$switch(2)">本地上传</span>'
|
|
||||||
+ '<span class="item" :class="active:tab === 3" :click="$switch(3)">' + lang[openType][1] + '</span>'
|
|
||||||
+ '<a href="javascript:;" :click="no" class="action-close do-ui-font"></a>'
|
|
||||||
+ '</dt>'
|
|
||||||
+ '<dt class="cont-box">'
|
|
||||||
+ '<div class="remote" :visible="tab === 1">'
|
|
||||||
+ '<section class="section do-fn-cl input"><span class="label">'+ lang[openType][2] + '</span>'
|
|
||||||
+ '<input class="txt" :duplex="attachAlt" />'
|
|
||||||
+ '</section>'
|
|
||||||
+ '<section class="section do-fn-cl input"><span class="label">'+ lang[openType][3] + '</span>'
|
|
||||||
+ '<input class="txt" :duplex="attach" />'
|
|
||||||
+ '</section>'
|
|
||||||
+ '<section class="section do-fn-cl">'
|
|
||||||
+ '<a href="javascript:;" class="submit" :click="$confirm">确定</a>'
|
|
||||||
+ '</section>'
|
|
||||||
+ '</div>'
|
|
||||||
+ '<div class="local" :visible="tab === 2">'
|
|
||||||
+ '<div class="select-file"><input id="meditor-attch" multiple :change="$change" type="file" class="hide" /><span class="file" :click="$select">选择文件</span><span class="tips">(上传大小限制:单文件最大 '
|
|
||||||
+ ((ME.maxSize/1048576).toFixed(2) - 0)
|
|
||||||
+ 'MB)</span></div>'
|
|
||||||
+ '<ul class="upload-box">'
|
|
||||||
+ '<li class="tr thead"><span class="td name">文件名</span><span class="td progress">上传进度</span><span class="td option">操作</span></li>'
|
|
||||||
+ '<li class="tr" :repeat="uploadFile">'
|
|
||||||
+ '<span class="td name" :text="el.name"></span>'
|
|
||||||
+ '<span class="td progress" :html="el.progress"></span>'
|
|
||||||
+ '<span class="td option"><a href="javascript:;" :click="$insert(el)">插入</a></span>'
|
|
||||||
+ '</li>'
|
|
||||||
+ '</ul>'
|
|
||||||
+ '</div>'
|
|
||||||
+ '<ul class="manager" :visible="tab === 3">'
|
|
||||||
+ '<li class="item" :repeat="attachList" :click="$insert(el)">'
|
|
||||||
+ '<span class="thumb" :html="el.thumb"></span>'
|
|
||||||
+ '<p class="name" :attr-title="el.name" :text="el.name"></p>'
|
|
||||||
+ '</li>'
|
|
||||||
+ '</ul>'
|
|
||||||
+ '</dt>'
|
|
||||||
+ '</dl>'
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* [uploadFile 文件上传]
|
|
||||||
* @param {[type]} files [文件列表]
|
|
||||||
* @param {[type]} vm [vm对象]
|
|
||||||
* @param {[type]} type [image/file]
|
|
||||||
*/
|
|
||||||
function uploadFile(files, vm){
|
|
||||||
for(var i = 0, it; it = files[i++];){
|
|
||||||
|
|
||||||
if(openType === 'image' && !/\.(jpg|jpeg|png|gif|bmp|webp|ico)$/.test(it.name)){
|
|
||||||
vm.uploadFile.push({name: it.name, progress: '<span class="red">0%(失败,不允许的文件类型)</span>', url: ''})
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if(ME.maxSize > 0 && it.size > ME.maxSize){
|
|
||||||
vm.uploadFile.push({name: it.name, progress: '<span class="red">0%(文件体积过大)</span>', url: ''})
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
var fixName = Date.now().toString(16) + it.name.slice(it.name.lastIndexOf('.'))
|
|
||||||
|
|
||||||
var idx = vm.uploadFile.length,
|
|
||||||
upload = new Uploader(vm.uploadUrl || ME.uploadUrl)
|
|
||||||
|
|
||||||
vm.uploadFile.push({name: it.name, progress: '0%', url: ''})
|
|
||||||
|
|
||||||
upload.field('file', it)
|
|
||||||
|
|
||||||
if(ME.beforeUpload){
|
|
||||||
ME.beforeUpload(fixName, function(qn){
|
|
||||||
|
|
||||||
upload.field('token', qn.token)
|
|
||||||
.field('key', qn.key)
|
|
||||||
.onProgress(function(val){
|
|
||||||
vm.uploadFile[idx].progress = val + '%'
|
|
||||||
}).onEnd(function(json){
|
|
||||||
vm.uploadFile[idx].url = qn.url
|
|
||||||
}).start()
|
|
||||||
})
|
|
||||||
}else{
|
|
||||||
upload.onProgress(function(val){
|
|
||||||
vm.uploadFile[idx].progress = val + '%'
|
|
||||||
}).onEnd(function(json){
|
|
||||||
vm.uploadFile[idx].url = json.data.url
|
|
||||||
}).start()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getAttach(vm, cb){
|
function getAttach(vm, cb) {
|
||||||
var xhr = new XMLHttpRequest(),
|
var xhr = new XMLHttpRequest(),
|
||||||
url = vm.manageUrl || ME.manageUrl;
|
url = vm.manageUrl || ME.manageUrl
|
||||||
|
|
||||||
if(/\?/.test(url)){
|
if (/\?/.test(url)) {
|
||||||
url += '&type=' + openType
|
url += '&type=' + openType
|
||||||
}else{
|
} else {
|
||||||
url += '?type=' + openType
|
url += '?type=' + openType
|
||||||
}
|
}
|
||||||
url += '&t=' + Math.random()
|
url += '&t=' + Math.random()
|
||||||
|
|
||||||
xhr.open('GET', url, true)
|
xhr.open('GET', url, true)
|
||||||
xhr.onreadystatechange = function(){
|
xhr.onreadystatechange = function() {
|
||||||
if(this.readyState === 4 &&
|
if (
|
||||||
this.status === 200 &&
|
this.readyState === 4 &&
|
||||||
this.responseText !== ''){
|
this.status === 200 &&
|
||||||
var res = this.responseText
|
this.responseText !== ''
|
||||||
try{
|
) {
|
||||||
res = JSON.parse(res)
|
var res = this.responseText
|
||||||
}catch(err){}
|
try {
|
||||||
cb(res)
|
res = JSON.parse(res)
|
||||||
}else{
|
} catch (err) {}
|
||||||
if(this.status !== 200 && this.responseText)
|
cb(res)
|
||||||
console.error(this.responseText)
|
} else {
|
||||||
|
if (this.status !== 200 && this.responseText)
|
||||||
|
console.error(this.responseText)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xhr.send()
|
||||||
|
}
|
||||||
|
|
||||||
|
function showDialog(elem, vm) {
|
||||||
|
opened = true
|
||||||
|
var offset = yua(elem).offset(),
|
||||||
|
layid = layer.open({
|
||||||
|
type: 7,
|
||||||
|
menubar: false,
|
||||||
|
shade: false,
|
||||||
|
fixed: true,
|
||||||
|
offset: [offset.top + 37 - ME.doc.scrollTop()],
|
||||||
|
tab: 2,
|
||||||
|
attach: '',
|
||||||
|
attachAlt: '',
|
||||||
|
uploadFile: [], //当前上传的列表
|
||||||
|
attachList: [], //附件管理列表
|
||||||
|
$switch: function(id) {
|
||||||
|
var lvm = yua.vmodels[layid]
|
||||||
|
|
||||||
|
lvm.tab = id
|
||||||
|
if (id === 3) {
|
||||||
|
lvm.attachList.clear()
|
||||||
|
if (cache[openType].length) {
|
||||||
|
lvm.attachList = cache[openType]
|
||||||
|
} else {
|
||||||
|
getAttach(vm, function(json) {
|
||||||
|
if (json) {
|
||||||
|
cache[openType] = json.data.list.map(function(it) {
|
||||||
|
it.thumb =
|
||||||
|
openType === 'image'
|
||||||
|
? '<img src="' + it.url + '"/>'
|
||||||
|
: '<em class="attach-icon"></em>'
|
||||||
|
return it
|
||||||
|
})
|
||||||
|
lvm.attachList = json.data.list
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xhr.send()
|
},
|
||||||
}
|
$select: yua.noop,
|
||||||
|
$change: yua.noop,
|
||||||
function showDialog(elem, vm){
|
$insert: function(it) {
|
||||||
opened = true
|
if (!it.url) {
|
||||||
var offset = yua(elem).offset(),
|
|
||||||
layid = layer.open({
|
|
||||||
type: 7,
|
|
||||||
menubar: false,
|
|
||||||
shade: false,
|
|
||||||
fixed: true,
|
|
||||||
offset: [offset.top + 37 - ME.doc.scrollTop()],
|
|
||||||
tab: 2,
|
|
||||||
attach: '',
|
|
||||||
attachAlt: '',
|
|
||||||
uploadFile: [], //当前上传的列表
|
|
||||||
attachList: [], //附件管理列表
|
|
||||||
$switch: function(id){
|
|
||||||
var lvm = yua.vmodels[layid]
|
|
||||||
|
|
||||||
lvm.tab = id
|
|
||||||
if(id === 3){
|
|
||||||
lvm.attachList.clear()
|
|
||||||
if(cache[openType].length){
|
|
||||||
lvm.attachList = cache[openType]
|
|
||||||
}else{
|
|
||||||
getAttach(vm, function(json){
|
|
||||||
if(json){
|
|
||||||
cache[openType] = json.data.list.map(function(it){
|
|
||||||
it.thumb = openType === 'image' ? '<img src="' + it.url + '"/>' : '<em class="attach-icon"></em>'
|
|
||||||
return it
|
|
||||||
})
|
|
||||||
lvm.attachList = json.data.list
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
$select: yua.noop,
|
|
||||||
$change: yua.noop,
|
|
||||||
$insert: function(it){
|
|
||||||
if(!it.url){
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var val = (openType === 'image' ? '!' : '')
|
|
||||||
+ '[' + it.name + '](' + it.url + ')'
|
|
||||||
ME.insert(vm.$editor, val)
|
|
||||||
},
|
|
||||||
$confirm: function(){
|
|
||||||
var lvm = yua.vmodels[layid]
|
|
||||||
if(!lvm.attach || !lvm.attachAlt){
|
|
||||||
return layer.alert('描述和地址不能为空')
|
|
||||||
}
|
|
||||||
var val = '![' + lvm.attachAlt + '](' + lvm.attach + ')'
|
|
||||||
|
|
||||||
ME.insert(vm.$editor, val)
|
|
||||||
lvm.no()
|
|
||||||
},
|
|
||||||
success: function(id){
|
|
||||||
var _this = yua.vmodels[id],
|
|
||||||
$file = document.body.querySelector('#meditor-attch')
|
|
||||||
|
|
||||||
_this.no = function(){
|
|
||||||
layer.close(id)
|
|
||||||
opened = false
|
|
||||||
}
|
|
||||||
_this.$select = function(){
|
|
||||||
var ev = document.createEvent('MouseEvent')
|
|
||||||
ev.initEvent('click', false, false)
|
|
||||||
$file.dispatchEvent(ev);
|
|
||||||
}
|
|
||||||
_this.$change = function(){
|
|
||||||
uploadFile(this.files, _this)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
content: fixCont()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ME.addon.image = function(elem, vm){
|
|
||||||
if(opened){
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
openType = 'image'
|
var val =
|
||||||
showDialog(elem, vm)
|
(openType === 'image' ? '!' : '') +
|
||||||
|
'[' +
|
||||||
|
it.name +
|
||||||
|
'](' +
|
||||||
|
it.url +
|
||||||
|
')'
|
||||||
|
ME.insert(vm.$editor, val)
|
||||||
|
},
|
||||||
|
$confirm: function() {
|
||||||
|
var lvm = yua.vmodels[layid]
|
||||||
|
if (!lvm.attach || !lvm.attachAlt) {
|
||||||
|
return layer.alert('描述和地址不能为空')
|
||||||
|
}
|
||||||
|
var val = '![' + lvm.attachAlt + '](' + lvm.attach + ')'
|
||||||
|
|
||||||
|
ME.insert(vm.$editor, val)
|
||||||
|
lvm.no()
|
||||||
|
},
|
||||||
|
success: function(id) {
|
||||||
|
var _this = yua.vmodels[id],
|
||||||
|
$file = document.body.querySelector('#meditor-attch')
|
||||||
|
|
||||||
|
_this.no = function() {
|
||||||
|
layer.close(id)
|
||||||
|
opened = false
|
||||||
|
}
|
||||||
|
_this.$select = function() {
|
||||||
|
var ev = document.createEvent('MouseEvent')
|
||||||
|
ev.initEvent('click', false, false)
|
||||||
|
$file.dispatchEvent(ev)
|
||||||
|
}
|
||||||
|
_this.$change = function() {
|
||||||
|
uploadFile(this.files, _this)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
content: fixCont()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
ME.addon.image = function(elem, vm) {
|
||||||
|
if (opened) {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
openType = 'image'
|
||||||
|
showDialog(elem, vm)
|
||||||
|
}
|
||||||
|
|
||||||
|
ME.addon.file = function(elem, vm) {
|
||||||
ME.addon.file = function(elem, vm){
|
if (opened) {
|
||||||
if(opened){
|
return
|
||||||
return
|
|
||||||
}
|
|
||||||
openType = 'file'
|
|
||||||
showDialog(elem, vm)
|
|
||||||
}
|
}
|
||||||
|
openType = 'file'
|
||||||
|
showDialog(elem, vm)
|
||||||
|
}
|
||||||
|
|
||||||
|
return $init
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return $init
|
|
||||||
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict'
|
'use strict'
|
||||||
import 'layer/base'
|
import 'layer/index'
|
||||||
|
|
||||||
function objArr(num) {
|
function objArr(num) {
|
||||||
var arr = []
|
let arr = []
|
||||||
while (num > 0) {
|
while (num > 0) {
|
||||||
arr.push({ v: 0 })
|
arr.push({ v: 0 })
|
||||||
num--
|
num--
|
||||||
|
@ -19,292 +19,373 @@ function objArr(num) {
|
||||||
function trim(str, sign) {
|
function trim(str, sign) {
|
||||||
return str.replace(new RegExp('^' + sign + '|' + sign + '$', 'g'), '')
|
return str.replace(new RegExp('^' + sign + '|' + sign + '$', 'g'), '')
|
||||||
}
|
}
|
||||||
function getOrderArr(len) {
|
|
||||||
var arr = [],
|
|
||||||
i = 0
|
|
||||||
while (i < len) {
|
|
||||||
arr.push(i++)
|
|
||||||
}
|
|
||||||
return arr
|
|
||||||
}
|
|
||||||
const addon = {
|
const addon = {
|
||||||
h1: function(elem, vm) {
|
h1: function(elem, vm) {
|
||||||
var offset = Anot(elem).offset(),
|
let that = this
|
||||||
wrap = ME.selection(vm.$editor, true) || '在此输入文本',
|
let editor = vm.$refs.editor
|
||||||
h1ID = layer.open({
|
let offset = Anot(elem).offset()
|
||||||
type: 7,
|
let wrap = this.selection(editor, true) || '在此输入文本'
|
||||||
menubar: false,
|
layer.open({
|
||||||
shadeClose: true,
|
type: 7,
|
||||||
fixed: true,
|
menubar: false,
|
||||||
$insert: function(level) {
|
maskClose: true,
|
||||||
wrap = wrap.replace(/^#{1,6} /, '')
|
fixed: true,
|
||||||
wrap = ME.repeat('#', level) + ' ' + wrap
|
insert: function(level) {
|
||||||
ME.insert(vm.$editor, wrap, true)
|
wrap = wrap.replace(/^#{1,6} /, '')
|
||||||
layer.close(h1ID)
|
wrap = that.repeat('#', level) + ' ' + wrap
|
||||||
},
|
that.insert(editor, wrap, true)
|
||||||
offset: [
|
this.close()
|
||||||
offset.top + 37 - ME.doc.scrollTop(),
|
},
|
||||||
'auto',
|
offset: [
|
||||||
'auto',
|
offset.top + 40 - that.doc.scrollTop(),
|
||||||
offset.left - ME.doc.scrollLeft()
|
'auto',
|
||||||
],
|
'auto',
|
||||||
content:
|
offset.left - that.doc.scrollLeft()
|
||||||
'<ul class="do-meditor-h1 do-fn-noselect do-meditor-font">' +
|
],
|
||||||
'<li :click="$insert(1)" class="h1">一级标题</li>' +
|
shift: {
|
||||||
'<li :click="$insert(2)" class="h2">二级标题</li>' +
|
top: offset.top - that.doc.scrollTop(),
|
||||||
'<li :click="$insert(3)" class="h3">三级标题</li>' +
|
left: offset.left - that.doc.scrollLeft()
|
||||||
'<li :click="$insert(4)" class="h4">四级标题</li>' +
|
},
|
||||||
'<li :click="$insert(5)" class="h5">五级标题</li>' +
|
content: `
|
||||||
'<li :click="$insert(6)" class="h6">六级标题</li>' +
|
<ul class="do-meditor-h1 do-fn-noselect do-meditor__font">
|
||||||
'</ul>'
|
<li :click="insert(1)" class="h1"><i class="do-meditor__icon icon-h1"></i>一级标题</li>
|
||||||
})
|
<li :click="insert(2)" class="h2"><i class="do-meditor__icon icon-h2"></i>二级标题</li>
|
||||||
|
<li :click="insert(3)" class="h3"><i class="do-meditor__icon icon-h3"></i>三级标题</li>
|
||||||
|
<li :click="insert(4)" class="h4"><i class="do-meditor__icon icon-h4"></i>四级标题</li>
|
||||||
|
<li :click="insert(5)" class="h5"><i class="do-meditor__icon icon-h5"></i>五级标题</li>
|
||||||
|
<li :click="insert(6)" class="h6"><i class="do-meditor__icon icon-h6"></i>六级标题</li>
|
||||||
|
</ul>`
|
||||||
|
})
|
||||||
},
|
},
|
||||||
quote: function(elem, vm) {
|
quote: function(elem, vm) {
|
||||||
var wrap = ME.selection(vm.$editor) || '在此输入文本'
|
let wrap = this.selection(vm.$refs.editor) || '在此输入文本'
|
||||||
wrap = '> ' + wrap
|
wrap = '> ' + wrap
|
||||||
|
|
||||||
ME.insert(vm.$editor, wrap, true)
|
this.insert(vm.$refs.editor, wrap, true)
|
||||||
},
|
},
|
||||||
bold: function(elem, vm) {
|
bold: function(elem, vm) {
|
||||||
var wrap = ME.selection(vm.$editor) || '在此输入文本',
|
let wrap = this.selection(vm.$refs.editor) || '在此输入文本'
|
||||||
wraped = trim(wrap, '\\*\\*')
|
let wraped = trim(wrap, '\\*\\*')
|
||||||
|
|
||||||
wrap = wrap === wraped ? '**' + wrap + '**' : wraped
|
wrap = wrap === wraped ? '**' + wrap + '**' : wraped
|
||||||
|
|
||||||
ME.insert(vm.$editor, wrap, true)
|
this.insert(vm.$refs.editor, wrap, true)
|
||||||
},
|
},
|
||||||
italic: function(elem, vm) {
|
italic: function(elem, vm) {
|
||||||
var wrap = ME.selection(vm.$editor) || '在此输入文本',
|
let wrap = this.selection(vm.$refs.editor) || '在此输入文本'
|
||||||
wraped = trim(wrap, '_')
|
let wraped = trim(wrap, '_')
|
||||||
|
|
||||||
wrap = wrap === wraped ? '_' + wrap + '_' : wraped
|
wrap = wrap === wraped ? '_' + wrap + '_' : wraped
|
||||||
|
|
||||||
ME.insert(vm.$editor, wrap, true)
|
this.insert(vm.$refs.editor, wrap, true)
|
||||||
},
|
},
|
||||||
through: function(elem, vm) {
|
through: function(elem, vm) {
|
||||||
var wrap = ME.selection(vm.$editor) || '在此输入文本',
|
let wrap = this.selection(vm.$refs.editor) || '在此输入文本'
|
||||||
wraped = trim(wrap, '~~')
|
let wraped = trim(wrap, '~~')
|
||||||
|
|
||||||
wrap = wrap === wraped ? '~~' + wrap + '~~' : wraped
|
wrap = wrap === wraped ? '~~' + wrap + '~~' : wraped
|
||||||
|
|
||||||
ME.insert(vm.$editor, wrap, true)
|
this.insert(vm.$refs.editor, wrap, true)
|
||||||
},
|
},
|
||||||
unordered: function(elem, vm) {
|
unordered: function(elem, vm) {
|
||||||
var wrap = ME.selection(vm.$editor) || '在此输入文本'
|
let wrap = this.selection(vm.$refs.editor) || '在此输入文本'
|
||||||
wrap = '* ' + wrap
|
wrap = '* ' + wrap
|
||||||
|
|
||||||
ME.insert(vm.$editor, wrap, false)
|
this.insert(vm.$refs.editor, wrap, false)
|
||||||
},
|
},
|
||||||
ordered: function(elem, vm) {
|
ordered: function(elem, vm) {
|
||||||
var wrap = ME.selection(vm.$editor) || '在此输入文本'
|
let wrap = this.selection(vm.$refs.editor) || '在此输入文本'
|
||||||
wrap = '1. ' + wrap
|
wrap = '1. ' + wrap
|
||||||
|
|
||||||
ME.insert(vm.$editor, wrap, false)
|
this.insert(vm.$refs.editor, wrap, false)
|
||||||
},
|
},
|
||||||
hr: function(elem, vm) {
|
hr: function(elem, vm) {
|
||||||
ME.insert(vm.$editor, '\n\n---\n\n', false)
|
this.insert(vm.$refs.editor, '\n\n---\n\n', false)
|
||||||
},
|
},
|
||||||
link: function(elem, vm) {
|
link: function(elem, vm) {
|
||||||
var offset = Anot(elem).offset(),
|
let that = this
|
||||||
wrap = ME.selection(vm.$editor) || '',
|
let offset = Anot(elem).offset()
|
||||||
layid = layer.open({
|
let wrap = this.selection(vm.$refs.editor) || ''
|
||||||
type: 7,
|
|
||||||
menubar: false,
|
layer.open({
|
||||||
shadeClose: true,
|
type: 7,
|
||||||
fixed: true,
|
menubar: false,
|
||||||
link: '',
|
maskClose: true,
|
||||||
linkName: wrap,
|
fixed: true,
|
||||||
linkTarget: 1,
|
link: '',
|
||||||
$confirm: function() {
|
linkName: wrap,
|
||||||
var lvm = Anot.vmodels[layid]
|
linkTarget: 1,
|
||||||
if (!lvm.link || !lvm.linkName) {
|
insert: function() {
|
||||||
return layer.alert('链接文字和地址不能为空')
|
if (!this.link || !this.linkName) {
|
||||||
}
|
return layer.toast('链接文字和地址不能为空', 'error')
|
||||||
var val =
|
}
|
||||||
'[' +
|
let val = `[${this.linkName}](${this.link} ${
|
||||||
lvm.linkName +
|
this.linkTarget === 1 ? ' "target=_blank"' : ''
|
||||||
'](' +
|
})`
|
||||||
lvm.link +
|
|
||||||
(lvm.linkTarget === 1 ? ' "target=_blank"' : '') +
|
that.insert(vm.$refs.editor, val, false)
|
||||||
')'
|
this.close()
|
||||||
ME.insert(vm.$editor, val, false)
|
},
|
||||||
layer.close(layid)
|
offset: [
|
||||||
},
|
offset.top + 40 - that.doc.scrollTop(),
|
||||||
offset: [
|
'auto',
|
||||||
offset.top + 37 - ME.doc.scrollTop(),
|
'auto',
|
||||||
'auto',
|
offset.left - that.doc.scrollLeft()
|
||||||
'auto',
|
],
|
||||||
offset.left - ME.doc.scrollLeft()
|
shift: {
|
||||||
],
|
top: offset.top - that.doc.scrollTop(),
|
||||||
content:
|
left: offset.left - that.doc.scrollLeft()
|
||||||
'<div class="do-meditor-common do-meditor-font">' +
|
},
|
||||||
'<section class="input"><span class="label">链接文字</span>' +
|
content: `
|
||||||
'<input class="txt" :duplex="linkName" />' +
|
<div class="do-meditor-common do-meditor__font">
|
||||||
'</section>' +
|
<section class="input">
|
||||||
'<section class="input"><span class="label">链接地址</span>' +
|
<input class="txt" :duplex="linkName" placeholder="链接文字"/>
|
||||||
'<input class="txt" :duplex="link"/>' +
|
</section>
|
||||||
'</section>' +
|
<section class="input">
|
||||||
'<section>' +
|
<input class="txt" :duplex="link" placeholder="链接地址"/>
|
||||||
'<label><input name="link" type="radio" class="radio" :duplex-number="linkTarget" value="1"/> 新窗口打开</label>' +
|
</section>
|
||||||
'<label><input name="link" type="radio" class="radio" :duplex-number="linkTarget" value="2"/> 本窗口打开</label>' +
|
<section>
|
||||||
'</section>' +
|
<label>
|
||||||
'<section>' +
|
<input
|
||||||
'<a href="javascript:;" class="submit" :click="$confirm">确定</a>' +
|
name="link"
|
||||||
'</section>' +
|
type="radio"
|
||||||
'</div>'
|
class="radio"
|
||||||
})
|
:duplex-number="linkTarget"
|
||||||
|
value="1"/>
|
||||||
|
新窗口打开
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<input
|
||||||
|
name="link"
|
||||||
|
type="radio"
|
||||||
|
class="radio"
|
||||||
|
:duplex-number="linkTarget"
|
||||||
|
value="2"/>
|
||||||
|
本窗口打开
|
||||||
|
</label>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<a
|
||||||
|
href="javascript:;"
|
||||||
|
class="do-meditor__button submit"
|
||||||
|
:click="insert">确定</a>
|
||||||
|
</section>
|
||||||
|
</div>`
|
||||||
|
})
|
||||||
},
|
},
|
||||||
time: function(elem, vm) {
|
time: function(elem, vm) {
|
||||||
ME.insert(vm.$editor, new Date().format(), false)
|
this.insert(vm.$refs.editor, new Date().format(), false)
|
||||||
},
|
},
|
||||||
face: function(elem, vm) {
|
face: function(elem, vm) {
|
||||||
var offset = Anot(elem).offset(),
|
let that = this
|
||||||
faceid = 0,
|
let offset = Anot(elem).offset()
|
||||||
layid = layer.open({
|
|
||||||
type: 7,
|
layer.open({
|
||||||
title: '插入表情',
|
type: 7,
|
||||||
fixed: true,
|
title: '插入表情',
|
||||||
shadeClose: true,
|
fixed: true,
|
||||||
arr: getOrderArr(36),
|
maskClose: true,
|
||||||
offset: [
|
arr: [
|
||||||
offset.top + 37 - ME.doc.scrollTop(),
|
'😀',
|
||||||
'auto',
|
'😅',
|
||||||
'auto',
|
'😂',
|
||||||
offset.left - ME.doc.scrollLeft()
|
'🤣',
|
||||||
],
|
'😇',
|
||||||
content:
|
'😉',
|
||||||
'<ul class="do-meditor-face">' +
|
'😍',
|
||||||
'<li class="item" :repeat="arr" ><img :attr-src="ME.path + \'/addon/face/\' + el + \'.gif\'" :click="$insert(this.src)" /></li>' +
|
'😗',
|
||||||
'</ul>',
|
'😋',
|
||||||
$insert: function(src) {
|
'😛',
|
||||||
ME.insert(vm.$editor, '![](' + src + ')', false)
|
'😜',
|
||||||
layer.close(layid)
|
'🤨',
|
||||||
}
|
'🧐',
|
||||||
})
|
'🤓',
|
||||||
|
'😎',
|
||||||
|
'😞',
|
||||||
|
'😔',
|
||||||
|
'😭',
|
||||||
|
'😤',
|
||||||
|
'😡',
|
||||||
|
'😱',
|
||||||
|
'😰',
|
||||||
|
'😓',
|
||||||
|
'😬',
|
||||||
|
'🙄',
|
||||||
|
'😴',
|
||||||
|
'😪',
|
||||||
|
'🤮',
|
||||||
|
'😷',
|
||||||
|
'💩',
|
||||||
|
'👻',
|
||||||
|
'💀',
|
||||||
|
'🤝',
|
||||||
|
'👎',
|
||||||
|
'👍',
|
||||||
|
'🙏'
|
||||||
|
],
|
||||||
|
offset: [
|
||||||
|
offset.top + 40 - that.doc.scrollTop(),
|
||||||
|
'auto',
|
||||||
|
'auto',
|
||||||
|
offset.left - that.doc.scrollLeft()
|
||||||
|
],
|
||||||
|
shift: {
|
||||||
|
top: offset.top - that.doc.scrollTop(),
|
||||||
|
left: offset.left - that.doc.scrollLeft()
|
||||||
|
},
|
||||||
|
content: `
|
||||||
|
<ul class="do-meditor-face">
|
||||||
|
<li class="item" :repeat="arr">
|
||||||
|
<span :html="el" :click="insert(el)"></span>
|
||||||
|
</li>
|
||||||
|
</ul>`,
|
||||||
|
insert: function(val) {
|
||||||
|
that.insert(vm.$refs.editor, val, false)
|
||||||
|
this.close()
|
||||||
|
}
|
||||||
|
})
|
||||||
},
|
},
|
||||||
table: function(elem, vm) {
|
table: function(elem, vm) {
|
||||||
var offset = Anot(elem).offset()
|
let that = this
|
||||||
|
let offset = Anot(elem).offset()
|
||||||
|
|
||||||
layer.open({
|
layer.open({
|
||||||
type: 7,
|
type: 7,
|
||||||
title: '0行 x 0列',
|
title: '0行 x 0列',
|
||||||
fixed: true,
|
fixed: true,
|
||||||
shadeClose: true,
|
maskClose: true,
|
||||||
offset: [
|
offset: [
|
||||||
offset.top + 37 - ME.doc.scrollTop(),
|
offset.top + 40 - that.doc.scrollTop(),
|
||||||
'auto',
|
'auto',
|
||||||
'auto',
|
'auto',
|
||||||
offset.left - ME.doc.scrollLeft()
|
offset.left - that.doc.scrollLeft()
|
||||||
],
|
],
|
||||||
|
shift: {
|
||||||
|
top: offset.top - that.doc.scrollTop(),
|
||||||
|
left: offset.left - that.doc.scrollLeft()
|
||||||
|
},
|
||||||
matrix: objArr(10).map(function() {
|
matrix: objArr(10).map(function() {
|
||||||
return objArr(10)
|
return objArr(10)
|
||||||
}),
|
}),
|
||||||
content:
|
content: `
|
||||||
'<ul class="do-meditor-table">' +
|
<ul class="do-meditor-table" ref="table">
|
||||||
'<li :repeat="matrix"><span :repeat-o="el" :class="{active: o.v}" :data="{x: $index, y: $outer.$index}"></span></li>' +
|
<li :repeat="matrix">
|
||||||
'</ul>',
|
<span
|
||||||
success: function(id) {
|
:repeat-o="el"
|
||||||
var tb = document.querySelector('.do-meditor-table'),
|
:class="{active: o.v}"
|
||||||
_this = Anot.vmodels[id],
|
:data="{x: $index, y: $outer.$index}"></span>
|
||||||
lastx,
|
</li>
|
||||||
lasty
|
</ul>`,
|
||||||
Anot(tb).bind('mousemove', function(ev) {
|
success: function() {
|
||||||
|
let tb = this.$refs.table
|
||||||
|
let lastx, lasty
|
||||||
|
|
||||||
|
Anot(tb).bind('mousemove', ev => {
|
||||||
if (ev.target.nodeName === 'SPAN') {
|
if (ev.target.nodeName === 'SPAN') {
|
||||||
var x = ev.target.dataset.x - 0,
|
let x = ev.target.dataset.x - 0
|
||||||
y = ev.target.dataset.y - 0
|
let y = ev.target.dataset.y - 0
|
||||||
if (x === lastx && y === lasty) {
|
if (x === lastx && y === lasty) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
lastx = x
|
lastx = x
|
||||||
lasty = y
|
lasty = y
|
||||||
_this.title = y + 1 + '行 x ' + (x + 1) + '列'
|
this.title = y + 1 + '行 x ' + (x + 1) + '列'
|
||||||
for (var i = 0; i <= 9; i++) {
|
for (let i = 0; i <= 9; i++) {
|
||||||
for (var j = 0; j <= 9; j++) {
|
for (let j = 0; j <= 9; j++) {
|
||||||
_this.matrix[i][j].v = i <= y && j <= x ? 1 : 0
|
this.matrix[i][j].v = i <= y && j <= x ? 1 : 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
Anot(tb).bind('mouseleave', function(ev) {
|
Anot(tb).bind('mouseleave', ev => {
|
||||||
lastx = -1
|
lastx = -1
|
||||||
lasty = -1
|
lasty = -1
|
||||||
_this.title = '0行 x 0列'
|
this.title = '0行 x 0列'
|
||||||
for (var i = 0; i <= 9; i++) {
|
for (let i = 0; i <= 9; i++) {
|
||||||
for (var j = 0; j <= 9; j++) {
|
for (let j = 0; j <= 9; j++) {
|
||||||
_this.matrix[i][j].v = 0
|
this.matrix[i][j].v = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
Anot(tb).bind('click', function(ev) {
|
Anot(tb).bind('click', ev => {
|
||||||
if (ev.target.nodeName === 'SPAN') {
|
if (ev.target.nodeName === 'SPAN') {
|
||||||
var x = ev.target.dataset.x - 0 + 1,
|
let x = ev.target.dataset.x - 0 + 1
|
||||||
y = ev.target.dataset.y - 0 + 1
|
let y = ev.target.dataset.y - 0 + 1
|
||||||
|
|
||||||
var val =
|
let thead = `\n\n${that.repeat('| 表头 ', x)}|\n`
|
||||||
'\n\n' +
|
let pipe = `${that.repeat('| -- ', x)}|\n`
|
||||||
ME.repeat('| 表头 ', x) +
|
let tbody = that.repeat(that.repeat('| ', x) + '|\n', y)
|
||||||
'|\n' +
|
|
||||||
ME.repeat('| -- ', x) +
|
that.insert(vm.$refs.editor, thead + pipe + tbody, false)
|
||||||
'|\n' +
|
this.close()
|
||||||
ME.repeat(ME.repeat('| ', x) + '|\n', y)
|
|
||||||
ME.insert(vm.$editor, val, false)
|
|
||||||
layer.close(id)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
image: function(elem, vm) {
|
image: function(elem, vm) {
|
||||||
var offset = Anot(elem).offset(),
|
let that = this
|
||||||
wrap = ME.selection(vm.$editor) || '',
|
let offset = Anot(elem).offset()
|
||||||
layid = layer.open({
|
let wrap = this.selection(vm.$refs.editor) || ''
|
||||||
type: 7,
|
|
||||||
menubar: false,
|
|
||||||
shadeClose: true,
|
|
||||||
fixed: true,
|
|
||||||
img: '',
|
|
||||||
imgAlt: wrap,
|
|
||||||
$confirm: function() {
|
|
||||||
var lvm = Anot.vmodels[layid]
|
|
||||||
if (!lvm.img || !lvm.imgAlt) {
|
|
||||||
return layer.alert('图片描述和图片地址不能为空')
|
|
||||||
}
|
|
||||||
var val = '![' + lvm.imgAlt + '](' + lvm.img + ')'
|
|
||||||
|
|
||||||
ME.insert(vm.$editor, val, false)
|
layer.open({
|
||||||
layer.close(layid)
|
type: 7,
|
||||||
},
|
menubar: false,
|
||||||
offset: [
|
maskClose: true,
|
||||||
offset.top + 37 - ME.doc.scrollTop(),
|
fixed: true,
|
||||||
'auto',
|
img: '',
|
||||||
'auto',
|
imgAlt: wrap,
|
||||||
offset.left - ME.doc.scrollLeft()
|
insert: function() {
|
||||||
],
|
if (!this.img || !this.imgAlt) {
|
||||||
content:
|
return layer.toast('链接文字和地址不能为空', 'error')
|
||||||
'<div class="do-meditor-common do-meditor-font">' +
|
}
|
||||||
'<section class="input"><span class="label">图片描述</span>' +
|
let val = `![${this.imgAlt}](${this.img})`
|
||||||
'<input class="txt" :duplex="imgAlt" />' +
|
|
||||||
'</section>' +
|
that.insert(vm.$refs.editor, val, false)
|
||||||
'<section class="input"><span class="label">图片地址</span>' +
|
this.close()
|
||||||
'<input class="txt" :duplex="img"/>' +
|
},
|
||||||
'</section>' +
|
offset: [
|
||||||
'<section>' +
|
offset.top + 40 - that.doc.scrollTop(),
|
||||||
'<a href="javascript:;" class="submit" :click="$confirm">确定</a>' +
|
'auto',
|
||||||
'</section>' +
|
'auto',
|
||||||
'</div>'
|
offset.left - that.doc.scrollLeft()
|
||||||
})
|
],
|
||||||
|
shift: {
|
||||||
|
top: offset.top - that.doc.scrollTop(),
|
||||||
|
left: offset.left - that.doc.scrollLeft()
|
||||||
|
},
|
||||||
|
content: `
|
||||||
|
<div class="do-meditor-common do-meditor__font">
|
||||||
|
<section class="input">
|
||||||
|
<input class="txt" :duplex="imgAlt" placeholder="图片描述"/>
|
||||||
|
</section>
|
||||||
|
<section class="input">
|
||||||
|
<input class="txt" :duplex="img" placeholder="图片地址"/>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<a
|
||||||
|
href="javascript:;"
|
||||||
|
class="do-meditor__button submit"
|
||||||
|
:click="insert">确定</a>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
})
|
||||||
},
|
},
|
||||||
file: function(elem, vm) {
|
attach: function(elem, vm) {
|
||||||
this.link(elem, vm, false)
|
this.addon.link.call(this, elem, vm, false)
|
||||||
},
|
},
|
||||||
inlinecode: function(elem, vm) {
|
inlinecode: function(elem, vm) {
|
||||||
var wrap = ME.selection(vm.$editor) || '在此输入文本',
|
let wrap = this.selection(vm.$refs.editor) || '在此输入文本'
|
||||||
wraped = trim(wrap, '`')
|
let wraped = trim(wrap, '`')
|
||||||
|
|
||||||
wrap = wrap === wraped ? '`' + wrap + '`' : wraped
|
wrap = wrap === wraped ? '`' + wrap + '`' : wraped
|
||||||
ME.insert(vm.$editor, wrap, true)
|
this.insert(vm.$refs.editor, wrap, true)
|
||||||
},
|
},
|
||||||
blockcode: function(elem, vm) {
|
blockcode: function(elem, vm) {
|
||||||
var layid = layer.open({
|
let that = this
|
||||||
|
layer.open({
|
||||||
type: 7,
|
type: 7,
|
||||||
title: '添加代码块',
|
title: '添加代码块',
|
||||||
$lang: [
|
$lang: [
|
||||||
|
@ -350,11 +431,11 @@ const addon = {
|
||||||
var val =
|
var val =
|
||||||
'\n```' + lvm.lang + '\n' + (lvm.code || '//在此输入代码') + '\n```\n'
|
'\n```' + lvm.lang + '\n' + (lvm.code || '//在此输入代码') + '\n```\n'
|
||||||
|
|
||||||
ME.insert(vm.$editor, val, false)
|
that.insert(vm.$refs.editor, val, false)
|
||||||
layer.close(layid)
|
layer.close(layid)
|
||||||
},
|
},
|
||||||
content:
|
content:
|
||||||
'<div class="do-meditor-codeblock do-meditor-font">' +
|
'<div class="do-meditor-codeblock do-meditor__font">' +
|
||||||
'<section class="do-fn-cl"><span class="label">语言类型</span>' +
|
'<section class="do-fn-cl"><span class="label">语言类型</span>' +
|
||||||
'<select :duplex="lang">' +
|
'<select :duplex="lang">' +
|
||||||
'<option :repeat="$lang" :attr-value="el.id">{{el.name || el.id}}</option>' +
|
'<option :repeat="$lang" :attr-value="el.id">{{el.name || el.id}}</option>' +
|
||||||
|
@ -384,9 +465,11 @@ const addon = {
|
||||||
layer.open({
|
layer.open({
|
||||||
type: 7,
|
type: 7,
|
||||||
title: '关于编辑器',
|
title: '关于编辑器',
|
||||||
offset: [offset.top + 37 - ME.doc.scrollTop()],
|
maskClose: true,
|
||||||
|
offset: [offset.top + 37 - this.doc.scrollTop()],
|
||||||
|
shift: { top: offset.top - this.doc.scrollTop() },
|
||||||
content:
|
content:
|
||||||
'<div class="do-meditor-about do-meditor-font">' +
|
'<div class="do-meditor-about do-meditor__font">' +
|
||||||
'<pre>' +
|
'<pre>' +
|
||||||
' __ __ _____ _ _ _\n' +
|
' __ __ _____ _ _ _\n' +
|
||||||
'| \\/ | ____|__| (_) |_ ___ _ __\n' +
|
'| \\/ | ____|__| (_) |_ ___ _ __\n' +
|
||||||
|
@ -394,7 +477,7 @@ const addon = {
|
||||||
'| | | | |__| (_| | | || (_) | |\n' +
|
'| | | | |__| (_| | | || (_) | |\n' +
|
||||||
'|_| |_|_____\\__,_|_|\\__\\___/|_| ' +
|
'|_| |_|_____\\__,_|_|\\__\\___/|_| ' +
|
||||||
'v' +
|
'v' +
|
||||||
ME.version +
|
this.version +
|
||||||
'</pre>' +
|
'</pre>' +
|
||||||
'<p>开源在线Markdown编辑器</p>' +
|
'<p>开源在线Markdown编辑器</p>' +
|
||||||
'<p><a target="_blank" href="https://doui.cc/product/meditor">https://doui.cc/product/meditor</a></p>' +
|
'<p><a target="_blank" href="https://doui.cc/product/meditor">https://doui.cc/product/meditor</a></p>' +
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
export default 1234
|
|
@ -17,13 +17,14 @@ marked.setOptions({
|
||||||
return Prism.highlight(code, Prism.languages[lang])
|
return Prism.highlight(code, Prism.languages[lang])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
var editorVM = []
|
let editorVM = []
|
||||||
Anot.ui.meditor = '1.0.0'
|
Anot.ui.meditor = '1.0.0'
|
||||||
|
const log = console.log
|
||||||
//存放编辑器公共静态资源
|
//存放编辑器公共静态资源
|
||||||
window.ME = {
|
window.ME = {
|
||||||
version: Anot.ui.meditor,
|
version: Anot.ui.meditor,
|
||||||
|
// 工具栏title
|
||||||
toolbar: {
|
toolbar: {
|
||||||
//工具栏title
|
|
||||||
pipe: '',
|
pipe: '',
|
||||||
h1: '标题',
|
h1: '标题',
|
||||||
quote: '引用文本',
|
quote: '引用文本',
|
||||||
|
@ -45,19 +46,19 @@ window.ME = {
|
||||||
fullscreen: '全屏',
|
fullscreen: '全屏',
|
||||||
about: '关于编辑器'
|
about: '关于编辑器'
|
||||||
},
|
},
|
||||||
addon, //已有插件
|
addon, // 已有插件
|
||||||
//往文本框中插入内容
|
// 往文本框中插入内容
|
||||||
insert: function(dom, val, isSelect) {
|
insert: function(dom, val, isSelect) {
|
||||||
if (document.selection) {
|
if (document.selection) {
|
||||||
dom.focus()
|
dom.focus()
|
||||||
var range = document.selection.createRange()
|
let range = document.selection.createRange()
|
||||||
range.text = val
|
range.text = val
|
||||||
dom.focus()
|
dom.focus()
|
||||||
range.moveStart('character', -1)
|
range.moveStart('character', -1)
|
||||||
} else if (dom.selectionStart || dom.selectionStart === 0) {
|
} else if (dom.selectionStart || dom.selectionStart === 0) {
|
||||||
var startPos = dom.selectionStart,
|
let startPos = dom.selectionStart
|
||||||
endPos = dom.selectionEnd,
|
let endPos = dom.selectionEnd
|
||||||
scrollTop = dom.scrollTop
|
let scrollTop = dom.scrollTop
|
||||||
|
|
||||||
dom.value =
|
dom.value =
|
||||||
dom.value.slice(0, startPos) +
|
dom.value.slice(0, startPos) +
|
||||||
|
@ -82,15 +83,15 @@ window.ME = {
|
||||||
if (document.selection) {
|
if (document.selection) {
|
||||||
return document.selection.createRange().text
|
return document.selection.createRange().text
|
||||||
} else {
|
} else {
|
||||||
var startPos = dom.selectionStart,
|
let startPos = dom.selectionStart
|
||||||
endPos = dom.selectionEnd
|
let endPos = dom.selectionEnd
|
||||||
|
|
||||||
if (endPos) {
|
if (endPos) {
|
||||||
//强制选择整行
|
//强制选择整行
|
||||||
if (line) {
|
if (line) {
|
||||||
startPos = dom.value.slice(0, startPos).lastIndexOf('\n')
|
startPos = dom.value.slice(0, startPos).lastIndexOf('\n')
|
||||||
|
|
||||||
var tmpEnd = dom.value.slice(endPos).indexOf('\n')
|
let tmpEnd = dom.value.slice(endPos).indexOf('\n')
|
||||||
tmpEnd = tmpEnd < 0 ? 0 : tmpEnd
|
tmpEnd = tmpEnd < 0 ? 0 : tmpEnd
|
||||||
|
|
||||||
startPos += 1 //把\n加上
|
startPos += 1 //把\n加上
|
||||||
|
@ -169,27 +170,24 @@ var elems = {
|
||||||
},
|
},
|
||||||
hr: '\n\n___\n\n',
|
hr: '\n\n___\n\n',
|
||||||
a: function(str, attr, inner) {
|
a: function(str, attr, inner) {
|
||||||
var href = attr.match(attrExp('href')),
|
let href = attr.match(attrExp('href'))
|
||||||
title = attr.match(attrExp('title')),
|
let title = attr.match(attrExp('title'))
|
||||||
tar = attr.match(attrExp('target'))
|
let tar = attr.match(attrExp('target'))
|
||||||
|
let attrs = ''
|
||||||
|
|
||||||
href = (href && href[1]) || ''
|
href = (href && href[1]) || null
|
||||||
title = (title && title[1]) || ''
|
title = (title && title[1]) || null
|
||||||
tar = (tar && tar[1]) || '_self'
|
tar = (tar && tar[1]) || '_self'
|
||||||
|
|
||||||
href = href === 'javascript:void(0);' ? 'javascript:;' : href
|
if (!href) {
|
||||||
|
return inner || href
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
href = href.replace('viod(0)', '')
|
||||||
'[' +
|
attrs = `target=${tar}`
|
||||||
(inner || href) +
|
attrs += title ? `;title=${title}` : ''
|
||||||
'](' +
|
|
||||||
href +
|
return `[${inner || href}](${href} "${attrs}")`
|
||||||
' "title=' +
|
|
||||||
title +
|
|
||||||
';target=' +
|
|
||||||
tar +
|
|
||||||
'")'
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
em: function(str, attr, inner) {
|
em: function(str, attr, inner) {
|
||||||
return (inner && '_' + inner + '_') || ''
|
return (inner && '_' + inner + '_') || ''
|
||||||
|
@ -233,7 +231,12 @@ function html2md(str) {
|
||||||
try {
|
try {
|
||||||
str = decodeURIComponent(str)
|
str = decodeURIComponent(str)
|
||||||
} catch (err) {}
|
} catch (err) {}
|
||||||
str = str.replace(/\t/g, ' ').replace(/<meta [^>]*>/, '')
|
|
||||||
|
str = str.replace(/\t/g, ' ').replace(/<meta [^>]*>/, '')
|
||||||
|
str = str.replace(
|
||||||
|
/<(div|span|dl|dd|dt|table|tr|td|thead|tbody|i|em|strong|h[1-6]|ul|ol|li) [^>]*>/g,
|
||||||
|
'<$1>'
|
||||||
|
)
|
||||||
|
|
||||||
for (var i in elems) {
|
for (var i in elems) {
|
||||||
var cb = elems[i],
|
var cb = elems[i],
|
||||||
|
@ -313,7 +316,7 @@ var defaultToolbar = [
|
||||||
'|',
|
'|',
|
||||||
'table',
|
'table',
|
||||||
'image',
|
'image',
|
||||||
'file',
|
'attach',
|
||||||
'inlinecode',
|
'inlinecode',
|
||||||
'blockcode',
|
'blockcode',
|
||||||
'|',
|
'|',
|
||||||
|
@ -330,7 +333,7 @@ function tool(name) {
|
||||||
return (
|
return (
|
||||||
'<span title="' +
|
'<span title="' +
|
||||||
ME.toolbar[name] +
|
ME.toolbar[name] +
|
||||||
'" class="icon-' +
|
'" class="do-meditor__icon icon-' +
|
||||||
name +
|
name +
|
||||||
'" ' +
|
'" ' +
|
||||||
(name !== 'pipe' ? ':click="onToolClick(\'' + name + '\', $event)"' : '') +
|
(name !== 'pipe' ? ':click="onToolClick(\'' + name + '\', $event)"' : '') +
|
||||||
|
@ -340,35 +343,43 @@ function tool(name) {
|
||||||
|
|
||||||
Anot.component('meditor', {
|
Anot.component('meditor', {
|
||||||
render: function() {
|
render: function() {
|
||||||
var toolbar = (this.toolbar || defaultToolbar)
|
let toolbar = (this.toolbar || defaultToolbar).map(it => tool(it)).join('')
|
||||||
.map(function(it) {
|
|
||||||
return tool(it)
|
|
||||||
})
|
|
||||||
.join('')
|
|
||||||
delete this.toolbar
|
delete this.toolbar
|
||||||
return (
|
|
||||||
'<div class="do-meditor do-meditor-font" :visible="editorVisible"' +
|
return `
|
||||||
' :class="{fullscreen: fullscreen, preview: preview}">' +
|
<div
|
||||||
'<div class="tool-bar do-ui-font do-fn-noselect">{toolbar}</div>' +
|
class="do-meditor do-meditor__font"
|
||||||
'<textarea ref="textarea" class="editor-body" spellcheck="false" :duplex="plainTxt" :attr="{disabled: disabled}" :on-paste="$paste($event)"></textarea>' +
|
:visible="editorVisible"
|
||||||
'<content class="md-preview do-marked-theme" :visible="preview" :html="htmlTxt"></content>' +
|
:class="{fullscreen: fullscreen, preview: preview}">
|
||||||
'</div>'
|
<div class="tool-bar do-fn-noselect">${toolbar}</div>
|
||||||
).replace(/\{toolbar\}/g, toolbar)
|
<textarea
|
||||||
|
ref="editor"
|
||||||
|
class="editor-body"
|
||||||
|
spellcheck="false"
|
||||||
|
:attr="{disabled: disabled}"
|
||||||
|
:duplex="plainTxt"
|
||||||
|
:on-paste="onPaste($event)"></textarea>
|
||||||
|
<content
|
||||||
|
class="md-preview do-marked-theme"
|
||||||
|
:visible="preview"
|
||||||
|
:html="htmlTxt"></content>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
},
|
},
|
||||||
|
|
||||||
construct: function(base, opt, attr) {
|
construct: function(props, state) {
|
||||||
Anot.mix(base, opt, attr)
|
// Anot.mix(base, opt, attr)
|
||||||
if (base.$addons && Array.isArray(base.$addons)) {
|
// if (base.$addons && Array.isArray(base.$addons)) {
|
||||||
extraAddons = base.$addons.map(function(name) {
|
// extraAddons = base.$addons.map(function(name) {
|
||||||
return ME.path + '/addon/' + name
|
// return ME.path + '/addon/' + name
|
||||||
})
|
// })
|
||||||
delete base.$addons
|
// delete base.$addons
|
||||||
|
// }
|
||||||
|
if (props.hasOwnProperty('$show')) {
|
||||||
|
state.editorVisible = props.$show
|
||||||
|
delete props.$show
|
||||||
}
|
}
|
||||||
if (base.hasOwnProperty('$show')) {
|
|
||||||
base.editorVisible = base.$show
|
|
||||||
delete base.$show
|
|
||||||
}
|
|
||||||
return base
|
|
||||||
},
|
},
|
||||||
componentWillMount: function(vm) {},
|
componentWillMount: function(vm) {},
|
||||||
componentDidMount: function(vm, elem) {
|
componentDidMount: function(vm, elem) {
|
||||||
|
@ -411,25 +422,32 @@ Anot.component('meditor', {
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
plainTxt: function(val) {
|
plainTxt: function(val) {
|
||||||
this.$compile()
|
this.compile()
|
||||||
//只有开启实时预览,才会赋值给htmlTxt
|
//只有开启实时预览,才会赋值给htmlTxt
|
||||||
if (this.preview) {
|
if (this.preview) {
|
||||||
this.htmlTxt = this.$htmlTxt
|
this.htmlTxt = this.$htmlTxt
|
||||||
}
|
}
|
||||||
this.$onUpdate(this.plainTxt, vm.$htmlTxt)
|
if (typeof this.props.onUpdate === 'function') {
|
||||||
|
this.props.onUpdate(this.plainTxt, this.$htmlTxt)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
state: {
|
state: {
|
||||||
disabled: false, //禁用编辑器
|
disabled: false, //禁用编辑器
|
||||||
fullscreen: false, //是否全屏
|
fullscreen: false, //是否全屏
|
||||||
preview: false, //是否显示预览
|
preview: false, //是否显示预览
|
||||||
$editor: null, //编辑器元素
|
// $editor: null, //编辑器元素
|
||||||
editorVisible: true,
|
editorVisible: true,
|
||||||
$htmlTxt: '', //临时储存html文本
|
$htmlTxt: '', //临时储存html文本
|
||||||
htmlTxt: '', //用于预览渲染
|
htmlTxt: '', //用于预览渲染
|
||||||
plainTxt: '', //纯md文本
|
plainTxt: '', //纯md文本
|
||||||
$safelyCompile: true
|
$safelyCompile: true
|
||||||
},
|
},
|
||||||
|
props: {
|
||||||
|
onSuccess: Anot.PropsTypes.isFunction(),
|
||||||
|
onUpdate: Anot.PropsTypes.isFunction(),
|
||||||
|
onFullscreen: Anot.PropsTypes.isFunction()
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onToolClick: function(name, ev) {
|
onToolClick: function(name, ev) {
|
||||||
if (ME.addon[name]) {
|
if (ME.addon[name]) {
|
||||||
|
@ -438,24 +456,23 @@ Anot.component('meditor', {
|
||||||
console.log('%c没有对应的插件%c[%s]', 'color:#f00;', '', name)
|
console.log('%c没有对应的插件%c[%s]', 'color:#f00;', '', name)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
$onSuccess: Anot.noop,
|
onPaste: function(ev) {
|
||||||
$onUpdate: Anot.noop,
|
|
||||||
$onFullscreen: Anot.noop,
|
|
||||||
$paste: function(ev) {
|
|
||||||
ev.preventDefault()
|
ev.preventDefault()
|
||||||
var txt = ev.clipboardData.getData('text/plain').trim(),
|
let txt = ev.clipboardData.getData('text/plain').trim()
|
||||||
html = ev.clipboardData.getData('text/html').trim()
|
let html = ev.clipboardData.getData('text/html').trim()
|
||||||
|
|
||||||
html = html2md(html)
|
html = html2md(html)
|
||||||
|
|
||||||
if (html) {
|
if (html) {
|
||||||
ME.insert(this, html)
|
ME.insert(ev.target, html)
|
||||||
} else if (txt) {
|
} else if (txt) {
|
||||||
ME.insert(this, txt)
|
ME.insert(ev.target, txt)
|
||||||
}
|
}
|
||||||
this.plainTxt = this.value
|
log(ev.target.value)
|
||||||
|
this.plainTxt = this.$refs.editor.value
|
||||||
},
|
},
|
||||||
compile: function() {
|
compile: function() {
|
||||||
|
log(this)
|
||||||
var txt = this.plainTxt.trim()
|
var txt = this.plainTxt.trim()
|
||||||
|
|
||||||
if (this.$safelyCompile) {
|
if (this.$safelyCompile) {
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -7,15 +7,13 @@
|
||||||
|
|
||||||
import './highlight.scss'
|
import './highlight.scss'
|
||||||
|
|
||||||
var _self = window
|
|
||||||
|
|
||||||
var Prism = (function() {
|
var Prism = (function() {
|
||||||
// Private helper vars
|
// Private helper vars
|
||||||
var lang = /\blang(?:uage)?-(\w+)\b/i
|
var lang = /\blang(?:uage)?-(\w+)\b/i
|
||||||
var uniqueId = 0
|
var uniqueId = 0
|
||||||
|
|
||||||
var _ = (_self.Prism = {
|
var _ = (window.Prism = {
|
||||||
manual: _self.Prism && _self.Prism.manual,
|
manual: window.Prism && window.Prism.manual,
|
||||||
util: {
|
util: {
|
||||||
encode: function(tokens) {
|
encode: function(tokens) {
|
||||||
if (tokens instanceof Token) {
|
if (tokens instanceof Token) {
|
||||||
|
@ -221,7 +219,7 @@ var Prism = (function() {
|
||||||
|
|
||||||
_.hooks.run('before-highlight', env)
|
_.hooks.run('before-highlight', env)
|
||||||
|
|
||||||
if (async && _self.Worker) {
|
if (async && window.Worker) {
|
||||||
var worker = new Worker(_.filename)
|
var worker = new Worker(_.filename)
|
||||||
|
|
||||||
worker.onmessage = function(evt) {
|
worker.onmessage = function(evt) {
|
||||||
|
@ -487,13 +485,13 @@ var Prism = (function() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_self.document) {
|
if (!window.document) {
|
||||||
if (!_self.addEventListener) {
|
if (!window.addEventListener) {
|
||||||
// in Node.js
|
// in Node.js
|
||||||
return _self.Prism
|
return window.Prism
|
||||||
}
|
}
|
||||||
// In worker
|
// In worker
|
||||||
_self.addEventListener(
|
window.addEventListener(
|
||||||
'message',
|
'message',
|
||||||
function(evt) {
|
function(evt) {
|
||||||
var message = JSON.parse(evt.data),
|
var message = JSON.parse(evt.data),
|
||||||
|
@ -501,15 +499,15 @@ var Prism = (function() {
|
||||||
code = message.code,
|
code = message.code,
|
||||||
immediateClose = message.immediateClose
|
immediateClose = message.immediateClose
|
||||||
|
|
||||||
_self.postMessage(_.highlight(code, _.languages[lang], lang))
|
window.postMessage(_.highlight(code, _.languages[lang], lang))
|
||||||
if (immediateClose) {
|
if (immediateClose) {
|
||||||
_self.close()
|
window.close()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
|
|
||||||
return _self.Prism
|
return window.Prism
|
||||||
}
|
}
|
||||||
|
|
||||||
//Get current script and highlight
|
//Get current script and highlight
|
||||||
|
@ -537,7 +535,7 @@ var Prism = (function() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return _self.Prism
|
return window.Prism
|
||||||
})()
|
})()
|
||||||
|
|
||||||
Prism.languages.markup = {
|
Prism.languages.markup = {
|
||||||
|
|
|
@ -232,7 +232,6 @@ Prism.languages.insertBefore('cpp', 'keyword', {
|
||||||
})
|
})
|
||||||
|
|
||||||
/*-----------------------coffeescript-----------------------*/
|
/*-----------------------coffeescript-----------------------*/
|
||||||
|
|
||||||
;(function(Prism) {
|
;(function(Prism) {
|
||||||
// Ignore comments starting with { to privilege string interpolation highlighting
|
// Ignore comments starting with { to privilege string interpolation highlighting
|
||||||
var comment = /#(?!\{).+/,
|
var comment = /#(?!\{).+/,
|
||||||
|
@ -322,7 +321,6 @@ Prism.languages.insertBefore('cpp', 'keyword', {
|
||||||
})(Prism)
|
})(Prism)
|
||||||
|
|
||||||
/*---------------------------ruby---------------------------*/
|
/*---------------------------ruby---------------------------*/
|
||||||
|
|
||||||
;(function(Prism) {
|
;(function(Prism) {
|
||||||
Prism.languages.ruby = Prism.languages.extend('clike', {
|
Prism.languages.ruby = Prism.languages.extend('clike', {
|
||||||
comment: [
|
comment: [
|
||||||
|
@ -650,7 +648,6 @@ Prism.languages.haskell = {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*---------------------------jade---------------------------*/
|
/*---------------------------jade---------------------------*/
|
||||||
|
|
||||||
;(function(Prism) {
|
;(function(Prism) {
|
||||||
Prism.languages.jade = {
|
Prism.languages.jade = {
|
||||||
comment: {
|
comment: {
|
||||||
|
@ -862,7 +859,6 @@ Prism.languages.json = {
|
||||||
Prism.languages.jsonp = Prism.languages.json
|
Prism.languages.jsonp = Prism.languages.json
|
||||||
|
|
||||||
/*--------------------------kotlin----------------------------*/
|
/*--------------------------kotlin----------------------------*/
|
||||||
|
|
||||||
;(function(Prism) {
|
;(function(Prism) {
|
||||||
Prism.languages.kotlin = Prism.languages.extend('clike', {
|
Prism.languages.kotlin = Prism.languages.extend('clike', {
|
||||||
keyword: {
|
keyword: {
|
||||||
|
@ -1525,7 +1521,6 @@ Prism.languages.rust = {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------*/
|
/*------------------------------------------------------------*/
|
||||||
|
|
||||||
;(function(Prism) {
|
;(function(Prism) {
|
||||||
Prism.languages.sass = Prism.languages.extend('css', {
|
Prism.languages.sass = Prism.languages.extend('css', {
|
||||||
// Sass comments don't need to be closed, only indented
|
// Sass comments don't need to be closed, only indented
|
||||||
|
@ -1676,7 +1671,6 @@ Prism.languages.scss['atrule'].inside.rest = Prism.util.clone(
|
||||||
)
|
)
|
||||||
|
|
||||||
/*-----------------------------smarty-------------------------*/
|
/*-----------------------------smarty-------------------------*/
|
||||||
|
|
||||||
;(function(Prism) {
|
;(function(Prism) {
|
||||||
var smarty_pattern = /\{\*[\s\S]+?\*\}|\{[\s\S]+?\}/g
|
var smarty_pattern = /\{\*[\s\S]+?\*\}|\{[\s\S]+?\}/g
|
||||||
var smarty_litteral_start = '{literal}'
|
var smarty_litteral_start = '{literal}'
|
||||||
|
|
Reference in New Issue