Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Batch convert local images #144

Merged
merged 2 commits into from
Mar 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Markdown 文档自动即时渲染为微信图文,让你不再为微信文章
- [x] 支持多图上传,可自定义配置图床
- [x] 支持自定义上传逻辑
- [x] 支持在编辑框右键弹出功能选项卡
- [x] 支持批量转换本地图片为线上图片

## 目前支持哪些图床

Expand Down
103 changes: 101 additions & 2 deletions src/pages/index/view/CodemirrorEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
<el-col
:span="12"
class="codeMirror-wrapper"
ref="codeMirrorWrapper"
@contextmenu.prevent.native="openMenu($event)"
>
<textarea
Expand Down Expand Up @@ -158,9 +159,107 @@ export default {
this.initEditor()
this.initCssEditor()
this.onEditorRefresh()
this.mdLocalToRemote()
})
},
methods: {
// 转换 markdown 中的本地图片为线上图片
// todo 处理事件覆盖
mdLocalToRemote() {
const vm = this
const dom = this.$refs.codeMirrorWrapper.$el

dom.ondragover = (evt) => evt.preventDefault()
dom.ondrop = async (evt) => {
evt.preventDefault()
for (const item of evt.dataTransfer.items) {
item.getAsFileSystemHandle().then(async (handle) => {
if (handle.kind === `directory`) {
const list = await showFileStructure(handle)
const md = await getMd({ list })
uploadMdImg({ md, list })
} else {
const file = await handle.getFile()
console.log(`file`, file)
}
})
}
}

// 从文件列表中查找一个 md 文件并解析
async function getMd({ list }) {
return new Promise((resolve, reject) => {
const { path, file } = list.find((item) => item.path.match(/\.md$/))
const reader = new FileReader()
reader.readAsText(file, `UTF-8`)
reader.onload = (evt) => {
resolve({
str: evt.target.result,
file,
path,
})
}
})
}

// 上传 md 中的图片
async function uploadMdImg({ md, list }) {
const mdImgList = [
...(md.str.matchAll(/!\[(.*?)\]\((.*?)\)/gm) || []),
].filter((item) => {
return item // 获取所有相对地址的图片
})
const root = md.path.match(/.+?\//)[0]
const resList = await Promise.all(
mdImgList.map((item) => {
return new Promise((resolve, reject) => {
let [, , matchStr] = item
matchStr = matchStr.replace(/^.\//, ``) // 处理 ./img/ 为 img/ 统一相对路径风格
const { file } =
list.find((f) => f.path === `${root}${matchStr}`) || {}
vm.uploadImage(file, (url) => {
resolve({ matchStr, url })
})
})
})
)
resList.forEach((item) => {
md.str = md.str
.replace(`](./${item.matchStr})`, `](${item.url})`)
.replace(`](${item.matchStr})`, `](${item.url})`)
})
vm.editor.setValue(md.str)
console.log(`resList`, resList, md.str)
}

// 转换文件系统句柄中的文件为文件列表
async function showFileStructure(root) {
const result = []
let cwd = ``
try {
const dirs = [root]
for (const dir of dirs) {
cwd += dir.name + `/`
for await (const [, handle] of dir) {
if (handle.kind === `file`) {
result.push({
path: cwd + handle.name,
file: await handle.getFile(),
})
} else {
result.push({
path: cwd + handle.name + `/`,
})
dirs.push(handle)
}
}
}
} catch (err) {
console.error(err)
}
return result
}
},
initEditor() {
this.initEditorEntity()
this.editor.on(`change`, (cm, e) => {
Expand Down Expand Up @@ -260,15 +359,15 @@ export default {
}
return true
},
uploadImage(file) {
uploadImage(file, cb) {
this.isImgLoading = true
toBase64(file)
.then((base64Content) => {
fileApi
.fileUpload(base64Content, file)
.then((url) => {
console.log(url)
this.uploaded(url)
cb ? cb(url) : this.uploaded(url)
})
.catch((err) => {
this.$message.error(err.message)
Expand Down