From e6be89acf8b72b4149d6b5ecfcbcbf19e88eaf4c Mon Sep 17 00:00:00 2001 From: Yang Date: Mon, 28 Dec 2020 17:07:34 +0800 Subject: [PATCH 01/19] test --- README.md | 35 ----------------------------------- install.sh | 13 ------------- linux_build.sh | 2 -- win-build.bat | 1 - win-install.bat | 8 -------- 5 files changed, 59 deletions(-) delete mode 100644 install.sh delete mode 100644 linux_build.sh delete mode 100644 win-build.bat delete mode 100644 win-install.bat diff --git a/README.md b/README.md index 007ece3c..bf892ade 100644 --- a/README.md +++ b/README.md @@ -102,41 +102,6 @@ + `Ctrl + B + V` 粘贴图片为 Base64 + `Ctrl + Alt + Left/Right` 切换编辑器 Tab -## 开发 -依赖安装和编译比较麻烦,请保证自己有足够耐心且有科学上网的手段。 - -### Windows -Windows 上安装 node-pty 需要费一番功夫,请参考 https://github.com/microsoft/node-pty#windows 配置编译环境。 - -```bat -REM Node 版本要求 12 v12.7.0 -node -v - -REM 前端 -cd frontend -REM 安装依赖 -yarn -REM 打包 -yarn run dist -REM 开发 -yarn run serve - -REM Electron 端 -cd ../ -REM 安装依赖 -win-install.bat -REM 打包 打包前请在前端目录运行打包命令 -win-build.bat -REM 开发 -yarn run start -``` - -### Liunx - TODO 手头没有环境,待完善 - -### OSX - TODO 手头没有环境,待完善 - ## 界面截图 ![截图](./help/3.png) ![截图](./help/5.png) diff --git a/install.sh b/install.sh deleted file mode 100644 index 3f15dad3..00000000 --- a/install.sh +++ /dev/null @@ -1,13 +0,0 @@ -# Electron's version. -export npm_config_target=6.0.0 -# The architecture of Electron, can be ia32 or x64. -export npm_config_arch=x64 -export npm_config_target_arch=x64 -# Download headers for Electron. -export npm_config_disturl=https://atom.io/download/electron -# Tell node-pre-gyp that we are building for Electron. -export npm_config_runtime=electron -# Tell node-pre-gyp to build module from source code. -export npm_config_build_from_source=true -# Install all dependencies, and store cache to ~/.electron-gyp. -HOME=~/.electron-gyp yarn && yarn run download-pandoc diff --git a/linux_build.sh b/linux_build.sh deleted file mode 100644 index e42d85a7..00000000 --- a/linux_build.sh +++ /dev/null @@ -1,2 +0,0 @@ -yarn run build -./node_modules/.bin/electron-builder --linux diff --git a/win-build.bat b/win-build.bat deleted file mode 100644 index 5e4dd1ff..00000000 --- a/win-build.bat +++ /dev/null @@ -1 +0,0 @@ -@yarn run build && yarn run electron-builder --win -p never diff --git a/win-install.bat b/win-install.bat deleted file mode 100644 index 4f3aeb17..00000000 --- a/win-install.bat +++ /dev/null @@ -1,8 +0,0 @@ -@echo off -setlocal -set npm_config_disturl=https://atom.io/download/electron -set npm_config_target=9.3.1 -set npm_config_runtime="electron" -set npm_config_cache=~\.npm-electron -yarn && yarn run download-pandoc -endlocal From 112494ee8d86a779563abcc61f27934e3ca4cb3b Mon Sep 17 00:00:00 2001 From: purocean Date: Mon, 28 Dec 2020 18:36:16 +0800 Subject: [PATCH 02/19] =?UTF-8?q?=E7=BB=88=E7=AB=AF=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E5=AD=97=E4=BD=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Xterm.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/Xterm.vue b/frontend/src/components/Xterm.vue index 709af357..9c1e61b8 100644 --- a/frontend/src/components/Xterm.vue +++ b/frontend/src/components/Xterm.vue @@ -46,7 +46,7 @@ export default defineComponent({ rows: 24, fontSize: 18, cursorStyle: 'underline', - fontFamily: 'Consolas', + // fontFamily: 'Consolas', fontWeightBold: '500', theme: { background: 'rgb(30, 31, 32)' From 49c1fe130181da0ae4757acefaa39d9e9ce651bc Mon Sep 17 00:00:00 2001 From: purocean Date: Mon, 28 Dec 2020 18:36:59 +0800 Subject: [PATCH 03/19] =?UTF-8?q?=E5=BF=BD=E7=95=A5=20macos=20=E7=9A=84?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 47ad7f2f..a5c6b6b5 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ bin # .yarnrc b.bat *.pfx +.DS_Store From 76a9ff0083d95d45dc87ba18ac3504621ebbcc58 Mon Sep 17 00:00:00 2001 From: purocean Date: Mon, 28 Dec 2020 18:37:32 +0800 Subject: [PATCH 04/19] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20macos=20=E6=89=93?= =?UTF-8?q?=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/release.yml | 4 +++- electron-builder.json | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8946f486..fc5293eb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -8,8 +8,10 @@ jobs: build: strategy: matrix: - os: [ubuntu-latest, windows-latest] + os: [macos-latest, ubuntu-latest, windows-latest] include: + - os: macos-latest + platform: 'mac' - os: windows-latest platform: 'win' - os: ubuntu-latest diff --git a/electron-builder.json b/electron-builder.json index 214ed5d6..ea75300c 100644 --- a/electron-builder.json +++ b/electron-builder.json @@ -32,6 +32,11 @@ "deb" ] }, + "mac": { + "target": [ + "dmg" + ] + }, "nsis": { "perMachine": false }, From 78e2acb18856276c5a0a840c720899f12121c6ce Mon Sep 17 00:00:00 2001 From: purocean Date: Tue, 29 Dec 2020 19:15:24 +0800 Subject: [PATCH 05/19] =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=89=98=E7=9B=98?= =?UTF-8?q?=E5=9B=BE=E6=A0=87=E5=B0=BA=E5=AF=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.ts | 2 +- src/assets/tray.png | Bin 0 -> 621 bytes src/assets/tray@2x.png | Bin 0 -> 734 bytes src/assets/tray@3x.png | Bin 0 -> 908 bytes src/assets/tray@4x.png | Bin 0 -> 1155 bytes 5 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 src/assets/tray.png create mode 100644 src/assets/tray@2x.png create mode 100644 src/assets/tray@3x.png create mode 100644 src/assets/tray@4x.png diff --git a/src/app.ts b/src/app.ts index f2f33ff5..0dfd94e9 100644 --- a/src/app.ts +++ b/src/app.ts @@ -295,7 +295,7 @@ if (!gotTheLock) { }, ]) - tray = new Tray(path.join(__dirname, './assets/icon.png')) + tray = new Tray(path.join(__dirname, './assets/tray.png')) tray.setToolTip('Yank Note 一款面向程序员的 Markdown 编辑器') tray.on('click', showWindow) tray.setContextMenu(contextMenu) diff --git a/src/assets/tray.png b/src/assets/tray.png new file mode 100644 index 0000000000000000000000000000000000000000..afa863b24d846fe7fb836e338a8750c38d2feee0 GIT binary patch literal 621 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl<6e(pbstU$g(vPY0F z14ES>14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>o0 zzfKVS(l7GMN%Hetq0h60J{=MGG+*%J5q_Y;Pe=H{%77}N=;Jp2Pum25=pzsv}|pX_LUmgZv+N z34ER}^#A|=hkb`Yj#McL@&kDk0T}hCFImjAbO|HlVh~!wIAMpp+;sgNPvw+>iWrl; z-Cc|vF8Q1QaySb-B8wRqxP?KOkzv*x37{Z*iKnkC`x72nZeE?W3v(=hLOq@?jv*44 zOHbVtYf@lnd6*d(?44sOc-`U5rZ<1%^*s98XYV^*&vqcmJld(#V~=@~5To`X-IU(L zff0V`F_W%MikTR6^KP%-C7(lmYR>%_}v7Or{tlOvCJv6Qyf_0P^M2hDz;l-=6?P&|9J>|@7iGtUFvrCQ<| zQIe8al4_M)lnSI6j0}tnbPbJkjVwY8%&bf;tqd)-4GgRd49!lvVtU&J%W50 z7^>757#dm_7=8hT8eT9klo~KFyh>nTu$sZZAYL$MSD+10Vtas3h%1o(GE3m|9HB3B z1U}Ce`m{>$;}QOkhxtEk7WjCP|4Ws~=UGCZ<_mr}$_G?~69F}@76j@Ak|6C61Tu%Fr>mZ~7uxFknYBS_9*)w940A!^)Fi#Pfw+GM6O zUh0))J?vu7(=BqKf_D`+4**;s}s>y+~hQB)M!xx5`rHtPgbi-2~B=Aqz9VZ!D zc8#aHVZv_1(#>bCJln_~>vEtdm$BxwZ1b(E^%5;SVn9!-mbgZgq$HN4S|t~y0x1R~ z10w@nLnB=yix2}dD^p7=LrZM~11kfAb6-8LqG-s?PsvQH#I0ffijSE<4Gf;HelF{r G5}E+P#vCC4 literal 0 HcmV?d00001 diff --git a/src/assets/tray@3x.png b/src/assets/tray@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..6a4796ed803f8dd1615d969ae454101f19c8512e GIT binary patch literal 908 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sEa{HEjtmSN`?>!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)pT}UnMXwSj}Ky5HFasE6@fg@j1XJ#1%x(7W_O%=+j)G z&vOJn%@+JJNBHw>q0jRLKhGEXv{>--62XuA`9B`v|9FW1<7ReEuekGuIH#(tV6^m(q(rv-u__W%*dYB1vn|A!-BH4BBHCLHGfc!2-&Qo+v) zgg)*T__Rv!^CBUjzyAOKzx}1M1kl?qB|(0{KpF>Nm6T^SUw-q!ox7~8x0D_$DLsCq zDF5(*{Db?lzZzM8HM2LfOWtH%Zhn__uZfln&=AHXZ+Dk~$9X<`fE>;OkH}&M25w;x zW@MN(2V^6AiKnkC`x72nZa#J`gJZjadJH{X978;gzn%6n=#YVkTe3@`VoqMh*0qnC zq;GBFJhe>MgyYA*d}Xt;wj)b+zUq10Gw=TWo!?)-^;ypGmxEj4NYWI4orku`@y&$> z!HfQE%DmYwm2>(CXIeszTqQ%-v)^1bIgX#^rO#EFnK0)N%k2c|uybAp3rqG%ab=57 zx9eE_`fGs4)O&{8w*y zl4=s`Kd(22rH9&g^X$AjHA^Ze(`M!-#jRD!%oQ&-{y$`wTz)ppY`J)o=al{RC!SA? zTX1>jA2tVxACGD#9C*rjs7Aiy!1?){Z~fLNJiC~-U0j``_MX{RdP`(kYX@0Ff!0JG}1M)2r)3TGPSfawA3~*ure?>_to<%iiX_$l+3hB+#2?; S_?QXQz~JfX=d#Wzp$Pzs)O%_G literal 0 HcmV?d00001 diff --git a/src/assets/tray@4x.png b/src/assets/tray@4x.png new file mode 100644 index 0000000000000000000000000000000000000000..0a9ec531f4c286d8af51bf8fcbfc067610639c5c GIT binary patch literal 1155 zcma)4drVVT96qVxfl+03epfL?+@K?)0^M9CdxCp5o+^EsK)@&{He=D@}mMUgZcy&~`zLv=UCua5@I5C8(7~mua?xLY)+Q3$nK;i;=V#p#%6^^bqM7wg;jn zhHH?p-#~PQVhtp#Cs`w84ba*zWcARh7uxQV%X(-rK-5TMUepLz1gy&VH{zw2`fR7O zjJ-;+-6R&{)YC(;Uy&T9Yho<@B??QBq=2{r;5`#KvPQ!4G47x$F!w{c~Yp2-( z3iVO!AjLH^+-2I~aBQys#0Ot=nldr|5YGR*5d%tn80oEyE4i^9*k~p0J8to=L z>8g~+MY;as<|!iG->Uv@4rA2vNLf;{ere{(fzfbKy>Mu1P+?-$|Nfre2L}y<8-DO> z=_q$I)h{^wHQq+j{9F)WFE#(!mg^r3j%0c20w1Y{%uSCq1Mu^{p;H5sFA&EM8XSqy z^q$N1?i1$`qn;D5jA_)fs_Wmv2)?Spadx(HznfR(+oFA`0i$VaHr1WCm+p<7h~Au< zH@8D@eaqS1!-j>r_4D?OuX)-gIWgrZ|MHBfrYa@n!0zGulle)b=DbgZisNMs(&`)H zn|{<8pVxhP+v;CE(GXh$lsi&B-hRa8-t=12o3^7lq0{?ZCoS$CQ1L*vr&^$RFp|Ad zG~ZO2G0=M~CBM*pA~?qIsQ8Ve9q)I4*e-nLv+>tNTj8^!8IRZ&`-Lpq(BW$&y!Y_w z3t6|0UlcyHZQ6(Tup*&W7+F=4H(ypOQk2A&|M)Wz8g{YF>cc-7Htp|{Ks?^EczRyq zF+5jkY=1&AUeo+=%KuXTGWA)}NnTj8Z_W3q!^@QJrzPEn#WF!fQNgU%yI}iFMQQQQ zuFfEpJ;}o}XS|d@Zpu-Q2ETg~zuRldsAOeEnldva{i95rK%g{Gx+@@XSK!_x>7J0F q;E;geol Date: Tue, 29 Dec 2020 19:23:36 +0800 Subject: [PATCH 06/19] =?UTF-8?q?macos=20=E4=B8=8A=E7=A6=81=E7=94=A8?= =?UTF-8?q?=E6=89=93=E5=BC=80=E7=AA=97=E5=8F=A3=E5=BF=AB=E6=8D=B7=E9=94=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/shortcut.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/shortcut.ts b/src/shortcut.ts index 9819f5f3..5476d135 100644 --- a/src/shortcut.ts +++ b/src/shortcut.ts @@ -1,9 +1,11 @@ +import * as os from 'os' import { globalShortcut, dialog } from 'electron' +const platform = os.platform() type AcceleratorType = 'show-main-window' | 'open-in-browser' export const getAccelerator = (type: AcceleratorType) => { return { - 'show-main-window': 'Super+N', + 'show-main-window': platform === 'darwin' ? null : 'Super+N', 'open-in-browser': 'Super+Shift+B' }[type] } @@ -11,6 +13,10 @@ export const getAccelerator = (type: AcceleratorType) => { export const registerShortcut = (shortcuts: {[key in AcceleratorType]: () => void}) => { Object.keys(shortcuts).forEach((key: AcceleratorType) => { const accelerator = getAccelerator(key) + if (!accelerator) { + return + } + globalShortcut.register(accelerator, shortcuts[key]) if (!globalShortcut.isRegistered(accelerator)) { From 72c19e78da5b8a6ca95a709ef1aceb5b81b9f7f4 Mon Sep 17 00:00:00 2001 From: purocean Date: Tue, 29 Dec 2020 19:54:52 +0800 Subject: [PATCH 07/19] =?UTF-8?q?mac=20=E4=B8=8A=E9=9A=90=E8=97=8F=20dock?= =?UTF-8?q?=20=E5=9B=BE=E6=A0=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/app.ts b/src/app.ts index 0dfd94e9..cf1f162c 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,5 +1,6 @@ import { app, BrowserWindow, Menu, Tray } from 'electron' import * as path from 'path' +import * as os from 'os' import { dialog } from 'electron' import * as yargs from 'yargs' import server from './server/main' @@ -8,6 +9,8 @@ import * as updater from './updater' import { getAccelerator, registerShortcut } from './shortcut' const opn = require('opn') +const isMacos = os.platform() === 'darwin' + let isDev = false const showTray = !(yargs.argv['disable-tray']) @@ -105,6 +108,8 @@ const createWindow = () => { const showWindow = () => { if (win) { const show = () => { + // macos 上隐藏图标 + isMacos && app.dock.hide() win.setSkipTaskbar(false) win.show() } From 858fde80a520351ce6940460558805261f710901 Mon Sep 17 00:00:00 2001 From: purocean Date: Tue, 29 Dec 2020 19:58:06 +0800 Subject: [PATCH 08/19] =?UTF-8?q?=E5=85=B3=E6=9C=BA=E6=97=B6=E5=80=99?= =?UTF-8?q?=E9=80=80=E5=87=BA=E5=BA=94=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app.ts b/src/app.ts index cf1f162c..d27e1cd4 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,4 +1,4 @@ -import { app, BrowserWindow, Menu, Tray } from 'electron' +import { app, BrowserWindow, Menu, Tray, powerMonitor } from 'electron' import * as path from 'path' import * as os from 'os' import { dialog } from 'electron' @@ -323,3 +323,5 @@ if (!gotTheLock) { } }) } + +powerMonitor.on('shutdown', quit) From a08fbdf2d05f12587308d2274a0adaae7449401e Mon Sep 17 00:00:00 2001 From: purocean Date: Tue, 29 Dec 2020 20:22:06 +0800 Subject: [PATCH 09/19] =?UTF-8?q?=E5=85=B3=E6=9C=BA=E6=97=B6=E5=80=99?= =?UTF-8?q?=E9=80=80=E5=87=BA=E5=BA=94=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app.ts b/src/app.ts index d27e1cd4..0e57754a 100644 --- a/src/app.ts +++ b/src/app.ts @@ -184,6 +184,8 @@ if (!gotTheLock) { 'open-in-browser': () => opn(getUrl()) }) + powerMonitor.on('shutdown', quit) + if (showTray) { const contextMenu = Menu.buildFromTemplate([ { @@ -323,5 +325,3 @@ if (!gotTheLock) { } }) } - -powerMonitor.on('shutdown', quit) From 6a051ec938d5ff733757face642219098eb90f28 Mon Sep 17 00:00:00 2001 From: purocean Date: Wed, 13 Jan 2021 13:35:17 +0800 Subject: [PATCH 10/19] =?UTF-8?q?=E8=B0=83=E6=95=B4=E9=BB=98=E8=AE=A4=20sh?= =?UTF-8?q?ell=20=E5=92=8C=E7=8E=AF=E5=A2=83=E5=8F=98=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/server/run.ts | 6 +++++- src/server/shell.ts | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/server/run.ts b/src/server/run.ts index 2d6fa80c..a7593f4d 100644 --- a/src/server/run.ts +++ b/src/server/run.ts @@ -41,7 +41,11 @@ const runCode = (language: string, code: string) => { return execFileSync('wsl.exe', ['--', runParams.cmd].concat(runParams.args).concat([code])).toString() } - return execFileSync(runParams.cmd, runParams.args.concat([code])).toString() + return execFileSync( + runParams.cmd, + runParams.args.concat([code]), + { env: process.env } + ).toString() } catch (e) { return e.message } diff --git a/src/server/shell.ts b/src/server/shell.ts index 2f65d91b..5b48e648 100644 --- a/src/server/shell.ts +++ b/src/server/shell.ts @@ -5,7 +5,7 @@ import { toWslPath } from './wsl' const configKey = 'shell' const CD_COMMAND_PREFIX = '--yank-note-run-command-cd--' -const defaultShell = os.platform() === 'win32' ? 'cmd.exe' : 'bash' +const defaultShell = os.platform() === 'win32' ? 'cmd.exe' : (process.env.SHELL || 'bash') const getShell = () => { const shell = config.get(configKey, defaultShell) From f6d0099212273d64fd2474708d114df181d12f5d Mon Sep 17 00:00:00 2001 From: purocean Date: Wed, 13 Jan 2021 14:35:34 +0800 Subject: [PATCH 11/19] =?UTF-8?q?=E8=BF=90=E8=A1=8C=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20path?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/server/run.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/server/run.ts b/src/server/run.ts index a7593f4d..5580ed74 100644 --- a/src/server/run.ts +++ b/src/server/run.ts @@ -6,6 +6,7 @@ import * as wsl from './wsl' import config from './config' const isWsl = wsl.isWsl +const isWin = os.platform() === 'win32' const runCode = (language: string, code: string) => { try { @@ -17,7 +18,7 @@ const runCode = (language: string, code: string) => { js: { cmd: 'node', args: ['-e'] }, } as {[key: string]: {cmd: string, args: string[]}} - if (language === 'bat') { + if (language === 'bat' && isWin) { const fileName = 'yn-run-cmd.bat' code = code.split('\n').slice(1).join('\n') // 去掉第一行的注释 if (isWsl) { @@ -36,15 +37,21 @@ const runCode = (language: string, code: string) => { return `不支持 ${language} 语言` } - const useWsl = os.platform() === 'win32' && config.get('runCodeUseWsl', false) + const useWsl = isWin && config.get('runCodeUseWsl', false) if (useWsl) { return execFileSync('wsl.exe', ['--', runParams.cmd].concat(runParams.args).concat([code])).toString() } + const env = { ...process.env } + const extPath = '/usr/local/bin' + if (!isWin && env.PATH.indexOf(extPath) < 0) { + env.PATH = `${extPath}:${env.PATH}` + } + return execFileSync( runParams.cmd, runParams.args.concat([code]), - { env: process.env } + { env } ).toString() } catch (e) { return e.message From 7c152cd975a89852b31b6092a6254eea7c84d608 Mon Sep 17 00:00:00 2001 From: purocean Date: Sat, 16 Jan 2021 23:58:54 +0800 Subject: [PATCH 12/19] =?UTF-8?q?=E9=80=82=E9=85=8D=20macOS=20=E5=BF=AB?= =?UTF-8?q?=E6=8D=B7=E9=94=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/FileTabs.vue | 17 ++--- frontend/src/components/Filter.vue | 42 ++++++------ frontend/src/components/MonacoEditor.vue | 16 ++--- frontend/src/components/Preview.vue | 15 +++-- frontend/src/components/StatusBar.vue | 22 +++--- frontend/src/plugins/CodePlugin.ts | 5 +- frontend/src/plugins/TocPlugin.ts | 3 +- frontend/src/useful/env.ts | 4 +- frontend/src/useful/shortcut.ts | 85 ++++++++++++++++++++++++ frontend/src/useful/startup.ts | 4 +- frontend/src/useful/utils.ts | 15 +++++ 11 files changed, 172 insertions(+), 56 deletions(-) create mode 100644 frontend/src/useful/shortcut.ts diff --git a/frontend/src/components/FileTabs.vue b/frontend/src/components/FileTabs.vue index b23089a1..2de25ae8 100644 --- a/frontend/src/components/FileTabs.vue +++ b/frontend/src/components/FileTabs.vue @@ -8,6 +8,7 @@ import Tabs from './Tabs.vue' import File from '../useful/file' import { defineComponent, onBeforeMount, onBeforeUnmount, ref, toRefs, watch } from 'vue' import { Components } from '../types' +import { isAction } from '../useful/shortcut' const blankUri = File.toUri(null) @@ -72,14 +73,14 @@ export default defineComponent({ } // 快捷键切换最近文档 - if (e.altKey && e.ctrlKey) { - if (e.key === 'ArrowLeft') { - const prev = findTab(-1) - prev && switchTab(prev) - } else if (e.key === 'ArrowRight') { - const next = findTab(1) - next && switchTab(next) - } + if (isAction(e, 'file-tabs-switch-left')) { + const prev = findTab(-1) + prev && switchTab(prev) + } + + if (isAction(e, 'file-tabs-switch-right')) { + const next = findTab(1) + next && switchTab(next) } } diff --git a/frontend/src/components/Filter.vue b/frontend/src/components/Filter.vue index efccceac..7def0b7f 100644 --- a/frontend/src/components/Filter.vue +++ b/frontend/src/components/Filter.vue @@ -8,6 +8,7 @@ import { useStore } from 'vuex' import { computed, defineComponent, onMounted, onUnmounted, ref, toRef } from 'vue' import { encodeMarkdownLink } from '../useful/utils' +import { getCurrentAction } from '../useful/shortcut' import { useBus } from '../useful/bus' import XMask from './Mask.vue' import QuickOpen from './QuickOpen.vue' @@ -24,26 +25,29 @@ export default defineComponent({ const withMarked = ref(true) function keydownHandler (e: KeyboardEvent) { - if (e.key === 'i' && e.ctrlKey && e.altKey) { - callback.value = (f: any) => { - const file = currentFile.value - if (file) { - const relativePath = f.path.replace(file.path.substr(0, file.path.lastIndexOf('/')), '.') - bus.emit('editor-insert-value', `[${f.name.replace(/\.[^.]+$/, '')}](${encodeMarkdownLink(relativePath)})`) + switch (getCurrentAction(e)) { + case 'insert-document': + callback.value = (f: any) => { + const file = currentFile.value + if (file) { + const relativePath = f.path.replace(file.path.substr(0, file.path.lastIndexOf('/')), '.') + bus.emit('editor-insert-value', `[${f.name.replace(/\.[^.]+$/, '')}](${encodeMarkdownLink(relativePath)})`) + } + callback.value = null } - callback.value = null - } - withMarked.value = false - e.preventDefault() - e.stopPropagation() - } else if (e.key === 'p' && e.ctrlKey) { - callback.value = (f: any) => { - store.commit('setCurrentFile', f) - callback.value = null - } - withMarked.value = true - e.preventDefault() - e.stopPropagation() + withMarked.value = false + e.preventDefault() + e.stopPropagation() + break + case 'show-quick-open': + callback.value = (f: any) => { + store.commit('setCurrentFile', f) + callback.value = null + } + withMarked.value = true + e.preventDefault() + e.stopPropagation() + break } } diff --git a/frontend/src/components/MonacoEditor.vue b/frontend/src/components/MonacoEditor.vue index 8aa00338..ae3d492d 100644 --- a/frontend/src/components/MonacoEditor.vue +++ b/frontend/src/components/MonacoEditor.vue @@ -12,7 +12,7 @@ import env from '../useful/env' const models: {[key: string]: monaco.editor.ITextModel} = {} -const keys: {[key: string]: boolean} = {} +let keys: {[key: string]: boolean} = {} export default defineComponent({ name: 'monaco-editor', @@ -80,17 +80,17 @@ export default defineComponent({ const KM = getMonaco().KeyMod const KC = getMonaco().KeyCode - getEditor().addCommand(KM.CtrlCmd | KM.Alt | KC.KEY_F, addAttachment) + getEditor().addCommand(KM.Shift | KM.Alt | KC.KEY_F, addAttachment) - getEditor().addCommand(KM.CtrlCmd | KM.Alt | KC.KEY_D, () => { + getEditor().addCommand(KM.Shift | KM.Alt | KC.KEY_D, () => { insert(dayjs().format('YYYY-MM-DD')) }) - getEditor().addCommand(KM.CtrlCmd | KM.Alt | KC.KEY_T, () => { + getEditor().addCommand(KM.Shift | KM.Alt | KC.KEY_T, () => { insert(dayjs().format('HH:mm:ss')) }) - getEditor().addCommand(KM.CtrlCmd | KM.Alt | KC.KEY_R, () => { + getEditor().addCommand(KM.Shift | KM.Alt | KC.KEY_R, () => { emit('xterm-run', getEditor().getModel()!!.getValueInRange(getEditor().getSelection()!!)) }) @@ -156,7 +156,7 @@ export default defineComponent({ function paste (e: ClipboardEvent) { if (getEditor().hasTextFocus()) { const items = e.clipboardData!!.items - if (keys.m || keys.M) { // 粘贴 HTML 转为 markdown + if (keys.d || keys.D) { // 粘贴 HTML 转为 markdown for (let i = 0; i < items.length; i++) { if (items[i].type.match(/^text\/html$/i)) { items[i].getAsString(str => { @@ -172,7 +172,7 @@ export default defineComponent({ for (let i = 0; i < items.length; i++) { const fileType = items[i].type if (fileType.match(/^image\/(png|jpg|jpeg|gif)$/i)) { - const asBase64 = keys.b || keys.B // Ctrl + v 粘贴的同时 按下了 B 键,就粘贴 base64 图像 + const asBase64 = keys.b || keys.B // 粘贴的同时 按下了 B 键,就粘贴 base64 图像 emit('paste-img', items[i].getAsFile(), asBase64) } } @@ -243,7 +243,7 @@ export default defineComponent({ if (e.type === 'keydown') { keys[e.key] = true } else { - keys[e.key] = false + keys = {} } } diff --git a/frontend/src/components/Preview.vue b/frontend/src/components/Preview.vue index 2e401335..fc019311 100644 --- a/frontend/src/components/Preview.vue +++ b/frontend/src/components/Preview.vue @@ -71,6 +71,8 @@ import 'highlight.js/styles/atom-one-dark.css' import 'katex/dist/katex.min.css' import { useBus } from '../useful/bus' import { useToast } from '../useful/toast' +import { hasCtrlCmd, isAction } from '../useful/shortcut' + HighlightLineNumber.addStyles() const markdown = Markdown({ @@ -311,7 +313,7 @@ export default defineComponent({ async function keydownHandler (e: KeyboardEvent) { // 转换所有外链图片到本地 - if (e.key === 'l' && e.ctrlKey && e.altKey) { + if (isAction(e, 'transform-img-link')) { e.preventDefault() e.stopPropagation() const result = [] @@ -420,14 +422,19 @@ export default defineComponent({ } // 复制标题链接 - if (['H1', 'H2', 'H3', 'H4', 'H5', 'H6'].indexOf(target.tagName) > -1 && target.id && e.ctrlKey) { + if (['H1', 'H2', 'H3', 'H4', 'H5', 'H6'].indexOf(target.tagName) > -1 && target.id && hasCtrlCmd(e)) { bus.emit('copy-text', encodeMarkdownLink(filePath.value) + '#' + encodeMarkdownLink(decodeURIComponent(target.id))) return preventEvent() } + // 复制内容 + if (target.classList.contains('copy-inner-text')) { + bus.emit('copy-text', target.innerText) + } + if (target.tagName === 'IMG') { const img = target as HTMLImageElement - if (e.ctrlKey && e.shiftKey) { // 转换外链图片到本地 + if (isAction(e, 'transform-img-link-by-click')) { // 转换外链图片到本地 const data = await transformImgOutLink(img) if (data) { bus.emit('tree-refresh') @@ -450,7 +457,7 @@ export default defineComponent({ return } - if (target.tagName === 'TD' && target.classList.contains('yank-td') && e.ctrlKey) { + if (target.tagName === 'TD' && target.classList.contains('yank-td') && hasCtrlCmd(e)) { const start = parseInt(target.dataset.sourceLine || '0') const end = parseInt(target.dataset.sourceLineEnd || '0') const td = target as HTMLTableDataCellElement diff --git a/frontend/src/components/StatusBar.vue b/frontend/src/components/StatusBar.vue index 2b5b651c..49325b31 100644 --- a/frontend/src/components/StatusBar.vue +++ b/frontend/src/components/StatusBar.vue @@ -9,11 +9,11 @@ 字符数:{{documentInfo.textLength}} 已选中:{{documentInfo.selectedLength}} -
切换侧栏
-
切换换行
-
切换预览
-
切换终端
-
README
+
切换侧栏
+
切换换行
+
切换预览
+
切换终端
+
README
特色功能说明
{{autoPreview ? '同步渲染-已开启' : '同步渲染-已关闭'}}
@@ -27,6 +27,7 @@ import { useStore } from 'vuex' import { useBus } from '../useful/bus' import RepositorySwitch from './RepositorySwitch.vue' import SvgIcon from '../components/SvgIcon.vue' +import { isAction, getActionLabel } from '../useful/shortcut' export default defineComponent({ name: 'status-bar', @@ -69,31 +70,31 @@ export default defineComponent({ } function keydownHandler (e: KeyboardEvent) { - if (e.key === 'e' && e.altKey) { + if (isAction(e, 'toggle-side')) { toggleSide() e.preventDefault() e.stopPropagation() } - if (e.key === 'v' && e.altKey) { + if (isAction(e, 'toggle-view')) { toggleView() e.preventDefault() e.stopPropagation() } - if (e.key === 'o' && e.altKey) { + if (isAction(e, 'toggle-xterm')) { toggleXterm() e.preventDefault() e.stopPropagation() } - if (e.key === 'w' && e.altKey) { + if (isAction(e, 'toggle-wrap')) { toggleWrap() e.preventDefault() e.stopPropagation() } - if (e.key === 'h' && e.altKey) { + if (isAction(e, 'toggle-readme')) { toggleReadme() e.preventDefault() e.stopPropagation() @@ -119,6 +120,7 @@ export default defineComponent({ toggleFeature, toggleRender, rerenderView, + getActionLabel, } }, }) diff --git a/frontend/src/plugins/CodePlugin.ts b/frontend/src/plugins/CodePlugin.ts index ec7d862d..7d96bf36 100644 --- a/frontend/src/plugins/CodePlugin.ts +++ b/frontend/src/plugins/CodePlugin.ts @@ -1,10 +1,11 @@ +import { getKeyLabel } from '@/useful/shortcut' import Markdown from 'markdown-it' export default (md: Markdown) => { const Fun = (fn: Function) => (tokens: any, idx: any, options: any, env: any, slf: any) => { if (tokens[idx].attrIndex('title') < 0) { - tokens[idx].attrPush(['title', 'Ctrl + 单击复制代码']) - tokens[idx].attrPush(['onclick', "event.ctrlKey && window.globalBus.emit('copy-text', this.innerText)"]) + tokens[idx].attrJoin('class', 'copy-inner-text') + tokens[idx].attrPush(['title', getKeyLabel('CtrlCmd') + ' + 单击复制']) } return (fn)(tokens, idx, options, env, slf) diff --git a/frontend/src/plugins/TocPlugin.ts b/frontend/src/plugins/TocPlugin.ts index 1243ea1f..99d9cb2c 100644 --- a/frontend/src/plugins/TocPlugin.ts +++ b/frontend/src/plugins/TocPlugin.ts @@ -1,6 +1,7 @@ // https://github.com/Oktavilla/markdown-it-table-of-contents import Markdown from 'markdown-it' +import { getKeyLabel } from '@/useful/shortcut' import { injectLineNumbers } from './SourceLinePlugin' @@ -185,7 +186,7 @@ export default (md: Markdown, o: any) => { } if (header.attrIndex('title') < 0) { - header.attrSet('title', 'Ctrl + 单击复制链接') + header.attrSet('title', getKeyLabel('CtrlCmd') + ' + 单击复制链接') } return injectLineNumbers(tokens, idx, opt, env, slf) diff --git a/frontend/src/useful/env.ts b/frontend/src/useful/env.ts index b7589d3c..a66bf01b 100644 --- a/frontend/src/useful/env.ts +++ b/frontend/src/useful/env.ts @@ -28,7 +28,7 @@ const openAlwaysOnTopWindow = (url: string, target = '_blank') => { } window.addEventListener('keydown', e => { - if (e.ctrlKey) { + if (e.ctrlKey || e.metaKey) { if (e.key === '0') { webContents.setZoomFactor(1) } else if (e.key === '=') { @@ -40,7 +40,7 @@ const openAlwaysOnTopWindow = (url: string, target = '_blank') => { }) window.addEventListener('mousewheel', e => { - if (e.ctrlKey) { + if (e.ctrlKey || e.metaKey) { changeZoomFactor(e.deltaY < 0) } }) diff --git a/frontend/src/useful/shortcut.ts b/frontend/src/useful/shortcut.ts new file mode 100644 index 00000000..52d2603d --- /dev/null +++ b/frontend/src/useful/shortcut.ts @@ -0,0 +1,85 @@ +import { getLogger } from './utils' + +const logger = getLogger('shortcut') + +const isMacOS = /macintosh|mac os x/i.test(navigator.userAgent) +const Ctrl = 'Ctrl' +const CtrlCmd = 'CtrlCmd' +const Alt = 'Alt' +const Shift = 'Shift' +const LeftClick = 0 + +type XKey = typeof Ctrl | typeof CtrlCmd | typeof Alt | typeof Shift + +const actions = { + 'toggle-side': [Alt, 'e'], + 'toggle-wrap': [Alt, 'w'], + 'toggle-view': [Alt, 'v'], + 'toggle-xterm': [Alt, 't'], + 'toggle-readme': [Alt, 'h'], + 'insert-document': [CtrlCmd, Alt, 'i'], + 'show-quick-open': [CtrlCmd, 'p'], + 'transform-img-link-by-click': [CtrlCmd, Shift, LeftClick], + 'transform-img-link': [CtrlCmd, Shift, 'l'], + 'file-tabs-switch-left': [Ctrl, Alt, 'ArrowLeft'], + 'file-tabs-switch-right': [Ctrl, Alt, 'ArrowRight'], +} + +type ActionName = keyof typeof actions + +export const getKeyLabel = (key: XKey | string | number) => { + switch (key) { + case CtrlCmd: + return isMacOS ? 'Cmd' : 'Ctrl' + + case Alt: + return isMacOS ? 'Option' : 'Ctrl' + + default: + return key.toString().toUpperCase() + } +} + +export const getActionLabel = (name: ActionName) => { + const keys: any[] = actions[name] + return keys.map(getKeyLabel).join(' + ') +} + +export const hasCtrlCmd = (e: KeyboardEvent | MouseEvent) => isMacOS ? e.metaKey : e.ctrlKey + +export const matchKeys = (e: KeyboardEvent | MouseEvent, keys: (string | number)[]) => { + for (const key of keys) { + switch (key) { + case CtrlCmd: + if (!hasCtrlCmd(e)) return false + break + case Alt: + if (!e.altKey) return false + break + case Ctrl: + if (!e.ctrlKey) return false + break + case Shift: + if (!e.shiftKey) return false + break + default: + if (e instanceof KeyboardEvent) { + if (key !== e.key && `Key${key.toString().toUpperCase()}` !== e.code) return false + } else { + if (key !== e.button) return false + } + } + } + + return true +} + +export const getCurrentAction = (e: KeyboardEvent | MouseEvent) => { + logger.debug('getCurrentAction', { e }) + return (Object.keys(actions) as ActionName[]).find(action => matchKeys(e, actions[action])) +} + +export const isAction = (e: KeyboardEvent | MouseEvent, name: ActionName) => { + logger.debug('isAction', name, e) + return matchKeys(e, actions[name]) +} diff --git a/frontend/src/useful/startup.ts b/frontend/src/useful/startup.ts index f770a683..2396b7be 100644 --- a/frontend/src/useful/startup.ts +++ b/frontend/src/useful/startup.ts @@ -35,7 +35,7 @@ export default function startup () { } window.addEventListener('keydown', e => { - if (e.ctrlKey) { + if (e.ctrlKey || e.metaKey) { if (e.key === '0') { webContents.setZoomFactor(1) } else if (e.key === '=') { @@ -49,7 +49,7 @@ export default function startup () { window.addEventListener('mousewheel', event => { const e = event as WheelEvent - if (e.ctrlKey) { + if (e.ctrlKey || e.metaKey) { changeZoomFactor(e.deltaY < 0) } }) diff --git a/frontend/src/useful/utils.ts b/frontend/src/useful/utils.ts index 634db6c8..8ef739aa 100644 --- a/frontend/src/useful/utils.ts +++ b/frontend/src/useful/utils.ts @@ -44,3 +44,18 @@ export const dataURItoBlobLink = (dataURI: string) => { const blob = new Blob([ab], { type: mimeString }) return window.URL.createObjectURL(blob) } + +export const getLogger = (subject: string) => { + const logger = (level: string) => (...args: any) => { + const time = `${new Date().toLocaleString()}.${Date.now() % 1000}` + ;(console as any)[level](`[${time}] ${subject} >`, ...args) + } + + return { + debug: logger('debug'), + log: logger('log'), + info: logger('info'), + warn: logger('warn'), + error: logger('error') + } +} From 8bb86baacca0ed26728f4c5851c212ac4bb110f1 Mon Sep 17 00:00:00 2001 From: purocean Date: Sat, 16 Jan 2021 23:59:10 +0800 Subject: [PATCH 13/19] =?UTF-8?q?=E7=9B=AE=E5=BD=95=E6=A0=91=E7=A7=BB?= =?UTF-8?q?=E9=99=A4=E9=BC=A0=E6=A0=87=E5=BF=AB=E6=8D=B7=E9=94=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/TreeNode.vue | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/frontend/src/components/TreeNode.vue b/frontend/src/components/TreeNode.vue index e6421735..b4d38299 100644 --- a/frontend/src/components/TreeNode.vue +++ b/frontend/src/components/TreeNode.vue @@ -1,14 +1,10 @@