mirror of
https://github.com/purocean/yn.git
synced 2026-09-24 15:46:02 +08:00
147 lines
4.2 KiB
TypeScript
147 lines
4.2 KiB
TypeScript
import TurndownService from 'turndown'
|
|
import { getEditor, insert } from '@fe/services/editor'
|
|
import { Plugin } from '@fe/context'
|
|
import { triggerHook } from '@fe/core/hook'
|
|
import { refreshTree } from '@fe/services/tree'
|
|
import { upload } from '@fe/services/base'
|
|
import store from '@fe/support/store'
|
|
import { encodeMarkdownLink, fileToBase64URL } from '@fe/utils'
|
|
import { isKeydown } from '@fe/core/command'
|
|
|
|
const IMAGE_REG = /^image\/(png|jpg|jpeg|gif)$/i
|
|
const HTML_REG = /^text\/html$/i
|
|
|
|
async function pasteHtml (html: string) {
|
|
const md = new TurndownService({ headingStyle: 'atx', codeBlockStyle: 'fenced', bulletListMarker: '+' }).turndown(html)
|
|
insert(md + '\n')
|
|
}
|
|
|
|
async function pasteImage (file: File, asBase64: boolean) {
|
|
if (asBase64) {
|
|
const uri = await fileToBase64URL(file)
|
|
insert(`\n`)
|
|
} else {
|
|
if (!store.state.currentFile) {
|
|
throw new Error('No file opened.')
|
|
}
|
|
|
|
if (!(await triggerHook('EDITOR_PASTE_IMAGE', { file }, { breakable: true }))) {
|
|
const assetPath = await upload(file, store.state.currentFile)
|
|
insert(`})\n`)
|
|
}
|
|
|
|
refreshTree()
|
|
}
|
|
}
|
|
|
|
function paste (e: ClipboardEvent) {
|
|
if (!getEditor().hasTextFocus()) {
|
|
return
|
|
}
|
|
|
|
const items = e.clipboardData!.items
|
|
if (isKeydown('D')) { // covert RFT to markdown
|
|
for (let i = 0; i < items.length; i++) {
|
|
if (items[i].type.match(HTML_REG)) {
|
|
items[i].getAsString(pasteHtml)
|
|
}
|
|
}
|
|
|
|
e.preventDefault()
|
|
e.stopPropagation()
|
|
} else {
|
|
for (let i = 0; i < items.length; i++) {
|
|
const fileType = items[i].type
|
|
if (fileType.match(IMAGE_REG)) {
|
|
const asBase64 = isKeydown('B') // press key b, paste image as base64
|
|
pasteImage(items[i].getAsFile()!, asBase64)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
export default {
|
|
name: 'editor-paste',
|
|
register: (ctx) => {
|
|
window.addEventListener('paste', paste as any, true)
|
|
|
|
const pasteImageAsBase64ActionId = 'plugin.editor-paste.insert-image-base64'
|
|
const pasteRtfActionId = 'plugin.editor-paste.insert-rtf'
|
|
|
|
const pasteImageFromClipboard = async (asBase64: boolean) => {
|
|
ctx.base.readFromClipboard(async (type, getType) => {
|
|
const match = type.match(IMAGE_REG)
|
|
if (match) {
|
|
const file = new File([await getType(type)], 'image.' + match[1], { type })
|
|
await pasteImage(file, asBase64)
|
|
const { editor } = await ctx.editor.whenEditorReady()
|
|
editor.focus()
|
|
}
|
|
})
|
|
}
|
|
|
|
const pasteRtf = () => {
|
|
ctx.base.readFromClipboard(async (type, getType) => {
|
|
if (type.match(HTML_REG)) {
|
|
const html = await (await getType(type)).text()
|
|
await pasteHtml(html)
|
|
const { editor } = await ctx.editor.whenEditorReady()
|
|
editor.focus()
|
|
}
|
|
})
|
|
}
|
|
|
|
ctx.statusBar.tapMenus(menus => {
|
|
menus['status-bar-insert']?.list?.push(
|
|
{
|
|
id: pasteImageAsBase64ActionId,
|
|
type: 'normal',
|
|
title: ctx.i18n.t('status-bar.insert.paste-img-base64'),
|
|
subTitle: 'Base64',
|
|
onClick: () => {
|
|
pasteImageFromClipboard(true)
|
|
}
|
|
},
|
|
{
|
|
id: pasteRtfActionId,
|
|
type: 'normal',
|
|
title: ctx.i18n.t('status-bar.insert.paste-rtf'),
|
|
subTitle: 'Markdown',
|
|
onClick: pasteRtf
|
|
},
|
|
{ type: 'separator' },
|
|
)
|
|
})
|
|
|
|
ctx.editor.whenEditorReady().then(({ editor }) => {
|
|
editor.addAction({
|
|
id: 'plugin.editor-paste.insert-image',
|
|
label: ctx.i18n.t('editor.context-menu.paste-image'),
|
|
contextMenuGroupId: 'clipboard',
|
|
contextMenuOrder: 1,
|
|
run: async () => {
|
|
pasteImageFromClipboard(false)
|
|
}
|
|
})
|
|
|
|
editor.addAction({
|
|
id: pasteImageAsBase64ActionId,
|
|
label: ctx.i18n.t('editor.context-menu.paste-image-as-base64'),
|
|
contextMenuGroupId: 'clipboard',
|
|
contextMenuOrder: 2,
|
|
run: () => {
|
|
pasteImageFromClipboard(true)
|
|
}
|
|
})
|
|
|
|
editor.addAction({
|
|
id: pasteRtfActionId,
|
|
label: ctx.i18n.t('editor.context-menu.paste-rtf-as-markdown'),
|
|
contextMenuGroupId: 'clipboard',
|
|
contextMenuOrder: 3,
|
|
run: pasteRtf,
|
|
})
|
|
})
|
|
}
|
|
} as Plugin
|