This repository has been archived on 2023-08-30. You can view files and clone it, but cannot push or open issues/pull-requests.
bytedo
/
wcui
Archived
1
0
Fork 0

修复框架在循环中动态增加VM导致作用域混乱的bug;优化layer组件的tips和loading;完成meditor的移植

old
宇天 2018-05-20 05:32:51 +08:00
parent 99b95e67e1
commit 869dc40ab3
47 changed files with 319 additions and 239 deletions

View File

@ -22,8 +22,9 @@ const jsOpt = {
plugins: [ plugins: [
'transform-es2015-modules-amd', 'transform-es2015-modules-amd',
'transform-decorators-legacy', '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 = { 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 jsFiles = fs.ls('./src/js/', true)
const cssFiles = fs.ls('./src/css/', true) const cssFiles = fs.ls('./src/css/', true)

View File

@ -65,7 +65,6 @@ const compileHtm = (entry, output) => {
/*===== ===*/ /*===== ===*/
/*=======================================================*/ /*=======================================================*/
const fontFiles = fs.ls('./src/font/', true)
const jsFiles = fs.ls('./src/js/', true) const jsFiles = fs.ls('./src/js/', true)
const cssFiles = fs.ls('./src/css/', true) const cssFiles = fs.ls('./src/css/', true)
@ -74,11 +73,6 @@ if (fs.isdir(buildDir)) {
log(chalk.cyan('清除旧目录 dist/')) log(chalk.cyan('清除旧目录 dist/'))
} }
// 字体文件直接复制
fontFiles.forEach(file => {
fs.cp('./src/font/' + file, './dist/font/' + file)
})
// css目录 // css目录
cssFiles.forEach(file => { cssFiles.forEach(file => {
if (/\.scss$/.test(file)) { if (/\.scss$/.test(file)) {

View File

@ -22,8 +22,9 @@ const jsOpt = {
plugins: [ plugins: [
'transform-es2015-modules-amd', 'transform-es2015-modules-amd',
'transform-decorators-legacy', '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 = { const cssOpt = {
@ -37,10 +38,12 @@ const compileJs = (entry, output) => {
} }
let t1 = Date.now() let t1 = Date.now()
let tmpOpt = jsOpt let tmpOpt = jsOpt
if (/anot/.test(entry)) { let code = ''
tmpOpt = Object.assign({}, jsOpt, { plugins: [] }) 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') code = uglify.minify(code).code.replace(/\.scss/g, '.css')
log( log(
'编译JS: %s, 耗时 %s ms', '编译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 jsFiles = fs.ls('./src/js/', true)
const cssFiles = fs.ls('./src/css/', true) const cssFiles = fs.ls('./src/css/', true)
@ -88,11 +90,6 @@ if (fs.isdir(buildDir)) {
log(chalk.cyan('清除旧目录 dist/')) log(chalk.cyan('清除旧目录 dist/'))
} }
// 字体文件直接复制
fontFiles.forEach(file => {
fs.cp('./src/font/' + file, './dist/font/' + file)
})
// css目录 // css目录
cssFiles.forEach(file => { cssFiles.forEach(file => {
if (/\.scss$/.test(file)) { if (/\.scss$/.test(file)) {

View File

@ -12,21 +12,25 @@
"type": "git", "type": "git",
"url": "git+https://github.com/yutent/doui.git" "url": "git+https://github.com/yutent/doui.git"
}, },
"keywords": ["doui", "Anot"], "keywords": [
"doui",
"Anot"
],
"author": "yutent", "author": "yutent",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"autoprefixer": "^7.2.6", "autoprefixer": "^7.2.6",
"babel-core": "^6.26.0", "babel-core": "^6.26.3",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-decorators-legacy": "^1.3.4", "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-plugin-transform-object-rest-spread": "^6.26.0",
"babel-preset-es2015": "^6.24.1", "babel-preset-es2015": "^6.24.1",
"chalk": "^2.3.2", "chalk": "^2.4.1",
"chokidar": "^1.7.0", "chokidar": "^1.7.0",
"iofs": "^1.0.3", "iofs": "^1.0.3",
"node-sass": "^4.8.2", "node-sass": "^4.9.0",
"postcss": "^6.0.19", "postcss": "^6.0.22",
"uglify-es": "^3.3.9" "uglify-es": "^3.3.9"
}, },
"dependencies": {} "dependencies": {}

View File

@ -234,6 +234,7 @@
vm.$id = $id vm.$id = $id
VMODELS[$id] = vm VMODELS[$id] = vm
Anot.nextTick(function() {
var $elem = document.querySelector('[anot=' + vm.$id + ']') var $elem = document.querySelector('[anot=' + vm.$id + ']')
if ($elem) { if ($elem) {
if ($elem === DOC.body) { if ($elem === DOC.body) {
@ -245,9 +246,14 @@
break break
} }
} }
scanTag($elem.parentNode, $parent ? [VMODELS[$parent.anotctrl]] : []) scanTag(
$elem.parentNode,
$parent ? [VMODELS[$parent.anotctrl]] : []
)
} }
} }
})
return vm return vm
} else { } else {
this[0] = this.element = source this[0] = this.element = source
@ -2172,6 +2178,7 @@
injectDependency(array, binding) injectDependency(array, binding)
} }
}) })
binding.getter = parseExpr(binding.expr, binding.vmodels, binding) binding.getter = parseExpr(binding.expr, binding.vmodels, binding)
binding.observers.forEach(function(a) { binding.observers.forEach(function(a) {
a.v.$watch(a.p, binding) a.v.$watch(a.p, binding)
@ -3038,8 +3045,8 @@
} }
function addAssign(vars, vmodel, name, binding) { function addAssign(vars, vmodel, name, binding) {
var ret = [], var ret = []
prefix = ' = ' + name + '.' var prefix = ' = ' + name + '.'
for (var i = vars.length, prop; (prop = vars[--i]); ) { for (var i = vars.length, prop; (prop = vars[--i]); ) {
var arr = prop.split('.') var arr = prop.split('.')
var first = arr[0] var first = arr[0]
@ -3137,7 +3144,7 @@
/* jshint ignore:start */ /* jshint ignore:start */
var fn2 = scpCompile( var fn2 = scpCompile(
names.concat( names.concat(
"'use strict';" + 'return function(vvv){' + expr + ' = vvv\n}\n' '"use strict";\n return function(vvv){' + expr + ' = vvv\n}\n'
) )
) )
/* jshint ignore:end */ /* jshint ignore:end */
@ -3178,6 +3185,18 @@
}) })
expr = '\nreturn ' + expr + ';' //IE全家 Function("return ")出错需要Function("return ;") 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 */ /* jshint ignore:start */
getter = scpCompile( getter = scpCompile(
names.concat( names.concat(
@ -3290,7 +3309,7 @@
Anot.injectBinding(binding) Anot.injectBinding(binding)
if (binding.getter && binding.element.nodeType === 1) { if (binding.getter && binding.element.nodeType === 1) {
//移除数据绑定,防止被二次解析 //移除数据绑定,防止被二次解析
//chrome使用removeAttributeNode移除不存在的特性节点时会报错 https://github.com/RubyLouvre/Anot/issues/99 //chrome使用removeAttributeNode移除不存在的特性节点时会报错
binding.element.removeAttribute(binding.name) binding.element.removeAttribute(binding.name)
} }
} }
@ -3505,8 +3524,8 @@
} }
function scanTag(elem, vmodels, node) { function scanTag(elem, vmodels, node) {
//扫描顺序 skip(0) --> anot(1) --> :if(10) --> :repeat(100) //扫描顺序 skip(0) --> anot(1) --> :if(10) --> :repeat(90)
//--> :if-loop(110) --> :attr(970) ...--> :each(1400)-->:with(1500)--〉:duplex(2000)垫后 //--> :if-loop(110) --> :attr(970) ...--> :duplex(2000)垫后
var skip = elem.getAttribute('skip') var skip = elem.getAttribute('skip')
node = elem.getAttributeNode('anot') node = elem.getAttributeNode('anot')
var vm = vmodels.concat() var vm = vmodels.concat()
@ -3557,15 +3576,16 @@
newVmodel.props[k] = props[k] newVmodel.props[k] = props[k]
delete props[k] delete props[k]
} else { } else {
Anot.error( console.error(
new TypeError(
'props.' + 'props.' +
k + k +
' needs [' + ' needs [' +
newVmodel.props[k].checkType + newVmodel.props[k].checkType +
'], but [' + '], but [' +
newVmodel.props[k].result + newVmodel.props[k].result +
'] given.', '] given.'
TypeError )
) )
} }
} }
@ -5463,11 +5483,6 @@
var kill = elem.previousSibling var kill = elem.previousSibling
var start = binding.start var start = binding.start
/*log(kill === start, kill)
while(kill !== start && kill.nodeName !== '#comment'){
parent.removeChild(kill)
kill = elem.previousSibling
}*/
if (clear) { if (clear) {
while (kill !== start) { while (kill !== start) {
parent.removeChild(kill) parent.removeChild(kill)
@ -5509,9 +5524,6 @@
) )
decorateProxy(proxy, binding, xtype) decorateProxy(proxy, binding, xtype)
} else { } else {
// if (xtype === "array") {
// proxy[param] = value[i]
// }
fragments.push({}) fragments.push({})
retain[keyOrId] = true retain[keyOrId] = true
} }
@ -5528,7 +5540,6 @@
if (xtype === 'array') { if (xtype === 'array') {
proxy.$first = i === 0 proxy.$first = i === 0
proxy.$last = i === length - 1 proxy.$last = i === length - 1
// proxy[param] = value[i]
} else { } else {
proxy.$val = toJson(value[keyOrId]) //这里是处理vm.object = newObject的情况 proxy.$val = toJson(value[keyOrId]) //这里是处理vm.object = newObject的情况
} }

View File

@ -33,6 +33,7 @@ let defconf = {
offset: [], // 弹窗出来后的坐标, 为数组,可有4个值,依次是 上右下左 offset: [], // 弹窗出来后的坐标, 为数组,可有4个值,依次是 上右下左
btns: ['确定', '取消'] // 弹窗的2个按钮的文字 btns: ['确定', '取消'] // 弹窗的2个按钮的文字
} }
const $doc = Anot(document)
const uuid = function() { const uuid = function() {
return 'layer-' + lid++ return 'layer-' + lid++
} }
@ -214,6 +215,9 @@ class __layer__ {
outerBox.classList.add('do-layer') outerBox.classList.add('do-layer')
if (state.mask) { if (state.mask) {
outerBox.classList.add('mask') outerBox.classList.add('mask')
if (state.container && state.container !== document.body) {
outerBox.classList.add('inner')
}
} }
if (state.maskColor) { if (state.maskColor) {
outerBox.style.background = state.maskColor outerBox.style.background = state.maskColor
@ -383,7 +387,6 @@ class __layer__ {
style.color = state.color style.color = state.color
style.opacity = 1 style.opacity = 1
let $container = Anot(container) let $container = Anot(container)
let $doc = Anot(document)
let $arrow = $container[0].querySelector('.arrow') let $arrow = $container[0].querySelector('.arrow')
let cw = $container.innerWidth() let cw = $container.innerWidth()
let ch = $container.innerHeight() let ch = $container.innerHeight()
@ -564,23 +567,26 @@ const _layer = {
return _layer.open(opt) return _layer.open(opt)
}, },
loading: function(style, time, cb) { loading: function(style, container, cb) {
style = style >>> 0 style = style >>> 0
style = style < 1 ? 1 : style > 5 ? 5 : style
if (typeof time === 'function') { if (typeof container === 'function') {
cb = time cb = container
time = 0 container = null
} else { } else {
time = time >>> 0 if (!(container instanceof HTMLElement)) {
container = null
}
if (typeof cb !== 'function') { if (typeof cb !== 'function') {
cb = Anot.noop cb = Anot.noop
} }
} }
return _layer.open({ return _layer.open({
container,
type: 6, type: 6,
load: style, load: style,
yes: cb, yes: cb,
timeout: time,
menubar: false, menubar: false,
background: 'none', background: 'none',
shift: 'ct', shift: 'ct',
@ -660,7 +666,7 @@ const _layer = {
} }
Anot.directive('layer', { Anot.directive('layer', {
priority: 1400, priority: 8090,
init: function(binding) { init: function(binding) {
// 去掉:layer属性,避免二次扫描 // 去掉:layer属性,避免二次扫描
binding.element.removeAttribute(binding.name) binding.element.removeAttribute(binding.name)
@ -671,13 +677,15 @@ Anot.directive('layer', {
}, },
update: function(val) { update: function(val) {
if (!val) { if (!val) {
console.error(this)
return console.error( return console.error(
`SyntaxError: Unexpected [${this.name}=${this.expr}]` `SyntaxError: Unexpected [${this.name}=${this.expr}]`
) )
} }
if (!this.param) {
let state = Object.assign({ type: 7, wrap: true }, this.element.dataset) let state = Object.assign({ type: 7, wrap: true }, this.element.dataset)
if (!this.param) {
let init = { $id: 'layerwrap-' + val, state, props: {} } let init = { $id: 'layerwrap-' + val, state, props: {} }
if (state.hasOwnProperty('area')) { if (state.hasOwnProperty('area')) {
@ -709,7 +717,72 @@ Anot.directive('layer', {
} }
layerDom[tmp.init.$id] = tmp.create() layerDom[tmp.init.$id] = tmp.create()
} else if (this.param === 'tips') { } 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)
} }
} }
}) })

View File

@ -75,9 +75,8 @@
/* tips类弹层(type 5) */ /* 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.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-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-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); &.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;} &.shift {transition: all .5s ease-out;}
&.inner {position:absolute;}
} }
&:active {z-index:65536;} &: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}
}

View File

@ -11,6 +11,10 @@ import 'layer/index'
import './attach.scss' import './attach.scss'
const $doc = Anot(document) const $doc = Anot(document)
const LANG = {
image: ['远程图片', '图片管理', '图片描述', '图片地址'],
file: ['远程附件', '附件管理', '附件描述', '附件地址']
}
class Uploader { class Uploader {
constructor(url) { 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) { const fixCont = function(vm, tool) {
let limit = false let limit = false
if (vm.props.uploadSizeLimit) { if (vm.props.uploadSizeLimit) {
@ -177,7 +103,7 @@ const fixCont = function(vm, tool) {
<a <a
href="javascript:;" href="javascript:;"
class="do-meditor__button submit" class="do-meditor__button submit"
:click="$confirm">确定</a> :click="confirm">确定</a>
</section> </section>
</div> </div>
<div class="local" :visible="tab === 2"> <div class="local" :visible="tab === 2">
@ -208,12 +134,20 @@ const fixCont = function(vm, tool) {
</li> </li>
</ul> </ul>
</div> </div>
<ul class="manager" :visible="tab === 3"> <div class="manager" :visible="tab === 3">
<li class="item" :repeat="attachList" :click="insert(el)"> <ul class="list-box">
<li
class="item"
:repeat="attachList"
:layer-tips="el.name"
:click="insert(el)">
<span class="thumb" :html="el.thumb"></span> <span class="thumb" :html="el.thumb"></span>
<p class="name" :attr-title="el.name" :text="el.name"></p> <p class="name" :text="el.name"></p>
</li> </li>
</ul> </ul>
</div>
</dd> </dd>
</dl>` </dl>`
} }
@ -296,7 +230,10 @@ function uploadScreenshot(vm, blob) {
if (vm.props.beforeUpload) { if (vm.props.beforeUpload) {
vm.props vm.props
.beforeUpload(attach, upload) .beforeUpload(attach, upload)
.then(upload => { .then(next => {
if (!next) {
return Promise.reject('something wrong with beforeUpload')
}
return upload.then(res => { return upload.then(res => {
return res.data 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) { function showDialog(elem, vm, tool) {
let offset = Anot(elem).offset() let offset = Anot(elem).offset()
@ -353,7 +259,10 @@ function showDialog(elem, vm, tool) {
type: 7, type: 7,
menubar: false, menubar: false,
fixed: true, fixed: true,
offset: [offset.top + 37 - $doc.scrollTop()], offset: [offset.top + 40 - $doc.scrollTop()],
shift: {
top: offset.top - $doc.scrollTop()
},
tab: 2, tab: 2,
attach: '', attach: '',
attachAlt: '', attachAlt: '',
@ -415,17 +324,90 @@ function showDialog(elem, vm, tool) {
vm.insert(val) vm.insert(val)
this.close() this.close()
}, },
content: fixCont(vm, tool) content: fixCont(vm, tool),
success() {
this.switchTab(3)
}
}) })
} }
const addon = { const plugin = {
__init__(ME) {
Object.assign(ME.vm.addon, {
attach(elem) { attach(elem) {
showDialog(elem, this, 'file') showDialog(elem, this, 'file')
}, },
image(elem) { image(elem) {
showDialog(elem, this, 'image') showDialog(elem, this, 'image')
} }
})
ME.vm.$refs.editor.addEventListener('paste', function(ev) {
ev.preventDefault()
let txt = ev.clipboardData.getData('text/plain')
//文本类型直接默认处理
if (txt) {
return
} }
export default addon 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 plugin

View File

@ -8,7 +8,14 @@
@import 'var.scss'; @import 'var.scss';
.do-meditor-attach {width:630px;height:300px;cursor:default;color:nth($cgr, 1); .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;} &:hover {color:nth($ct, 1);font-size:28px;}
} }
@ -65,15 +72,19 @@
.red {color:#f30;} .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; .list-box {width:100%;column-count:4;column-gap: 5;}
&:hover {background:#f7f7f7;} .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;}
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@ -1 +0,0 @@
export default 1234

View File

@ -108,12 +108,13 @@ const ELEMS = {
strong: function(str, attr, inner) { strong: function(str, attr, inner) {
return (inner && '**' + inner + '**') || '' return (inner && '**' + inner + '**') || ''
}, },
code: function(str, attr, inner) {
return (inner && '`' + inner + '`') || ''
},
pre: function(str, attr, inner) { pre: function(str, attr, inner) {
return '\n\n```\n' + inner + '\n```\n' return '\n\n```\n' + inner + '\n```\n'
}, },
code: function(str, attr, inner) {
return (inner && '`' + inner + '`') || ''
},
blockquote: function(str, attr, inner) { blockquote: function(str, attr, inner) {
return '> ' + inner.trim() return '> ' + inner.trim()
}, },
@ -154,15 +155,12 @@ function html2md(str) {
str = decodeURIComponent(str) str = decodeURIComponent(str)
} catch (err) {} } catch (err) {}
str = str.replace(/\t/g, ' ').replace(/<meta [^>]*>/, '')
str = str str = str
.replace(/\t/g, ' ')
.replace(/<meta [^>]*>/, '')
.replace(attrExp('class', 'g'), '') .replace(attrExp('class', 'g'), '')
.replace(attrExp('style', 'g'), '') .replace(attrExp('style', 'g'), '')
str = str .replace(/<(?!a |img )(\w+) [^>]*>/g, '<$1>')
.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(/<svg[^>]*>.*?<\/svg>/g, '{invalid image}')
// log(str) // log(str)
@ -176,6 +174,9 @@ function html2md(str) {
} }
} else { } else {
str = str.replace(exp, cb) str = str.replace(exp, cb)
if (i === 'pre') {
str = str.replace(/<[/]?code>/g, '')
}
} }
// 对另外3种同类标签做一次处理 // 对另外3种同类标签做一次处理
@ -262,9 +263,6 @@ class MEObject {
hide() { hide() {
this.vm.editorVisible = false this.vm.editorVisible = false
} }
extends(addon) {
Object.assign(this.vm.addon, addon)
}
} }
Anot.component('meditor', { Anot.component('meditor', {
@ -290,8 +288,7 @@ Anot.component('meditor', {
class="editor-body" class="editor-body"
spellcheck="false" spellcheck="false"
:attr="{disabled: disabled}" :attr="{disabled: disabled}"
:duplex="plainTxt" :duplex="plainTxt"></textarea>
:on-paste="onPaste($event)"></textarea>
<content <content
ref="preview" ref="preview"
class="md-preview do-marked-theme" 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 => { $editor.bind('scroll', ev => {
let syncTop = let syncTop =
ev.target.scrollTop / ev.target.scrollHeight * preview.scrollHeight ev.target.scrollTop / ev.target.scrollHeight * preview.scrollHeight
@ -441,20 +453,7 @@ Anot.component('meditor', {
console.log('%c没有对应的插件%c[%s]', 'color:#f00;', '', name) 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() { compile: function() {
let txt = this.plainTxt.trim() let txt = this.plainTxt.trim()