mirror of
https://github.com/purocean/yn.git
synced 2026-09-24 15:46:02 +08:00
refactor: 重构代码目录,规范事件和Action
This commit is contained in:
+5
-6
@@ -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
@@ -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
@@ -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 = () => {
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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,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)
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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} = {}
|
||||
|
||||
|
||||
@@ -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 || ''
|
||||
}
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
},
|
||||
|
||||
@@ -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))) {
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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?.()
|
||||
}
|
||||
@@ -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()
|
||||
@@ -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)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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(`})\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)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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,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')
|
||||
|
||||
@@ -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,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 {
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,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'
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
// Process 
|
||||
// ^^^^^^^^ this size specification
|
||||
|
||||
import { Plugin } from '@fe/context/plugin'
|
||||
import { Plugin } from '@fe/context'
|
||||
|
||||
'use strict'
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,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) => {
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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,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 => {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,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'
|
||||
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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,4 +1,4 @@
|
||||
import { Plugin } from '@fe/context/plugin'
|
||||
import { Plugin } from '@fe/context'
|
||||
|
||||
export default {
|
||||
name: 'status-bar-tool',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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')
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)}`
|
||||
@@ -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)
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@@ -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;
|
||||
@@ -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'
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user