From fc2d74ef9fc68f3e2271c4b49a1d34b31182f9d1 Mon Sep 17 00:00:00 2001 From: purocean Date: Thu, 4 Jul 2024 14:20:36 +0800 Subject: [PATCH 01/27] docs: fix typo --- README.md | 2 +- README_ZH-CN.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5198397a1..50d7c4f48 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ For more information on how to use the following functions, please see [characte 6. feat: Support automatic scrolling to the bottom when running code. 7. feat: Automatically trigger Wiki link suggestions when typing `【【`. 8. feat: Other interaction experience optimizations and bug fixes. -9. dix: Disable automatic updates for the Windows zip version to avoid repeated upgrade failure issues. +9. fix: Disable automatic updates for the Windows zip version to avoid repeated upgrade failure issues. 10. feat(plugin): The `markdown-link` plugin exposes the `mdRuleConvertLink`, `htmlHandleLink` methods. 11. feat(plugin): `ctx.doc.switchDoc` adds more parameters, supporting jumping to a specified location. 12. feat(plugin): Add the `ctx.routines.changePosition` method to jump to a specified location in the current document. diff --git a/README_ZH-CN.md b/README_ZH-CN.md index 77a17f70e..6ff6dee40 100644 --- a/README_ZH-CN.md +++ b/README_ZH-CN.md @@ -88,7 +88,7 @@ 6. feat: 代码运行支持自动滚动到底部 7. feat: 输入 `【【` 时自动触发 Wiki 链接建议 8. feat: 其他交互体验优化和问题修复 -9. dix: Windows zip 版本禁用自动更新,避免反复升级失败问题 +9. fix: Windows zip 版本禁用自动更新,避免反复升级失败问题 10. feat(plugin): `markdown-link` 插件暴露 `mdRuleConvertLink`, `htmlHandleLink` 方法 11. feat(plugin): `ctx.doc.switchDoc` 增加更多参数,支持跳转到指定位置 12. feat(plugin): 增加 `ctx.routines.changePosition` 方法,用以跳转到当前文档的指定位置 From d98af31ba7a352a3414da626079a732032808bf8 Mon Sep 17 00:00:00 2001 From: purocean Date: Thu, 4 Jul 2024 18:30:43 +0800 Subject: [PATCH 02/27] feat: optimize history-stack logic --- src/renderer/plugins/history-stack.ts | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/renderer/plugins/history-stack.ts b/src/renderer/plugins/history-stack.ts index 1ec11b7d7..7fa374ea7 100644 --- a/src/renderer/plugins/history-stack.ts +++ b/src/renderer/plugins/history-stack.ts @@ -47,8 +47,19 @@ export default { function record (doc: Doc, position: PositionState | null) { const newState: State = { doc: { type: doc.type, repo: doc.repo, name: doc.name, path: doc.path }, position } - if (ctx.lib.lodash.isEqual(newState, stack[idx])) { - return + // check same doc + if (stack[idx] && ctx.doc.isSameFile(doc, stack[idx].doc)) { + if (position) { + // check same position + if (ctx.lib.lodash.isEqual(position, stack[idx].position)) { + return + } + } else { + // not special position, check if already has position + if (isScrollPosition(stack[idx].position)) { + return + } + } } stack.splice(idx + 1, stack.length) @@ -91,6 +102,10 @@ export default { return } + if (!doc && !opts?.position) { + return + } + const _doc = doc || ctx.store.state.currentFile if (!_doc) { return From 8a2bdf9c1820db27b2a9caae771062a12c53246f Mon Sep 17 00:00:00 2001 From: purocean Date: Fri, 5 Jul 2024 13:41:09 +0800 Subject: [PATCH 03/27] refactor: add plain-text renderer for .txt files --- src/renderer/plugins/build-in-renderers.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/renderer/plugins/build-in-renderers.ts b/src/renderer/plugins/build-in-renderers.ts index 685fb436a..c905f5691 100644 --- a/src/renderer/plugins/build-in-renderers.ts +++ b/src/renderer/plugins/build-in-renderers.ts @@ -39,5 +39,21 @@ export default { return ctx.lib.vue.h(ctx.embed.IFrame, { html: src, triggerParentKeyBoardEvent: true, iframeProps }) }, }) + + ctx.renderer.registerRenderer({ + name: 'plain-text', + when (env) { + return !!(env.file && env.file.path.toLowerCase().endsWith('.txt')) + }, + render (src) { + return ctx.lib.vue.h('div', { + style: { + padding: '20px', + whiteSpace: 'pre-wrap', + wordBreak: 'break-all', + }, + }, src) + }, + }) } } as Plugin From 9a851a3c0a91e0c09557c58852eb17b68aa77393 Mon Sep 17 00:00:00 2001 From: purocean Date: Fri, 5 Jul 2024 14:13:04 +0800 Subject: [PATCH 04/27] refactor: use MARKDOWN_FILE_EXT --- src/renderer/plugins/editor-path-completion.ts | 5 +++-- src/renderer/plugins/markdown-link.ts | 9 +++++---- src/renderer/plugins/markdown-macro.ts | 3 ++- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/renderer/plugins/editor-path-completion.ts b/src/renderer/plugins/editor-path-completion.ts index 8552fa67a..393cf1011 100644 --- a/src/renderer/plugins/editor-path-completion.ts +++ b/src/renderer/plugins/editor-path-completion.ts @@ -5,6 +5,7 @@ import type * as Monaco from 'monaco-editor' import type { Ctx, Plugin } from '@fe/context' import type { Components } from '@fe/types' import type Token from 'markdown-it/lib/token' +import { MARKDOWN_FILE_EXT } from '@share/misc' enum CompletionContextKind { Link, // [...](|) @@ -116,7 +117,7 @@ class CompletionProvider implements Monaco.languages.CompletionItemProvider { if (!isAnchorInCurrentDoc) { if (context.anchorInfo) { // Anchor to a different document const currentFile = this.ctx.store.state.currentFile - if (!currentFile || !context.anchorInfo.beforeAnchor.endsWith('.md')) { + if (!currentFile || !context.anchorInfo.beforeAnchor.endsWith(MARKDOWN_FILE_EXT)) { return { suggestions: [] } } @@ -253,7 +254,7 @@ class CompletionProvider implements Monaco.languages.CompletionItemProvider { let beforeAnchor = anchorMatch[1] if (anchorMatch[1] && !this.ctx.utils.path.extname(beforeAnchor)) { - beforeAnchor += '.md' + beforeAnchor += MARKDOWN_FILE_EXT } return { diff --git a/src/renderer/plugins/markdown-link.ts b/src/renderer/plugins/markdown-link.ts index 6a1dac5ab..0f303cd5d 100644 --- a/src/renderer/plugins/markdown-link.ts +++ b/src/renderer/plugins/markdown-link.ts @@ -12,6 +12,7 @@ import { getAllCustomEditors } from '@fe/services/editor' import { fetchTree } from '@fe/support/api' import type { Doc } from '@share/types' import type { Components, PositionState } from '@fe/types' +import { MARKDOWN_FILE_EXT } from '@share/misc' async function getFirstMatchPath (repo: string, dir: string, fileName: string) { if (fileName.includes('/')) { @@ -24,7 +25,7 @@ async function getFirstMatchPath (repo: string, dir: string, fileName: string) { if ( item.type === 'file' && (p === normalizeSep(join(dir, fileName)) || - p === normalizeSep(join(dir, `${fileName}.md`))) + p === normalizeSep(join(dir, fileName + MARKDOWN_FILE_EXT))) ) { return item.path } @@ -42,7 +43,7 @@ async function getFirstMatchPath (repo: string, dir: string, fileName: string) { const findByName = (items: Components.Tree.Node[]): string | null => { for (const item of items) { - if (item.type === 'file' && (item.name === fileName || item.name === `${fileName}.md`)) { + if (item.type === 'file' && (item.name === fileName || item.name === `${fileName}${MARKDOWN_FILE_EXT}`)) { return item.path } @@ -135,7 +136,7 @@ function handleLink (link: HTMLAnchorElement): boolean { path = normalizeSep(path) path = path.replace(/:/g, '/') // replace all ':' to '/' path = await getFirstMatchPath(fileRepo, dir, path) || path - path = path.endsWith('.md') ? path : `${path}.md` + path = path.endsWith(MARKDOWN_FILE_EXT) ? path : `${path}${MARKDOWN_FILE_EXT}` } if (!path.startsWith('/')) { // to absolute path @@ -211,7 +212,7 @@ function convertLink (state: StateCore) { if (isAnchor) { // keep markdown file. - if (fileName.endsWith('.md')) { + if (fileName.endsWith(MARKDOWN_FILE_EXT)) { return } diff --git a/src/renderer/plugins/markdown-macro.ts b/src/renderer/plugins/markdown-macro.ts index 699b26409..54c4b5d12 100644 --- a/src/renderer/plugins/markdown-macro.ts +++ b/src/renderer/plugins/markdown-macro.ts @@ -2,6 +2,7 @@ import { escapeRegExp, merge, omit } from 'lodash-es' import frontMatter from 'front-matter' import type { Plugin } from '@fe/context' import type { BuildInSettings, Doc } from '@fe/types' +import { MARKDOWN_FILE_EXT } from '@share/misc' import type { MenuItem } from '@fe/services/status-bar' import { render } from '@fe/services/view' import { t } from '@fe/services/i18n' @@ -207,7 +208,7 @@ async function include ( return { __macroResult: true, value: 'Error: $include maximum call stack size exceeded [3]' } } - if (!path.endsWith('.md')) { + if (!path.endsWith(MARKDOWN_FILE_EXT)) { return { __macroResult: true, value: 'Error: $include markdown file only' } } From 9e55edce704c4ed43072f22b3ddf3449e42e9850 Mon Sep 17 00:00:00 2001 From: purocean Date: Fri, 5 Jul 2024 17:05:31 +0800 Subject: [PATCH 05/27] feat: add `ctx.i18n.$$t` method --- src/renderer/services/i18n.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/renderer/services/i18n.ts b/src/renderer/services/i18n.ts index 11faaed98..cb018159c 100644 --- a/src/renderer/services/i18n.ts +++ b/src/renderer/services/i18n.ts @@ -24,6 +24,19 @@ export function t (path: MsgPath, ...args: string[]) { return translate(getCurrentLanguage(), path, ...args) } +/** + * Dynamic translate + * @param path + * @param args + * @returns + */ +export function $$t (path: MsgPath, ...args: string[]): string { + return Object.freeze({ + toString: () => t(path, ...args), + toJson: () => JSON.stringify(t(path, ...args)) + }) as any +} + /** * Get language * @returns From 7d788a41dba8c2b9674bc0d4eb243f9c375ccced Mon Sep 17 00:00:00 2001 From: purocean Date: Fri, 5 Jul 2024 18:06:42 +0800 Subject: [PATCH 06/27] feat: support register document type --- src/renderer/components/CreateFilePanel.vue | 82 ++++++++ src/renderer/components/FileTabs.vue | 6 +- src/renderer/components/GetStarted.vue | 4 +- src/renderer/components/QuickOpen.vue | 4 +- .../plugins/file-tree-context-menu.ts | 4 +- src/renderer/services/document.ts | 179 ++++++++++++++++-- src/renderer/types.ts | 17 ++ src/share/i18n/languages/en.ts | 4 +- src/share/i18n/languages/zh-CN.ts | 4 +- src/share/i18n/languages/zh-TW.ts | 4 +- 10 files changed, 275 insertions(+), 33 deletions(-) create mode 100644 src/renderer/components/CreateFilePanel.vue diff --git a/src/renderer/components/CreateFilePanel.vue b/src/renderer/components/CreateFilePanel.vue new file mode 100644 index 000000000..d3da8e370 --- /dev/null +++ b/src/renderer/components/CreateFilePanel.vue @@ -0,0 +1,82 @@ + + + + + diff --git a/src/renderer/components/FileTabs.vue b/src/renderer/components/FileTabs.vue index ec6a4d6b8..10451d6b0 100644 --- a/src/renderer/components/FileTabs.vue +++ b/src/renderer/components/FileTabs.vue @@ -21,7 +21,7 @@ import { Alt, CtrlCmd, getKeysLabel, Shift } from '@fe/core/keybinding' import type { Components, Doc, PathItem } from '@fe/types' import { registerHook, removeHook } from '@fe/core/hook' import { registerAction, removeAction } from '@fe/core/action' -import { isEncrypted, isMarkdownFile, isOutOfRepo, isSameFile, isSubOrSameFile, switchDoc, toUri } from '@fe/services/document' +import { isEncrypted, isOutOfRepo, isSameFile, isSubOrSameFile, supported, switchDoc, toUri } from '@fe/services/document' import store from '@fe/support/store' import { useI18n } from '@fe/services/i18n' import { FileTabs } from '@fe/services/workbench' @@ -152,7 +152,7 @@ export default defineComponent({ async function handleMoved (payload?: { oldDoc: Doc, newDoc: Doc }) { if (payload) { if ( - isMarkdownFile(payload.newDoc) && + supported(payload.newDoc) && isSameFile(payload.oldDoc, currentFile.value) ) { await switchFile(payload.newDoc) @@ -162,7 +162,7 @@ export default defineComponent({ } function handleDocCreated ({ doc }: { doc: Doc | null }) { - if (!doc || isMarkdownFile(doc)) { + if (!doc || supported(doc)) { switchFile(doc) } } diff --git a/src/renderer/components/GetStarted.vue b/src/renderer/components/GetStarted.vue index 05bdfdd98..6f1572158 100644 --- a/src/renderer/components/GetStarted.vue +++ b/src/renderer/components/GetStarted.vue @@ -76,7 +76,7 @@ import store from '@fe/support/store' import { showManager as showExtensionManager } from '@fe/others/extension' import { showPremium, getPurchased } from '@fe/others/premium' import { showSettingPanel } from '@fe/services/setting' -import { createDoc, isMarkdownFile, switchDoc } from '@fe/services/document' +import { createDoc, supported, switchDoc } from '@fe/services/document' import { getActionHandler } from '@fe/core/action' useI18n() @@ -89,7 +89,7 @@ const files = computed(() => { let tmp: any[] = [] tree.forEach((node: any) => { - if (isMarkdownFile(node)) { + if (supported(node)) { const time = map[`${node.repo}|${node.path}`] if (time) { tmp.push({ node, time }) diff --git a/src/renderer/components/QuickOpen.vue b/src/renderer/components/QuickOpen.vue index 7cd72d8c3..821d893d3 100644 --- a/src/renderer/components/QuickOpen.vue +++ b/src/renderer/components/QuickOpen.vue @@ -50,7 +50,7 @@ import { computed, defineComponent, nextTick, onMounted, ref, toRefs, watch } fr import { useI18n } from '@fe/services/i18n' import fuzzyMatch from '@fe/others/fuzzy-match' import { fetchSettings } from '@fe/services/setting' -import { isMarkdownFile, isMarked } from '@fe/services/document' +import { isMarked, supported } from '@fe/services/document' import store from '@fe/support/store' import { PathItem } from '@fe/types' @@ -101,7 +101,7 @@ export default defineComponent({ let tmp: any[] = [] tree.forEach((node: any) => { - if (isMarkdownFile(node)) { + if (supported(node)) { tmp.push(node) } diff --git a/src/renderer/plugins/file-tree-context-menu.ts b/src/renderer/plugins/file-tree-context-menu.ts index cb3a2a9bc..47e198ca5 100644 --- a/src/renderer/plugins/file-tree-context-menu.ts +++ b/src/renderer/plugins/file-tree-context-menu.ts @@ -89,12 +89,10 @@ export default { node.marked = vueCtx.localMarked.value } - const isMarkdown = ctx.doc.isMarkdownFile(node) - const t = ctx.i18n.t items.push(...[ - ...(isMarkdown ? [ + ...(ctx.doc.supported(node) ? [ { id: 'mark', label: node.marked ? t('tree.context-menu.unmark') : t('tree.context-menu.mark'), diff --git a/src/renderer/services/document.ts b/src/renderer/services/document.ts index 748087a6a..a2aa2c7fb 100644 --- a/src/renderer/services/document.ts +++ b/src/renderer/services/document.ts @@ -1,29 +1,36 @@ -import { Fragment, h } from 'vue' +import { Fragment, h, shallowRef } from 'vue' import AsyncLock from 'async-lock' import { cloneDeep } from 'lodash-es' import { Optional } from 'utility-types' import { URI } from 'monaco-editor/esm/vs/base/common/uri.js' +import * as ioc from '@fe/core/ioc' import * as misc from '@share/misc' import extensions from '@fe/others/file-extensions' 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, PathItem, SwitchDocOpts } from '@fe/types' +import { DocType, type Doc, type DocCategory, type PathItem, type SwitchDocOpts } from '@fe/types' import { basename, dirname, extname, isBelongTo, join, normalizeSep, relative, resolve } from '@fe/utils/path' import { getActionHandler } from '@fe/core/action' import { triggerHook } from '@fe/core/hook' import { FLAG_MAS, HELP_REPO_NAME } from '@fe/support/args' import * as api from '@fe/support/api' -import { getLogger } from '@fe/utils' +import { fileToBase64URL, getLogger } from '@fe/utils' import { isWindows } from '@fe/support/env' +import CreateFilePanel from '@fe/components/CreateFilePanel.vue' import { getAllRepos, getRepo, inputPassword, openPath, showItemInFolder } from './base' -import { t } from './i18n' +import { $$t, t } from './i18n' import { getSetting, setSetting } from './setting' const logger = getLogger('document') const lock = new AsyncLock() +const supportedExtensionCache = { + sortedExtensions: [] as string[], + types: new Map() +} + function decrypt (content: any, password: string) { if (!password) { throw new Error(t('no-password')) @@ -95,6 +102,10 @@ export function isMarkdownFile (doc: Doc) { return !!(doc && doc.type === 'file' && misc.isMarkdownFile(doc.path)) } +export function supported (doc: Doc) { + return !!(doc && doc.type === 'file' && supportedExtensionCache.sortedExtensions.some(x => doc.path.endsWith(x))) +} + /** * Check if the document is out of a repository. * @param doc @@ -169,29 +180,47 @@ export function toUri (doc?: PathItem | null): string { export async function createDoc (doc: Pick, baseDoc: Doc): Promise export async function createDoc (doc: Optional, 'path'>, baseDoc?: Doc): Promise export async function createDoc (doc: Optional, 'path'>, baseDoc?: Doc) { + const docType = shallowRef(null) + if (!doc.path) { if (baseDoc) { const currentPath = baseDoc.type === 'dir' ? baseDoc.path : dirname(baseDoc.path) - const newFilename = 'new.md' + const categories = getAllDocCategories() + const markdownCategory = categories.find(x => x.category === 'markdown') + const mdType = markdownCategory?.types.find(x => x.extension.includes(misc.MARKDOWN_FILE_EXT)) + docType.value = mdType + + const newFilename = 'new' let filename = await useModal().input({ title: t('document.create-dialog.title'), hint: t('document.create-dialog.hint'), - content: t('document.current-path', currentPath), + modalWidth: '600px', + component: () => h(CreateFilePanel, { + currentPath, + categories, + docType: docType.value, + onUpdateDocType: (value: DocType | null | undefined) => { + docType.value = value + } + }), value: newFilename, - select: [ - 0, - newFilename.lastIndexOf('.') > -1 ? newFilename.lastIndexOf('.') : newFilename.length, - 'forward' - ], + select: true, }) if (!filename) { return } - if (!misc.isMarkdownFile(filename)) { - filename = filename.replace(/\/$/, '') + misc.MARKDOWN_FILE_EXT + if (!docType.value) { + throw new Error('Need doc type') + } + + const ext = docType.value.extension[0] || '' + + filename = filename.replace(/\/$/, '') + if (!filename.endsWith(ext)) { + filename += ext } doc.path = join(currentPath, normalizeSep(filename)) @@ -203,13 +232,42 @@ export async function createDoc (doc: Optional }) if (doc) { - doc.plain = extensions.supported(doc.name) + doc.plain = !!(extensions.supported(doc.name) || resolveDocType(doc.name)?.type?.plain) doc.absolutePath = getAbsolutePath(doc) } @@ -825,3 +888,79 @@ export function showHistory (doc: Doc) { export function hideHistory () { getActionHandler('doc.hide-history')() } + +function cacheSupportedExtension () { + supportedExtensionCache.types.clear() + supportedExtensionCache.sortedExtensions = [] + + for (const category of getAllDocCategories()) { + for (const type of category.types) { + for (const ext of type.extension) { + supportedExtensionCache.types.set(ext, { type, category }) + supportedExtensionCache.sortedExtensions.push(ext) + } + } + } + + supportedExtensionCache.sortedExtensions.sort((a, b) => b.length - a.length) +} + +/** + * register document category + * @param docCategory + */ +export function registerDocCategory (docCategory: DocCategory) { + ioc.register('DOC_CATEGORIES', docCategory) + cacheSupportedExtension() +} + +/** + * remove document category + * @param category + */ +export function removeDocCategory (category: string) { + ioc.removeWhen('DOC_CATEGORIES', item => item.category === category) + cacheSupportedExtension() +} + +/** + * get all document categories + * @returns + */ +export function getAllDocCategories () { + return ioc.get('DOC_CATEGORIES') +} + +/** + * resolve document type + * @param filename + */ +export function resolveDocType (filename: string) { + const ext = supportedExtensionCache.sortedExtensions.find(ext => filename.endsWith(ext)) + return ext ? supportedExtensionCache.types.get(ext) : null +} + +registerDocCategory({ + category: 'markdown', + displayName: 'Markdown', + types: [ + { + id: 'markdown-md', + displayName: $$t('markdown-file'), + extension: [misc.MARKDOWN_FILE_EXT], + plain: true, + buildNewContent: filename => { + return `# ${filename.replace(/\.md$/i, '')}\n` + } + }, + { + id: 'markdown-encrypted-md', + displayName: $$t('encrypted-markdown-file'), + extension: [misc.ENCRYPTED_MARKDOWN_FILE_EXT], + plain: true, + buildNewContent: filename => { + return `# ${filename.replace(/\.md$/i, '')}\n` + } + }, + ] +}) diff --git a/src/renderer/types.ts b/src/renderer/types.ts index 1c6b4a7a2..f09704c22 100644 --- a/src/renderer/types.ts +++ b/src/renderer/types.ts @@ -523,6 +523,22 @@ export type Renderer = { render (src: string, env: RenderEnv): string | VNode | VNode[] } +type BuildNewContentResult = string | Blob | { base64Content: string } + +export type DocType = { + id: string, + extension: [string, ...string[]], + displayName: string, + plain?: boolean, + buildNewContent?: (filename: string) => Promise | BuildNewContentResult, +} + +export type DocCategory = { + category: string, + displayName: string, + types: DocType[], +} + export interface CodeRunner { name: string; order?: number; @@ -551,6 +567,7 @@ export type BuildInIOCTypes = { [key in keyof BuildInHookTypes]: any; } & { EDITOR_CUSTOM_EDITOR: CustomEditor, RENDERERS: Renderer, CODE_RUNNER: CodeRunner; + DOC_CATEGORIES: DocCategory } export type FrontMatterAttrs = { diff --git a/src/share/i18n/languages/en.ts b/src/share/i18n/languages/en.ts index abb98ea95..9f49da138 100644 --- a/src/share/i18n/languages/en.ts +++ b/src/share/i18n/languages/en.ts @@ -36,6 +36,8 @@ const data = { 'learn-more': 'Learn More', 'default': 'Default', 'print': 'Print', + 'markdown-file': 'Markdown File', + 'encrypted-markdown-file': 'Encrypted Markdown File', 'premium': { 'confetti': 'Confetti', 'need-purchase': '[%s] Premium is required', @@ -184,7 +186,7 @@ const data = { 'wrong-password': 'Wrong Password', 'file-transform-error': 'Encrypted and unencrypted files cannot be converted to each other', 'create-dialog': { - 'title': 'Create a file (encrypted file ends with .c.md)', + 'title': 'Create a file', 'hint': 'File name', }, 'create-dir-dialog': { diff --git a/src/share/i18n/languages/zh-CN.ts b/src/share/i18n/languages/zh-CN.ts index b1e5cfd84..4ba6b43e9 100644 --- a/src/share/i18n/languages/zh-CN.ts +++ b/src/share/i18n/languages/zh-CN.ts @@ -37,6 +37,8 @@ const data: BaseLanguage = { 'learn-more': '了解更多', 'default': '默认', 'print': '打印', + 'markdown-file': 'Markdown 文件', + 'encrypted-markdown-file': '加密的 Markdown 文件', 'premium': { 'confetti': '彩色纸屑', 'need-purchase': '[%s] 需要高级版', @@ -185,7 +187,7 @@ const data: BaseLanguage = { 'wrong-password': '密码错误', 'file-transform-error': '加密文件和非加密文件不能互相转换', 'create-dialog': { - 'title': '创建文件(加密文件以 .c.md 结尾)', + 'title': '创建文件', 'hint': '文件名', }, 'create-dir-dialog': { diff --git a/src/share/i18n/languages/zh-TW.ts b/src/share/i18n/languages/zh-TW.ts index 35e80a1c8..0e4218dc3 100644 --- a/src/share/i18n/languages/zh-TW.ts +++ b/src/share/i18n/languages/zh-TW.ts @@ -37,6 +37,8 @@ const data: BaseLanguage = { 'learn-more': '了解更多', 'default': '預設', 'print': '列印', + 'markdown-file': 'Markdown 檔案', + 'encrypted-markdown-file': '加密 Markdown 檔案', 'premium': { 'confetti': '彩色紙屑', 'need-purchase': '[%s] 需高級版', @@ -185,7 +187,7 @@ const data: BaseLanguage = { 'wrong-password': '密碼錯誤', 'file-transform-error': '加密文件和非加密文件不能互相轉換', 'create-dialog': { - 'title': '創建文件(加密文件以 .c.md 結尾)', + 'title': '創建文件', 'hint': '文件名', }, 'create-dir-dialog': { From 0111f7a317171d1894bd84079ff3cde0454d50c9 Mon Sep 17 00:00:00 2001 From: purocean Date: Fri, 5 Jul 2024 18:07:00 +0800 Subject: [PATCH 07/27] chore: bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d8c2c8a00..4e042b225 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "yank.note", - "version": "3.72.2", + "version": "3.73.0", "description": "Yank Note: A highly extensible Markdown editor, designed for productivity.", "main": "dist/main/app.js", "license": "AGPL-3.0", From 9ba5ab818efe977e3a60114d67e5948fee24f069 Mon Sep 17 00:00:00 2001 From: purocean Date: Fri, 5 Jul 2024 19:19:39 +0800 Subject: [PATCH 08/27] chore: improve category list layout in CreateFilePanel.vue --- src/renderer/components/CreateFilePanel.vue | 32 +++++++++++++-------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/renderer/components/CreateFilePanel.vue b/src/renderer/components/CreateFilePanel.vue index d3da8e370..c52da413c 100644 --- a/src/renderer/components/CreateFilePanel.vue +++ b/src/renderer/components/CreateFilePanel.vue @@ -1,17 +1,19 @@