Skip to content

Commit 37dcae9

Browse files
feat(editor): add embed image in mardown (#201)
1 parent b1ee963 commit 37dcae9

File tree

7 files changed

+62
-4
lines changed

7 files changed

+62
-4
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
"prettier-plugin-sh": "0.8.2",
6969
"prettier-plugin-toml": "^0.3.1",
7070
"sanitize-html": "^2.7.0",
71+
"slash": "^3.0.0",
7172
"universal-analytics": "^0.5.3",
7273
"vercel-toast": "^1.5.5",
7374
"vue": "^3.2.33",

pnpm-lock.yaml

Lines changed: 4 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/services/ipc/fs.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { store } from '../../store'
2+
import { ipcMain } from 'electron'
3+
import { ensureDirSync, copySync } from 'fs-extra'
4+
import { join, parse } from 'path'
5+
import { nanoid } from 'nanoid'
6+
import slash from 'slash'
7+
8+
const ASSETS_DIR = 'assets'
9+
10+
export const subscribeToFs = () => {
11+
ipcMain.handle<string, string>('main:copy-to-assets', (event, payload) => {
12+
return new Promise(resolve => {
13+
const storagePath = store.preferences.get('storagePath')
14+
const payloadPath = payload
15+
const assetsPath = join(storagePath, ASSETS_DIR)
16+
const { ext } = parse(payloadPath)
17+
18+
const name = `${nanoid()}${ext}`
19+
const dest = join(assetsPath, name)
20+
21+
ensureDirSync(assetsPath)
22+
copySync(payloadPath, dest)
23+
24+
resolve(slash(join(ASSETS_DIR, name)))
25+
})
26+
})
27+
}

src/main/services/ipc/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { subscribeToContextMenu } from './context-menu'
2+
import { subscribeToFs } from './fs'
23
import { subscribeToNotification } from './notifications'
34
import { subscribeToPrettier } from './prettier'
45

56
export const subscribeToChannels = () => {
67
subscribeToContextMenu()
78
subscribeToNotification()
89
subscribeToPrettier()
10+
subscribeToFs()
911
}

src/renderer/components/editor/EditorCodemirror.vue

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,21 @@ const init = async () => {
159159
})
160160
editor.on('scroll', hideScrollbar)
161161
162+
editor.on('paste', async (cm, e) => {
163+
if (props.lang === 'markdown') {
164+
const item = e.clipboardData?.items[0]
165+
166+
if (item?.type.startsWith('image')) {
167+
e.preventDefault()
168+
169+
const blob = item.getAsFile()
170+
const path = await ipc.invoke('main:copy-to-assets', blob?.path)
171+
172+
cm.replaceSelection(`![](./${path})`)
173+
}
174+
}
175+
})
176+
162177
editor.setOption('extraKeys', {
163178
'Cmd-F': () => {
164179
emitter.emit('search:focus', true)

src/renderer/components/markdown/TheMarkdown.vue

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@ import { useSnippetStore } from '@/store/snippets'
1212
import sanitizeHtml from 'sanitize-html'
1313
import hljs from 'highlight.js'
1414
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
15-
import { ipc } from '@/electron'
15+
import { ipc, store } from '@/electron'
1616
import { marked } from 'marked'
1717
import mermaid from 'mermaid'
1818
import { useHljsTheme } from '@/composable'
1919
20+
const isDev = import.meta.env.DEV
21+
2022
interface Props {
2123
value: string
2224
}
@@ -68,7 +70,7 @@ onMounted(() => {
6870
6971
const getRenderer = () => {
7072
const raw = marked.parse(props.value)
71-
const html = sanitizeHtml(raw, {
73+
let html = sanitizeHtml(raw, {
7274
allowedTags: [
7375
'h1',
7476
'h2',
@@ -151,6 +153,14 @@ const getRenderer = () => {
151153
]
152154
}
153155
})
156+
157+
const re = /src="\.\//g
158+
const path = store.preferences.get('storagePath')
159+
160+
html = isDev
161+
? html.replace(re, `src="file://${path}/`)
162+
: html.replace(re, `src="${path}/`)
163+
154164
return html
155165
}
156166

src/shared/types/main/index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ type MainAction =
5454
| 'open-url'
5555
| 'prettier'
5656
| 'focus'
57+
| 'copy-to-assets'
5758

5859
type ApiAction = 'snippet-create'
5960

0 commit comments

Comments
 (0)