重构插件代码

This commit is contained in:
purocean
2021-04-27 16:14:40 +08:00
parent df829634b7
commit 0263059ebc
24 changed files with 183 additions and 166 deletions
+2 -1
View File
@@ -50,7 +50,8 @@ import Footnote from 'markdown-it-footnote'
import Highlight from 'highlight.js'
import file from '../useful/file'
import { getMarkdownItPlugins, triggerHook } from '../useful/plugin'
import { triggerHook } from '../useful/plugin'
import { getPlugins as getMarkdownItPlugins } from '../useful/plugin/markdown'
import { useBus } from '../useful/bus'
import 'github-markdown-css/github-markdown.css'
+4 -4
View File
@@ -12,7 +12,7 @@
<script lang="ts">
import { defineComponent, onBeforeUnmount, ref } from 'vue'
import { useBus } from '../useful/bus'
import { getStatusBarMenus, StatusBarMenuItem } from '../useful/plugin'
import { getMenus, MenuItem } from '../useful/plugin/status-bar'
export default defineComponent({
name: 'status-bar-menu',
@@ -24,10 +24,10 @@ export default defineComponent({
},
setup (props) {
const bus = useBus()
const list = ref(getStatusBarMenus('status-bar', props.position))
const list = ref(getMenus(props.position))
const showList = ref(true)
const handleItemClick = (item: StatusBarMenuItem) => {
const handleItemClick = (item: MenuItem) => {
item.onClick && item.onClick(item)
showList.value = false
setTimeout(() => {
@@ -36,7 +36,7 @@ export default defineComponent({
}
const updateMenu = () => {
list.value = getStatusBarMenus('status-bar', props.position)
list.value = getMenus(props.position)
}
bus.on('status-bar-menu-update', updateMenu)
+1 -1
View File
@@ -145,7 +145,7 @@ const runScript = (el: HTMLElement) => {
export default {
name: 'applet',
register: ctx => {
ctx.registerMarkdownItPlugin(RunPlugin)
ctx.markdown.registerPlugin(RunPlugin)
function runAppletScript ({ getViewDom }: any) {
const refView: HTMLElement = getViewDom()
+1 -1
View File
@@ -158,7 +158,7 @@ const load = async (el: HTMLIFrameElement, url?: string) => {
export default {
name: 'drawio',
register: ctx => {
ctx.registerMarkdownItPlugin(MarkdownItPlugin)
ctx.markdown.registerPlugin(MarkdownItPlugin)
ctx.registerHook('ON_VIEW_RENDER', ({ getViewDom }) => {
const refView: HTMLElement = getViewDom()
+1 -1
View File
@@ -88,7 +88,7 @@ window.addEventListener('beforeprint', () => {
export default {
name: 'markdown-toc',
register: ctx => {
ctx.registerMarkdownItPlugin(EChartsPlugin)
ctx.markdown.registerPlugin(EChartsPlugin)
ctx.registerHook('ON_VIEW_RENDER', () => {
update()
})
+1 -1
View File
@@ -4,7 +4,7 @@ import { Plugin, Ctx } from '@/useful/plugin'
export default {
name: 'markdown-code',
register: (ctx: Ctx) => {
ctx.registerMarkdownItPlugin(md => {
ctx.markdown.registerPlugin(md => {
const Fun = (fn: Function) => (tokens: any, idx: any, options: any, env: any, slf: any) => {
if (tokens[idx].attrIndex('title') < 0) {
tokens[idx].attrJoin('class', 'copy-inner-text')
+1 -1
View File
@@ -91,7 +91,7 @@ export default {
return false
})
ctx.registerMarkdownItPlugin(md => {
ctx.markdown.registerPlugin(md => {
md.renderer.rules.link_open = (tokens, idx, options, _, slf) => {
if (tokens[idx].attrIndex('target') < 0) {
tokens[idx].attrPush(['target', '_blank'])
+1 -1
View File
@@ -19,7 +19,7 @@ export const injectLineNumbers = buildFunction('source-line')
export default {
name: 'markdown-source-line',
register: ctx => {
ctx.registerMarkdownItPlugin(md => {
ctx.markdown.registerPlugin(md => {
md.renderer.rules.paragraph_open = injectLineNumbers
md.renderer.rules.heading_open = injectLineNumbers
md.renderer.rules.list_item_open = injectLineNumbers
+1 -1
View File
@@ -206,6 +206,6 @@ const MarkdownItPlugin = (md: Markdown, o: any) => {
export default {
name: 'markdown-toc',
register: ctx => {
ctx.registerMarkdownItPlugin(MarkdownItPlugin)
ctx.markdown.registerPlugin(MarkdownItPlugin)
}
} as Plugin
+1 -1
View File
@@ -32,7 +32,7 @@ const MermaidPlugin = (md: Markdown) => {
export default {
name: 'mermaid',
register: ctx => {
ctx.registerMarkdownItPlugin(MermaidPlugin)
ctx.markdown.registerPlugin(MermaidPlugin)
ctx.registerHook('ON_VIEW_RENDER', () => mermaid.init('.mermaid'))
}
} as Plugin
+1 -1
View File
@@ -189,7 +189,7 @@ const render = async (ele: HTMLElement) => {
export default {
name: 'mind-map',
register: ctx => {
ctx.registerMarkdownItPlugin(md => {
ctx.markdown.registerPlugin(md => {
md.renderer.rules.bullet_list_open = renderRule
})
+1 -1
View File
@@ -142,7 +142,7 @@ const MarkdownItPlugin = function umlPlugin (md: Markdown, options: any) {
export default {
name: 'markdown-plantuml',
register: ctx => {
ctx.registerMarkdownItPlugin(MarkdownItPlugin)
ctx.markdown.registerPlugin(MarkdownItPlugin)
const updatePlantuml = ({ getViewDom }: any) => {
const refView: HTMLElement = getViewDom()
+1 -1
View File
@@ -72,7 +72,7 @@ const clearCache = () => {
export default {
name: 'run-code',
register: ctx => {
ctx.registerMarkdownItPlugin(RunPlugin)
ctx.markdown.registerPlugin(RunPlugin)
ctx.registerHook('ON_STARTUP', clearCache)
}
} as Plugin
+2 -3
View File
@@ -19,7 +19,7 @@ export default {
}
Object.entries(actions).forEach(([key, item]) => {
item.shortcut && ctx.registerShortcutAction(key, item.shortcut)
item.shortcut && ctx.shortcut.addAction(key, item.shortcut)
})
function keydownHandler (e: KeyboardEvent) {
@@ -35,9 +35,8 @@ export default {
window.addEventListener('keydown', keydownHandler, true)
ctx.updateStatusBarMenu({
ctx.statusBar.updateMenu({
id: 'status-bar-help',
location: 'status-bar',
position: 'right',
title: '帮助',
list: Object.entries(actions).map(([key, item]) => {
@@ -1,4 +1,5 @@
import { Plugin, StatusBarMenu } from '@/useful/plugin'
import { Plugin } from '@/useful/plugin'
import { Menu as StatusBarMenu } from '@/useful/plugin/status-bar'
import store from '@/store'
import { useBus } from '@/useful/bus'
import { $args } from '@/useful/global-args'
@@ -40,14 +41,13 @@ export default {
const menu = {
id: 'status-bar-repository-switch',
location: 'status-bar',
position: 'left',
title: '仓库',
} as StatusBarMenu
function updateMenu () {
const { currentRepo, repositories } = store.state
ctx.updateStatusBarMenu({
ctx.statusBar.updateMenu({
...menu,
title: currentRepo ? `仓库: ${currentRepo.name}` : '未选择仓库',
list: Object.keys(repositories).map(name => {
@@ -64,7 +64,7 @@ export default {
})
}
ctx.updateStatusBarMenu(menu)
ctx.statusBar.updateMenu(menu)
bus.on('switch-repo-by-name', chooseRepoByName)
bus.on('editor-ready', initRepo)
+2 -3
View File
@@ -30,7 +30,7 @@ export default {
},
}
Object.entries(actions).forEach(([key, item]) => ctx.registerShortcutAction(key, item.shortcut))
Object.entries(actions).forEach(([key, item]) => ctx.shortcut.addAction(key, item.shortcut))
function keydownHandler (e: KeyboardEvent) {
for (const [key, item] of Object.entries(actions)) {
@@ -45,9 +45,8 @@ export default {
window.addEventListener('keydown', keydownHandler, true)
ctx.updateStatusBarMenu({
ctx.statusBar.updateMenu({
id: 'status-bar-view',
location: 'status-bar',
position: 'left',
title: '视图',
list: Object.entries(actions).map(([key, item]) => {
@@ -55,8 +55,8 @@ const actionClick = 'transform-img-link-by-click'
export default {
name: 'transform-img-out-link',
register: (ctx: Ctx) => {
ctx.registerShortcutAction(actionKeydown, [CtrlCmd, Shift, 'l'])
ctx.registerShortcutAction(actionClick, [CtrlCmd, Shift, LeftClick])
ctx.shortcut.addAction(actionKeydown, [CtrlCmd, Shift, 'l'])
ctx.shortcut.addAction(actionClick, [CtrlCmd, Shift, LeftClick])
ctx.registerHook('ON_VIEW_KEY_DOWN', async (e: KeyboardEvent, refView: HTMLElement) => {
const toast = useToast()
-138
View File
@@ -1,138 +0,0 @@
import { addAction } from './shortcut'
import { getLogger } from './utils'
import Markdown from 'markdown-it'
import { useBus } from './bus'
export type HookType = 'ON_STARTUP'
| 'ON_VIEW_ELEMENT_CLICK'
| 'ON_VIEW_KEY_DOWN'
| 'ON_VIEW_RENDER'
| 'ON_VIEW_RENDERED'
| 'ON_VIEW_MOUNTED'
| 'ON_VIEW_FILE_CHANGE'
| 'ON_VIEW_BEFORE_CONVERT'
| 'ON_TREE_NODE_SELECT'
export interface Plugin {
name: string;
register?: (ctx: Ctx) => void;
}
export type HookFun = (...args: any[]) => boolean | void | Promise<boolean | void>
export type StatusBarMenuItem = {
id: string;
type: 'normal';
title: string;
tips?: string;
onClick?: (item: StatusBarMenuItem) => void;
}
export type MenuLocation = 'status-bar'
export interface StatusBarMenu {
id: string;
title: string;
tips?: string;
location: MenuLocation;
position: 'left' | 'right';
onClick?: (menu: StatusBarMenu) => void;
list?: (StatusBarMenuItem | { type: 'separator' })[];
}
const logger = getLogger('plugin')
const bus = useBus()
const plugins: {[name: string]: Plugin} = {}
const hooks: { [key in HookType]?: {fun: HookFun; once: boolean}[] } = {}
const markdownItPlugins: {plugin: any; params: any}[] = []
const statusBarMenus: { [key: string]: StatusBarMenu } = {}
const ctx = {
registerShortcutAction (name: string, keys: (string | number)[]) {
addAction(name, keys)
},
registerHook: (type: HookType, fun: HookFun, once = false) => {
if (Array.isArray(hooks[type])) {
hooks[type] = [...hooks[type]!!, { fun, once }]
} else {
hooks[type] = [{ fun, once }]
}
},
removeHook: (type: HookType, fun: HookFun) => {
if (Array.isArray(hooks[type])) {
hooks[type] = hooks[type]!!.filter(x => x.fun !== fun)
}
},
registerMarkdownItPlugin: (plugin: (md: Markdown, ...args: any) => void, params?: any) => {
markdownItPlugins.push({ plugin, params })
},
updateStatusBarMenu: (menu: StatusBarMenu) => {
statusBarMenus[menu.id] = menu
bus.emit('status-bar-menu-update', menu)
},
removeStatusBarMenu: (id: string) => {
delete statusBarMenus[id]
bus.emit('status-bar-menu-update')
}
}
export type Ctx = typeof ctx;
export const register = (plugin: Plugin) => {
logger.debug('register', plugin)
plugins[plugin.name] = plugin
plugin.register && plugin.register(ctx)
}
export const init = () => {
logger.debug('init')
const localPlugins = [
require('@/plugins/status-bar-repository-switch'),
require('@/plugins/status-bar-view'),
require('@/plugins/status-bar-help'),
require('@/plugins/markdown-source-line'),
require('@/plugins/markdown-toc'),
require('@/plugins/markdown-code'),
require('@/plugins/markdown-link'),
require('@/plugins/code-line-number'),
require('@/plugins/transform-img-out-link'),
require('@/plugins/copy-text'),
require('@/plugins/table-cell-edit'),
require('@/plugins/switch-todo'),
require('@/plugins/run-code'),
require('@/plugins/plantuml'),
require('@/plugins/drawio'),
require('@/plugins/mind-map'),
require('@/plugins/mermaid'),
require('@/plugins/applet'),
require('@/plugins/echarts'),
]
localPlugins.forEach((plugin) => {
if (plugin.__esModule && plugin.default) {
register(plugin.default)
} else {
register(plugin)
}
})
}
export const triggerHook = async (type: HookType, ...args: any[]) => {
logger.debug('triggerHook', type, args)
for (const { fun, once } of (hooks[type] || [])) {
once && ctx.removeHook(type, fun)
if (await fun(...args)) {
return true
}
}
return false
}
export const getMarkdownItPlugins = () => markdownItPlugins
export const getStatusBarMenus = (location: MenuLocation, position: string) =>
Object.values(statusBarMenus).filter(x => x.location === location && x.position === position)
init()
+21
View File
@@ -0,0 +1,21 @@
export default [
require('@/plugins/status-bar-repository-switch'),
require('@/plugins/status-bar-view'),
require('@/plugins/status-bar-help'),
require('@/plugins/markdown-source-line'),
require('@/plugins/markdown-toc'),
require('@/plugins/markdown-code'),
require('@/plugins/markdown-link'),
require('@/plugins/code-line-number'),
require('@/plugins/transform-img-out-link'),
require('@/plugins/copy-text'),
require('@/plugins/table-cell-edit'),
require('@/plugins/switch-todo'),
require('@/plugins/run-code'),
require('@/plugins/plantuml'),
require('@/plugins/drawio'),
require('@/plugins/mind-map'),
require('@/plugins/mermaid'),
require('@/plugins/applet'),
require('@/plugins/echarts'),
]
+79
View File
@@ -0,0 +1,79 @@
import * as shortcut from '@/useful/shortcut'
import { getLogger } from '@/useful/utils'
import { useBus } from '@/useful/bus'
import buildInPlugins from './build-in'
import store from '@/store'
import * as tree from './tree'
import * as statusBar from './status-bar'
import * as view from './view'
import * as markdown from './markdown'
export type HookType = 'ON_STARTUP' | tree.HookType | view.HookType
export interface Plugin {
name: string;
register?: (ctx: Ctx) => void;
}
export type HookFun = (...args: any[]) => boolean | void | Promise<boolean | void>
const logger = getLogger('plugin')
const bus = useBus()
const plugins: {[name: string]: Plugin} = {}
const hooks: { [key in HookType]?: {fun: HookFun; once: boolean}[] } = {}
const ctx = {
bus,
store,
shortcut,
registerHook: (type: HookType, fun: HookFun, once = false) => {
if (Array.isArray(hooks[type])) {
hooks[type] = [...hooks[type]!!, { fun, once }]
} else {
hooks[type] = [{ fun, once }]
}
},
removeHook: (type: HookType, fun: HookFun) => {
if (Array.isArray(hooks[type])) {
hooks[type] = hooks[type]!!.filter(x => x.fun !== fun)
}
},
triggerHook: async (type: HookType, ...args: any[]) => {
logger.debug('triggerHook', type, args)
for (const { fun, once } of (hooks[type] || [])) {
once && ctx.removeHook(type, fun)
if (await fun(...args)) {
return true
}
}
return false
},
markdown: markdown.ctx,
statusBar: statusBar.ctx
}
export type Ctx = typeof ctx;
export const register = (plugin: Plugin) => {
logger.debug('register', plugin)
plugins[plugin.name] = plugin
plugin.register && plugin.register(ctx)
}
export const init = () => {
logger.debug('init')
buildInPlugins.forEach((plugin) => {
if (plugin.__esModule && plugin.default) {
register(plugin.default)
} else {
register(plugin)
}
})
}
export const triggerHook = ctx.triggerHook
init()
+11
View File
@@ -0,0 +1,11 @@
import Markdown from 'markdown-it'
const markdownItPlugins: {plugin: any; params: any}[] = []
export const getPlugins = () => markdownItPlugins
export const ctx = {
registerPlugin: (plugin: (md: Markdown, ...args: any) => void, params?: any) => {
markdownItPlugins.push({ plugin, params })
}
}
+37
View File
@@ -0,0 +1,37 @@
import { useBus } from '@/useful/bus'
const bus = useBus()
export type MenuItem = {
id: string;
type: 'normal';
title: string;
tips?: string;
onClick?: (item: MenuItem) => void;
}
export interface Menu {
id: string;
title: string;
tips?: string;
position: 'left' | 'right';
onClick?: (menu: Menu) => void;
list?: (MenuItem | { type: 'separator' })[];
}
const menus: { [key: string]: Menu } = {}
export const getMenus = (position: string) =>
Object.values(menus).filter(x => x.position === position)
export const ctx = {
getMenus,
updateMenu: (menu: Menu) => {
menus[menu.id] = menu
bus.emit('status-bar-menu-update', menu)
},
removeMenu: (id: string) => {
delete menus[id]
bus.emit('status-bar-menu-update')
},
}
+1
View File
@@ -0,0 +1 @@
export type HookType = 'ON_TREE_NODE_SELECT'
+7
View File
@@ -0,0 +1,7 @@
export type HookType = 'ON_VIEW_ELEMENT_CLICK'
| 'ON_VIEW_KEY_DOWN'
| 'ON_VIEW_RENDER'
| 'ON_VIEW_RENDERED'
| 'ON_VIEW_MOUNTED'
| 'ON_VIEW_FILE_CHANGE'
| 'ON_VIEW_BEFORE_CONVERT'