From 9af1a135c1afa4927901bd1fa15928ce04a90ceb Mon Sep 17 00:00:00 2001 From: purocean Date: Sun, 28 Jun 2020 21:16:32 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=BD=AC=E6=8D=A2?= =?UTF-8?q?=E5=A4=96=E9=93=BE=E5=9B=BE=E7=89=87=E4=B8=BA=E6=9C=AC=E5=9C=B0?= =?UTF-8?q?=E5=9B=BE=E7=89=87=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Preview.vue | 70 ++++++++++++++++++----------- src/server/main.ts | 3 +- 2 files changed, 47 insertions(+), 26 deletions(-) diff --git a/frontend/src/components/Preview.vue b/frontend/src/components/Preview.vue index 7fd56f44a..5cb0314e2 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) { @@ -256,37 +266,43 @@ export default { this.todoCount = this.$refs.view.querySelectorAll('input[type=checkbox]').length this.todoDoneCount = this.$refs.view.querySelectorAll('input[type=checkbox][checked]').length }, - transformImgOutLink (img) { + async transformImgOutLink (img) { const transform = ximg => { 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) + 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:')) { - 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)) - }) - }) + 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 +380,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/src/server/main.ts b/src/server/main.ts index 545f41f86..30df393c1 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() } From f0cabc6140ee1ad991ee740795ff56455970a3b4 Mon Sep 17 00:00:00 2001 From: purocean Date: Sun, 28 Jun 2020 21:21:13 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=9B=BE=E7=89=87?= =?UTF-8?q?=E7=9B=B8=E5=AF=B9=E9=93=BE=E6=8E=A5=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Preview.vue | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/frontend/src/components/Preview.vue b/frontend/src/components/Preview.vue index 5cb0314e2..f9cf1a547 100644 --- a/frontend/src/components/Preview.vue +++ b/frontend/src/components/Preview.vue @@ -219,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 ` Date: Sun, 28 Jun 2020 21:24:10 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E5=8D=87=E7=BA=A7=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 ++++++-- package.json | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 01484601c..cb5537363 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/package.json b/package.json index ee17a5b22..6a1cb906e 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",