mirror of
https://github.com/purocean/yn.git
synced 2026-10-12 23:31:39 +08:00
重构插件代码
This commit is contained in:
@@ -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'
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
})
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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'])
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
})
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
@@ -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'),
|
||||
]
|
||||
@@ -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()
|
||||
@@ -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 })
|
||||
}
|
||||
}
|
||||
@@ -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')
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export type HookType = 'ON_TREE_NODE_SELECT'
|
||||
@@ -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'
|
||||
Reference in New Issue
Block a user