Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ node_modules
.DS_Store
.idea
.vscode/api-key.txt
with-key-build.sh
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -466,14 +466,14 @@
"type": "boolean",
"markdownDescription": "创建本地博文时, 是否根据博文分类保存到对应的文件夹中"
},
"cnblogsClientForVSCode.automaticallyExtractImages": {
"cnblogsClientForVSCode.autoExtractImages": {
"order": 6,
"default": "disable",
"scope": "application",
"enum": [
"disable",
"local",
"dataurl",
"fs",
"dataUrl",
"web",
"any"
],
Expand Down
95 changes: 55 additions & 40 deletions src/commands/extract-images.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
import { MessageItem, MessageOptions, ProgressLocation, Range, Uri, window, workspace, WorkspaceEdit } from 'vscode'
import { ImageSrc, MarkdownImagesExtractor, ImageInfo, newImageSrcFilter } from '@/services/images-extractor.service'
import { ImageInfo, ImageSrc, MkdImgExtractor, newImageSrcFilter } from '@/services/mkd-img-extractor.service'

type ExtractOption = MessageItem & Partial<{ imageSrc: ImageSrc }>
const extractOptions: readonly ExtractOption[] = [
{ title: '提取本地图片', imageSrc: ImageSrc.local },
{ title: '提取网络图片', imageSrc: ImageSrc.web },
{ title: '提取全部', imageSrc: ImageSrc.any },
{ title: '取消', imageSrc: undefined, isCloseAffordance: true },
]

export async function extractImages(arg: unknown, inputImageSrc: ImageSrc | undefined) {

export async function extractImages(arg: unknown, inputImageSrc?: ImageSrc) {
if (!(arg instanceof Uri && arg.scheme === 'file')) return

const editor = window.visibleTextEditors.find(x => x.document.fileName === arg.fsPath)
Expand All @@ -19,40 +13,60 @@ export async function extractImages(arg: unknown, inputImageSrc: ImageSrc | unde
await textDocument.save()

const markdown = (await workspace.fs.readFile(arg)).toString()
const extractor = new MarkdownImagesExtractor(markdown, arg)
const extractor = new MkdImgExtractor(markdown, arg)

const images = extractor.findImages()
if (images.length <= 0)
void (!inputImageSrc != null ? window.showWarningMessage('没有找到可以提取的图片') : undefined)

const availableWebImagesCount = images.filter(newImageSrcFilter(ImageSrc.web)).length
const availableLocalImagesCount = images.filter(newImageSrcFilter(ImageSrc.local)).length
const result =
extractOptions.find(x => inputImageSrc != null && x.imageSrc === inputImageSrc) ??
(await window.showInformationMessage<ExtractOption>(
if (images.length <= 0) {
void (!inputImageSrc !== undefined ? window.showWarningMessage('没有找到可以提取的图片') : undefined)
return
}

const getExtractOption = () => {
const webImgCount = images.filter(newImageSrcFilter(ImageSrc.web)).length
const dataUrlImgCount = images.filter(newImageSrcFilter(ImageSrc.dataUrl)).length
const fsImgCount = images.filter(newImageSrcFilter(ImageSrc.fs)).length

const displayOptions: ExtractOption[] = [
{ title: '提取全部', imageSrc: ImageSrc.any },
{ title: '提取网络图片', imageSrc: ImageSrc.web },
{ title: '提取 Data Url 图片', imageSrc: ImageSrc.dataUrl },
{ title: '提取本地图片', imageSrc: ImageSrc.fs },
{ title: '取消', imageSrc: undefined, isCloseAffordance: true },
]

if (inputImageSrc !== undefined)
return Promise.resolve(displayOptions.find(ent => ent.imageSrc === inputImageSrc))

// if src is not specified:
return window.showInformationMessage<ExtractOption>(
'要提取哪些图片? 此操作会替换源文件中的图片链接!',
{
modal: true,
detail:
`共找到 ${availableWebImagesCount} 张可以提取的网络图片\n` +
`${availableLocalImagesCount} 张可以提取的本地图片`,
'共找到:\n' +
`${webImgCount} 张可以提取的网络图片\n` +
`${dataUrlImgCount} 张可以提取的 Data Url 图片\n` +
`${fsImgCount} 张可以提取的本地图片`,
} as MessageOptions,
...extractOptions
))
...displayOptions
)
}

const extractImageSrc = (await getExtractOption())?.imageSrc

if (!(result && result.imageSrc !== undefined)) return
if (extractImageSrc === undefined) return

extractor.imageSrc = result.imageSrc
extractor.imageSrc = extractImageSrc

const failedImages = await window.withProgress(
{ title: '提取图片', location: ProgressLocation.Notification },
{ title: '正在提取图片', location: ProgressLocation.Notification },
async progress => {
extractor.onProgress = (idx, images) => {
const total = images.length
const image = images[idx]
extractor.onProgress = (count, info) => {
const total = info.length
const image = info[count]
progress.report({
increment: (idx / total) * 80,
message: `[${idx + 1} / ${total}] 正在提取 ${image.link}`,
increment: (count / total) * 80,
message: `[${count + 1} / ${total}] 正在提取 ${image.data}`,
})
}

Expand All @@ -65,25 +79,26 @@ export async function extractImages(arg: unknown, inputImageSrc: ImageSrc | unde
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
.map(([src, dst]) => [src, dst!])
.map(([src, dst]) => {
const startPos = textDocument.positionAt(src.startOffset)
const endPos = textDocument.positionAt(
src.startOffset + src.prefix.length + src.link.length + src.postfix.length
const posL = textDocument.positionAt(src.startOffset)
const posR = textDocument.positionAt(
src.startOffset + src.prefix.length + src.data.length + src.postfix.length
)
const range = new Range(startPos, endPos)
const range = new Range(posL, posR)

// just for ts type inferring
const ret: [Range, ImageInfo] = [range, dst]
return ret
})
.reduce((we, [range, dst]) => {
if (range) {
progress.report({
increment: (idx / extractedLen) * 20 + 80,
message: `[${idx + 1} / ${extractedLen}] 正在替换图片链接 ${dst.link}`,
message: `[${idx + 1} / ${extractedLen}] 正在替换图片链接 ${dst.data}`,
})
const newText = dst.prefix + dst.link + dst.postfix
const newText = dst.prefix + dst.data + dst.postfix
we.replace(textDocument.uri, range, newText, {
needsConfirmation: false,
label: dst.link,
label: dst.data,
})
}

Expand All @@ -96,10 +111,10 @@ export async function extractImages(arg: unknown, inputImageSrc: ImageSrc | unde
}
)

if (failedImages && failedImages.length > 0) {
if (failedImages.length > 0) {
const info = failedImages
.map(x => [x.link, extractor.errors.find(([link]) => link === x.link)?.[1] ?? ''].join(','))
.map(info => [info.data, extractor.errors.find(([link]) => link === info.data)?.[1] ?? ''].join(','))
.join('\n')
window.showErrorMessage(`${failedImages.length}张图片提取失败: ${info}`).then(undefined, console.warn)
window.showErrorMessage(`${failedImages.length} 张图片提取失败: ${info}`).then(undefined, console.warn)
}
}
13 changes: 9 additions & 4 deletions src/commands/posts-list/upload-post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,11 @@ export const saveLocalDraftToCnblogs = async (localDraft: LocalDraft) => {
AlertService.warning('本地文件已删除, 无法新建博文')
return false
}
if (Settings.automaticallyExtractImagesType)
await extractImages(localDraft.filePathUri, Settings.automaticallyExtractImagesType).catch(console.warn)

console.log(Settings.autoExtractImgType)

if (Settings.autoExtractImgType !== undefined)
await extractImages(localDraft.filePathUri, Settings.autoExtractImgType).catch(console.warn)

postToSave.postBody = await localDraft.readAllText()
return true
Expand All @@ -138,8 +141,10 @@ export const uploadPostToCnblogs = async (input: Post | PostTreeItem | PostEditD
const localFilePath = PostFileMapManager.getFilePath(postId)
if (!localFilePath) return AlertService.warning('本地无该博文的编辑记录')

if (Settings.automaticallyExtractImagesType)
await extractImages(Uri.file(localFilePath), Settings.automaticallyExtractImagesType).catch(console.warn)
console.log(Settings.autoExtractImgType)

if (Settings.autoExtractImgType !== undefined)
await extractImages(Uri.file(localFilePath), Settings.autoExtractImgType).catch(console.warn)

await saveFilePendingChanges(localFilePath)
post.postBody = (await workspace.fs.readFile(Uri.file(localFilePath))).toString()
Expand Down
12 changes: 7 additions & 5 deletions src/services/image.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,20 @@ import path from 'path'
class ImageService {
async upload<T extends Readable & { name?: string; fileName?: string; filename?: string; path?: string | Buffer }>(
file: T
): Promise<string> {
) {
// eslint-disable-next-line @typescript-eslint/naming-convention
const FormData = (await import('form-data')).default
const form = new FormData()
const { name, fileName, filename, path: _path } = file
const finalName = path.basename(isString(_path) ? _path : fileName || filename || name || 'image.png')
const ext = path.extname(finalName)

const mime = await import('mime')
const mimeType = mime.lookup(ext, 'image/png')
form.append('image', file, { filename: finalName, contentType: mimeType })

const fd = new (await import('form-data')).default()
fd.append('image', file, { filename: finalName, contentType: mimeType })

const response = await httpClient.post(`${globalContext.config.apiBaseUrl}/api/posts/body/images`, {
body: form,
body: fd,
})

return response.body
Expand Down
Loading