Skip to content

Commit

Permalink
Merge branch 'release/3.75.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
purocean committed Aug 4, 2024
2 parents c5729a5 + 2aa057e commit 5abf55f
Show file tree
Hide file tree
Showing 33 changed files with 1,206 additions and 672 deletions.
14 changes: 8 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,16 @@ For more information on how to use the following functions, please see [characte

## Changelogs

### [v3.74.0](https://github.com/purocean/yn/releases/tag/v3.74.0) 2024-07-23
### [v3.75.1](https://github.com/purocean/yn/releases/tag/v3.75.1) 2024-07-23

[Windows](https://github.com/purocean/yn/releases/download/v3.74.0/Yank-Note-win-x64-3.74.0.exe) | [macOS arm64](https://github.com/purocean/yn/releases/download/v3.74.0/Yank-Note-mac-arm64-3.74.0.dmg) | [macOS x64](https://github.com/purocean/yn/releases/download/v3.74.0/Yank-Note-mac-x64-3.74.0.dmg) | [Linux AppImage](https://github.com/purocean/yn/releases/download/v3.74.0/Yank-Note-linux-x86_64-3.74.0.AppImage) | [Linux deb](https://github.com/purocean/yn/releases/download/v3.74.0/Yank-Note-linux-amd64-3.74.0.deb)
[Windows](https://github.com/purocean/yn/releases/download/v3.75.1/Yank-Note-win-x64-3.75.1.exe) | [macOS arm64](https://github.com/purocean/yn/releases/download/v3.75.1/Yank-Note-mac-arm64-3.75.1.dmg) | [macOS x64](https://github.com/purocean/yn/releases/download/v3.75.1/Yank-Note-mac-x64-3.75.1.dmg) | [Linux AppImage](https://github.com/purocean/yn/releases/download/v3.75.1/Yank-Note-linux-x86_64-3.75.1.AppImage) | [Linux deb](https://github.com/purocean/yn/releases/download/v3.75.1/Yank-Note-linux-amd64-3.75.1.deb)

1. feat: Support configuring the maximum width of the preview area content display in settings.
2. refactor: Run JavaScript code in Web Worker by default, and terminate execution when switching documents.
3. fix: Fix the error that occurs when the terminal shell configuration is an empty string.
4. fix: Fix the issue where the to-do list cannot be completed after upgrading the Monaco editor.
1. feat: Add option to create custom file extensions in the file panel creation
2. feat: Support for editing `.gitignore` files
3. feat: Support for pasting webp images
4. feat: Experience optimization, add prompt for editing read-only files
5. feat: Experience optimization, adjust the position of the "Duplicate Files" menu
6. fix(plugin): Fix the handling of the `Request` object in `ctx.api.proxyFetch`

[More release notes](https://github.com/purocean/yn/releases)

Expand Down
14 changes: 8 additions & 6 deletions README_ZH-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,16 @@

## 更新日志

### [v3.74.0](https://github.com/purocean/yn/releases/tag/v3.74.0) 2024-07-23
### [v3.75.1](https://github.com/purocean/yn/releases/tag/v3.75.1) 2024-07-23

[Windows](https://github.com/purocean/yn/releases/download/v3.74.0/Yank-Note-win-x64-3.74.0.exe) | [macOS arm64](https://github.com/purocean/yn/releases/download/v3.74.0/Yank-Note-mac-arm64-3.74.0.dmg) | [macOS x64](https://github.com/purocean/yn/releases/download/v3.74.0/Yank-Note-mac-x64-3.74.0.dmg) | [Linux AppImage](https://github.com/purocean/yn/releases/download/v3.74.0/Yank-Note-linux-x86_64-3.74.0.AppImage) | [Linux deb](https://github.com/purocean/yn/releases/download/v3.74.0/Yank-Note-linux-amd64-3.74.0.deb)
[Windows](https://github.com/purocean/yn/releases/download/v3.75.1/Yank-Note-win-x64-3.75.1.exe) | [macOS arm64](https://github.com/purocean/yn/releases/download/v3.75.1/Yank-Note-mac-arm64-3.75.1.dmg) | [macOS x64](https://github.com/purocean/yn/releases/download/v3.75.1/Yank-Note-mac-x64-3.75.1.dmg) | [Linux AppImage](https://github.com/purocean/yn/releases/download/v3.75.1/Yank-Note-linux-x86_64-3.75.1.AppImage) | [Linux deb](https://github.com/purocean/yn/releases/download/v3.75.1/Yank-Note-linux-amd64-3.75.1.deb)

1. feat: 支持在设置中配置预览区域内容显示最大宽度
2. refactor: 默认在 Web Worker 中运行 JavaScript 代码,切换文档时候中止执行
3. fix: 修复终端 shell 配置空字符串时候报错问题
4. fix: 修复升级 Monaco 编辑器后不能补全待办列表问题
1. feat: 创建文件面板增加创建自定义扩展名选项
2. feat: 支持编辑 `.gitignore` 文件
3. feat: 支持粘贴 webp 图片
4. feat: 体验优化,增加只读文件编辑提示
5. feat: 体验优化,调整“重复文件”菜单位置
6. fix(plugin): 修复 `ctx.api.proxyFetch``Request` 对象的处理

[更多发布说明](https://github.com/purocean/yn/releases)

Expand Down
32 changes: 15 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "yank.note",
"version": "3.74.0",
"version": "3.75.1",
"description": "Yank Note: A highly extensible Markdown editor, designed for productivity.",
"main": "dist/main/app.js",
"license": "AGPL-3.0",
Expand Down Expand Up @@ -94,25 +94,24 @@
"@types/turndown": "^5.0.0",
"@types/uuid": "^8.3.4",
"@types/yargs": "^15.0.0",
"@typescript-eslint/eslint-plugin": "^6.16.0",
"@typescript-eslint/parser": "^6.16.0",
"@vitejs/plugin-vue": "^4.5.0",
"@vitejs/plugin-vue-jsx": "^3.1.0",
"@vue/compiler-sfc": "^3.3.13",
"@typescript-eslint/eslint-plugin": "^7.18.0",
"@typescript-eslint/parser": "^7.18.0",
"@vitejs/plugin-vue": "^5.1.2",
"@vitejs/plugin-vue-jsx": "^4.0.0",
"@vue/compiler-sfc": "^3.4.35",
"@vue/eslint-config-standard": "^8.0.1",
"@vue/eslint-config-typescript": "^12.0.0",
"@vue/eslint-config-typescript": "^13.0.0",
"autoprefixer": "^10.4.16",
"canvas-confetti": "^1.6.0",
"crypto-js": "^4.2.0",
"dom-to-image": "^2.6.0",
"electron": "28.3.3",
"electron-builder": "^23.6.0",
"eslint": "^8.56.0",
"eslint": "^8.57.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-standard": "^5.0.0",
"eslint-plugin-vue": "^9.19.2",
"eslint-plugin-promise": "^7.0.0",
"eslint-plugin-vue": "^9.27.0",
"filenamify": "^5.1.0",
"front-matter": "^4.0.2",
"husky": "^8.0.1",
Expand Down Expand Up @@ -144,14 +143,13 @@
"ts-jest": "^29.1.1",
"ts-node": "^10.9.2",
"turndown": "^7.2.0",
"typedoc": "^0.25.4",
"typescript": "^4.9.5",
"typedoc": "^0.26.5",
"typescript": "^5.5.4",
"utility-types": "^3.10.0",
"viewerjs": "^1.11.6",
"vite": "^4.5.3",
"vue": "^3.3.13",
"vue-router": "^4.0.0-0",
"vue-tsc": "^1.8.26",
"vite": "^5.3.5",
"vue": "^3.4.35",
"vue-tsc": "^2.0.29",
"xterm": "^4.18.0",
"xterm-addon-fit": "^0.5.0",
"xterm-theme": "^1.1.0"
Expand Down
15 changes: 15 additions & 0 deletions src/main/server/file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,21 @@ export function stat (repo: string, p: string) {
}, p)
}

export function checkWriteable (repo: string, p: string) {
return withRepo(repo, async (_, targetPath) => {
if (readonly) {
return false
}

try {
await fs.access(targetPath, fs.constants.W_OK)
return true
} catch (error) {
return false
}
}, p)
}

export function write (repo: string, p: string, content: any): Promise<string> {
if (readonly) throw new Error('Readonly')

Expand Down
12 changes: 8 additions & 4 deletions src/main/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import config from '../config'
import * as jwt from '../jwt'
import { getAction } from '../action'
import * as extension from '../extension'
import type { FileReadResult } from '../../share/types'

const isLocalhost = (address: string) => {
return ip.isEqual(address, '127.0.0.1') || ip.isEqual(address, '::1')
Expand All @@ -38,7 +39,7 @@ const noCache = (ctx: any) => {
}

const checkPermission = (ctx: any, next: any) => {
const token = ctx.query._token || (ctx.headers['x-yn-authorization'] || ctx.headers.authorization || '').replace('Bearer ', '')
const token = ctx.query._token || (ctx.headers['x-yn-authorization'] ?? (ctx.headers.authorization || '')).replace('Bearer', '').trim()

if (ctx.req._protocol || (!token && isLocalhost(ctx.request.ip))) {
ctx.req.jwt = { role: 'admin' }
Expand Down Expand Up @@ -122,11 +123,14 @@ const fileContent = async (ctx: any, next: any) => {

const content = await file.read(repo, path)

ctx.body = result('ok', 'success', {
const data: FileReadResult = {
content: content.toString(asBase64 ? 'base64' : undefined),
hash: await file.hash(repo, path),
stat: await file.stat(repo, path)
})
stat: await file.stat(repo, path),
writeable: await file.checkWriteable(repo, path),
}

ctx.body = result('ok', 'success', data)
} else if (ctx.method === 'POST') {
const { oldHash, content, asBase64, repo, path } = ctx.request.body

Expand Down
3 changes: 0 additions & 3 deletions src/renderer/App.vue

This file was deleted.

File renamed without changes.
6 changes: 4 additions & 2 deletions src/renderer/components/CreateFilePanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
@click="emits('updateDocType', item)"
>
<input type="radio" :checked="item.id === docType?.id" />
{{ item.displayName }}({{ item.extension[0] }})
<span>{{ item.displayName }}</span>
<span v-if="item.extension.join(',')">({{ item.extension.join(',') }})</span>
</div>
</template>
</div>
Expand Down Expand Up @@ -48,7 +49,8 @@ const xCategories = computed(() => props.categories.map(x => ({
.create-file-panel {
.category-list-wrapper {
max-height: calc(100vh - 300px);
overflow-y: auto
overflow-y: auto;
margin-bottom: 10px;
}
.category {
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/components/DefaultEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export default defineComponent({
await nextTick()
getEditor().updateOptions({
readOnly: FLAG_READONLY || !current || !current.plain
readOnly: FLAG_READONLY || !current || !current.plain || current.writeable === false
})
if (isDefault()) {
Expand Down
3 changes: 1 addition & 2 deletions src/renderer/components/ExtensionManager.vue
Original file line number Diff line number Diff line change
Expand Up @@ -705,8 +705,7 @@ onUnmounted(() => {
.body {
display: flex;
height: calc(100vh - 7vh - 50px);
max-height: 900px;
height: calc(100vh - 7vh - 100px);
}
.side {
Expand Down
4 changes: 3 additions & 1 deletion src/renderer/components/FileTabs.vue
Original file line number Diff line number Diff line change
Expand Up @@ -338,11 +338,13 @@ export default defineComponent({
const fileTabs = computed(() => (tabs.value as Components.FileTabs.Item[]).map(tab => {
if (currentFile.value && tab.key === toUri(currentFile.value)) {
const status = currentFile.value.status
const { status, writeable } = currentFile.value
let mark = ''
if (!isSaved.value) {
mark = '*'
} else if (writeable === false) {
mark = '🔒'
} else if (status === 'saved') {
mark = ''
} else if (status === 'save-failed') {
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/components/KeyboardShortcuts.vue
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ onUnmounted(() => {
.wrapper {
width: 90vw;
max-width: 900px;
max-width: 1024px;
background: var(--g-color-backdrop);
backdrop-filter: var(--g-backdrop-filter);
margin: auto;
Expand Down
7 changes: 5 additions & 2 deletions src/renderer/components/ModalUi.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
<component v-if="component" :is="component" />
<p class="content" v-if="content">{{content}}</p>
<template v-if="type === 'input'">
<textarea class="textarea" v-if="inputType === 'textarea'" ref="refInput" rows="5" :placeholder="inputHint" :readonly="inputReadonly" v-model="inputValue" tabindex="2" />
<input class="input" v-else ref="refInput" :type="inputType" :placeholder="inputHint" :readonly="inputReadonly" v-model="inputValue" @keypress.enter.stop.prevent="ok" tabindex="2" />
<textarea class="textarea" v-if="inputType === 'textarea'" ref="refInput" rows="5" :placeholder="inputHint" :readonly="inputReadonly" v-model="inputValue" tabindex="2" :maxlength="inputMaxLength > 0 ? inputMaxLength : undefined" />
<input class="input" v-else ref="refInput" :type="inputType" :placeholder="inputHint" :readonly="inputReadonly" v-model="inputValue" @keypress.enter.stop.prevent="ok" tabindex="2" :maxlength="inputMaxLength > 0 ? inputMaxLength : undefined" />
</template>
<div class="action">
<component v-if="action" :is="action" />
Expand Down Expand Up @@ -47,6 +47,7 @@ export default defineComponent({
const inputValue = ref('')
const inputHint = ref('')
const inputReadonly = ref(false)
const inputMaxLength = ref(0)
const modalWidth = ref<string | undefined>(undefined)
let resolveFun: Function | null = null
Expand Down Expand Up @@ -113,6 +114,7 @@ export default defineComponent({
inputType.value = params.type || 'text'
inputValue.value = params.value || ''
inputHint.value = params.hint || ''
inputMaxLength.value = params.maxlength || 0
inputReadonly.value = params.readonly || false
modalWidth.value = params.modalWidth
component.value = params.component
Expand Down Expand Up @@ -155,6 +157,7 @@ export default defineComponent({
inputValue,
inputHint,
inputReadonly,
inputMaxLength,
modalWidth,
}
},
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/core/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export function getActionHandler <T extends string> (name: T): ActionHandler<T>
const action = getAction(name)
if (action) {
if (!(action.when && !action.when())) {
result = (action.handler)?.(...args)
result = (action.handler)?.apply(null, args)
}
}

Expand Down
6 changes: 2 additions & 4 deletions src/renderer/index.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
import '@fe/others/demo'

import { createApp } from 'vue'
import App from '@fe/App.vue'
import router from '@fe/router'
import Main from '@fe/Main.vue'

import directives from '@fe/directives'
import toast from '@fe/support/ui/toast'
import modal from '@fe/support/ui/modal'
import contextmenu from '@fe/support/ui/context-menu'
import quickFilter from '@fe/support/ui/quick-filter'

const app = createApp(App)
const app = createApp(Main)

app.use(directives)
app.use(router)
app.use(toast)
app.use(modal)
app.use(contextmenu)
Expand Down
4 changes: 3 additions & 1 deletion src/renderer/others/file-extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,9 @@ const extensions = [
]

const supported = (name: string) => {
return extensions.includes(extname(name.toLowerCase()))
name = name.toLowerCase()
const ext = extname(name) || name.startsWith('.') ? name : ''
return ext ? extensions.includes(ext) : false
}

export default {
Expand Down
2 changes: 2 additions & 0 deletions src/renderer/plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ import watchFileRefresh from '@fe/plugins/watch-file-refresh'
import previewFontSize from '@fe/plugins/preview-font-size'
import dropToOpenFile from '@fe/plugins/drop-to-open-file'
import recordRecentDocument from '@fe/plugins/record-recent-document'
import aiCopilot from '@fe/plugins/ai-copilot'

export default [
buildInRenderers,
Expand Down Expand Up @@ -148,4 +149,5 @@ export default [
dropToOpenFile,
recordRecentDocument,
markdownGithubAlerts,
aiCopilot,
]
45 changes: 45 additions & 0 deletions src/renderer/plugins/ai-copilot.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Plugin } from '@fe/context'
import { getInitialized, getLoadStatus } from '@fe/others/extension'
import type { languages } from 'monaco-editor'

export default {
name: 'ai-copilot',
register: ctx => {
ctx.editor.whenEditorReady().then(({ monaco }) => {
const extensionId = '@yank-note/extension-ai-copilot'
const actionId = 'install-ai-copilot-extension'
const checkExtensionLoaded = () => !!getLoadStatus(extensionId).version

monaco.languages.registerCodeActionProvider('*', {
provideCodeActions (): languages.CodeActionList {
const actionTitle = ctx.i18n.t('edit-or-generate-text-using-ai')

if (!getInitialized() || checkExtensionLoaded()) {
return { dispose: () => 0, actions: [] }
}

const actions: languages.CodeAction[] = [{
title: actionTitle,
command: { id: actionId, title: actionTitle },
kind: 'refactor',
diagnostics: [],
isPreferred: true,
}]

return {
dispose: () => 0,
actions
}
},

async resolveCodeAction (codeAction: languages.CodeAction): Promise<languages.CodeAction | undefined> {
if (codeAction.command?.id === actionId) {
ctx.showExtensionManager(extensionId)
}

return undefined
}
})
})
}
} as Plugin
Loading

0 comments on commit 5abf55f

Please sign in to comment.