refactor: 重构代码目录,规范事件和Action

This commit is contained in:
purocean
2021-10-26 15:58:20 +08:00
parent caad48426c
commit 15ce89353f
102 changed files with 662 additions and 640 deletions
+5 -6
View File
@@ -5,13 +5,12 @@
"entryPointStrategy": "expand",
"readme": "none",
"entryPoints": [
"src/renderer/core",
"src/renderer/context",
"src/renderer/support/api.ts",
"src/renderer/support/bus.ts",
"src/renderer/support/types.ts",
"src/renderer/support/modal.ts",
"src/renderer/support/toast.ts",
"src/renderer/utils"
"src/renderer/support",
"src/renderer/services",
"src/renderer/utils",
"src/renderer/types.ts"
],
"exclude": [
"src/renderer/utils/fuzzy-match.ts"
+3 -3
View File
@@ -221,13 +221,13 @@ function run (type) {
switch (type) {
case 'md5':
output.value = CryptoJS.MD5(input.value).toString().toLowerCase()
output.value = ctx.lib.cryptojs.MD5(input.value).toString().toLowerCase()
break
case 'sha1':
output.value = CryptoJS.SHA1(input.value).toString().toLowerCase()
output.value = ctx.lib.cryptojs.SHA1(input.value).toString().toLowerCase()
break
case 'sha256':
output.value = CryptoJS.SHA256(input.value).toString().toLowerCase()
output.value = ctx.lib.cryptojs.SHA256(input.value).toString().toLowerCase()
break
}
output.focus()
+1 -1
View File
@@ -167,7 +167,7 @@ const showSetting = () => {
}
showWindow()
win.webContents.executeJavaScript('window.ctx.action.getActionHandler("status-bar.show-setting")();', true)
win.webContents.executeJavaScript('window.ctx.setting.showSettingPanel();', true)
}
const serve = () => {
+1 -1
View File
@@ -12,7 +12,7 @@
<script lang="ts">
import { defineComponent, nextTick, onBeforeUnmount, onMounted, ref } from 'vue'
import { Components } from '@fe/support/types'
import type { Components } from '@fe/types'
export default defineComponent({
name: 'context-menu',
+4 -4
View File
@@ -7,10 +7,10 @@
<script lang="ts">
import { defineComponent, nextTick, onBeforeMount, onMounted, ref, toRefs, watch } from 'vue'
import { useStore } from 'vuex'
import { useBus } from '@fe/support/bus'
import { isEncrypted, saveDoc, toUri } from '@fe/context/document'
import { whenEditorReady } from '@fe/context/editor'
import type { Doc } from '@fe/support/types'
import { useBus } from '@fe/core/bus'
import { isEncrypted, saveDoc, toUri } from '@fe/services/document'
import { whenEditorReady } from '@fe/services/editor'
import type { Doc } from '@fe/types'
import MonacoEditor from './MonacoEditor.vue'
export default defineComponent({
+7 -7
View File
@@ -59,11 +59,11 @@
<script lang="ts">
import { useStore } from 'vuex'
import { computed, defineComponent, reactive, ref, toRefs } from 'vue'
import { isElectron, nodeRequire } from '@fe/utils/env'
import { getActionHandler } from '@fe/context/action'
import { FLAG_DEMO } from '@fe/support/global-args'
import { triggerHook } from '@fe/context/plugin'
import { useToast } from '@fe/support/toast'
import { isElectron, nodeRequire } from '@fe/support/env'
import { getContentHtml } from '@fe/services/view'
import { FLAG_DEMO } from '@fe/support/args'
import { triggerHook } from '@fe/core/plugin'
import { useToast } from '@fe/support/ui/toast'
import { sleep } from '@fe/utils'
import XMask from './Mask.vue'
@@ -180,7 +180,7 @@ export default defineComponent({
const source = convert.fromType === 'markdown'
? currentFile.value.content
: getActionHandler('view.get-content-html')().replace(/src="api/g, `src="${baseUrl}api`)
: getContentHtml().replace(/src="api/g, `src="${baseUrl}api`)
convert.fileName = `${fileName.value}.${convert.toType}`
convert.source = filterHtml(source)
@@ -192,7 +192,7 @@ export default defineComponent({
async function ok () {
try {
await exportDoc()
} catch (error) {
} catch (error: any) {
toast.show('warning', error.message)
throw error
}
+5 -5
View File
@@ -5,11 +5,11 @@
<script lang="ts">
import { useStore } from 'vuex'
import { computed, defineComponent, onBeforeMount, onBeforeUnmount, ref, toRefs, watch } from 'vue'
import { Alt, Ctrl } from '@fe/context/shortcut'
import { Components, Doc } from '@fe/support/types'
import { useBus } from '@fe/support/bus'
import { ensureCurrentFileSaved, isEncrypted, isSubOrSameFile, switchDoc, toUri } from '@fe/context/document'
import { registerAction, removeAction } from '@fe/context/action'
import { Alt, Ctrl } from '@fe/core/shortcut'
import type { Components, Doc } from '@fe/types'
import { useBus } from '@fe/core/bus'
import { ensureCurrentFileSaved, isEncrypted, isSubOrSameFile, switchDoc, toUri } from '@fe/services/document'
import { registerAction, removeAction } from '@fe/core/action'
import Tabs from './Tabs.vue'
const blankUri = toUri(null)
+3 -3
View File
@@ -6,11 +6,11 @@
<script lang="ts">
import { computed, defineComponent, onMounted, onUnmounted, ref } from 'vue'
import { switchDoc } from '@fe/context/document'
import { switchDoc } from '@fe/services/document'
import XMask from './Mask.vue'
import { registerAction, removeAction } from '@fe/context/action'
import { registerAction, removeAction } from '@fe/core/action'
import QuickOpen from './QuickOpen.vue'
import { CtrlCmd } from '@fe/context/shortcut'
import { CtrlCmd } from '@fe/core/shortcut'
export default defineComponent({
name: 'x-filter',
+4 -4
View File
@@ -33,10 +33,10 @@
<script lang="ts">
import { defineComponent, onBeforeUnmount, onMounted, ref, toRefs } from 'vue'
import { useStore } from 'vuex'
import { useBus } from '@fe/support/bus'
import { $args, FLAG_DISABLE_XTERM } from '@fe/support/global-args'
import { emitResize } from '@fe/context/layout'
import { isElectron } from '@fe/utils/env'
import { useBus } from '@fe/core/bus'
import { $args, FLAG_DISABLE_XTERM } from '@fe/support/args'
import { emitResize } from '@fe/services/layout'
import { isElectron } from '@fe/support/env'
let resizeOrigin: any = null
+1 -1
View File
@@ -18,7 +18,7 @@
<script lang="ts">
import { defineComponent, nextTick, ref } from 'vue'
import XMask from './Mask.vue'
import { Components } from '@fe/support/types'
import type { Components } from '@fe/types'
type ModalType = '' | 'confirm' | 'input'
+3 -3
View File
@@ -5,9 +5,9 @@
<script lang="ts">
import type * as monaco from 'monaco-editor'
import { defineComponent, onMounted, ref } from 'vue'
import { defaultOptions } from '@fe/context/editor'
import { toUri } from '@fe/context/document'
import { useBus } from '@fe/support/bus'
import { defaultOptions } from '@fe/services/editor'
import { toUri } from '@fe/services/document'
import { useBus } from '@fe/core/bus'
const models: {[key: string]: monaco.editor.ITextModel} = {}
+7 -10
View File
@@ -43,12 +43,13 @@ import { debounce } from 'lodash-es'
import { useStore } from 'vuex'
import { computed, defineComponent, nextTick, onBeforeUnmount, onMounted, ref, toRefs, watch } from 'vue'
import { extname } from '@fe/utils/path'
import { isElectron } from '@fe/utils/env'
import { markdown } from '@fe/context/markdown'
import { triggerHook } from '@fe/context/plugin'
import { useBus } from '@fe/support/bus'
import { getActionHandler, registerAction, removeAction } from '@fe/context/action'
import { revealLineInCenter } from '@fe/context/editor'
import { isElectron } from '@fe/support/env'
import { markdown } from '@fe/services/markdown'
import { triggerHook } from '@fe/core/plugin'
import { useBus } from '@fe/core/bus'
import { registerAction, removeAction } from '@fe/core/action'
import { revealLineInCenter } from '@fe/services/editor'
import { showExport } from '@fe/services/document'
import Render from './Render.vue'
import SvgIcon from './SvgIcon.vue'
@@ -196,10 +197,6 @@ export default defineComponent({
window.print()
}
function showExport () {
getActionHandler('doc.show-export')()
}
function getContentHtml () {
return refView.value?.outerHTML || ''
}
+1 -1
View File
@@ -49,7 +49,7 @@ import { debounce } from 'lodash-es'
import { computed, defineComponent, nextTick, onMounted, ref, toRefs, watch } from 'vue'
import { useStore } from 'vuex'
import * as api from '@fe/support/api'
import fuzzyMatch from '@fe/utils/fuzzy-match'
import fuzzyMatch from '@fe/others/fuzzy-match'
type TabKey = 'marked' | 'search' | 'file'
+3 -3
View File
@@ -14,9 +14,9 @@ import { useStore } from 'vuex'
import { computed, defineComponent, onMounted, ref } from 'vue'
import { JSONEditor } from '@json-editor/json-editor'
import * as api from '@fe/support/api'
import { useToast } from '@fe/support/toast'
import { getThemeName, setTheme } from '@fe/context/theme'
import { fetchSettings, getSchema, writeSettings } from '@fe/context/setting'
import { useToast } from '@fe/support/ui/toast'
import { getThemeName, setTheme } from '@fe/services/theme'
import { fetchSettings, getSchema, writeSettings } from '@fe/services/setting'
JSONEditor.defaults.language = 'zh'
JSONEditor.defaults.languages.zh = { ...JSONEditor.defaults.languages.en }
+2 -2
View File
@@ -26,8 +26,8 @@
<script lang="ts">
import { defineComponent, onBeforeUnmount, ref } from 'vue'
import { getMenus, MenuItem } from '@fe/context/status-bar'
import { hookAction } from '@fe/context/action'
import { hookAction } from '@fe/core/action'
import { getMenus, MenuItem } from '@fe/services/status-bar'
import SvgIcon from './SvgIcon.vue'
export default defineComponent({
+2 -2
View File
@@ -20,8 +20,8 @@
<script lang="ts">
import Sortable from 'sortablejs'
import { computed, defineComponent, nextTick, onMounted, ref, watch } from 'vue'
import { useContextMenu } from '@fe/support/context-menu'
import { Components } from '@fe/support/types'
import { useContextMenu } from '@fe/support/ui/context-menu'
import type { Components } from '@fe/types'
import SvgIcon from './SvgIcon.vue'
export default defineComponent({
+3 -3
View File
@@ -31,10 +31,10 @@
<script lang="ts">
import { computed, defineComponent, onBeforeUnmount, onMounted, ref, toRefs, watch } from 'vue'
import { useStore } from 'vuex'
import { isElectron, isMacOS, nodeRequire } from '@fe/utils/env'
import { isEncrypted } from '@fe/context/document'
import { isElectron, isMacOS, nodeRequire } from '@fe/support/env'
import { isEncrypted } from '@fe/services/document'
import SvgIcon from './SvgIcon.vue'
import { Doc } from '@fe/support/types'
import type { Doc } from '@fe/types'
export default defineComponent({
name: 'title-bar',
+1 -1
View File
@@ -4,7 +4,7 @@
<script lang="ts">
import { defineComponent, ref } from 'vue'
import { Components } from '@fe/support/types'
import type { Components } from '@fe/types'
interface ToastData {
type: Components.Toast.ToastType;
+5 -9
View File
@@ -6,7 +6,7 @@
</template>
</aside>
<aside v-else class="side">
<div class="add-repo-btn" @click="showSetting">
<div class="add-repo-btn" @click="showSettingPanel">
添加仓库
<div class="add-repo-desc">选择一个位置保存笔记</div>
</div>
@@ -16,10 +16,10 @@
<script lang="ts">
import { computed, defineComponent, onBeforeMount, toRefs, watch } from 'vue'
import { useStore } from 'vuex'
import { useContextMenu } from '@fe/support/context-menu'
import { getActionHandler } from '@fe/context/action'
import { refreshRepo, refreshTree } from '@fe/context/tree'
import { useContextMenu } from '@fe/support/ui/context-menu'
import { refreshRepo, refreshTree } from '@fe/services/tree'
import TreeNode from './TreeNode.vue'
import { showSettingPanel } from '@fe/services/setting'
export default defineComponent({
name: 'tree',
@@ -40,10 +40,6 @@ export default defineComponent({
])
}
function showSetting () {
getActionHandler('status-bar.show-setting')()
}
onBeforeMount(() => {
refreshTree()
})
@@ -56,7 +52,7 @@ export default defineComponent({
tree,
refreshRepo,
showContextMenu,
showSetting,
showSettingPanel,
hasRepo,
}
},
+7 -7
View File
@@ -32,12 +32,12 @@
<script lang="ts">
import { computed, defineComponent, nextTick, PropType, ref, toRefs, watch } from 'vue'
import { useStore } from 'vuex'
import { useContextMenu } from '@fe/support/context-menu'
import Extensions from '@fe/support/extensions'
import { triggerHook } from '@fe/context/plugin'
import { getContextMenuItems } from '@fe/context/tree'
import type { Components } from '@fe/support/types'
import { createDoc, openInOS, switchDoc } from '@fe/context/document'
import { useContextMenu } from '@fe/support/ui/context-menu'
import extensions from '@fe/others/extensions'
import { triggerHook } from '@fe/core/plugin'
import { getContextMenuItems } from '@fe/services/tree'
import type { Components } from '@fe/types'
import { createDoc, openInOS, switchDoc } from '@fe/services/document'
import SvgIcon from './SvgIcon.vue'
export default defineComponent({
@@ -69,7 +69,7 @@ export default defineComponent({
async function select (item: any) {
if (item.type !== 'dir') {
if (Extensions.supported(item.name)) {
if (extensions.supported(item.name)) {
switchDoc(item)
} else {
if (!(await triggerHook('ON_TREE_NODE_SELECT', item))) {
+5 -5
View File
@@ -13,12 +13,12 @@ import { defineComponent, nextTick, onBeforeMount, onBeforeUnmount, ref } from '
import { useStore } from 'vuex'
import { Terminal } from 'xterm'
import { FitAddon } from 'xterm-addon-fit'
import { useBus } from '@fe/support/bus'
import { $args, FLAG_DEMO, FLAG_DISABLE_XTERM } from '@fe/support/global-args'
import { toggleXterm } from '@fe/context/layout'
import { registerAction, removeAction } from '@fe/context/action'
import { useBus } from '@fe/core/bus'
import { $args, FLAG_DEMO, FLAG_DISABLE_XTERM } from '@fe/support/args'
import { toggleXterm } from '@fe/services/layout'
import { registerAction, removeAction } from '@fe/core/action'
import { getLogger } from '@fe/utils'
import { getColorScheme } from '@fe/context/theme'
import { getColorScheme } from '@fe/services/theme'
import { OneHalfLight, OneHalfDark } from 'xterm-theme'
import SvgIcon from './SvgIcon.vue'
+28 -24
View File
@@ -1,37 +1,32 @@
import { useBus } from '@fe/support/bus'
import { useToast } from '@fe/support/toast'
import { useModal } from '@fe/support/modal'
import store from '@fe/support/store'
import storage from '@fe/utils/storage'
import * as storage from '@fe/utils/storage'
import * as utils from '@fe/utils/index'
import * as env from '@fe/utils/env'
import * as plugin from '@fe/core/plugin'
import * as action from '@fe/core/action'
import * as shortcut from '@fe/core/shortcut'
import { useBus } from '@fe/core/bus'
import { useToast } from '@fe/support/ui/toast'
import { useModal } from '@fe/support/ui/modal'
import * as env from '@fe/support/env'
import store from '@fe/support/store'
import * as api from '@fe/support/api'
import * as doc from '@fe/services/document'
import * as view from '@fe/services/view'
import * as tree from '@fe/services/tree'
import * as markdown from '@fe/services/markdown'
import * as statusBar from '@fe/services/status-bar'
import * as layout from '@fe/services/layout'
import * as editor from '@fe/services/editor'
import * as theme from '@fe/services/theme'
import * as setting from '@fe/services/setting'
import * as embed from '@fe/support/embed'
import * as lib from './lib'
import * as action from './action'
import * as doc from './document'
import * as shortcut from './shortcut'
import * as view from './view'
import * as tree from './tree'
import * as markdown from './markdown'
import * as statusBar from './status-bar'
import * as layout from './layout'
import * as editor from './editor'
import * as theme from './theme'
import * as embed from './embed'
import * as setting from './setting'
export type CtxHookType = view.HookType | tree.HookType | doc.HookType
const bus = useBus()
const ctx = {
api,
bus,
store,
action,
doc,
shortcut,
ui: { useToast, useModal },
tree,
markdown,
statusBar,
@@ -45,8 +40,17 @@ const ctx = {
lib,
env,
utils,
bus: useBus(),
ui: { useToast, useModal },
registerHook: plugin.registerHook,
removeHook: plugin.removeHook,
triggerHook: plugin.triggerHook,
registerPlugin: plugin.register,
}
window.ctx = ctx
export type Ctx = typeof ctx
export type Plugin = plugin.Plugin<Ctx>
export default ctx
+2 -1
View File
@@ -1,3 +1,4 @@
export * as lodash from 'lodash-es'
export * as vue from 'vue'
export { default as crypto } from 'crypto-js'
export { default as dayjs } from 'dayjs'
export { default as cryptojs } from 'crypto-js'
-24
View File
@@ -1,24 +0,0 @@
import { getActionHandler } from './action'
export type HookType = 'ON_VIEW_ELEMENT_CLICK'
| 'ON_VIEW_ELEMENT_DBCLICK'
| 'ON_VIEW_KEY_DOWN'
| 'ON_VIEW_SCROLL'
| 'ON_VIEW_RENDER'
| 'ON_VIEW_RENDERED'
| 'ON_VIEW_MOUNTED'
| 'ON_VIEW_FILE_CHANGE'
export type ActionName = 'view.refresh' | 'view.reveal-line' | 'view.scroll-top-to' | 'view.get-content-html'
export function refresh () {
getActionHandler('view.refresh')()
}
export function revealLine (line: number) {
getActionHandler('view.reveal-line')(line)
}
export function scrollTopTo (top: number) {
getActionHandler('view.scroll-top-to')(top)
}
@@ -1,16 +1,15 @@
import { getLogger } from '@fe/utils'
import { useBus } from '@fe/support/bus'
import type { ActionName as ViewActionName } from './view'
import type { ActionName as LayoutActionName } from './layout'
import type { ActionName as StatusBarActionName } from './status-bar'
import type { ActionName as TreeActionName } from './tree'
import type { ActionName as DocActionName } from './document'
import type { ActionName as EditorActionName } from './editor'
import { useBus } from '@fe/core/bus'
import { BuildInActionName } from '@fe/types'
import { registerCommand, removeCommand } from './shortcut'
const logger = getLogger('action')
const bus = useBus()
export type ActionHandler = ((...args: any[]) => any)
export type ActionName = BuildInActionName
export type HookType = 'before-run' | 'after-run'
export interface Action {
name: string,
keys?: null | (string | number)[]
@@ -18,17 +17,13 @@ export interface Action {
when?: () => boolean
}
export type ActionHandler = ((...args: any[]) => any)
export type ActionName = ViewActionName | LayoutActionName | StatusBarActionName | TreeActionName | DocActionName | EditorActionName
export type HookType = 'before-run' | 'after-run'
export const actions: { [id: string]: Action } = {}
export function hookAction (type: HookType, name: ActionName, handler: (payload: any) => void): () => void
export function hookAction (type: HookType, name: string, handler: (payload: any) => void): () => void
export function hookAction (type: HookType, name: string, handler: (payload: any) => void) {
bus.on(`action.${type}.${name}`, handler)
return () => bus.off(`action.${type}.${name}`, handler)
bus.on(`action.${type}.${name}` as any, handler)
return () => bus.off(`action.${type}.${name}` as any, handler)
}
export function registerAction (action: Action) {
@@ -50,7 +45,7 @@ export function getActionHandler (name: string): ActionHandler
export function getActionHandler (name: string) {
logger.debug('getActionHandler', name)
return (...args: any[]) => {
bus.emit(`action.before-run.${name}`, args)
bus.emit(`action.before-run.${name}` as any, args)
let result: any
@@ -61,7 +56,7 @@ export function getActionHandler (name: string) {
}
}
bus.emit(`action.after-run.${name}`, result)
bus.emit(`action.after-run.${name}` as any, result)
return result
}
}
+43
View File
@@ -0,0 +1,43 @@
import type { BuildInEvents } from '@fe/types'
import mitt, { Emitter, WildcardHandler } from 'mitt'
const emitter = mitt()
// debug
// emitter.on('*', (type, payload) => {
// console.log('debug bus >', type, payload)
// })
export type BuildInEventType = keyof BuildInEvents
export type Handler<T = any> = (event: T) => void;
export type BuildInEventTypeWithoutPayload = { [K in keyof BuildInEvents]: BuildInEvents[K] extends never ? K : never }[keyof BuildInEvents]
export type BuildInEventTypeWithPayload = keyof Omit<BuildInEvents, BuildInEventTypeWithoutPayload>
export interface XEmitter extends Emitter {
once<T extends BuildInEventType>(type: T, handler: Handler<BuildInEvents[T]>): void;
once(type: '*', handler: WildcardHandler): void;
on<T extends BuildInEventType>(type: T, handler: Handler<BuildInEvents[T]>): void;
on(type: '*', handler: WildcardHandler): void;
off<T extends BuildInEventType>(type: T, handler: Handler<BuildInEvents[T]>): void;
off(type: '*', handler: WildcardHandler): void;
emit<T extends BuildInEventTypeWithPayload>(type: T, event: BuildInEvents[T]): void;
emit<T extends BuildInEventTypeWithoutPayload>(type: T): void;
emit(type: '*', event?: any): void;
}
(emitter as any).once = (type: any, handler: any) => {
const wrappedHandler = (evt: any) => {
handler(evt)
emitter.off(type, wrappedHandler)
}
emitter.on(type, wrappedHandler)
}
export function useBus () {
return emitter as XEmitter
}
export default function install () {
window.globalBus = emitter
}
@@ -1,15 +1,10 @@
import type { HookType } from '@fe/types'
import { getLogger } from '@fe/utils'
import buildInPlugins from './build-in-plugins'
import context, { CtxHookType } from './index'
const logger = getLogger('plugin')
const ctx = { ...context, registerHook, removeHook, triggerHook }
export type Ctx = typeof ctx;
export type HookType = 'ON_STARTUP' | 'ON_PASTE_IMAGE' | CtxHookType
export type HookFun = (...args: any[]) => boolean | void | Promise<boolean | void>
export interface Plugin {
export interface Plugin<Ctx = any> {
name: string;
register?: (ctx: Ctx) => void;
}
@@ -34,7 +29,7 @@ export function removeHook (type: HookType, fun: HookFun) {
export async function triggerHook (type: HookType, ...args: any[]) {
logger.debug('triggerHook', type, args)
for (const { fun, once } of (hooks[type] || [])) {
once && ctx.removeHook(type, fun)
once && removeHook(type, fun)
if (await fun(...args)) {
return true
}
@@ -43,24 +38,22 @@ export async function triggerHook (type: HookType, ...args: any[]) {
return false
}
export function register (plugin: Plugin) {
export function register <Ctx> (plugin: Plugin, ctx: Ctx) {
logger.debug('register', plugin)
plugins[plugin.name] = plugin
plugin.register && plugin.register(ctx)
}
function init () {
export function init <Ctx> (plugins: Plugin[], ctx: Ctx) {
logger.debug('init')
buildInPlugins.forEach((plugin) => {
register(plugin)
plugins.forEach((plugin) => {
register(plugin, ctx)
})
window.registerPlugin = register
window.registerPlugin = (plugin: Plugin) => register(plugin, ctx)
const script = window.document.createElement('script')
script.src = '/api/plugins'
window.document.body.appendChild(script)
}
init()
@@ -1,6 +1,6 @@
import { upperFirst } from 'lodash-es'
import { getLogger } from '@fe/utils'
import { isMacOS } from '@fe/utils/env'
import { isMacOS } from '@fe/support/env'
import { getActionHandler } from './action'
const logger = getLogger('shortcut')
@@ -100,7 +100,7 @@ export function isCommand (e: KeyboardEvent | MouseEvent, id: string) {
export function runCommand (command: Command) {
if (typeof command.handler === 'string') {
return getActionHandler(command.handler)()
return getActionHandler(command.handler as any)()
} else {
return command.handler?.()
}
+8 -8
View File
@@ -1,14 +1,14 @@
import './support/demo'
import '@fe/others/demo'
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import App from '@fe/App.vue'
import router from '@fe/router'
import store from './support/store'
import bus from './support/bus'
import toast from './support/toast'
import modal from './support/modal'
import contextmenu from './support/context-menu'
import bus from '@fe/core/bus'
import store from '@fe/support/store'
import toast from '@fe/support/ui/toast'
import modal from '@fe/support/ui/modal'
import contextmenu from '@fe/support/ui/context-menu'
const app = createApp(App)
@@ -1,7 +1,7 @@
import { setTheme } from '@fe/context/theme'
import storage from '@fe/utils/storage'
import { FLAG_DEMO } from './global-args'
import { useToast } from './toast'
import { setTheme } from '@fe/services/theme'
import * as storage from '@fe/utils/storage'
import { FLAG_DEMO } from '@fe/support/args'
import { useToast } from '@fe/support/ui/toast'
if (FLAG_DEMO) {
storage.clear()
+4 -7
View File
@@ -1,14 +1,11 @@
import { Plugin, Ctx } from '@fe/context/plugin'
import { hasCtrlCmd } from '@fe/context/shortcut'
import { encodeMarkdownLink } from '@fe/utils'
import { copyText } from '@fe/support/copy-text'
import { Plugin } from '@fe/context'
import { hasCtrlCmd } from '@fe/core/shortcut'
import { copyText, encodeMarkdownLink } from '@fe/utils'
import store from '@fe/support/store'
export default {
name: 'copy-text',
register: (ctx: Ctx) => {
ctx.action.registerAction({ name: 'app.copy-text', handler: copyText })
register: (ctx) => {
ctx.registerHook('ON_VIEW_ELEMENT_CLICK', async (e: MouseEvent) => {
const target = e.target as HTMLElement
@@ -1,5 +1,5 @@
import type { Plugin, Ctx } from '@fe/context/plugin'
import type { Doc } from '@fe/support/types'
import type { Plugin, Ctx } from '@fe/context'
import type { BuildInActionName, Doc } from '@fe/types'
export default {
name: 'document-history-stack',
@@ -7,8 +7,8 @@ export default {
let stack: Doc[] = []
let idx = -1
const backId = 'plugin.document-history-stack.back'
const forwardId = 'plugin.document-history-stack.forward'
const backId: BuildInActionName = 'plugin.document-history-stack.back'
const forwardId: BuildInActionName = 'plugin.document-history-stack.forward'
function go (offset: number) {
const index = idx + offset
@@ -46,7 +46,7 @@ export default {
subTitle: ctx.shortcut.getKeysLabel(backId),
onClick: () => ctx.action.getActionHandler(backId)()
},
].concat(list.filter(x => ![forwardId, backId].includes(x.id)) as any)
].concat(list.filter(x => ![forwardId, backId].includes(x.id as BuildInActionName)) as any)
}
})
}
@@ -57,7 +57,7 @@ export default {
updateMenu()
}
ctx.bus.on('doc.switched', (file?: Doc) => {
ctx.bus.on('doc.switched', (file?: Doc | null) => {
if (file) {
if (!ctx.doc.isSameFile(stack[idx], file)) {
stack.splice(idx + 1, stack.length)
+5 -5
View File
@@ -1,13 +1,13 @@
import dayjs from 'dayjs'
import { insert, whenEditorReady } from '@fe/context/editor'
import type { Plugin } from '@fe/context/plugin'
import { insert, whenEditorReady } from '@fe/services/editor'
import type { Plugin } from '@fe/context'
import * as api from '@fe/support/api'
import store from '@fe/support/store'
import { encodeMarkdownLink } from '@fe/utils'
import { Doc } from '@fe/support/types'
import type { Doc } from '@fe/types'
import { dirname, isBelongTo, join, relative } from '@fe/utils/path'
import { getActionHandler } from '@fe/context/action'
import { refreshTree } from '@fe/context/tree'
import { getActionHandler } from '@fe/core/action'
import { refreshTree } from '@fe/services/tree'
async function uploadFile (file: any, asImage: boolean) {
if (!store.state.currentFile) {
+2 -2
View File
@@ -1,7 +1,7 @@
/* eslint-disable no-template-curly-in-string */
import dayjs from 'dayjs'
import { getMonaco, insert, whenEditorReady } from '@fe/context/editor'
import type { Plugin } from '@fe/context/plugin'
import { getMonaco, insert, whenEditorReady } from '@fe/services/editor'
import type { Plugin } from '@fe/context'
function createDependencyProposals (range: any) {
const monaco = getMonaco()
+6 -5
View File
@@ -1,7 +1,8 @@
import TurndownService from 'turndown'
import { getEditor, insert } from '@fe/context/editor'
import { Plugin, triggerHook } from '@fe/context/plugin'
import { refreshTree } from '@fe/context/tree'
import { getEditor, insert } from '@fe/services/editor'
import { Plugin } from '@fe/context'
import { triggerHook } from '@fe/core/plugin'
import { refreshTree } from '@fe/services/tree'
import * as api from '@fe/support/api'
import store from '@fe/support/store'
import { encodeMarkdownLink, fileToBase64URL } from '@fe/utils'
@@ -33,7 +34,7 @@ async function pasteImage (file: File, asBase64: boolean) {
throw new Error('当前未打开文件')
}
if (!(await triggerHook('ON_PASTE_IMAGE', file))) {
if (!(await triggerHook('ON_EDITOR_PASTE_IMAGE', file))) {
const { repo, path } = store.state.currentFile
const { relativePath } = await api.upload(repo, path, file)
insert(`![图片](${encodeMarkdownLink(relativePath)})\n`)
@@ -80,7 +81,7 @@ export default {
const pasteRtfActionId = 'plugin.editor-paste.insert-rtf'
const getClipboardContent = async (callback: (type: string, getType: (type: string) => Promise<Blob>) => Promise<void>) => {
const result = await navigator.permissions.query({ name: 'clipboard-read' })
const result = await navigator.permissions.query({ name: 'clipboard-read' as any })
if (result.state === 'denied') {
ctx.ui.useToast().show('warning', '请授予剪切板权限')
@@ -1,5 +1,5 @@
import { Plugin, Ctx } from '@fe/context/plugin'
import { FLAG_DISABLE_XTERM } from '@fe/support/global-args'
import { Plugin, Ctx } from '@fe/context'
import { FLAG_DISABLE_XTERM } from '@fe/support/args'
export default {
name: 'markdown-link',
@@ -48,8 +48,8 @@ export default {
...(isMarkdown ? [
{ id: 'create', label: '当前目录创建新文件', onClick: () => ctx.doc.createDoc({ repo: node.repo }, node) }
] : []),
{ id: 'copy-name', label: '复制名称', onClick: () => ctx.action.getActionHandler('app.copy-text')(node.name) },
{ id: 'copy-name', label: '复制路径', onClick: () => ctx.action.getActionHandler('app.copy-text')(node.path) }
{ id: 'copy-name', label: '复制名称', onClick: () => ctx.utils.copyText(node.name) },
{ id: 'copy-name', label: '复制路径', onClick: () => ctx.utils.copyText(node.path) }
] as typeof items)
})
}
+4 -4
View File
@@ -1,5 +1,5 @@
import { Plugin, Ctx } from '@fe/context/plugin'
import { FLAG_DEMO } from '@fe/support/global-args'
import { Plugin, Ctx } from '@fe/context'
import { FLAG_DEMO } from '@fe/support/args'
export default {
name: 'image-hosting-picgo',
@@ -42,7 +42,7 @@ export default {
if (!url) {
ctx.ui.useToast().show('warning', '请先配置 PicGo 图床接口地址')
ctx.action.getActionHandler('status-bar.show-setting')()
ctx.setting.showSettingPanel()
throw new Error('未配置 PicGo 图床上传地址')
}
@@ -77,7 +77,7 @@ export default {
}
})
ctx.registerHook('ON_PASTE_IMAGE', async (file: File) => {
ctx.registerHook('ON_EDITOR_PASTE_IMAGE', async (file: File) => {
if (!ctx.setting.getSettings()[settingKeyPaste]) {
return false
}
+1 -1
View File
@@ -1,6 +1,6 @@
import { debounce } from 'lodash-es'
import Viewer from 'viewerjs'
import type { Plugin } from '@fe/context/plugin'
import type { Plugin } from '@fe/context'
import 'viewerjs/dist/viewer.css'
let viewer: any
+4 -7
View File
@@ -1,9 +1,8 @@
import { h } from 'vue'
import CryptoJS from 'crypto-js'
import dayjs from 'dayjs'
import Markdown from 'markdown-it'
import { Plugin } from '@fe/context/plugin'
import { IFrame } from '@fe/context/embed'
import { Plugin } from '@fe/context'
import { IFrame } from '@fe/support/embed'
import { md5 } from '@fe/utils'
const MarkdownItPlugin = (md: Markdown) => {
const temp = md.renderer.rules.fence!.bind(md.renderer.rules)
@@ -16,7 +15,7 @@ const MarkdownItPlugin = (md: Markdown) => {
return temp(tokens, idx, options, env, slf)
}
const hash = CryptoJS.MD5(code).toString()
const hash = md5(code)
const appletId = `applet-${hash}-${idx}`
const appletTitle = firstLine.replace('<!--', '').replace('-->', '').replace('--applet--', '').trim()
@@ -40,8 +39,6 @@ const MarkdownItPlugin = (md: Markdown) => {
onLoad (iframe: HTMLIFrameElement) {
const win = iframe.contentWindow as any
win.appletId = appletId
win.CryptoJS = CryptoJS
win.dayjs = dayjs
win.init?.()
win.resize()
},
+1 -1
View File
@@ -1,5 +1,5 @@
import { h, VNode } from 'vue'
import { Plugin } from '@fe/context/plugin'
import { Plugin } from '@fe/context'
import SvgIcon from '@fe/components/SvgIcon.vue'
export default {
@@ -1,5 +1,5 @@
import Highlight from 'highlight.js'
import { Plugin, Ctx } from '@fe/context/plugin'
import { Plugin, Ctx } from '@fe/context'
import { getLogger } from '@fe/utils'
const logger = getLogger('markdown-code')
+6 -6
View File
@@ -1,12 +1,12 @@
import { computed, defineComponent, getCurrentInstance, h, onBeforeUnmount, ref, VNode, watch } from 'vue'
import CryptoJS from 'crypto-js'
import Markdown from 'markdown-it'
import { Plugin } from '@fe/context/plugin'
import { getActionHandler } from '@fe/context/action'
import { Plugin } from '@fe/context'
import { getActionHandler } from '@fe/core/action'
import * as api from '@fe/support/api'
import { FLAG_DISABLE_XTERM } from '@fe/support/global-args'
import { FLAG_DISABLE_XTERM } from '@fe/support/args'
import SvgIcon from '@fe/components/SvgIcon.vue'
import { CtrlCmd, getKeyLabel, matchKeys } from '@fe/context/shortcut'
import { CtrlCmd, getKeyLabel, matchKeys } from '@fe/core/shortcut'
import { md5 } from '@fe/utils'
const cache: Record<string, string> = {}
@@ -22,7 +22,7 @@ const RunCode = defineComponent({
setup (props) {
const instance = getCurrentInstance()
const result = ref('')
const hash = computed(() => CryptoJS.MD5(props.code).toString())
const hash = computed(() => md5(props.code))
const id = Date.now()
let hasResult = false
+1 -1
View File
@@ -1,6 +1,6 @@
import MarkdownItContainer from 'markdown-it-container'
import { h } from 'vue'
import { Plugin } from '@fe/context/plugin'
import { Plugin } from '@fe/context'
import type Token from 'markdown-it/lib/token'
export default {
+4 -4
View File
@@ -1,10 +1,10 @@
import Markdown from 'markdown-it'
import { defineComponent, h, ref, watch } from 'vue'
import { Plugin } from '@fe/context/plugin'
import { buildSrc, IFrame } from '@fe/context/embed'
import { Plugin } from '@fe/context'
import { buildSrc, IFrame } from '@fe/support/embed'
import * as api from '@fe/support/api'
import { useBus } from '@fe/support/bus'
import { openWindow } from '@fe/utils/env'
import { useBus } from '@fe/core/bus'
import { openWindow } from '@fe/support/env'
const Drawio = defineComponent({
name: 'drawio',
+5 -5
View File
@@ -1,12 +1,12 @@
import { h } from 'vue'
import * as echarts from 'echarts'
import CryptoJS from 'crypto-js'
import Markdown from 'markdown-it'
import { Plugin } from '@fe/context/plugin'
import { getColorScheme } from '@fe/context/theme'
import { Plugin } from '@fe/context'
import { getColorScheme } from '@fe/services/theme'
import { md5 } from '@fe/utils'
const render = (code: string) => {
const id = `echart-${CryptoJS.MD5(code).toString()}-${Math.random().toString(36).substr(2)}`
const id = `echart-${md5(code).toString()}-${Math.random().toString(36).substr(2)}`
return h(
'div', { class: 'echarts', id, 'data-code': encodeURIComponent(code) })
@@ -60,7 +60,7 @@ const update = (theme: string | undefined = undefined, animation: boolean | unde
charts[id] = { chart, img }
}
} catch (error) {
} catch (error: any) {
el.innerText = error
}
}
+1 -1
View File
@@ -6,7 +6,7 @@
// https://github.com/markdown-it/markdown-it-footnote/blob/master/index.js
import { createVNode, Fragment } from 'vue'
import { Plugin } from '@fe/context/plugin'
import { Plugin } from '@fe/context'
// Process footnotes
//
+1 -1
View File
@@ -1,4 +1,4 @@
import { Plugin } from '@fe/context/plugin'
import { Plugin } from '@fe/context'
import StateBlock from 'markdown-it/lib/rules_block/state_block'
import StateInline from 'markdown-it/lib/rules_inline/state_inline'
import Token from 'markdown-it/lib/token'
+1 -1
View File
@@ -6,7 +6,7 @@
// Process ![test]( x =100x200)
// ^^^^^^^^ this size specification
import { Plugin } from '@fe/context/plugin'
import { Plugin } from '@fe/context'
'use strict'
+1 -1
View File
@@ -14,7 +14,7 @@ for rendering output.
import katex from 'katex'
import { h } from 'vue'
import { Plugin } from '@fe/context/plugin'
import { Plugin } from '@fe/context'
// Test if potential opening or closing delimieter
// Assumes that there is a "$" at state.src[pos]
+4 -4
View File
@@ -1,11 +1,11 @@
import StateCore from 'markdown-it/lib/rules_core/state_core'
import Token from 'markdown-it/lib/token'
import { Plugin, Ctx } from '@fe/context/plugin'
import { Plugin } from '@fe/context'
import store from '@fe/support/store'
import { sleep } from '@fe/utils'
import { isElectron, nodeRequire } from '@fe/utils/env'
import { isElectron, nodeRequire } from '@fe/support/env'
import { basename, dirname, join } from '@fe/utils/path'
import { switchDoc } from '@fe/context/document'
import { switchDoc } from '@fe/services/document'
const handleLink = (link: HTMLAnchorElement) => {
const { currentFile } = store.state
@@ -144,7 +144,7 @@ function convertLink (state: StateCore) {
export default {
name: 'markdown-link',
register: (ctx: Ctx) => {
register: (ctx) => {
ctx.registerHook('ON_VIEW_ELEMENT_CLICK', async (e: MouseEvent) => {
const target = e.target as HTMLElement
+8 -9
View File
@@ -1,19 +1,18 @@
import { defineComponent, h, ref, watch } from 'vue'
import Markdown from 'markdown-it'
import { Plugin } from '@fe/context/plugin'
import { Plugin } from '@fe/context'
import { getLogger } from '@fe/utils'
import { Doc } from '@fe/support/types'
import { useModal } from '@fe/support/modal'
import { useToast } from '@fe/support/toast'
import type { Doc } from '@fe/types'
import { useModal } from '@fe/support/ui/modal'
import { useToast } from '@fe/support/ui/toast'
import { dirname, join } from '@fe/utils/path'
import { isElectron, openWindow } from '@fe/utils/env'
import { isElectron, openWindow } from '@fe/support/env'
import store from '@fe/support/store'
import * as api from '@fe/support/api'
import { refreshTree } from '@fe/context/tree'
import { buildSrc, IFrame } from '@fe/context/embed'
import { refreshTree } from '@fe/services/tree'
import { buildSrc, IFrame } from '@fe/support/embed'
import Mask from '@fe/components/Mask.vue'
import { FLAG_DEMO } from '@fe/support/global-args'
import { FLAG_DEMO } from '@fe/support/args'
const logger = getLogger('plugin-markdown-luckysheet')
+1 -1
View File
@@ -1,6 +1,6 @@
import Markdown from 'markdown-it'
import mermaid from 'mermaid/dist/mermaid.js'
import { Plugin } from '@fe/context/plugin'
import { Plugin } from '@fe/context'
import { h } from 'vue'
const mermaidChart: any = (code: string) => {
+7 -8
View File
@@ -1,12 +1,11 @@
import { defineComponent, h, onMounted, ref, watch } from 'vue'
import { debounce } from 'lodash-es'
import Renderer from 'markdown-it/lib/renderer'
import { Plugin } from '@fe/context/plugin'
import crypto from '@fe/utils/crypto'
import { dataURItoBlobLink } from '@fe/utils'
import { openWindow } from '@fe/utils/env'
import storage from '@fe/utils/storage'
import { buildSrc } from '@fe/context/embed'
import { Plugin } from '@fe/context'
import { dataURItoBlobLink, strToBase64 } from '@fe/utils'
import { openWindow } from '@fe/support/env'
import * as storage from '@fe/utils/storage'
import { buildSrc } from '@fe/support/embed'
const layoutStorageKey = 'mind-map-layout'
let links = ''
@@ -129,10 +128,10 @@ const render = async (ele: HTMLElement, content: string) => {
switch (type) {
case 'svg':
download('data:image/svg+xml;base64,' + crypto.strToBase64(await km.exportData('svg')), 'mindmap.svg')
download('data:image/svg+xml;base64,' + strToBase64(await km.exportData('svg')), 'mindmap.svg')
break
case 'km':
download('data:application/octet-stream;base64,' + crypto.strToBase64(await km.exportData('json')), 'mindmap.km')
download('data:application/octet-stream;base64,' + strToBase64(await km.exportData('json')), 'mindmap.km')
break
case 'png':
download(await km.exportData('png'), 'mindmap.png')
+1 -1
View File
@@ -3,7 +3,7 @@ import { debounce } from 'lodash-es'
import { defineComponent, h, nextTick, onMounted, reactive, ref, watch } from 'vue'
import Markdown from 'markdown-it'
import Token from 'markdown-it/lib/token'
import { Plugin } from '@fe/context/plugin'
import { Plugin } from '@fe/context'
const emptySrc = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs='
@@ -2,7 +2,7 @@ import { createVNode, Fragment, Comment, Text, VNode } from 'vue'
import Token from 'markdown-it/lib/token'
import Renderer from 'markdown-it/lib/renderer'
import { escapeHtml, unescapeAll } from 'markdown-it/lib/common/utils'
import { Plugin } from '@fe/context/plugin'
import { Plugin } from '@fe/context'
const attrNameReg = /^[a-zA-Z_:][a-zA-Z0-9:._-]*/
const defaultRules = {} as any
+1 -1
View File
@@ -1,4 +1,4 @@
import { Plugin } from '@fe/context/plugin'
import { Plugin } from '@fe/context'
import Renderer from 'markdown-it/lib/renderer'
const buildFunction = (className: string): Renderer.RenderRule => {
+2 -2
View File
@@ -1,8 +1,8 @@
import { Plugin, Ctx } from '@fe/context/plugin'
import { Plugin } from '@fe/context'
export default {
name: 'markdown-table',
register: (ctx: Ctx) => {
register: (ctx) => {
ctx.theme.addStyles(`
@media screen {
.markdown-view .markdown-body .table-wrapper {
+1 -1
View File
@@ -8,7 +8,7 @@
// https://github.com/blog/1825-task-lists-in-all-markdown-documents
import Markdown from 'markdown-it'
import { Plugin } from '@fe/context/plugin'
import { Plugin } from '@fe/context'
let disableCheckboxes = true
+2 -2
View File
@@ -2,8 +2,8 @@
import Markdown from 'markdown-it'
import StateInline from 'markdown-it/lib/rules_inline/state_inline'
import { getKeyLabel } from '@fe/context/shortcut'
import { Plugin } from '@fe/context/plugin'
import { getKeyLabel } from '@fe/core/shortcut'
import { Plugin } from '@fe/context'
import { injectLineNumbers } from './markdown-source-line'
+2 -2
View File
@@ -1,5 +1,5 @@
import { FLAG_DEMO, URL_GITHUB, URL_MAS } from '@fe/support/global-args'
import { Plugin } from '@fe/context/plugin'
import { FLAG_DEMO, URL_GITHUB, URL_MAS } from '@fe/support/args'
import { Plugin } from '@fe/context'
export default {
name: 'status-bar-get',
+3 -3
View File
@@ -1,6 +1,6 @@
import { showHelp } from '@fe/context/document'
import { Plugin } from '@fe/context/plugin'
import { Alt, getKeysLabel } from '@fe/context/shortcut'
import { showHelp } from '@fe/services/document'
import { Plugin } from '@fe/context'
import { Alt, getKeysLabel } from '@fe/core/shortcut'
export default {
name: 'status-bar-help',
@@ -1,6 +1,6 @@
import { Plugin } from '@fe/context/plugin'
import { getActionHandler } from '@fe/context/action'
import { getKeysLabel } from '@fe/context/shortcut'
import { Plugin } from '@fe/context'
import { getActionHandler } from '@fe/core/action'
import { getKeysLabel } from '@fe/core/shortcut'
export default {
name: 'status-bar-navigation',
@@ -1,46 +1,17 @@
import type { Plugin } from '@fe/context/plugin'
import type { Plugin } from '@fe/context'
export default {
name: 'status-bar-presentation',
register: ctx => {
const present = (flag: boolean) => {
if (flag) {
ctx.ui.useToast().show('info', '按下 Esc 键退出演示模式')
}
ctx.store.commit('setPresentation', flag)
setTimeout(() => {
ctx.bus.emit('global.resize')
}, 0)
}
const enterPresentation = ctx.action.registerAction({
name: 'status-bar.enter-presentation',
handler: () => present(true),
keys: ['F5']
})
ctx.action.registerAction({
name: 'status-bar.exit-presentation',
handler: () => present(false),
keys: [ctx.shortcut.Escape],
when: () => {
const el = window.document.activeElement
return ctx.store.state.presentation &&
el?.tagName !== 'INPUT' &&
el?.tagName !== 'TEXTAREA' &&
[...document.body.children] // 判断页面是否有浮层遮住
.filter(x => x.tagName === 'DIV' && x.clientWidth > 10 && x.clientHeight > 10)
.length < 2
}
})
const action = ctx.action.getAction('view.enter-presentation')
ctx.statusBar.tapMenus(menus => {
menus['status-bar-presentation'] = {
id: 'status-bar-presentation',
position: 'right',
tips: `预览 (${ctx.shortcut.getKeysLabel(enterPresentation.name)})`,
tips: `预览 (${ctx.shortcut.getKeysLabel(action!.name)})`,
icon: 'presentation',
onClick: () => present(true)
onClick: () => ctx.view.enterPresent()
}
})
}
+2 -2
View File
@@ -1,6 +1,6 @@
import { Plugin } from '@fe/context/plugin'
import { Plugin } from '@fe/context'
import store from '@fe/support/store'
import { getActionHandler } from '@fe/context/action'
import { getActionHandler } from '@fe/core/action'
export default {
name: 'status-bar-refresh',
@@ -1,9 +1,9 @@
import { Plugin } from '@fe/context/plugin'
import { Plugin } from '@fe/context'
import store from '@fe/support/store'
import { $args } from '@fe/support/global-args'
import { $args } from '@fe/support/args'
import { basename } from '@fe/utils/path'
import { switchDoc } from '@fe/context/document'
import { whenEditorReady } from '@fe/context/editor'
import { switchDoc } from '@fe/services/document'
import { whenEditorReady } from '@fe/services/editor'
export default {
name: 'status-bar-repository-switch',
+2 -7
View File
@@ -1,20 +1,15 @@
import store from '@fe/support/store'
import { Plugin } from '@fe/context/plugin'
import { Plugin } from '@fe/context'
export default {
name: 'status-bar-setting',
register: ctx => {
const showSetting = () => store.commit('setShowSetting', true)
ctx.action.registerAction({ name: 'status-bar.show-setting', handler: showSetting })
ctx.statusBar.tapMenus(menus => {
menus['status-bar-setting'] = {
id: 'status-bar-setting',
position: 'left',
tips: '设置',
icon: 'cog',
onClick: showSetting
onClick: ctx.setting.showSettingPanel
}
})
}
+2 -2
View File
@@ -1,5 +1,5 @@
import type { Plugin } from '@fe/context/plugin'
import { FLAG_DISABLE_XTERM } from '@fe/support/global-args'
import type { Plugin } from '@fe/context'
import { FLAG_DISABLE_XTERM } from '@fe/support/args'
export default {
name: 'status-bar-terminal',
+1 -1
View File
@@ -1,4 +1,4 @@
import { Plugin } from '@fe/context/plugin'
import { Plugin } from '@fe/context'
export default {
name: 'status-bar-tool',
+4 -4
View File
@@ -1,7 +1,7 @@
import { Plugin } from '@fe/context/plugin'
import { FLAG_DISABLE_XTERM } from '@fe/support/global-args'
import { getActionHandler } from '@fe/context/action'
import { getKeysLabel } from '@fe/context/shortcut'
import { Plugin } from '@fe/context'
import { FLAG_DISABLE_XTERM } from '@fe/support/args'
import { getActionHandler } from '@fe/core/action'
import { getKeysLabel } from '@fe/core/shortcut'
export default {
name: 'status-bar-view',
+3 -3
View File
@@ -1,10 +1,10 @@
import dayjs from 'dayjs'
import { getLineContent, replaceLine } from '@fe/context/editor'
import { Plugin, Ctx } from '@fe/context/plugin'
import { getLineContent, replaceLine } from '@fe/services/editor'
import { Plugin } from '@fe/context'
export default {
name: 'switch-todo',
register: (ctx: Ctx) => {
register: (ctx) => {
ctx.registerHook('ON_VIEW_ELEMENT_CLICK', async (e: MouseEvent) => {
const target = e.target as HTMLElement
+4 -4
View File
@@ -1,11 +1,11 @@
import { debounce } from 'lodash-es'
import type { Plugin, Ctx } from '@fe/context/plugin'
import type { Doc } from '@fe/support/types'
import type { Plugin } from '@fe/context'
import type { Doc } from '@fe/types'
import { sleep } from '@fe/utils'
export default {
name: 'sync-scroll',
register: (ctx: Ctx) => {
register: (ctx) => {
type ScrollTop = { editor?: number, view?: number }
const STORAGE_KEY = 'plugin.scroll-position'
@@ -29,7 +29,7 @@ export default {
}
// 切换文件后恢复滚动位置
ctx.bus.on('doc.switched', async (file?: Doc) => {
ctx.bus.on('doc.switched', async (file?: Doc | null) => {
if (file) {
await sleep(0)
+7 -7
View File
@@ -1,9 +1,9 @@
import { useModal } from '@fe/support/modal'
import { Plugin, Ctx } from '@fe/context/plugin'
import { hasCtrlCmd } from '@fe/context/shortcut'
import { getActionHandler } from '@fe/context/action'
import { useToast } from '@fe/support/toast'
import { getLineContent, replaceLine } from '@fe/context/editor'
import { useModal } from '@fe/support/ui/modal'
import { Plugin } from '@fe/context'
import { hasCtrlCmd } from '@fe/core/shortcut'
import { getActionHandler } from '@fe/core/action'
import { useToast } from '@fe/support/ui/toast'
import { getLineContent, replaceLine } from '@fe/services/editor'
const editTableCell = async (start: number, end: number, cellIndex: number, input: HTMLTextAreaElement | null) => {
const toast = useToast()
@@ -123,7 +123,7 @@ const editTableCell = async (start: number, end: number, cellIndex: number, inpu
export default {
name: 'table-cell-edit',
register: (ctx: Ctx) => {
register: (ctx) => {
const handleClick = async (e: MouseEvent, modal: boolean) => {
const target = e.target as HTMLElement
@@ -1,12 +1,13 @@
import mime from 'mime-types'
import * as api from '@fe/support/api'
import { encodeMarkdownLink } from '@fe/utils'
import { useToast } from '@fe/support/toast'
import { useToast } from '@fe/support/ui/toast'
import store from '@fe/support/store'
import { CtrlCmd, getKeysLabel, isCommand, LeftClick, Shift } from '@fe/context/shortcut'
import { replaceValue } from '@fe/context/editor'
import { Plugin, Ctx } from '@fe/context/plugin'
import { refreshTree } from '@fe/context/tree'
import { CtrlCmd, getKeysLabel, isCommand, LeftClick, Shift } from '@fe/core/shortcut'
import { replaceValue } from '@fe/services/editor'
import { Plugin } from '@fe/context'
import { refreshTree } from '@fe/services/tree'
import type { BuildInActionName } from '@fe/types'
async function transformImgOutLink (img: HTMLImageElement) {
const { currentFile } = store.state
@@ -54,8 +55,8 @@ async function transformImgOutLink (img: HTMLImageElement) {
return null
}
const actionKeydown = 'plugin.transform-img-link'
const actionClick = 'plugin.transform-img-link-by-click'
const actionKeydown: BuildInActionName = 'plugin.transform-img-link.all'
const actionClick: BuildInActionName = 'plugin.transform-img-link.single-by-click'
let refView: HTMLElement
async function transformAll () {
@@ -105,7 +106,7 @@ async function handleClick (e: MouseEvent) {
export default {
name: 'transform-img-out-link',
register: (ctx: Ctx) => {
register: (ctx) => {
ctx.action.registerAction({
name: actionKeydown,
keys: [CtrlCmd, Shift, 'l'],
@@ -1,28 +1,13 @@
import { Optional } from 'utility-types'
import Crypto from '@fe/utils/crypto'
import { useModal } from '@fe/support/modal'
import { useToast } from '@fe/support/toast'
import * as crypto from '@fe/utils/crypto'
import { useModal } from '@fe/support/ui/modal'
import { useToast } from '@fe/support/ui/toast'
import store from '@fe/support/store'
import type { Doc } from '@fe/support/types'
import type { Doc } from '@fe/types'
import { basename, dirname, isBelongTo, join } from '@fe/utils/path'
import { useBus } from '@fe/support/bus'
import { useBus } from '@fe/core/bus'
import * as api from '@fe/support/api'
import { getLogger } from '@fe/utils'
import { registerAction } from './action'
export type ActionName = 'doc.create'
| 'doc.create'
| 'doc.delete'
| 'doc.move'
| 'doc.mark'
| 'doc.unmark'
| 'doc.open-in-os'
| 'doc.save'
| 'doc.switch'
| 'doc.show-help'
| 'doc.show-export'
export type HookType = 'ON_DOC_BEFORE_EXPORT'
const logger = getLogger('document')
const bus = useBus()
@@ -32,7 +17,7 @@ function decrypt (content: any, password: string) {
throw new Error('未输入解密密码')
}
return Crypto.decrypt(content, password)
return crypto.decrypt(content, password)
}
function encrypt (content: any, password: string) {
@@ -40,7 +25,7 @@ function encrypt (content: any, password: string) {
throw new Error('未输入解密密码')
}
return Crypto.encrypt(content, password)
return crypto.encrypt(content, password)
}
async function inputPassword (title: string, filename: string, throwError = false) {
@@ -253,7 +238,7 @@ export async function saveDoc (doc: Doc, content: string) {
contentHash: hash,
status: 'saved'
})
bus.emit('doc.saved', store.state.currentFile)
bus.emit('doc.saved', store.state.currentFile!)
} catch (error: any) {
store.commit('setCurrentFile', { ...doc, status: 'save-failed' })
useToast().show('warning', error.message)
@@ -361,15 +346,3 @@ export async function showHelp (doc: string) {
export function showExport () {
store.commit('setShowExport', true)
}
registerAction({ name: 'doc.create', handler: createDoc })
registerAction({ name: 'doc.duplicate', handler: duplicateDoc })
registerAction({ name: 'doc.delete', handler: deleteDoc })
registerAction({ name: 'doc.move', handler: moveDoc })
registerAction({ name: 'doc.mark', handler: markDoc })
registerAction({ name: 'doc.unmark', handler: unmarkDoc })
registerAction({ name: 'doc.open-in-os', handler: openInOS })
registerAction({ name: 'doc.save', handler: saveDoc })
registerAction({ name: 'doc.switch', handler: switchDoc })
registerAction({ name: 'doc.show-help', handler: showHelp })
registerAction({ name: 'doc.show-export', handler: showExport })
@@ -1,12 +1,10 @@
import * as Monaco from 'monaco-editor'
import { $args } from '@fe/support/global-args'
import { isElectron } from '@fe/utils/env'
import { useBus } from '@fe/support/bus'
import { $args } from '@fe/support/args'
import { isElectron } from '@fe/support/env'
import { useBus } from '@fe/core/bus'
import { getColorScheme } from './theme'
import { registerAction } from './action'
import { Alt } from './shortcut'
export type ActionName = 'editor.toggle-wrap'
import { registerAction } from '../core/action'
import { Alt } from '../core/shortcut'
const bus = useBus()
@@ -135,7 +133,7 @@ bus.on('monaco.before-init', (payload: any) => {
})
})
bus.on('monaco.ready', (payload: any) => {
bus.on('monaco.ready', (payload) => {
monaco = payload.monaco
editor = payload.editor
@@ -1,12 +1,8 @@
import { nextTick } from 'vue'
import store from '@fe/support/store'
import { useBus } from '@fe/support/bus'
import { getActionHandler, registerAction } from './action'
import { Alt } from './shortcut'
export type ActionName = 'layout.toggle-view'
| 'layout.toggle-side'
| 'layout.toggle-xterm'
import { useBus } from '@fe/core/bus'
import { getActionHandler, registerAction } from '../core/action'
import { Alt } from '../core/shortcut'
const bus = useBus()
@@ -1,5 +1,6 @@
import * as api from '@fe/support/api'
import { FLAG_DISABLE_XTERM } from '@fe/support/global-args'
import { FLAG_DISABLE_XTERM } from '@fe/support/args'
import store from '@fe/support/store'
import { getThemeName } from './theme'
const schema = {
@@ -113,3 +114,11 @@ export async function writeSettings (value: Record<string, any>) {
export function getSettings () {
return settings
}
export function showSettingPanel () {
store.commit('setShowSetting', true)
}
export function hideSettingPanel () {
store.commit('setShowSetting', false)
}
@@ -1,7 +1,5 @@
import { debounce } from 'lodash-es'
import { getActionHandler } from './action'
export type ActionName = 'status-bar.show-setting' | 'status-bar.refresh-menu'
import { getActionHandler } from '../core/action'
export type MenuItem = {
id: string;
@@ -1,5 +1,6 @@
import { useBus } from '@fe/support/bus'
import storage from '@fe/utils/storage'
import { useBus } from '@fe/core/bus'
import type { ThemeName } from '@fe/types'
import * as storage from '@fe/utils/storage'
const bus = useBus()
@@ -23,7 +24,7 @@ export function getColorScheme () {
return theme
}
export function setTheme (name: 'system' | 'dark' | 'light') {
export function setTheme (name: ThemeName) {
document.documentElement.setAttribute('app-theme', name)
bus.emit('theme.change', name)
storage.set('app.theme', name)
@@ -1,10 +1,8 @@
import type { Ref } from 'vue'
import type { Components } from '@fe/support/types'
import type { Components } from '@fe/types'
import store from '@fe/support/store'
import { registerAction } from './action'
import { registerAction } from '../core/action'
export type ActionName = 'tree.refresh'
export type HookType = 'ON_TREE_NODE_SELECT'
export type MenuItem = Components.ContextMenu.Item
export type VueCtx = { localMarked: Ref<boolean | null> }
export type BuildContextMenu = (items: MenuItem[], node: Components.Tree.Node, vueCtx: VueCtx) => void
+60
View File
@@ -0,0 +1,60 @@
import { useBus } from '@fe/core/bus'
import { Escape } from '@fe/core/shortcut'
import { getActionHandler, registerAction } from '@fe/core/action'
import { useToast } from '@fe/support/ui/toast'
import store from '@fe/support/store'
function present (flag: boolean) {
if (flag) {
useToast().show('info', '按下 Esc 键退出演示模式')
}
store.commit('setPresentation', flag)
setTimeout(() => {
useBus().emit('global.resize')
}, 0)
}
export function refresh () {
getActionHandler('view.refresh')()
}
export function revealLine (line: number) {
getActionHandler('view.reveal-line')(line)
}
export function scrollTopTo (top: number) {
getActionHandler('view.scroll-top-to')(top)
}
export function getContentHtml () {
return getActionHandler('view.get-content-html')()
}
export function enterPresent () {
getActionHandler('view.enter-presentation')()
}
export function exitPresent () {
getActionHandler('view.exit-presentation')()
}
registerAction({
name: 'view.enter-presentation',
handler: () => present(true),
keys: ['F5']
})
registerAction({
name: 'view.exit-presentation',
handler: () => present(false),
keys: [Escape],
when: () => {
const el = window.document.activeElement
return store.state.presentation &&
el?.tagName !== 'INPUT' &&
el?.tagName !== 'TEXTAREA' &&
[...document.body.children] // 判断页面是否有浮层遮住
.filter(x => x.tagName === 'DIV' && x.clientWidth > 10 && x.clientHeight > 10)
.length < 2
}
})
@@ -1,16 +1,52 @@
import { useBus } from '@fe/support/bus'
import { isElectron, nodeRequire } from '@fe/utils/env'
import { triggerHook } from '@fe/context/plugin'
import store, { getLastOpenFile } from '@fe/support/store'
import { Doc } from '@fe/support/types'
import { hasCtrlCmd } from './shortcut'
import { showHelp, switchDoc, unmarkDoc } from './document'
import { refreshTree } from './tree'
import { getSelectionInfo, whenEditorReady } from './editor'
import { fetchSettings } from './setting'
import { useBus } from '@fe/core/bus'
import { isElectron, nodeRequire } from '@fe/support/env'
import { init, triggerHook } from '@fe/core/plugin'
import store from '@fe/support/store'
import * as storage from '@fe/utils/storage'
import { basename } from '@fe/utils/path'
import type { Doc } from '@fe/types'
import { hasCtrlCmd } from '@fe/core/shortcut'
import { showHelp, switchDoc, unmarkDoc } from '@fe/services/document'
import { refreshTree } from '@fe/services/tree'
import { getSelectionInfo, whenEditorReady } from '@fe/services/editor'
import { fetchSettings } from '@fe/services/setting'
import plugins from '@fe/plugins'
import ctx from '@fe/context'
init(plugins, ctx)
const bus = useBus()
function getLastOpenFile (repoName?: string) {
const currentFile = storage.get('currentFile')
const recentOpenTime = storage.get('recentOpenTime', {}) as {[key: string]: number}
repoName ??= storage.get('currentRepo')?.name
if (!repoName) {
return null
}
if (currentFile && currentFile.repo === repoName) {
return currentFile
}
const item = Object.entries(recentOpenTime)
.filter(x => x[0].startsWith(repoName + '|'))
.sort((a, b) => b[1] - a[1])[0]
if (!item) {
return null
}
const path = item[0].split('|', 2)[1]
if (!path) {
return null
}
return { repo: repoName, name: basename(path), path }
}
export default function startup () {
triggerHook('ON_STARTUP')
+5 -6
View File
@@ -1,10 +1,9 @@
import { slugify } from 'transliteration'
import { basename, relative, extname, join, dirname } from '@fe/utils/path'
import { fileToBase64URL } from '@fe/utils'
import { isElectron } from '@fe/utils/env'
import Crypto from '@fe/utils/crypto'
import { Doc } from './types'
import { FLAG_DEMO } from './global-args'
import { binMd5, fileToBase64URL } from '@fe/utils'
import { isElectron } from '@fe/support/env'
import { Doc } from '@fe/types'
import { FLAG_DEMO } from './args'
async function fetchHttp (input: RequestInfo, init?: RequestInit) {
const response = await fetch(input, init)
@@ -129,7 +128,7 @@ export async function upload (repo: string, belongPath: string, uploadFile: any,
}
const fileBase64Url = await fileToBase64URL(uploadFile)
const filename = name || Crypto.binMd5(fileBase64Url).substr(0, 8) + extname(uploadFile.name)
const filename = name || binMd5(fileBase64Url).substr(0, 8) + extname(uploadFile.name)
const formData = new FormData()
const dirName = slugify(basename(belongPath))
-29
View File
@@ -1,29 +0,0 @@
import mitt, { Emitter, EventType, Handler, WildcardHandler } from 'mitt'
const emitter = mitt()
// debug
// emitter.on('*', (type, payload) => {
// console.log('debug bus >', type, payload)
// })
export interface XEmitter extends Emitter {
once<T = any>(type: EventType, handler: Handler<T>): void;
once(type: '*', handler: WildcardHandler): void;
}
(emitter as any).once = (type: any, handler: any) => {
const wrappedHandler = (evt: any) => {
handler(evt)
emitter.off(type, wrappedHandler)
}
emitter.on(type, wrappedHandler)
}
export function useBus () {
return emitter as XEmitter
}
export default function install () {
window.globalBus = emitter
}
-23
View File
@@ -1,23 +0,0 @@
import { useToast } from '@fe/support/toast'
export function copyText (text?: string) {
if (text === undefined) {
return
}
const toast = useToast()
const textarea = document.createElement('textarea')
textarea.style.position = 'absolute'
textarea.style.background = 'red'
textarea.style.left = '-999999px'
textarea.style.top = '-999999px'
textarea.style.zIndex = '-1000'
textarea.style.opacity = '0'
textarea.value = text
document.body.appendChild(textarea)
textarea.select()
document.execCommand('copy')
document.body.removeChild(textarea)
toast.show('info', '已复制')
}
@@ -1,6 +1,6 @@
import { debounce } from 'lodash-es'
import { defineComponent, h, IframeHTMLAttributes, onBeforeMount, onBeforeUnmount, PropType, ref, watch } from 'vue'
import { useBus } from '@fe/support/bus'
import { useBus } from '@fe/core/bus'
export function buildSrc (html: string, title = '', globalStyle = false) {
return `/embed/#title=${encodeURIComponent(title)}&with-global-style=${globalStyle}&html=${encodeURIComponent(html)}`
+15 -45
View File
@@ -1,57 +1,27 @@
import { omit } from 'lodash-es'
import { createStore } from 'vuex'
import Storage from '@fe/utils/storage'
import { basename } from '@fe/utils/path'
import * as storage from '@fe/utils/storage'
import * as api from '@fe/support/api'
import { Doc } from './types'
export const getLastOpenFile = (repoName?: string) => {
const currentFile = Storage.get('currentFile')
const recentOpenTime = Storage.get('recentOpenTime', {}) as {[key: string]: number}
repoName ??= Storage.get('currentRepo')?.name
if (!repoName) {
return null
}
if (currentFile && currentFile.repo === repoName) {
return currentFile
}
const item = Object.entries(recentOpenTime)
.filter(x => x[0].startsWith(repoName + '|'))
.sort((a, b) => b[1] - a[1])[0]
if (!item) {
return null
}
const path = item[0].split('|', 2)[1]
if (!path) {
return null
}
return { repo: repoName, name: basename(path), path }
}
import type { Doc } from '@fe/types'
export default createStore({
state: {
repositories: {} as any,
tree: null,
showSide: Storage.get('showSide', true),
showView: Storage.get('showView', true),
showEditor: Storage.get('showEditor', true),
showSide: storage.get('showSide', true),
showView: storage.get('showView', true),
showEditor: storage.get('showEditor', true),
showXterm: false,
autoPreview: true,
showSetting: false,
showExport: false,
presentation: false,
currentContent: '',
currentRepo: Storage.get('currentRepo'),
currentRepo: storage.get('currentRepo'),
currentFile: null as Doc | null,
recentOpenTime: Storage.get('recentOpenTime', {}),
tabs: Storage.get('tabs', []),
recentOpenTime: storage.get('recentOpenTime', {}),
tabs: storage.get('tabs', []),
selectionInfo: {
textLength: 0,
selectedLength: 0,
@@ -73,15 +43,15 @@ export default createStore({
},
setShowView (state, data) {
state.showView = data
Storage.set('showView', data)
storage.set('showView', data)
},
setShowEditor (state, data) {
state.showEditor = data
Storage.set('showEditor', data)
storage.set('showEditor', data)
},
setShowSide (state, data) {
state.showSide = data
Storage.set('showSide', data)
storage.set('showSide', data)
},
setShowSetting (state, data) {
state.showSetting = data
@@ -97,7 +67,7 @@ export default createStore({
},
setTabs (state, data) {
state.tabs = data
Storage.set('tabs', data)
storage.set('tabs', data)
},
setShowXterm (state, data) {
state.showXterm = data
@@ -111,16 +81,16 @@ export default createStore({
setCurrentRepo (state, data) {
state.currentRepo = data
state.tree = null
Storage.set('currentRepo', data)
storage.set('currentRepo', data)
},
setCurrentFile (state, data: Doc | null) {
state.currentFile = data
Storage.set('currentFile', omit(data, 'content'))
storage.set('currentFile', omit(data, 'content'))
if (data) {
state.recentOpenTime = { ...(state.recentOpenTime || {}), [`${data.repo}|${data.path}`]: new Date().valueOf() }
Storage.set('recentOpenTime', state.recentOpenTime)
storage.set('recentOpenTime', state.recentOpenTime)
}
},
},
-71
View File
@@ -1,71 +0,0 @@
export interface Doc {
type: 'file' | 'dir';
name: string;
repo: string;
path: string;
content?: string;
title?: string;
passwordHash?: string;
contentHash?: string;
status?: 'loaded' | 'save-failed' | 'saved';
}
export namespace Components {
export namespace Modal {
export type ConfirmModalParams = { title?: string; content?: string }
export type InputModalParams = {
type?: string;
title?: string;
content?: string;
value?: string;
hint?: string;
modalWidth?: string;
select?: boolean | [number, number, 'forward' | 'backward' | 'none'];
}
}
export namespace Toast {
export type ToastType = 'warning' | 'info'
}
export namespace ContextMenu {
export type SeparatorItem = { type: 'separator' }
export type NormalItem = {
type?: 'normal';
id: string;
label: string;
onClick: (item?: NormalItem) => void;
}
export type Item = SeparatorItem | NormalItem
}
export namespace Tabs {
export interface Item {
key: string;
label: string;
description?: string;
payload: any;
fixed?: boolean;
}
}
export namespace FileTabs {
export interface Item extends Tabs.Item {
payload: {
file: Doc | null;
};
}
}
export namespace Tree {
export interface Node extends Pick<Doc, 'type' | 'name' | 'path' | 'repo'> {
mtime?: number;
birthtime?: number;
marked?: boolean;
children?: Node[];
}
}
}
@@ -1,8 +1,8 @@
import { App, ComponentPublicInstance, createApp } from 'vue'
import { Components } from '@fe/support/types'
import type { Components } from '@fe/types'
import Modal from '@fe/components/ContextMenu.vue'
interface Instance extends ComponentPublicInstance {
export interface Instance extends ComponentPublicInstance {
show: (menuItems: Components.ContextMenu.Item[]) => void;
}
@@ -1,5 +1,5 @@
import { App, ComponentPublicInstance, createApp } from 'vue'
import { Components } from '@fe/support/types'
import type { Components } from '@fe/types'
import Modal from '@fe/components/ModalUi.vue'
export interface Instance extends ComponentPublicInstance {
@@ -1,6 +1,6 @@
import { App, ComponentPublicInstance, createApp } from 'vue'
import Toast from '@fe/components/Toast.vue'
import { Components } from '@fe/support/types'
import { Components } from '@fe/types'
export interface Instance extends ComponentPublicInstance {
show: (type: Components.Toast.ToastType, content: string, timeout?: number) => void;
+135
View File
@@ -0,0 +1,135 @@
import type * as Monaco from 'monaco-editor'
export interface Doc {
type: 'file' | 'dir';
name: string;
repo: string;
path: string;
content?: string;
title?: string;
passwordHash?: string;
contentHash?: string;
status?: 'loaded' | 'save-failed' | 'saved';
}
export namespace Components {
export namespace Modal {
export type ConfirmModalParams = { title?: string; content?: string }
export type InputModalParams = {
type?: string;
title?: string;
content?: string;
value?: string;
hint?: string;
modalWidth?: string;
select?: boolean | [number, number, 'forward' | 'backward' | 'none'];
}
}
export namespace Toast {
export type ToastType = 'warning' | 'info'
}
export namespace ContextMenu {
export type SeparatorItem = { type: 'separator' }
export type NormalItem = {
type?: 'normal';
id: string;
label: string;
onClick: (item?: NormalItem) => void;
}
export type Item = SeparatorItem | NormalItem
}
export namespace Tabs {
export interface Item {
key: string;
label: string;
description?: string;
payload: any;
fixed?: boolean;
}
}
export namespace FileTabs {
export interface Item extends Tabs.Item {
payload: {
file: Doc | null;
};
}
}
export namespace Tree {
export interface Node extends Pick<Doc, 'type' | 'name' | 'path' | 'repo'> {
mtime?: number;
birthtime?: number;
marked?: boolean;
children?: Node[];
}
}
}
export type ThemeName = 'system' | 'dark' | 'light'
export type BuildInEvents = {
'global.resize': never,
'theme.change': ThemeName,
'monaco.change-value': { uri: string, value: string },
'monaco.before-init': { monaco: typeof Monaco },
'monaco.ready': { editor: Monaco.editor.IStandaloneCodeEditor, monaco: typeof Monaco },
'editor.ready': { editor: Monaco.editor.IStandaloneCodeEditor, monaco: typeof Monaco },
'editor.change': { uri: string, value: string },
'doc.created': Doc,
'doc.deleted': Doc,
'doc.moved': { oldDoc: Doc, newDoc: Doc },
'doc.saved': Doc,
'doc.switched': Doc | null,
'doc.switch-failed': { doc?: Doc | null, message: string },
'doc.changed': Doc,
}
export type HookType = 'ON_STARTUP'
| 'ON_EDITOR_PASTE_IMAGE'
| 'ON_VIEW_ELEMENT_CLICK'
| 'ON_VIEW_ELEMENT_DBCLICK'
| 'ON_VIEW_KEY_DOWN'
| 'ON_VIEW_SCROLL'
| 'ON_VIEW_RENDER'
| 'ON_VIEW_RENDERED'
| 'ON_VIEW_MOUNTED'
| 'ON_VIEW_FILE_CHANGE'
| 'ON_TREE_NODE_SELECT'
| 'ON_DOC_BEFORE_EXPORT'
export type BuildInActionName = 'view.refresh'
| 'view.reveal-line'
| 'view.scroll-top-to'
| 'view.get-content-html'
| 'view.enter-presentation'
| 'view.exit-presentation'
| 'layout.toggle-view'
| 'layout.toggle-side'
| 'layout.toggle-xterm'
| 'layout.toggle-editor'
| 'status-bar.refresh-menu'
| 'tree.refresh'
| 'editor.toggle-wrap'
| 'filter.show-quick-open'
| 'filter.choose-document'
| 'file-tabs.switch-left'
| 'file-tabs.switch-right'
| 'file-tabs.switch-next'
| 'xterm.run-code'
| 'xterm.run'
| 'xterm.init'
| 'plugin.document-history-stack.back'
| 'plugin.document-history-stack.forward'
| 'plugin.image-hosting-picgo.upload'
| 'plugin.status-bar-help.show-readme'
| 'plugin.status-bar-help.show-features'
| 'plugin.status-bar-help.show-shortcuts'
| 'plugin.transform-img-link.all'
| 'plugin.transform-img-link.single-by-click'
+3 -23
View File
@@ -1,6 +1,6 @@
import CryptoJS from 'crypto-js'
const getCryptKey = (password: string) => {
function getCryptKey (password: string) {
if (!password) {
throw new Error('未输入密码')
}
@@ -8,7 +8,7 @@ const getCryptKey = (password: string) => {
return CryptoJS.MD5(password).toString().substr(0, 16)
}
const encrypt = (content: any, password: string) => {
export function encrypt (content: any, password: string) {
let key: any = getCryptKey(password)
let iv: any = key
const passwordHash = CryptoJS.MD5(key).toString()
@@ -25,7 +25,7 @@ const encrypt = (content: any, password: string) => {
return { content: encrypted.toString(), passwordHash }
}
const decrypt = (content: any, password: string) => {
export function decrypt (content: any, password: string) {
let key: any = getCryptKey(password)
let iv: any = key
const passwordHash = CryptoJS.MD5(key).toString()
@@ -46,23 +46,3 @@ const decrypt = (content: any, password: string) => {
return { content: result, passwordHash }
}
const md5 = (content: any) => {
return CryptoJS.MD5(content).toString()
}
const binMd5 = (data: any) => {
return md5(CryptoJS.enc.Latin1.parse(data))
}
export const strToBase64 = (str: string) => {
return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(str))
}
export default {
encrypt,
decrypt,
md5,
binMd5,
strToBase64,
}
+37 -1
View File
@@ -1,5 +1,7 @@
import CryptoJS from 'crypto-js'
import { useToast } from '@fe/support/ui/toast'
export * as path from './path'
export * as env from './env'
export * as storage from './storage'
export * as crypto from './crypto'
@@ -62,3 +64,37 @@ export function objectInsertAfterKey (obj: {}, key: string, content: {}) {
}
return Object.fromEntries(items)
}
export function md5 (content: any) {
return CryptoJS.MD5(content).toString()
}
export function binMd5 (data: any) {
return md5(CryptoJS.enc.Latin1.parse(data))
}
export function strToBase64 (str: string) {
return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(str))
}
export function copyText (text?: string) {
if (text === undefined) {
return
}
const toast = useToast()
const textarea = document.createElement('textarea')
textarea.style.position = 'absolute'
textarea.style.background = 'red'
textarea.style.left = '-999999px'
textarea.style.top = '-999999px'
textarea.style.zIndex = '-1000'
textarea.style.opacity = '0'
textarea.value = text
document.body.appendChild(textarea)
textarea.select()
document.execCommand('copy')
document.body.removeChild(textarea)
toast.show('info', '已复制')
}

Some files were not shown because too many files have changed in this diff Show More