Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/orange-guests-kneel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@dolphin/chrome-extension': patch
---

feat: support encode image as Base64 (< 100 KiB)
3 changes: 3 additions & 0 deletions apps/chrome-extension/src/common/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export enum SettingKey {
Grid = 'general.grid',
TextHighlight = 'general.text_highlight',
DownloadFileWithUniqueName = 'download.file_with_unique_name',
EncodeImageAsBase64 = 'download.encode_image_as_base64',
}

export enum Theme {
Expand Down Expand Up @@ -44,6 +45,7 @@ export interface Settings {
[SettingKey.Grid]: (typeof Grid)[keyof typeof Grid]
[SettingKey.TextHighlight]: boolean
[SettingKey.DownloadFileWithUniqueName]: boolean
[SettingKey.EncodeImageAsBase64]: boolean
}

export const fallbackSettings: Settings = {
Expand All @@ -56,6 +58,7 @@ export const fallbackSettings: Settings = {
[SettingKey.Grid]: Grid.Flatten,
[SettingKey.TextHighlight]: true,
[SettingKey.DownloadFileWithUniqueName]: false,
[SettingKey.EncodeImageAsBase64]: false,
}

export const getSettings = async <Key extends keyof Settings>(
Expand Down
24 changes: 24 additions & 0 deletions apps/chrome-extension/src/pages/options/download.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const { t } = useI18n()
const schema = z.object({
[SettingKey.DownloadMethod]: z.enum(DownloadMethod),
[SettingKey.DownloadFileWithUniqueName]: z.boolean(),
[SettingKey.EncodeImageAsBase64]: z.boolean(),
})

const { query, mutation } = useSettings()
Expand All @@ -49,6 +50,7 @@ watch(query.data, newValues => {
values: pick(newValues, [
SettingKey.DownloadMethod,
SettingKey.DownloadFileWithUniqueName,
SettingKey.EncodeImageAsBase64,
]),
})
}
Expand Down Expand Up @@ -143,6 +145,28 @@ const downloadMethodDescription = computed(() => {
/>
</Field>
</VeeField>
<VeeField
v-slot="{ field, errors }"
:name="`[${SettingKey.EncodeImageAsBase64}]`"
>
<Field orientation="horizontal" :data-invalid="!!errors.length">
<FieldContent>
<FieldLabel for="form-vee-download-encode-image-as-base64">{{
t('download.encode_image_as_base64')
}}</FieldLabel>
<FieldError v-if="errors.length" :errors="errors" />
</FieldContent>
<Skeleton v-if="query.isPending.value" class="h-9 w-40" />
<Switch
v-else
id="form-vee-download-encode-image-as-base64"
:name="field.name"
:model-value="field.value"
:aria-invalid="!!errors.length"
@update:model-value="field.onChange"
/>
</Field>
</VeeField>
<Button
type="submit"
class="relative"
Expand Down
2 changes: 2 additions & 0 deletions apps/chrome-extension/src/pages/shared/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export const i18n = createI18n({
'Preserve text highlighting (font color, font background color)',
'download.file_with_unique_name':
'Use UUID for image and diagram filenames',
'download.encode_image_as_base64': 'Encode image as Base64 (< 100 KiB)',
'download.method': 'Download Method',
'download.method.placeholder': 'Select download method',
'download.method.direct': 'Direct Download',
Expand Down Expand Up @@ -79,6 +80,7 @@ export const i18n = createI18n({
'general.grid.to_html': '转换成 HTML',
'general.text_highlight': '保留文本高亮(字体颜色、字体背景颜色)',
'download.file_with_unique_name': '图片和图表文件使用 UUID 命名',
'download.encode_image_as_base64': '将图片编码为 Base64(< 100 KiB)',
'download.method': '下载方式',
'download.method.placeholder': '选择下载方式',
'download.method.direct': '直接下载',
Expand Down
4 changes: 3 additions & 1 deletion apps/chrome-extension/src/pages/shared/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ export const useSettings = <
| SettingKey.Table
| SettingKey.Grid
| SettingKey.TextHighlight
| SettingKey.DownloadFileWithUniqueName,
| SettingKey.DownloadFileWithUniqueName
| SettingKey.EncodeImageAsBase64,
>(
options: { keys?: Key[] } = {},
): {
Expand All @@ -46,6 +47,7 @@ export const useSettings = <
SettingKey.Grid,
SettingKey.TextHighlight,
SettingKey.DownloadFileWithUniqueName,
SettingKey.EncodeImageAsBase64,
] as Key[],
} = options

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import i18next from 'i18next'
import { Toast, Docx, docx, type mdast } from '@dolphin/lark'
import { Minute, OneHundred, Second, waitFor } from '@dolphin/common'
import {
Minute,
OneHundred,
Second,
waitFor,
blobToBase64,
} from '@dolphin/common'
import { fileSave, supported } from 'browser-fs-access'
import { fs } from '@zip.js/zip.js'
import normalizeFileName from 'filenamify/browser'
Expand Down Expand Up @@ -154,11 +160,17 @@ const downloadImage = async (
signal?: AbortSignal
useUUID?: boolean
markdownFileName?: string
encodeImageAsBase64?: boolean
} = {},
): Promise<DownloadResult | null> => {
if (!image.data) return null

const { signal, useUUID = false, markdownFileName = '' } = options
const {
signal,
useUUID = false,
markdownFileName = '',
encodeImageAsBase64 = false,
} = options

const { name: originName, fetchSources, fetchBlob } = image.data

Expand All @@ -174,6 +186,11 @@ const downloadImage = async (
const content = await fetchBlob()
if (!content) return null

if (encodeImageAsBase64 && content.size < 100 * 1024) {
image.url = await blobToBase64(content)
return null
}

const baseName = markdownFileName
? `${markdownFileName}-diagram.png`
: 'diagram.png'
Expand Down Expand Up @@ -237,6 +254,11 @@ const downloadImage = async (
},
})

if (encodeImageAsBase64 && blob.size < 100 * 1024) {
image.url = await blobToBase64(blob)
return null
}

image.url = filename

return {
Expand Down Expand Up @@ -379,6 +401,7 @@ const downloadFiles = async (
signal?: AbortSignal
useUUID?: boolean
markdownFileName?: string
encodeImageAsBase64?: boolean
} = {},
): Promise<DownloadResult[]> => {
const {
Expand All @@ -388,6 +411,7 @@ const downloadFiles = async (
signal,
useUUID = false,
markdownFileName = '',
encodeImageAsBase64 = false,
} = options

let completeEventCalled = false
Expand Down Expand Up @@ -423,6 +447,7 @@ const downloadFiles = async (
signal,
useUUID,
markdownFileName,
encodeImageAsBase64,
})
: await downloadFile(file, {
signal,
Expand Down Expand Up @@ -549,6 +574,7 @@ const main = async (options: { signal?: AbortSignal } = {}) => {
SettingKey.Grid,
SettingKey.TextHighlight,
SettingKey.DownloadFileWithUniqueName,
SettingKey.EncodeImageAsBase64,
])

const { root, images, files, tableWithParents, mentionUsers } =
Expand Down Expand Up @@ -609,13 +635,15 @@ const main = async (options: { signal?: AbortSignal } = {}) => {
signal,
useUUID: settings[SettingKey.DownloadFileWithUniqueName],
markdownFileName: recommendName,
encodeImageAsBase64: settings[SettingKey.EncodeImageAsBase64],
}),
// Diagrams must be downloaded one by one
downloadFiles(diagrams, {
batchSize: 1,
signal,
useUUID: settings[SettingKey.DownloadFileWithUniqueName],
markdownFileName: recommendName,
encodeImageAsBase64: settings[SettingKey.EncodeImageAsBase64],
}),
downloadFiles(files, {
onProgress: progress => {
Expand Down
11 changes: 11 additions & 0 deletions packages/common/src/image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,14 @@ export const imageDataToBlob = (
canvas.toBlob(resolve)
})
}

export const blobToBase64 = (blob: Blob): Promise<string> => {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onload = () => {
resolve(reader.result as string)
}
reader.onerror = reject
reader.readAsDataURL(blob)
})
}
Loading