修复框架在循环中动态增加VM导致作用域混乱的bug;优化layer组件的tips和loading;完成meditor的移植
|
@ -22,8 +22,9 @@ const jsOpt = {
|
|||
plugins: [
|
||||
'transform-es2015-modules-amd',
|
||||
'transform-decorators-legacy',
|
||||
'transform-class-properties',
|
||||
'transform-object-rest-spread'
|
||||
'transform-object-rest-spread',
|
||||
['transform-es2015-classes', { loose: true }],
|
||||
['transform-es2015-for-of', { loose: true }]
|
||||
]
|
||||
}
|
||||
const cssOpt = {
|
||||
|
@ -78,7 +79,6 @@ const compileHtm = (entry, output) => {
|
|||
/*===== ===*/
|
||||
/*=======================================================*/
|
||||
|
||||
const fontFiles = fs.ls('./src/font/', true)
|
||||
const jsFiles = fs.ls('./src/js/', true)
|
||||
const cssFiles = fs.ls('./src/css/', true)
|
||||
|
||||
|
|
|
@ -65,7 +65,6 @@ const compileHtm = (entry, output) => {
|
|||
/*===== ===*/
|
||||
/*=======================================================*/
|
||||
|
||||
const fontFiles = fs.ls('./src/font/', true)
|
||||
const jsFiles = fs.ls('./src/js/', true)
|
||||
const cssFiles = fs.ls('./src/css/', true)
|
||||
|
||||
|
@ -74,11 +73,6 @@ if (fs.isdir(buildDir)) {
|
|||
log(chalk.cyan('清除旧目录 dist/'))
|
||||
}
|
||||
|
||||
// 字体文件直接复制
|
||||
fontFiles.forEach(file => {
|
||||
fs.cp('./src/font/' + file, './dist/font/' + file)
|
||||
})
|
||||
|
||||
// css目录
|
||||
cssFiles.forEach(file => {
|
||||
if (/\.scss$/.test(file)) {
|
||||
|
|
|
@ -22,8 +22,9 @@ const jsOpt = {
|
|||
plugins: [
|
||||
'transform-es2015-modules-amd',
|
||||
'transform-decorators-legacy',
|
||||
'transform-class-properties',
|
||||
'transform-object-rest-spread'
|
||||
'transform-object-rest-spread',
|
||||
['transform-es2015-classes', { loose: true }],
|
||||
['transform-es2015-for-of', { loose: true }]
|
||||
]
|
||||
}
|
||||
const cssOpt = {
|
||||
|
@ -37,10 +38,12 @@ const compileJs = (entry, output) => {
|
|||
}
|
||||
let t1 = Date.now()
|
||||
let tmpOpt = jsOpt
|
||||
if (/anot/.test(entry)) {
|
||||
tmpOpt = Object.assign({}, jsOpt, { plugins: [] })
|
||||
let code = ''
|
||||
if (!/anot/.test(entry)) {
|
||||
code = babel.transformFileSync(entry, jsOpt).code
|
||||
} else {
|
||||
code = fs.cat(entry).toString()
|
||||
}
|
||||
let { code } = babel.transformFileSync(entry, tmpOpt)
|
||||
code = uglify.minify(code).code.replace(/\.scss/g, '.css')
|
||||
log(
|
||||
'编译JS: %s, 耗时 %s ms',
|
||||
|
@ -79,7 +82,6 @@ const compileHtm = (entry, output) => {
|
|||
/*===== ===*/
|
||||
/*=======================================================*/
|
||||
|
||||
const fontFiles = fs.ls('./src/font/', true)
|
||||
const jsFiles = fs.ls('./src/js/', true)
|
||||
const cssFiles = fs.ls('./src/css/', true)
|
||||
|
||||
|
@ -88,11 +90,6 @@ if (fs.isdir(buildDir)) {
|
|||
log(chalk.cyan('清除旧目录 dist/'))
|
||||
}
|
||||
|
||||
// 字体文件直接复制
|
||||
fontFiles.forEach(file => {
|
||||
fs.cp('./src/font/' + file, './dist/font/' + file)
|
||||
})
|
||||
|
||||
// css目录
|
||||
cssFiles.forEach(file => {
|
||||
if (/\.scss$/.test(file)) {
|
||||
|
|
16
package.json
|
@ -12,21 +12,25 @@
|
|||
"type": "git",
|
||||
"url": "git+https://github.com/yutent/doui.git"
|
||||
},
|
||||
"keywords": ["doui", "Anot"],
|
||||
"keywords": [
|
||||
"doui",
|
||||
"Anot"
|
||||
],
|
||||
"author": "yutent",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^7.2.6",
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-plugin-transform-class-properties": "^6.24.1",
|
||||
"babel-core": "^6.26.3",
|
||||
"babel-plugin-transform-decorators-legacy": "^1.3.4",
|
||||
"babel-plugin-transform-es2015-classes": "^6.24.1",
|
||||
"babel-plugin-transform-es2015-for-of": "^6.23.0",
|
||||
"babel-plugin-transform-object-rest-spread": "^6.26.0",
|
||||
"babel-preset-es2015": "^6.24.1",
|
||||
"chalk": "^2.3.2",
|
||||
"chalk": "^2.4.1",
|
||||
"chokidar": "^1.7.0",
|
||||
"iofs": "^1.0.3",
|
||||
"node-sass": "^4.8.2",
|
||||
"postcss": "^6.0.19",
|
||||
"node-sass": "^4.9.0",
|
||||
"postcss": "^6.0.22",
|
||||
"uglify-es": "^3.3.9"
|
||||
},
|
||||
"dependencies": {}
|
||||
|
|
|
@ -234,20 +234,26 @@
|
|||
vm.$id = $id
|
||||
VMODELS[$id] = vm
|
||||
|
||||
var $elem = document.querySelector('[anot=' + vm.$id + ']')
|
||||
if ($elem) {
|
||||
if ($elem === DOC.body) {
|
||||
scanTag($elem, [])
|
||||
} else {
|
||||
var $parent = $elem
|
||||
while (($parent = $parent.parentNode)) {
|
||||
if ($parent.anotctrl) {
|
||||
break
|
||||
Anot.nextTick(function() {
|
||||
var $elem = document.querySelector('[anot=' + vm.$id + ']')
|
||||
if ($elem) {
|
||||
if ($elem === DOC.body) {
|
||||
scanTag($elem, [])
|
||||
} else {
|
||||
var $parent = $elem
|
||||
while (($parent = $parent.parentNode)) {
|
||||
if ($parent.anotctrl) {
|
||||
break
|
||||
}
|
||||
}
|
||||
scanTag(
|
||||
$elem.parentNode,
|
||||
$parent ? [VMODELS[$parent.anotctrl]] : []
|
||||
)
|
||||
}
|
||||
scanTag($elem.parentNode, $parent ? [VMODELS[$parent.anotctrl]] : [])
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return vm
|
||||
} else {
|
||||
this[0] = this.element = source
|
||||
|
@ -2172,6 +2178,7 @@
|
|||
injectDependency(array, binding)
|
||||
}
|
||||
})
|
||||
|
||||
binding.getter = parseExpr(binding.expr, binding.vmodels, binding)
|
||||
binding.observers.forEach(function(a) {
|
||||
a.v.$watch(a.p, binding)
|
||||
|
@ -3038,8 +3045,8 @@
|
|||
}
|
||||
|
||||
function addAssign(vars, vmodel, name, binding) {
|
||||
var ret = [],
|
||||
prefix = ' = ' + name + '.'
|
||||
var ret = []
|
||||
var prefix = ' = ' + name + '.'
|
||||
for (var i = vars.length, prop; (prop = vars[--i]); ) {
|
||||
var arr = prop.split('.')
|
||||
var first = arr[0]
|
||||
|
@ -3137,7 +3144,7 @@
|
|||
/* jshint ignore:start */
|
||||
var fn2 = scpCompile(
|
||||
names.concat(
|
||||
"'use strict';" + 'return function(vvv){' + expr + ' = vvv\n}\n'
|
||||
'"use strict";\n return function(vvv){' + expr + ' = vvv\n}\n'
|
||||
)
|
||||
)
|
||||
/* jshint ignore:end */
|
||||
|
@ -3178,11 +3185,23 @@
|
|||
})
|
||||
expr = '\nreturn ' + expr + ';' //IE全家 Function("return ")出错,需要Function("return ;")
|
||||
}
|
||||
// log('')
|
||||
// log(
|
||||
// names
|
||||
// .concat(
|
||||
// "'use strict';\ntry{\nvar " +
|
||||
// assigns.join(',\n') +
|
||||
// expr +
|
||||
// '\n}catch(e){console.log(e)}'
|
||||
// )
|
||||
// .join('')
|
||||
// )
|
||||
// log('')
|
||||
/* jshint ignore:start */
|
||||
getter = scpCompile(
|
||||
names.concat(
|
||||
"'use strict';\ntry{\nvar " +
|
||||
assigns.join(',\n') +
|
||||
"'use strict';\ntry{\n var " +
|
||||
assigns.join(',\n ') +
|
||||
expr +
|
||||
'\n}catch(e){console.log(e)}'
|
||||
)
|
||||
|
@ -3290,7 +3309,7 @@
|
|||
Anot.injectBinding(binding)
|
||||
if (binding.getter && binding.element.nodeType === 1) {
|
||||
//移除数据绑定,防止被二次解析
|
||||
//chrome使用removeAttributeNode移除不存在的特性节点时会报错 https://github.com/RubyLouvre/Anot/issues/99
|
||||
//chrome使用removeAttributeNode移除不存在的特性节点时会报错
|
||||
binding.element.removeAttribute(binding.name)
|
||||
}
|
||||
}
|
||||
|
@ -3505,8 +3524,8 @@
|
|||
}
|
||||
|
||||
function scanTag(elem, vmodels, node) {
|
||||
//扫描顺序 skip(0) --> anot(1) --> :if(10) --> :repeat(100)
|
||||
//--> :if-loop(110) --> :attr(970) ...--> :each(1400)-->:with(1500)--〉:duplex(2000)垫后
|
||||
//扫描顺序 skip(0) --> anot(1) --> :if(10) --> :repeat(90)
|
||||
//--> :if-loop(110) --> :attr(970) ...--> :duplex(2000)垫后
|
||||
var skip = elem.getAttribute('skip')
|
||||
node = elem.getAttributeNode('anot')
|
||||
var vm = vmodels.concat()
|
||||
|
@ -3557,15 +3576,16 @@
|
|||
newVmodel.props[k] = props[k]
|
||||
delete props[k]
|
||||
} else {
|
||||
Anot.error(
|
||||
'props.' +
|
||||
k +
|
||||
' needs [' +
|
||||
newVmodel.props[k].checkType +
|
||||
'], but [' +
|
||||
newVmodel.props[k].result +
|
||||
'] given.',
|
||||
TypeError
|
||||
console.error(
|
||||
new TypeError(
|
||||
'props.' +
|
||||
k +
|
||||
' needs [' +
|
||||
newVmodel.props[k].checkType +
|
||||
'], but [' +
|
||||
newVmodel.props[k].result +
|
||||
'] given.'
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -5463,11 +5483,6 @@
|
|||
var kill = elem.previousSibling
|
||||
var start = binding.start
|
||||
|
||||
/*log(kill === start, kill)
|
||||
while(kill !== start && kill.nodeName !== '#comment'){
|
||||
parent.removeChild(kill)
|
||||
kill = elem.previousSibling
|
||||
}*/
|
||||
if (clear) {
|
||||
while (kill !== start) {
|
||||
parent.removeChild(kill)
|
||||
|
@ -5509,9 +5524,6 @@
|
|||
)
|
||||
decorateProxy(proxy, binding, xtype)
|
||||
} else {
|
||||
// if (xtype === "array") {
|
||||
// proxy[param] = value[i]
|
||||
// }
|
||||
fragments.push({})
|
||||
retain[keyOrId] = true
|
||||
}
|
||||
|
@ -5528,7 +5540,6 @@
|
|||
if (xtype === 'array') {
|
||||
proxy.$first = i === 0
|
||||
proxy.$last = i === length - 1
|
||||
// proxy[param] = value[i]
|
||||
} else {
|
||||
proxy.$val = toJson(value[keyOrId]) //这里是处理vm.object = newObject的情况
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ let defconf = {
|
|||
offset: [], // 弹窗出来后的坐标, 为数组,可有4个值,依次是 上右下左
|
||||
btns: ['确定', '取消'] // 弹窗的2个按钮的文字
|
||||
}
|
||||
const $doc = Anot(document)
|
||||
const uuid = function() {
|
||||
return 'layer-' + lid++
|
||||
}
|
||||
|
@ -214,6 +215,9 @@ class __layer__ {
|
|||
outerBox.classList.add('do-layer')
|
||||
if (state.mask) {
|
||||
outerBox.classList.add('mask')
|
||||
if (state.container && state.container !== document.body) {
|
||||
outerBox.classList.add('inner')
|
||||
}
|
||||
}
|
||||
if (state.maskColor) {
|
||||
outerBox.style.background = state.maskColor
|
||||
|
@ -383,7 +387,6 @@ class __layer__ {
|
|||
style.color = state.color
|
||||
style.opacity = 1
|
||||
let $container = Anot(container)
|
||||
let $doc = Anot(document)
|
||||
let $arrow = $container[0].querySelector('.arrow')
|
||||
let cw = $container.innerWidth()
|
||||
let ch = $container.innerHeight()
|
||||
|
@ -564,23 +567,26 @@ const _layer = {
|
|||
|
||||
return _layer.open(opt)
|
||||
},
|
||||
loading: function(style, time, cb) {
|
||||
loading: function(style, container, cb) {
|
||||
style = style >>> 0
|
||||
style = style < 1 ? 1 : style > 5 ? 5 : style
|
||||
|
||||
if (typeof time === 'function') {
|
||||
cb = time
|
||||
time = 0
|
||||
if (typeof container === 'function') {
|
||||
cb = container
|
||||
container = null
|
||||
} else {
|
||||
time = time >>> 0
|
||||
if (!(container instanceof HTMLElement)) {
|
||||
container = null
|
||||
}
|
||||
if (typeof cb !== 'function') {
|
||||
cb = Anot.noop
|
||||
}
|
||||
}
|
||||
return _layer.open({
|
||||
container,
|
||||
type: 6,
|
||||
load: style,
|
||||
yes: cb,
|
||||
timeout: time,
|
||||
menubar: false,
|
||||
background: 'none',
|
||||
shift: 'ct',
|
||||
|
@ -660,7 +666,7 @@ const _layer = {
|
|||
}
|
||||
|
||||
Anot.directive('layer', {
|
||||
priority: 1400,
|
||||
priority: 8090,
|
||||
init: function(binding) {
|
||||
// 去掉:layer属性,避免二次扫描
|
||||
binding.element.removeAttribute(binding.name)
|
||||
|
@ -671,13 +677,15 @@ Anot.directive('layer', {
|
|||
},
|
||||
update: function(val) {
|
||||
if (!val) {
|
||||
console.error(this)
|
||||
return console.error(
|
||||
`SyntaxError: Unexpected [${this.name}=${this.expr}]`
|
||||
)
|
||||
}
|
||||
|
||||
let state = Object.assign({ type: 7, wrap: true }, this.element.dataset)
|
||||
|
||||
if (!this.param) {
|
||||
let state = Object.assign({ type: 7, wrap: true }, this.element.dataset)
|
||||
let init = { $id: 'layerwrap-' + val, state, props: {} }
|
||||
|
||||
if (state.hasOwnProperty('area')) {
|
||||
|
@ -709,7 +717,72 @@ Anot.directive('layer', {
|
|||
}
|
||||
layerDom[tmp.init.$id] = tmp.create()
|
||||
} else if (this.param === 'tips') {
|
||||
_layer.tips(val, this.element)
|
||||
let tips = document.createElement('div')
|
||||
let cont = document.createElement('span')
|
||||
let arrow = document.createElement('i')
|
||||
tips.className = 'do-layer__tips'
|
||||
cont.className = 'layer-content'
|
||||
arrow.className = 'arrow'
|
||||
cont.textContent = val
|
||||
tips.appendChild(cont)
|
||||
tips.appendChild(arrow)
|
||||
this.element.appendChild(tips)
|
||||
|
||||
if (state.color) {
|
||||
style.color = state.color
|
||||
}
|
||||
if (state.color) {
|
||||
style.background = state.background
|
||||
}
|
||||
|
||||
let style = {}
|
||||
let css = getComputedStyle(tips)
|
||||
let $container = Anot(this.element)
|
||||
let cw = $container.innerWidth()
|
||||
let ch = $container.innerHeight()
|
||||
let ol = $container.offset().left - $doc.scrollLeft()
|
||||
let ot = $container.offset().top - $doc.scrollTop()
|
||||
|
||||
let layw = parseInt(css.width)
|
||||
let layh = parseInt(css.height)
|
||||
let arrowOffset = ['top']
|
||||
|
||||
Anot(tips).css(style)
|
||||
|
||||
$container.bind('mouseenter', ev => {
|
||||
let tmpStyle = { visibility: 'visible' }
|
||||
ol = $container.offset().left - $doc.scrollLeft()
|
||||
ot = $container.offset().top - $doc.scrollTop()
|
||||
|
||||
if (ot + 18 < layh) {
|
||||
arrowOffset[0] = 'bottom'
|
||||
arrow.style.borderBottomColor = state.background
|
||||
tmpStyle.top = ot + ch + 8
|
||||
} else {
|
||||
arrow.style.borderTopColor = state.background
|
||||
tmpStyle.top = ot - layh - 8
|
||||
}
|
||||
|
||||
if (ol + cw * 0.7 + layw > window.innerWidth) {
|
||||
tmpStyle.left = ol + cw * 0.3 - layw
|
||||
arrowOffset[1] = 'left'
|
||||
} else {
|
||||
tmpStyle.left = ol + cw * 0.7
|
||||
}
|
||||
|
||||
arrow.classList.add('offset-' + arrowOffset.join('-'))
|
||||
Anot(tips).css(tmpStyle)
|
||||
})
|
||||
$container.bind('mouseleave', () => {
|
||||
setTimeout(() => {
|
||||
arrow.classList.remove('offset-' + arrowOffset.join('-'))
|
||||
arrowOffset = ['top']
|
||||
arrow.style.borderBottomColor = ''
|
||||
arrow.style.borderTopColor = ''
|
||||
tips.style.visibility = 'hidden'
|
||||
}, 100)
|
||||
})
|
||||
// _layer.tips(val, this.element)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -75,9 +75,8 @@
|
|||
|
||||
|
||||
/* tips类弹层(type 5) */
|
||||
&.type-5 {visibility:hidden;position:fixed;z-index:65534;min-width:75px;max-width:600px;line-height:1.5;color:#fff;background:rgba(0,0,0,.5);opacity:0;box-shadow:none;-webkit-transition:opacity .3s ease-in-out;-moz-transition:opacity .3s ease-in-out;transition:opacity .3s ease-in-out;
|
||||
&.type-5 {visibility:hidden;position:fixed;z-index:65534;min-width:75px;max-width:600px;padding:10px;line-height:1.5;color:#fff;background:rgba(0,0,0,.5);box-shadow:none;
|
||||
|
||||
// &.active {visibility:visible;opacity:1;}
|
||||
i.arrow {position:absolute;width:0;height:0;border:6px solid transparent;content: ""}
|
||||
i.offset-top {left:5px;bottom:-14px;border-top:8px solid rgba(0,0,0,.5);}
|
||||
i.offset-bottom {left:5px;top:-14px;border-bottom:8px solid rgba(0,0,0,.5);}
|
||||
|
@ -189,12 +188,23 @@
|
|||
&.mask {position:fixed;z-index:65534;left:0;top:0;width:100%;height:100%;background:rgba(0,0,0,.3);
|
||||
|
||||
&.shift {transition: all .5s ease-out;}
|
||||
|
||||
&.inner {position:absolute;}
|
||||
}
|
||||
&:active {z-index:65536;}
|
||||
}
|
||||
|
||||
|
||||
/* 指令式的tips */
|
||||
.do-layer__tips {visibility:hidden;position:fixed;z-index:65534;min-width:75px;max-width:600px;padding:10px;line-height:1.5;border-radius:3px;font-size:14px;color:#fff;background:rgba(0,0,0,.5);
|
||||
|
||||
i.arrow {position:absolute;width:0;height:0;border:6px solid transparent;content: ""}
|
||||
i.offset-top {left:5px;bottom:-14px;border-top:8px solid rgba(0,0,0,.5);}
|
||||
i.offset-bottom {left:5px;top:-14px;border-bottom:8px solid rgba(0,0,0,.5);}
|
||||
i.offset-top-left {right:5px;bottom:-14px;border-top:8px solid rgba(0,0,0,.5);}
|
||||
i.offset-bottom-left {right:5px;top:-14px;border-bottom:8px solid rgba(0,0,0,.5);}
|
||||
|
||||
.layer-content {min-height:20px;margin:0;padding:0}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -11,6 +11,10 @@ import 'layer/index'
|
|||
import './attach.scss'
|
||||
|
||||
const $doc = Anot(document)
|
||||
const LANG = {
|
||||
image: ['远程图片', '图片管理', '图片描述', '图片地址'],
|
||||
file: ['远程附件', '附件管理', '附件描述', '附件地址']
|
||||
}
|
||||
|
||||
class Uploader {
|
||||
constructor(url) {
|
||||
|
@ -64,84 +68,6 @@ class Uploader {
|
|||
}
|
||||
}
|
||||
|
||||
var $init = function(vm) {
|
||||
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()
|
||||
})
|
||||
}
|
||||
|
||||
let cache = {
|
||||
//缓存附件列表
|
||||
image: [],
|
||||
file: []
|
||||
}
|
||||
|
||||
const LANG = {
|
||||
image: ['远程图片', '图片管理', '图片描述', '图片地址'],
|
||||
file: ['远程附件', '附件管理', '附件描述', '附件地址']
|
||||
}
|
||||
|
||||
const fixCont = function(vm, tool) {
|
||||
let limit = false
|
||||
if (vm.props.uploadSizeLimit) {
|
||||
|
@ -177,7 +103,7 @@ const fixCont = function(vm, tool) {
|
|||
<a
|
||||
href="javascript:;"
|
||||
class="do-meditor__button submit"
|
||||
:click="$confirm">确定</a>
|
||||
:click="confirm">确定</a>
|
||||
</section>
|
||||
</div>
|
||||
<div class="local" :visible="tab === 2">
|
||||
|
@ -208,12 +134,20 @@ const fixCont = function(vm, tool) {
|
|||
</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>
|
||||
<div class="manager" :visible="tab === 3">
|
||||
<ul class="list-box">
|
||||
<li
|
||||
class="item"
|
||||
:repeat="attachList"
|
||||
:layer-tips="el.name"
|
||||
:click="insert(el)">
|
||||
|
||||
<span class="thumb" :html="el.thumb"></span>
|
||||
<p class="name" :text="el.name"></p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</dd>
|
||||
</dl>`
|
||||
}
|
||||
|
@ -296,7 +230,10 @@ function uploadScreenshot(vm, blob) {
|
|||
if (vm.props.beforeUpload) {
|
||||
vm.props
|
||||
.beforeUpload(attach, upload)
|
||||
.then(upload => {
|
||||
.then(next => {
|
||||
if (!next) {
|
||||
return Promise.reject('something wrong with beforeUpload')
|
||||
}
|
||||
return upload.then(res => {
|
||||
return res.data
|
||||
})
|
||||
|
@ -315,37 +252,6 @@ function uploadScreenshot(vm, blob) {
|
|||
}
|
||||
}
|
||||
|
||||
function getAttach(vm, cb) {
|
||||
var xhr = new XMLHttpRequest(),
|
||||
url = vm.manageUrl || ME.manageUrl
|
||||
|
||||
if (/\?/.test(url)) {
|
||||
url += '&type=' + openType
|
||||
} else {
|
||||
url += '?type=' + openType
|
||||
}
|
||||
url += '&t=' + Math.random()
|
||||
|
||||
xhr.open('GET', url, true)
|
||||
xhr.onreadystatechange = function() {
|
||||
if (
|
||||
this.readyState === 4 &&
|
||||
this.status === 200 &&
|
||||
this.responseText !== ''
|
||||
) {
|
||||
var res = this.responseText
|
||||
try {
|
||||
res = JSON.parse(res)
|
||||
} catch (err) {}
|
||||
cb(res)
|
||||
} else {
|
||||
if (this.status !== 200 && this.responseText)
|
||||
console.error(this.responseText)
|
||||
}
|
||||
}
|
||||
xhr.send()
|
||||
}
|
||||
|
||||
function showDialog(elem, vm, tool) {
|
||||
let offset = Anot(elem).offset()
|
||||
|
||||
|
@ -353,7 +259,10 @@ function showDialog(elem, vm, tool) {
|
|||
type: 7,
|
||||
menubar: false,
|
||||
fixed: true,
|
||||
offset: [offset.top + 37 - $doc.scrollTop()],
|
||||
offset: [offset.top + 40 - $doc.scrollTop()],
|
||||
shift: {
|
||||
top: offset.top - $doc.scrollTop()
|
||||
},
|
||||
tab: 2,
|
||||
attach: '',
|
||||
attachAlt: '',
|
||||
|
@ -415,17 +324,90 @@ function showDialog(elem, vm, tool) {
|
|||
vm.insert(val)
|
||||
this.close()
|
||||
},
|
||||
content: fixCont(vm, tool)
|
||||
content: fixCont(vm, tool),
|
||||
success() {
|
||||
this.switchTab(3)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const addon = {
|
||||
attach(elem) {
|
||||
showDialog(elem, this, 'file')
|
||||
},
|
||||
image(elem) {
|
||||
showDialog(elem, this, 'image')
|
||||
const plugin = {
|
||||
__init__(ME) {
|
||||
Object.assign(ME.vm.addon, {
|
||||
attach(elem) {
|
||||
showDialog(elem, this, 'file')
|
||||
},
|
||||
image(elem) {
|
||||
showDialog(elem, this, 'image')
|
||||
}
|
||||
})
|
||||
|
||||
ME.vm.$refs.editor.addEventListener('paste', function(ev) {
|
||||
ev.preventDefault()
|
||||
let txt = ev.clipboardData.getData('text/plain')
|
||||
|
||||
//文本类型直接默认处理
|
||||
if (txt) {
|
||||
return
|
||||
}
|
||||
|
||||
if (ev.clipboardData.items) {
|
||||
let items = ev.clipboardData.items
|
||||
let len = items.length
|
||||
let blob = null
|
||||
|
||||
for (let it of items) {
|
||||
if (it.type.indexOf('image') > -1) {
|
||||
blob = it.getAsFile()
|
||||
}
|
||||
}
|
||||
|
||||
if (blob !== null) {
|
||||
layer.toast('截图处理中...')
|
||||
// 压缩截图,避免文件过大
|
||||
let reader = new FileReader()
|
||||
reader.onload = function() {
|
||||
let img = document.createElement('img')
|
||||
let canvas = document.createElement('canvas')
|
||||
|
||||
img.onload = function() {
|
||||
canvas.width = img.width
|
||||
canvas.height = img.height
|
||||
|
||||
let ctx = canvas.getContext('2d')
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height)
|
||||
ctx.drawImage(this, 0, 0, canvas.width, canvas.height)
|
||||
|
||||
// 目前 IE和Safari的toBlob方法还不支持图片质量的设定
|
||||
if (canvas.toBlob && (window.chrome || window.sidebar)) {
|
||||
canvas.toBlob(
|
||||
function(obj) {
|
||||
uploadScreenshot(ME.vm, obj)
|
||||
},
|
||||
'image/jpeg',
|
||||
0.8
|
||||
)
|
||||
} else {
|
||||
let base64 = canvas.toDataURL('image/jpeg', 0.8)
|
||||
let buf = atob(base64.split(',')[1])
|
||||
let intArr = new Uint8Array(buf.length)
|
||||
let obj = null
|
||||
|
||||
for (let i = 0; i < buf.length; i++) {
|
||||
intArr[i] = buf.charCodeAt(i)
|
||||
}
|
||||
obj = new Blob([intArr], { type: 'image/jpeg' })
|
||||
|
||||
uploadScreenshot(ME.vm, obj)
|
||||
}
|
||||
}
|
||||
img.src = this.result
|
||||
}
|
||||
reader.readAsDataURL(blob)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default addon
|
||||
export default plugin
|
||||
|
|
|
@ -8,7 +8,14 @@
|
|||
@import 'var.scss';
|
||||
|
||||
.do-meditor-attach {width:630px;height:300px;cursor:default;color:nth($cgr, 1);
|
||||
dt.close {position:absolute;z-index:65539;top:-8px;right:-8px;width:40px;height:40px;line-height:40px;font-size:20px;text-align:center;cursor:pointer;
|
||||
|
||||
::-webkit-scrollbar {width:5px;height:5px;background:nth($cp, 2);}
|
||||
::-webkit-scrollbar:hover {background:nth($cp, 1);}
|
||||
::-webkit-scrollbar-button {display:none;}
|
||||
::-webkit-scrollbar-thumb {background:nth($cgr, 2);}
|
||||
::-webkit-scrollbar-thumb:hover {background:nth($cgr, 1);}
|
||||
|
||||
dt.close {position:absolute;z-index:65539;top:-15px;right:-10px;width:30px;height:30px;line-height:30px;font-size:20px;text-align:center;cursor:pointer;
|
||||
|
||||
&:hover {color:nth($ct, 1);font-size:28px;}
|
||||
}
|
||||
|
@ -65,15 +72,19 @@
|
|||
.red {color:#f30;}
|
||||
}
|
||||
|
||||
.manager {overflow:hidden;overflow-y:auto;width:100%;height:255px;padding:10px;
|
||||
.manager {overflow:hidden;overflow-y:auto;width:100%;height:300px;
|
||||
|
||||
.item {float:left;width:22%;height:130px;margin:10px 1.5%;padding:5px;
|
||||
&:hover {background:#f7f7f7;}
|
||||
.list-box {width:100%;column-count:4;column-gap: 5;}
|
||||
.item {margin:0 0 10px;padding:5px;text-align:center;background:nth($cp, 2); break-inside: avoid;@include ts(background);
|
||||
|
||||
&:hover {background:nth($cp, 3)}
|
||||
|
||||
.thumb {display:block;width:100%;}
|
||||
.name {overflow:hidden;height:30px;line-height:30px; text-align:center;}
|
||||
img {width:100%;height:auto;}
|
||||
em {line-height:1;font-size:50px;}
|
||||
}
|
||||
.thumb {display:block;width:100%;height:100px;}
|
||||
.name {overflow:hidden;height:20px;line-height:30px; text-align:center;}
|
||||
img {width:100%;height:100%;}
|
||||
em {line-height:100px;font-size:50px;}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Before Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 7.6 KiB |
Before Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 16 KiB |
|
@ -1 +0,0 @@
|
|||
export default 1234
|
|
@ -108,12 +108,13 @@ const ELEMS = {
|
|||
strong: function(str, attr, inner) {
|
||||
return (inner && '**' + inner + '**') || ''
|
||||
},
|
||||
code: function(str, attr, inner) {
|
||||
return (inner && '`' + inner + '`') || ''
|
||||
},
|
||||
|
||||
pre: function(str, attr, inner) {
|
||||
return '\n\n```\n' + inner + '\n```\n'
|
||||
},
|
||||
code: function(str, attr, inner) {
|
||||
return (inner && '`' + inner + '`') || ''
|
||||
},
|
||||
blockquote: function(str, attr, inner) {
|
||||
return '> ' + inner.trim()
|
||||
},
|
||||
|
@ -154,16 +155,13 @@ function html2md(str) {
|
|||
str = decodeURIComponent(str)
|
||||
} catch (err) {}
|
||||
|
||||
str = str.replace(/\t/g, ' ').replace(/<meta [^>]*>/, '')
|
||||
str = str
|
||||
.replace(/\t/g, ' ')
|
||||
.replace(/<meta [^>]*>/, '')
|
||||
.replace(attrExp('class', 'g'), '')
|
||||
.replace(attrExp('style', 'g'), '')
|
||||
str = str
|
||||
.replace(
|
||||
/<(div|span|header|footer|nav|dl|dd|dt|table|tr|td|thead|tbody|i|em|b|strong|h[1-6]|ul|ol|li|p|pre) [^>]*>/g,
|
||||
'<$1>'
|
||||
)
|
||||
.replace(/<svg [^>]*>.*?<\/svg>/g, '{invalid image}')
|
||||
.replace(/<(?!a |img )(\w+) [^>]*>/g, '<$1>')
|
||||
.replace(/<svg[^>]*>.*?<\/svg>/g, '{invalid image}')
|
||||
|
||||
// log(str)
|
||||
for (let i in ELEMS) {
|
||||
|
@ -176,6 +174,9 @@ function html2md(str) {
|
|||
}
|
||||
} else {
|
||||
str = str.replace(exp, cb)
|
||||
if (i === 'pre') {
|
||||
str = str.replace(/<[/]?code>/g, '')
|
||||
}
|
||||
}
|
||||
|
||||
// 对另外3种同类标签做一次处理
|
||||
|
@ -262,9 +263,6 @@ class MEObject {
|
|||
hide() {
|
||||
this.vm.editorVisible = false
|
||||
}
|
||||
extends(addon) {
|
||||
Object.assign(this.vm.addon, addon)
|
||||
}
|
||||
}
|
||||
|
||||
Anot.component('meditor', {
|
||||
|
@ -290,8 +288,7 @@ Anot.component('meditor', {
|
|||
class="editor-body"
|
||||
spellcheck="false"
|
||||
:attr="{disabled: disabled}"
|
||||
:duplex="plainTxt"
|
||||
:on-paste="onPaste($event)"></textarea>
|
||||
:duplex="plainTxt"></textarea>
|
||||
<content
|
||||
ref="preview"
|
||||
class="md-preview do-marked-theme"
|
||||
|
@ -326,6 +323,21 @@ Anot.component('meditor', {
|
|||
}
|
||||
})
|
||||
|
||||
$editor.bind('paste', ev => {
|
||||
ev.preventDefault()
|
||||
let txt = ev.clipboardData.getData('text/plain').trim()
|
||||
let html = ev.clipboardData.getData('text/html').trim()
|
||||
|
||||
html = html2md(html)
|
||||
|
||||
if (html) {
|
||||
this.insert(html)
|
||||
} else if (txt) {
|
||||
this.insert(txt)
|
||||
}
|
||||
this.plainTxt = this.$refs.editor.value
|
||||
})
|
||||
|
||||
$editor.bind('scroll', ev => {
|
||||
let syncTop =
|
||||
ev.target.scrollTop / ev.target.scrollHeight * preview.scrollHeight
|
||||
|
@ -441,20 +453,7 @@ Anot.component('meditor', {
|
|||
console.log('%c没有对应的插件%c[%s]', 'color:#f00;', '', name)
|
||||
}
|
||||
},
|
||||
onPaste: function(ev) {
|
||||
ev.preventDefault()
|
||||
let txt = ev.clipboardData.getData('text/plain').trim()
|
||||
let html = ev.clipboardData.getData('text/html').trim()
|
||||
|
||||
html = html2md(html)
|
||||
|
||||
if (html) {
|
||||
this.insert(html)
|
||||
} else if (txt) {
|
||||
this.insert(txt)
|
||||
}
|
||||
this.plainTxt = this.$refs.editor.value
|
||||
},
|
||||
compile: function() {
|
||||
let txt = this.plainTxt.trim()
|
||||
|
||||
|
|