diff --git a/README.md b/README.md index 01484601..cb553736 100644 --- a/README.md +++ b/README.md @@ -142,12 +142,16 @@ yarn run start ## 更新日志 [最新发布](https://github.com/purocean/yn/releases) -### [v2.3.3](https://github.com/purocean/yn/releases/tag/v2.3.3) 2020-06-11 -1. 修正标题过长导致大纲目录样式异常 +### [v2.3.4](https://github.com/purocean/yn/releases/tag/v2.3.4) 2020-06-28 +1. 优化图片相对链接解析 +2. 优化转换外链图片为本地图片功能
展开查看更多版本记录 +### [v2.3.3](https://github.com/purocean/yn/releases/tag/v2.3.3) 2020-06-11 +1. 修正标题过长导致大纲目录样式异常 + ### [v2.3.2](https://github.com/purocean/yn/releases/tag/v2.3.2) 2020-04-27 1. 调整启动命令行参数 diff --git a/frontend/src/components/Preview.vue b/frontend/src/components/Preview.vue index 7fd56f44..f9cf1a54 100644 --- a/frontend/src/components/Preview.vue +++ b/frontend/src/components/Preview.vue @@ -159,14 +159,24 @@ export default { this.width = this.$refs['view-wrapper'].clientWidth this.height = this.$refs['view-wrapper'].clientHeight }, - keydownHandler (e) { + async keydownHandler (e) { // 转换所有外链图片到本地 if (e.key === 'l' && e.ctrlKey && e.altKey) { - this.$refs.view.querySelectorAll('img').forEach(img => { - this.transformImgOutLink(img) - }) e.preventDefault() e.stopPropagation() + const result = [] + const imgList = [...this.$refs.view.querySelectorAll('img')] + for (let i = 0; i < imgList.length; i++) { + this.$toast.show('info', `正在转换外链图片 ${i + 1}/${imgList.length}`) + + const img = imgList[i] + const data = await this.transformImgOutLink(img) + if (data) { + result.push(data) + } + } + result.forEach(data => this.$bus.emit('editor-replace-value', data.oldLink, data.replacedLink)) + this.$bus.emit('tree-refresh') } }, handleScroll (e) { @@ -209,6 +219,11 @@ export default { } return `[${alt}](api/attachment/${encodeURIComponent(fileName)}?repo=${repo}&path=${encodeURIComponent(filePath)})` + }).replace(/]*)src=["']?(\.\/[^\s'"]*)["']?/ig, (match, _, path) => { + path = decodeURI(path) // 提前解码一次,有的链接已经预先编码 + const fileName = file.basename(path) + const filePath = `${basePath}/${path}` + return ` { const canvas = document.createElement('canvas') canvas.width = ximg.naturalWidth canvas.height = ximg.naturalHeight canvas.getContext('2d').drawImage(ximg, 0, 0) - canvas.toBlob(async blob => { - const imgFile = new File([blob], 'file.png') - const { relativePath } = await file.upload(this.fileRepo, this.filePath, imgFile) - this.$bus.emit('tree-refresh') - this.$bus.emit('editor-replace-value', img.src, relativePath) - }) - } - - if (img.src.startsWith('data:')) { - transform(img) - } else if ( - img.src.startsWith('http://') || - img.src.startsWith('https://') - ) { - window.fetch(`api/proxy?url=${encodeURIComponent(img.src)}`).then(r => { - r.blob().then(async blob => { - const imgFile = new File([blob], 'file.' + mime.extension(r.headers.get('content-type'))) - const { relativePath } = await file.upload(this.fileRepo, this.filePath, imgFile) - this.$bus.emit('tree-refresh') - this.$bus.emit('editor-replace-value', img.src, encodeMarkdownLink(relativePath)) + return new Promise((resolve, reject) => { + canvas.toBlob(async blob => { + try { + const imgFile = new File([blob], 'file.png') + const { relativePath } = await file.upload(this.fileRepo, this.filePath, imgFile) + resolve(relativePath) + } catch (error) { + reject(error) + } }) }) } + + let replacedLink = null + if (img.src.startsWith('data:')) { + replacedLink = await transform(img) + } else if (img.getAttribute('src').startsWith('http://') || img.getAttribute('src').startsWith('https://')) { + const res = await window.fetch(`api/proxy?url=${encodeURIComponent(img.src)}&headers=${img.getAttribute('headers') || ''}`) + const blob = await res.blob() + const imgFile = new File([blob], 'file.' + mime.extension(res.headers.get('content-type'))) + const { relativePath } = await file.upload(this.fileRepo, this.filePath, imgFile) + replacedLink = relativePath + } + + if (replacedLink) { + return { oldLink: img.src, replacedLink: encodeMarkdownLink(replacedLink) } + } + + return null }, - handleClick (e) { + async handleClick (e) { const target = e.target const preventEvent = () => { @@ -364,7 +385,11 @@ export default { if (target.tagName === 'IMG') { const img = target if (e.ctrlKey && e.shiftKey) { // 转换外链图片到本地 - this.transformImgOutLink(img) + const data = await this.transformImgOutLink(img) + if (data) { + this.$bus.emit('tree-refresh') + this.$bus.emit('editor-replace-value', data.oldLink, data.replacedLink) + } } else if (img.parentElement.tagName === 'A') { handleLink(img.parentElement) } else { diff --git a/package.json b/package.json index ee17a5b2..6a1cb906 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "yank.note.yang", - "version": "2.3.3", + "version": "2.3.4", "description": "Yank Note 一款面向程序员的 Markdown 笔记应用", "main": "dist/app.js", "license": "Apache-2.0", diff --git a/src/server/main.ts b/src/server/main.ts index 545f41f8..30df393c 100644 --- a/src/server/main.ts +++ b/src/server/main.ts @@ -154,7 +154,8 @@ const convertFile = async (ctx: any, next: any) => { const proxy = async (ctx: any, next: any) => { if (ctx.path.startsWith('/api/proxy')) { const url = ctx.query.url - ctx.body = request(url) + const headers = ctx.query.headers ? JSON.parse(ctx.query.headers) : undefined + ctx.body = request(url, {headers}) } else { await next() }