Skip to content

Commit

Permalink
feat: support copy markdown
Browse files Browse the repository at this point in the history
  • Loading branch information
purocean committed Mar 7, 2022
1 parent 2ffce48 commit f1f8d88
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 15 deletions.
77 changes: 65 additions & 12 deletions src/renderer/plugins/copy-rendered-content.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Plugin } from '@fe/context'
import type Token from 'markdown-it/lib/token'

export default {
name: 'copy-rendered-content',
Expand All @@ -8,7 +9,7 @@ export default {
inlineLocalImage: false,
uploadLocalImage: false,
highlightCode: false,
type: 'rtf' as 'html' | 'rtf',
type: 'rtf' as 'html' | 'rtf' | 'markdown',
})

const panel = ctx.lib.vue.defineComponent({
Expand All @@ -25,25 +26,75 @@ export default {

return () => <div class="copy-rendered-content">
<div>
<div class="label">{ctx.i18n.t('copy-rendered-content.options')}</div>
<div class="label">{ctx.i18n.t('copy-rendered-content.type')}</div>
<div>
<label><input v-model={options.inlineLocalImage} type="checkbox" /> {ctx.i18n.t('copy-rendered-content.inline-image')} </label>
<label><input v-model={options.uploadLocalImage} type="checkbox" /> {ctx.i18n.t('copy-rendered-content.upload-image')} </label>
<label><input v-model={options.inlineStyle} type="checkbox" /> {ctx.i18n.t('copy-rendered-content.inline-style')} </label>
<label><input v-model={options.highlightCode} type="checkbox" /> {ctx.i18n.t('copy-rendered-content.highlight-code')} </label>
<label><input v-model={options.type} type="radio" value="rtf" /> {ctx.i18n.t('copy-rendered-content.rtf')}</label>
<label><input v-model={options.type} type="radio" value="html" /> HTML </label>
<label><input v-model={options.type} type="radio" value="markdown" /> Markdown </label>
</div>
</div>
<div>
<div class="label">{ctx.i18n.t('copy-rendered-content.type')}</div>
<div class="label">{ctx.i18n.t('copy-rendered-content.options')}</div>
<div>
<label><input v-model={options.type} type="radio" value="rtf" /> {ctx.i18n.t('copy-rendered-content.rtf')}</label>
<label><input v-model={options.type} type="radio" value="html" /> HTML </label>
<label><input v-model={options.inlineLocalImage} type="checkbox" /> {ctx.i18n.t('copy-rendered-content.inline-image')} </label>
<label><input v-model={options.uploadLocalImage} type="checkbox" /> {ctx.i18n.t('copy-rendered-content.upload-image')} </label>
{options.type !== 'markdown' && <label><input v-model={options.inlineStyle} type="checkbox" /> {ctx.i18n.t('copy-rendered-content.inline-style')} </label>}
{options.type !== 'markdown' && <label><input v-model={options.highlightCode} type="checkbox" /> {ctx.i18n.t('copy-rendered-content.highlight-code')} </label>}
</div>
</div>
</div>
}
})

async function transformMarkdown () {
let markdown = ctx.store.state.currentContent
const tokens = ctx.view.getRenderEnv()?.tokens
if (!markdown || !tokens) {
return
}

const processImg = async (tokens: Token[]) => {
for (let token of tokens) {
if (token.children) {
await processImg(token.children)
}


if (token.tag === 'img' && token.attrGet(ctx.constant.DOM_ATTR_NAME.LOCAL_IMAGE)) {
const srcAttr = token.attrGet('src')
const originSrc = token.attrGet(ctx.constant.DOM_ATTR_NAME.ORIGIN_SRC)
if (srcAttr && originSrc) {
const res: Response = await ctx.api.fetchHttp(srcAttr)
const fileName = ctx.utils.path.basename(originSrc)
const file = new File(
[await res.blob()],
fileName,
{ type: ctx.lib.mime.getType(fileName) || undefined }
)

let url: string | undefined
if (options.inlineLocalImage) {
url = await ctx.utils.fileToBase64URL(file)
} else if (options.uploadLocalImage) {
url = await ctx.action.getActionHandler('plugin.image-hosting-picgo.upload')(file)
}

if (url) {
markdown = markdown.replace(
new RegExp(ctx.utils.encodeMarkdownLink(originSrc), 'g'),
ctx.utils.encodeMarkdownLink(url)
)
}
}
}
}
}

await processImg(tokens)

return markdown
}

async function copyContent () {
if (await ctx.ui.useModal().confirm({
title: ctx.i18n.t('status-bar.tool.copy-content'),
Expand All @@ -52,17 +103,19 @@ export default {
try {
const startedAt = Date.now()
ctx.ui.useToast().show('info', ctx.i18n.t('loading'), 10000)
const html = await ctx.view.getContentHtml(options)
const content = options.type === 'markdown'
? await transformMarkdown()
: await ctx.view.getContentHtml(options)

if (Date.now() - startedAt > 3000) {
await ctx.ui.useModal().alert({ content: ctx.i18n.t('copy-rendered-content.complete') })
}

if (options.type === 'rtf') {
await ctx.base.writeToClipboard('text/html', html)
await ctx.base.writeToClipboard('text/html', content)
ctx.ui.useToast().show('info', ctx.i18n.t('copied'))
} else {
ctx.utils.copyText(html)
ctx.utils.copyText(content)
}
} catch (error: any) {
console.error(error)
Expand Down
1 change: 1 addition & 0 deletions src/renderer/services/markdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,6 @@ markdown.block.tokenize = function (state, startLine, endLine) {

markdown.core.ruler.after('normalize', 'after_normalize', state => {
state.env.source = state.src
state.env.tokens = state.tokens
return true
})
9 changes: 8 additions & 1 deletion src/renderer/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Language } from '@share/i18n'
import type Token from 'markdown-it/lib/token'
import type * as Monaco from 'monaco-editor'

export interface PathItem {
Expand Down Expand Up @@ -92,7 +93,13 @@ export type ThemeName = 'system' | 'dark' | 'light'
export type LanguageName = 'system' | Language
export type ExportTypes = 'pdf' | 'docx' | 'html' | 'rst' | 'adoc'

export type RenderEnv = { source: string, file: Doc | null, renderCount: number, attributes?: Record<string, any> }
export type RenderEnv = {
source: string,
file: Doc | null,
renderCount: number,
attributes?: Record<string, any>,
tokens: Token[]
}

export type BuildInSettings = {
'repos': Repo[],
Expand Down
1 change: 0 additions & 1 deletion src/share/i18n/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,6 @@ const data = {
'use-html': 'Use the rendered HTML source',
'use-markdown': 'Use markdown source',
'loading': 'Converting, please wait...',
'include-css': 'Include CSS',
},
'title-bar': {
'pin': 'Pin',
Expand Down
1 change: 0 additions & 1 deletion src/share/i18n/languages/zh-CN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,6 @@ const data: BaseLanguage = {
'use-html': '使用渲染后的 HTML 转换',
'use-markdown': '使用 Markdown 转换',
'loading': '转换中,请稍候……',
'include-css': '包含 CSS',
},
'title-bar': {
'pin': '置顶窗口',
Expand Down

0 comments on commit f1f8d88

Please sign in to comment.