Skip to content

Commit

Permalink
feat: 区分浏览器环境与Electron环境导出
Browse files Browse the repository at this point in the history
- 浏览器环境直接将图片内联
- Electron环境将图片导出到本地文件
  • Loading branch information
ZiuChen committed Jun 24, 2023
1 parent 80bda70 commit b858d62
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 35 deletions.
4 changes: 3 additions & 1 deletion public/preload.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const { resolve, basename, extname } = require('path')
const { readFileSync, statSync } = require('fs')
const { readFileSync, statSync, writeFileSync, mkdirSync } = require('fs')
const { createHash } = require('crypto')
const { Buffer } = require('buffer')

Expand All @@ -9,6 +9,8 @@ window.preload = {
extname,
readFileSync,
statSync,
writeFileSync,
mkdirSync,
createHash,
Buffer
}
5 changes: 2 additions & 3 deletions src/common/plugins/customImagePlugin.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import type { BytemdPlugin } from 'bytemd'
import { loadImage } from '@/utils'
import { visit } from 'unist-util-visit'
import { markdownImages, imageCache } from './instance'
import { loadImage } from '@/utils'

/**
* 自定义解析图片链接插件
*/
export function customImagePlugin(): BytemdPlugin {
const markdownImages: any[] = []
const imageCache: Record<string, string> = {}
return {
remark: (processor) => {
// @ts-ignore
Expand Down
71 changes: 41 additions & 30 deletions src/common/plugins/exportPlugin.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import type { BytemdPlugin } from 'bytemd'
import { useArticleStore } from '@/store'
import { markdownImages, imageCache } from './instance'
import { Buffer, resolve, mkdirSync, writeFileSync } from '@/preload'
import { isElectron } from '@/utils'

export function exportPlugin(): BytemdPlugin {
const store = useArticleStore()
Expand All @@ -12,30 +15,6 @@ export function exportPlugin(): BytemdPlugin {
handler: {
type: 'dropdown',
actions: [
// {
// title: '导出为 HTML',
// icon: '',
// handler: {
// type: 'action',
// click: (ctx) => {}
// }
// },
// {
// title: '导出为 PDF',
// icon: '',
// handler: {
// type: 'action',
// click: (ctx) => {}
// }
// },
// {
// title: '导出为图片',
// icon: '',
// handler: {
// type: 'action',
// click: (ctx) => {}
// }
// },
{
title: '导出为 Markdown',
icon: '',
Expand All @@ -44,12 +23,44 @@ export function exportPlugin(): BytemdPlugin {
click: ({ editor }) => {
const title = store.title
const data = editor.getValue()
const blob = new Blob([data], { type: 'text/plain;charset=utf-8' })
const url = URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = `${title}.md`
link.click()

// 浏览器环境的图片为链接/base64 直接内联即可
// Electron则为attachment开头的哈希索引 需要从缓存中保存到本地
if (!isElectron) {
const blob = new Blob([data], { type: 'text/plain;charset=utf-8' })
const url = URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = `${title}.md`
link.click()
return
}

// 为文章创建新的文件夹
const folder = resolve(utools.getPath('downloads'), title)
mkdirSync(folder)

// 将内联的图片保存到本地
for (const { url } of markdownImages) {
const hash = url.split(':').pop()
const base64 = imageCache[hash] || ''
if (base64) {
const matches = base64.match(/^data:([A-Za-z-+/]+);base64,(.+)$/)
const fileType = (matches && matches[1]) || '' // 文件类型,例如 "image/png"
const fileData = (matches && matches[2]) || '' // 文件数据部分
const buffer = Buffer.from(fileData, 'base64')
writeFileSync(resolve(folder, `${hash}.${fileType.split('/').pop()}`), buffer)
}
}

// 替换MD文档中的图片路径为相对路径
const dataWithRelativePath = data.replace(
/\!\[(.*?)\]\(attachment:(.*?)\)/g,
'![$1]($2.png)'
)

// 保存到本地
writeFileSync(resolve(folder, `${title}.md`), dataWithRelativePath)
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions src/common/plugins/instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,9 @@ export const plugins = [
exportPlugin(),
pasteImagePlugin()
]

// 保存图片DOM节点 包含当前文档图片的hash索引合集
export const markdownImages = [] as any[]

// 缓存图片数据 hash => base64
export const imageCache = {} as Record<string, string>
14 changes: 13 additions & 1 deletion src/preload/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import type { resolve as _resolve, basename as _basename, extname as _extname } from 'path'
import type { readFileSync as _readFileSync, statSync as _statSync } from 'fs'
import type {
readFileSync as _readFileSync,
statSync as _statSync,
mkdirSync as _mkdirSync,
writeFileSync as _writeFileSync
} from 'fs'
import type { createHash as _createHash } from 'crypto'
import type { Buffer as _Buffer } from 'buffer'

Expand All @@ -11,6 +16,8 @@ declare global {
extname: typeof _extname
readFileSync: typeof _readFileSync
statSync: typeof _statSync
mkdirSync: typeof _mkdirSync
writeFileSync: typeof _writeFileSync
createHash: typeof _createHash
Buffer: typeof _Buffer
}
Expand All @@ -35,6 +42,11 @@ export const readFileSync =

export const statSync = window.preload?.statSync || (emptyFuncFactory() as typeof _statSync)

export const mkdirSync = window.preload?.mkdirSync || (emptyFuncFactory() as typeof _mkdirSync)

export const writeFileSync =
window.preload?.writeFileSync || (emptyFuncFactory() as typeof _writeFileSync)

export const createHash = window.preload?.createHash || (emptyFuncFactory() as typeof _createHash)

export const Buffer = window.preload?.Buffer || (emptyFuncFactory() as typeof _Buffer)

0 comments on commit b858d62

Please sign in to comment.