├── .gitignore ├── 5-docker ├── .env ├── mysql │ └── my.cnf ├── srs │ └── rtc2rtmp.conf └── compose.yml ├── 1-system ├── 3-command.zsh ├── zsh-vi-mode.zsh ├── main.zsh ├── .gitconfig ├── 1-env.zsh ├── cursor-state.zsh ├── vi-basic.zsh ├── 2-aliases.zsh ├── .zimrc ├── .nvim.vim ├── .commitlintrc.js ├── .zshrc └── .vimrc ├── 3-js ├── index.md ├── package.json ├── word-sort.js ├── bili-danmu.js ├── pnpm-lock.yaml ├── diary-stats.js └── diary-stats-utools.js ├── 6-chrome └── stylish │ ├── 1-现代 JS 教程.css │ ├── 3-语雀.css │ └── 2-打字测试.css ├── 4-shell └── syncFileConfig.sh ├── README.md └── 2-vscode ├── extensions.txt ├── keybindings.json └── settings.json /.gitignore: -------------------------------------------------------------------------------- 1 | **/node_modules 2 | **/tmp 3 | dist 4 | build 5 | .DS_Store 6 | -------------------------------------------------------------------------------- /5-docker/.env: -------------------------------------------------------------------------------- 1 | # mysql 数据库配置 2 | MYSQL_ROOT=root 3 | MYSQL_ROOT_PASSWORD=password 4 | -------------------------------------------------------------------------------- /1-system/3-command.zsh: -------------------------------------------------------------------------------- 1 | # 自定义命令 2 | 3 | # 新建目录并进入 4 | nd() { 5 | mkdir -p -- "$1" && 6 | cd -P -- "$1" 7 | } 8 | -------------------------------------------------------------------------------- /3-js/index.md: -------------------------------------------------------------------------------- 1 | > 1 2 | 3 | - Austria 4 | - athens 5 | - directory 6 | - experience 7 | 8 | > 2 9 | 10 | - age 11 | - name 12 | - sex 13 | -------------------------------------------------------------------------------- /1-system/zsh-vi-mode.zsh: -------------------------------------------------------------------------------- 1 | # 提升 ZVM 切换速度 2 | KEYTIMEOUT=50 3 | 4 | bindkey -M vicmd "H" vi-beginning-of-line 5 | bindkey -M vicmd "L" vi-end-of-line 6 | -------------------------------------------------------------------------------- /6-chrome/stylish/1-现代 JS 教程.css: -------------------------------------------------------------------------------- 1 | .main_width-limit { 2 | max-width: 1080px; 3 | } 4 | 5 | pre, 6 | code { 7 | font-family: 'Input Mono Freeze' !important; 8 | } 9 | -------------------------------------------------------------------------------- /1-system/main.zsh: -------------------------------------------------------------------------------- 1 | source ~/.config/zsh/1-env.zsh 2 | source ~/.config/zsh/2-aliases.zsh 3 | source ~/.config/zsh/3-command.zsh 4 | source ~/.config/zsh/zsh-vi-mode.zsh 5 | -------------------------------------------------------------------------------- /3-js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module", 3 | "dependencies": { 4 | "axios": "^1.7.2", 5 | "clipboardy": "^4.0.0", 6 | "number-precision": "^1.6.0" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /1-system/.gitconfig: -------------------------------------------------------------------------------- 1 | # This is Git's per-user configuration file. 2 | [user] 3 | name = fengstats 4 | email = feng2860984180@163.com 5 | [core] 6 | ignorecase = false 7 | quotepath = false 8 | -------------------------------------------------------------------------------- /1-system/1-env.zsh: -------------------------------------------------------------------------------- 1 | # 导出环境变量 2 | 3 | export LC_ALL=en_US.UTF-8 4 | export LANG=en_US.UTF-8 5 | 6 | # proxy 7 | export https_proxy=http://127.0.0.1:7890 http_proxy=http://127.0.0.1:7890 all_proxy=socks5://127.0.0.1:7890 8 | -------------------------------------------------------------------------------- /1-system/cursor-state.zsh: -------------------------------------------------------------------------------- 1 | # 配置终端光标状态 2 | 3 | # NOTE: 用于每次新的命令行始终保持细条光标样式,可以覆盖 VS Code 的终端光标样式 4 | # 终端启动的时候使用细条光标(竖条) 5 | echo -ne '\e[5 q' 6 | 7 | # 每个新的提示(对话)都使用细条光标 8 | preexec() { 9 | echo -ne '\e[5 q' 10 | } 11 | _fix_cursor() { 12 | echo -ne '\e[5 q' 13 | } 14 | precmd_functions+=(_fix_cursor) 15 | -------------------------------------------------------------------------------- /1-system/vi-basic.zsh: -------------------------------------------------------------------------------- 1 | bindkey -v 2 | # 不同模式下切换光标状态: 细条 或者 块状 3 | function zle-keymap-select { 4 | if [[ ${KEYMAP} == vicmd ]] || [[ $1 = 'block' ]]; then 5 | echo -ne '\e[1 q' 6 | elif [[ ${KEYMAP} == main ]] || [[ ${KEYMAP} == viins ]] || [[ ${KEYMAP} = '' ]] || [[ $1 = 'beam' ]]; then 7 | echo -ne '\e[5 q' 8 | fi 9 | } 10 | zle -N zle-keymap-select 11 | -------------------------------------------------------------------------------- /6-chrome/stylish/3-语雀.css: -------------------------------------------------------------------------------- 1 | /* 笔记内容:中心区域 */ 2 | .ne-paragraph-spacing-relax.ne-typography-classic, 3 | .ne-viewer.ne-paragraph-spacing-relax.ne-typography-classic .ne-viewer-body { 4 | font-family: Arial, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Helvetica Neue, Helvetica, Arial, sans-serif, 5 | Segoe UI; 6 | } 7 | 8 | /* 左侧目录 */ 9 | .catalogTreeItem-module_CatalogItem_xkX7p 10 | .catalogTreeItem-module_content_fLFbS 11 | .catalogTreeItem-module_titleWrapper_sFyDt 12 | .catalogTreeItem-module_title_snpKw { 13 | font-family: Arial; 14 | } 15 | -------------------------------------------------------------------------------- /5-docker/mysql/my.cnf: -------------------------------------------------------------------------------- 1 | # 数据库配置文件:可以配置存储引擎,字符集,最大连接数等等 2 | # utf8mb4: 更广泛的字符编码和表情符号 3 | 4 | [mysqld] 5 | # 兼容 8.0 之前的客户端服务 6 | default-authentication-plugin=mysql_native_password 7 | 8 | # 设置服务器字符编码 9 | character-set-server=utf8mb4 10 | collation-server=utf8mb4_unicode_ci 11 | 12 | # 忽略数据表名大小写:该属性只有初始化构建时才生效 13 | # lower_case_table_names=1 14 | 15 | # 最大允许传输包大小 16 | max_allowed_packet=20M 17 | 18 | # 最大连接数 19 | max_connections=5000 20 | 21 | [mysql] 22 | host=localhost 23 | # user=test 24 | # password=test 25 | # 设置客户端默认字符集 26 | default-character-set=utf8mb4 27 | 28 | [client] 29 | port=3306 30 | default-character-set=utf8mb4 31 | -------------------------------------------------------------------------------- /1-system/2-aliases.zsh: -------------------------------------------------------------------------------- 1 | # 配置别名命令 2 | 3 | alias sshroot='ssh root@fenglive.icu' 4 | alias so='source ~/.zshrc && exec zsh' 5 | 6 | # 系统 7 | alias ra='ranger' 8 | alias q='exit' 9 | alias x='exit' 10 | alias c='clear' 11 | alias o='open .' 12 | alias yp='copypath' 13 | alias cz='czg' 14 | 15 | # Git 16 | alias gs='git status' 17 | alias gad='git add .' 18 | alias gcm="git commit -m" 19 | alias gpull='git pull' 20 | alias gpush='git push' 21 | 22 | # 显示当前目录信息 23 | alias l='exa' 24 | alias ll='exa -1' 25 | alias ls='exa -lbF --git' 26 | alias lt='exa --tree --level=2' 27 | alias la='exa -lbhHigUmuSa --time-style=long-iso --git --color-scale' 28 | -------------------------------------------------------------------------------- /1-system/.zimrc: -------------------------------------------------------------------------------- 1 | # 内置扩展 2 | zmodule environment 3 | zmodule input 4 | zmodule termtitle 5 | zmodule utility 6 | zmodule completion 7 | zmodule git-info 8 | zmodule duration-info 9 | zmodule prompt-pwd 10 | zmodule magicmace 11 | 12 | # 其他扩展 13 | zmodule romkatv/powerlevel10k 14 | zmodule zsh-users/zsh-completions 15 | zmodule zsh-users/zsh-autosuggestions 16 | zmodule zsh-users/zsh-history-substring-search 17 | zmodule zdharma-continuum/fast-syntax-highlighting 18 | zmodule supercrabtree/k 19 | zmodule hlissner/zsh-autopair 20 | zmodule jeffreytse/zsh-vi-mode 21 | 22 | # oh-my-zsh 的扩展 23 | # clipboard 里面有个命令(copyclip)是 copypath 需要用的,所以必须先加载进来 24 | zmodule ohmyzsh/ohmyzsh --root lib --source clipboard.zsh 25 | zmodule ohmyzsh/ohmyzsh --root plugins/copypath 26 | zmodule ohmyzsh/ohmyzsh --root plugins/autojump 27 | -------------------------------------------------------------------------------- /3-js/word-sort.js: -------------------------------------------------------------------------------- 1 | // 单词排序脚本 2 | 3 | import fs from 'fs' 4 | import path from 'path' 5 | import { fileURLToPath } from 'url' 6 | 7 | // 在 ES Module 里面不能直接用 __dirname 麻烦死我了 8 | // NOTE: 因为我在 package.json 中配置 type: module 9 | const _fileName = fileURLToPath(import.meta.url) 10 | const filePath = process.argv.slice(2)[0] || path.join(path.dirname(_fileName), 'index.md') 11 | const data = fs.readFileSync(filePath, 'utf8') 12 | 13 | let text = '' 14 | let match = null 15 | // const regex = /(> .*)\n([\s\S]*?)(?=\n{2}|$)/g 16 | const regex = /(>.*)\n([\s\S]*?)(?=(>.*)|$)/g 17 | while ((match = regex.exec(data)) !== null) { 18 | // 匹配出所有的单词 19 | const title = match[1] 20 | const words = match[2].match(/\w+/g) 21 | text += title + '\n\n- ' + words.sort().join('\n- ') + '\n\n' 22 | } 23 | 24 | // 写入文件 25 | fs.writeFileSync(filePath, text, 'utf8') 26 | -------------------------------------------------------------------------------- /5-docker/srs/rtc2rtmp.conf: -------------------------------------------------------------------------------- 1 | 2 | listen 1935; 3 | max_connections 1000; 4 | daemon off; 5 | srs_log_tank console; 6 | 7 | http_server { 8 | enabled on; 9 | listen 8080; 10 | dir ./objs/nginx/html; 11 | } 12 | 13 | http_api { 14 | enabled on; 15 | } 16 | stats { 17 | network 0; 18 | } 19 | rtc_server { 20 | enabled on; 21 | listen 8000; # UDP port 22 | # @see https://ossrs.net/lts/zh-cn/docs/v4/doc/webrtc#config-candidate 23 | candidate $CANDIDATE; 24 | } 25 | 26 | vhost __defaultVhost__ { 27 | rtc { 28 | enabled on; 29 | # @see https://ossrs.net/lts/zh-cn/docs/v4/doc/webrtc#rtmp-to-rtc 30 | rtmp_to_rtc on; 31 | # @see https://ossrs.net/lts/zh-cn/docs/v4/doc/webrtc#rtc-to-rtmp 32 | rtc_to_rtmp on; 33 | # https://github.com/ossrs/srs/issues/2677 34 | # https://github.com/ossrs/srs/issues/3102 35 | pli_for_rtmp 0.5; 36 | } 37 | 38 | http_remux { 39 | enabled on; 40 | mount [vhost]/[app]/[stream].flv; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /6-chrome/stylish/2-打字测试.css: -------------------------------------------------------------------------------- 1 | /* 整个打字区域 */ 2 | #content { 3 | margin-top: 66px; 4 | height: 720px !important; 5 | } 6 | 7 | /* 所有行 */ 8 | #content .typing .text { 9 | font-family: Input Mono Freeze !important; 10 | height: 0.5em; 11 | border: 0 !important; 12 | border-bottom: 1px solid #ccc; 13 | } 14 | 15 | /* 输入框 */ 16 | #content .typing input { 17 | height: 0; 18 | font-family: Input Mono Freeze !important; 19 | z-index: -999; 20 | } 21 | 22 | /* 正在输入的行 */ 23 | #content div.typing_on, 24 | #content div.typing_on div { 25 | background-color: #fff !important; 26 | } 27 | #content div.typing_on div > span { 28 | position: relative; 29 | } 30 | #content div.typing_on .green:last-child:after, 31 | #content div.typing_on .red:last-child:after { 32 | content: ''; 33 | position: absolute; 34 | left: auto; 35 | width: 0.6em; 36 | height: 1.3em; 37 | border-bottom: 0.15em solid #0984e3; 38 | /* animation: sparkle 0.6s infinite; */ 39 | } 40 | 41 | /* 一闪一闪的动画 */ 42 | @keyframes sparkle { 43 | 0% { 44 | opacity: 1; 45 | } 46 | 50% { 47 | opacity: 0.5; 48 | } 49 | 100% { 50 | opacity: 1; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /4-shell/syncFileConfig.sh: -------------------------------------------------------------------------------- 1 | # system path 2 | userPath="/Users/feng" 3 | vscodeSystemPath="${userPath}/Library/Application Support/Code/User" 4 | zshPath="${userPath}/.config/zsh" 5 | 6 | # my config path 7 | configPath="${userPath}/codebase/utils/config" 8 | systemPath="${configPath}/1-system" 9 | vsocdePath="${configPath}/2-vscode" 10 | pathArr=(${systemPath} ${vsocdePath}) 11 | 12 | # 自动校验创建目录 13 | for item in "${pathArr[@]}"; do 14 | if [ ! -d "${item}" ]; then 15 | mkdir -p "${item}" 16 | echo "${item} 路径目录创建成功!" 17 | fi 18 | done 19 | 20 | # gitconfig 21 | cat ${userPath}/.gitconfig >${systemPath}/.gitconfig 22 | # czg 23 | cat ${userPath}/.commitlintrc.js >${systemPath}/.commitlintrc.js 24 | # vim 25 | cat ${userPath}/.vim/vimrc >${systemPath}/.vimrc 26 | cat ${userPath}/.vim/nvim.vim >${systemPath}/.nvim.vim 27 | # zimrc 28 | cat ${userPath}/.zimrc >${systemPath}/.zimrc 29 | # zshrc 30 | cat ${userPath}/.zshrc >${systemPath}/.zshrc 31 | # other zsh 32 | # NOTE: -f 参数代表强制覆盖,若想递归复制可以添加 -r 参数 33 | cp -f ${zshPath}/* ${systemPath}/ 34 | 35 | # VS Code 36 | # NOTE: 双引号用于解析变量,双引号内的变量可以被扩展,而单引号内的变量则不会被扩展 37 | # 这里需要再添加一个双引号才能特殊处理带有空格的目录/文件名 38 | # grep -v 取反,简单做下数据脱敏(key)-e 指定多个模式 39 | grep -v -e "secret" -e "baidu.comate.license" "${vscodeSystemPath}/settings.json" >${vsocdePath}/settings.json 40 | cat "${vscodeSystemPath}/keybindings.json" >${vsocdePath}/keybindings.json 41 | 42 | echo "
✅ 同步 config 配置文件完成!
" 43 | -------------------------------------------------------------------------------- /5-docker/compose.yml: -------------------------------------------------------------------------------- 1 | # docker compose 版本 2 | version: '3.7' 3 | 4 | services: 5 | # 服务名称 6 | mysql: 7 | # 镜像 8 | image: mysql:8.0 9 | # docker 重启后容器也跟着重启 10 | restart: always 11 | # 构建容器后所执行的命令 12 | command: 13 | # 服务器加了个更广泛的字符编码和表情符号,在 my.cnf 可覆盖 14 | # --character-set-server=utf8mb4 15 | # --collation-server=utf8mb4_unicode_ci 16 | # --lower-case-table-names=1 # NOTE: 忽略数据表名大小写:该属性只有初始化构建时才生效,my.cnf 无法覆盖,必须重新配置 mysql 服务 17 | # 端口映射 18 | ports: 19 | - 3306:3306 20 | # 卷体积映射:docker compose 的好处就是可以使用相对路径 21 | volumes: 22 | # 配置文件:需要本地目录存在这个文件 23 | - ./mysql/conf/my.cnf:/etc/my.cnf 24 | # 数据目录:本地存在目录即可 25 | - ./mysql/data:/var/lib/mysql 26 | # 环境变量 27 | environment: 28 | # 用户密码 29 | MYSQL_USER: ${MYSQL_ROOT} 30 | MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} 31 | # 时区 32 | TZ: Asia/Shanghai 33 | 34 | srs: 35 | image: registry.cn-hangzhou.aliyuncs.com/ossrs/srs:5 36 | restart: always 37 | environment: 38 | # 在 srs 内部配置文件用得上,比如 rtc2rtmp.conf 39 | # - CANDIDATE=$(ifconfig en6 inet | grep 'inet ' | awk '{print $2}') # TODO: 有点问题,有空再看 40 | - CANDIDATE=192.168.1.2 # NOTE: 写死的 ip 可能会变,注意检查 41 | command: 42 | ./objs/srs -c conf/rtc2rtmp.conf 43 | ports: 44 | - 8080:8080 45 | - 1935:1935 46 | - 1985:1985 47 | - 8000:8000/udp 48 | volumes: 49 | # NOTE: 这种方式你要确保本地有 conf 和 objs 以及内部配置文件信息 50 | - ./srs/conf:/usr/local/srs/conf 51 | - ./srs/objs:/usr/local/srs/objs 52 | # 这里直接 volume 名字即可 53 | # - srs_conf:/usr/local/srs/conf 54 | # - srs_objs:/usr/local/srs/objs 55 | 56 | # 在 docker run 命令使用 Docker 内的 Volumes 时 Dokcer 会自动创建好 57 | # 但在 compose 内不行,要先在顶层先定义 volumes 名称用于创建 58 | # volumes: 59 | # srs_conf: 60 | # srs_objs: 61 | -------------------------------------------------------------------------------- /1-system/.nvim.vim: -------------------------------------------------------------------------------- 1 | " Settings 2 | " =============================================== 3 | set clipboard=unnamedplus 4 | set clipboard=unnamed 5 | set ignorecase smartcase 6 | set ttimeout ttimeoutlen=10 7 | 8 | " Key Map 9 | " =============================================== 10 | let mapleader=" " 11 | " nmap j gj 12 | " nmap k gk 13 | " 临时解决一下折叠行自动展开问题 14 | map J 4gj 15 | map K 4gk 16 | nmap '' ysiw' 17 | nmap "" ysiw" 18 | noremap H ^ 19 | noremap L g_ 20 | nnoremap U 21 | nnoremap vv viw 22 | nnoremap die ggdG 23 | nnoremap vie ggvG 24 | nnoremap df V$%d 25 | nnoremap iw V$% 26 | nnoremap yf V$%y 27 | nnoremap ; :nohl 28 | vnoremap p "_dP 29 | " vnoremap '' S' 30 | 31 | " VS Code Notify 32 | " =============================================== 33 | " basic 34 | nnoremap e call VSCodeNotify('workbench.action.toggleSidebarVisibility') 35 | nnoremap l call VSCodeNotify('workbench.action.toggleAuxiliaryBar') 36 | nnoremap s call VSCodeNotify('workbench.action.files.save') 37 | nnoremap q call VSCodeNotify('workbench.action.closeActiveEditor') 38 | nnoremap w call VSCodeNotify('workbench.action.files.saveWithoutFormatting') 39 | nnoremap e call VSCodeNotify('workbench.action.toggleSidebarVisibility') 40 | " editor 41 | nnoremap s call VSCodeNotify('leap.find') 42 | nnoremap zj call VSCodeNotify('editor.gotoNextFold') 43 | nnoremap zk call VSCodeNotify('editor.gotoPreviousFold') 44 | nnoremap zc call VSCodeNotify('editor.fold') 45 | nnoremap zo call VSCodeNotify('editor.unfold') 46 | nnoremap zC call VSCodeNotify('editor.foldAll') 47 | nnoremap zO call VSCodeNotify('editor.unfoldAll') 48 | " nnoremap gj call VSCodeNotify('cursorMove', { 'to': 'down', 'by': 'wrappedLine', 'value': v:count1 }) 49 | " nnoremap gk call VSCodeNotify('cursorMove', { 'to': 'up', 'by': 'wrappedLine', 'value': v:count1 }) 50 | " nnoremap i call VSCodeNotify('extension.toggleBool') 51 | 52 | " Plugins 53 | " =============================================== 54 | call plug#begin('~/.vim/plugged') 55 | Plug 'gcmt/wildfire.vim' 56 | Plug 'tpope/vim-surround' 57 | call plug#end() 58 | -------------------------------------------------------------------------------- /3-js/bili-danmu.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | 3 | const request = axios.create({ 4 | headers: { 5 | 'User-Agent': 6 | 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36', 7 | Referer: 'https://www.bilibili.com/', 8 | }, 9 | }) 10 | 11 | request.interceptors.response.use( 12 | (response) => response.data, 13 | (err) => { 14 | console.log(err) 15 | }, 16 | ) 17 | 18 | let count = 100 19 | 20 | async function sendReq() { 21 | // 三个变量需要控制 22 | // msg 弹幕 23 | // cookie 24 | // csrf 验证 25 | // roomid 房间号 26 | 27 | const msg = count-- 28 | const roomid = '24337535' 29 | const csrf = 'd9869c210ec46e4a22c7b49e7b6c8bef' 30 | 31 | const res = await request({ 32 | url: 'https://api.live.bilibili.com/msg/send', 33 | method: 'POST', 34 | headers: { 35 | cookie: `Hm_lpvt_8a6e55dbd2870f0f5bc9194cddf32a02=1719750073; Hm_lvt_8a6e55dbd2870f0f5bc9194cddf32a02=1719750073; PVID=6; browser_resolution=1756-1001; CURRENT_FNVAL=4048; bili_ticket=eyJhbGciOiJIUzI1NiIsImtpZCI6InMwMyIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MjAwMDkyNjgsImlhdCI6MTcxOTc1MDAwOCwicGx0IjotMX0.4xLm1sY2H4sdDOGHHFDtPSfCH4hAl2cL5cQDJ0vy8jk; bili_ticket_expires=1720009208; bp_t_offset_3546561336314420=948808372184940544; home_feed_column=5; b_lsid=4510F78D8_19069176086; enable_web_push=DISABLE; header_theme_version=CLOSE; sid=6ugtopg9; LIVE_BUVID=AUTO7017141061232796; DedeUserID=3546561336314420; DedeUserID__ckMd5=7d88b7f3940d5e75; SESSDATA=8dad6bc2%2C1729657772%2Cbe34b%2A41CjCfxU8MV6b9uHoy_rynrikLq0BIEXzAWKKulelMMSIe7BMnG9U0DZcC-BYTL945GdYSVnpEQ1dIMGFVSVZfWXFSUjhueVpzcUc0b2hPY3JfYWQ4ajBveEFBRkpVblFGSTJlbU1QZElnQ3hmRS1rTEUwVl9KR1pLRkVHUXJCc1piLVF1TW11WHl3IIEC; bili_jct=d9869c210ec46e4a22c7b49e7b6c8bef; FEED_LIVE_VERSION=V_WATCHLATER_PIP_WINDOW3; buvid_fp=e91b03d2e1ed017e755baff80ded460c; _uuid=9DD9BE11-EA53-D4E9-FCFC-E6D1AB5E2DE527149infoc; buvid4=DC6A0D8F-FBA1-1AE6-7E3D-2662B1421CD227327-024042604-szwJdP2i5gLa6D9G20NMIw%3D%3D; rpdid=|(u)~m~Y)uku0J'u~||YJ|lYu; b_nut=1700630560; buvid3=14B1BF0D-524D-B89C-BBBF-0E8C47F5FFEE60432infoc`, 36 | 'Content-Type': 'application/x-www-form-urlencoded', 37 | }, 38 | data: { 39 | msg, 40 | csrf, 41 | roomid, 42 | // 下面这几个固定的,但是必须要发 43 | fontsize: 25, 44 | color: 5816798, 45 | rnd: 1719748133, 46 | }, 47 | }) 48 | 49 | if (res.code === 0) { 50 | console.log(`弹幕: ${msg} 发送成功 ✅`) 51 | } else { 52 | console.log(`弹幕: ${msg} 发送失败 ❌`) 53 | console.log(res) 54 | } 55 | } 56 | 57 | function getRandomNum(min, max) { 58 | const num = Math.floor(Math.random() * (max - min + 1)) + min 59 | console.log(num) 60 | return num 61 | } 62 | 63 | sendReq() 64 | 65 | setInterval(() => { 66 | sendReq() 67 | }, 22000) 68 | -------------------------------------------------------------------------------- /1-system/.commitlintrc.js: -------------------------------------------------------------------------------- 1 | // .commitlintrc.js 2 | 3 | module.exports = { 4 | rules: { 5 | // @see: https://commitlint.js.org/#/reference-rules 6 | }, 7 | prompt: { 8 | alias: { 9 | fd: 'docs: fix typos', 10 | ur: 'docs: update README', 11 | cu: 'chore: update', 12 | }, 13 | messages: { 14 | type: '选择你要提交的类型 :', 15 | scope: '选择一个提交范围(可选):', 16 | customScope: '请输入自定义的提交范围 :', 17 | subject: '填写简短精炼的变更描述 :\n', 18 | body: '填写更加详细的变更描述(可选)。使用 "|" 换行 :\n', 19 | breaking: '列举非兼容性重大的变更(可选)。使用 "|" 换行 :\n', 20 | footerPrefixesSelect: '选择关联issue前缀(可选):', 21 | customFooterPrefix: '输入自定义issue前缀 :', 22 | footer: '列举关联issue (可选) 例如: #31, #I3244 :\n', 23 | confirmCommit: '是否提交或修改commit?', 24 | }, 25 | types: [ 26 | { value: 'feat', name: 'feat: ✨ 新增功能 | A new feature' }, 27 | { value: 'fix', name: 'fix: 🐛 修复缺陷 | A bug fix' }, 28 | { value: 'docs', name: 'docs: 📝 文档更新 | Documentation only changes' }, 29 | { value: 'style', name: 'style: 💄 代码格式 | Changes that do not affect the meaning of the code' }, 30 | { value: 'refactor', name: 'refactor: ♻️ 代码重构 | A code change that neither fixes a bug nor adds a feature' }, 31 | { value: 'perf', name: 'perf: ⚡️ 性能提升 | A code change that improves performance' }, 32 | { value: 'test', name: 'test: ✅ 测试相关 | Adding missing tests or correcting existing tests' }, 33 | { value: 'build', name: 'build: 📦️ 构建相关 | Changes that affect the build system or external dependencies' }, 34 | { value: 'ci', name: 'ci: 🎡 持续集成 | Changes to our CI configuration files and scripts' }, 35 | { value: 'revert', name: 'revert: ⏪️ 回退代码 | Revert to a commit' }, 36 | { value: 'chore', name: 'chore: 🛠 其他修改 | Other changes that do not modify src or test files' }, 37 | ], 38 | useEmoji: false, 39 | emojiAlign: 'center', 40 | useAI: false, 41 | aiNumber: 1, 42 | themeColorCode: '', 43 | scopes: [], 44 | allowCustomScopes: true, 45 | allowEmptyScopes: true, 46 | customScopesAlign: 'bottom', 47 | customScopesAlias: 'custom', 48 | emptyScopesAlias: 'empty', 49 | upperCaseSubject: false, 50 | markBreakingChangeMode: false, 51 | allowBreakingChanges: ['feat', 'fix'], 52 | breaklineNumber: 100, 53 | breaklineChar: '|', 54 | skipQuestions: [], 55 | issuePrefixes: [ 56 | // 如果使用 gitee 作为开发管理 57 | { value: 'link', name: 'link: 链接 ISSUES 进行中' }, 58 | { value: 'closed', name: 'closed: 标记 ISSUES 已完成' }, 59 | ], 60 | customIssuePrefixAlign: 'top', 61 | emptyIssuePrefixAlias: 'skip', 62 | customIssuePrefixAlias: 'custom', 63 | allowCustomIssuePrefix: true, 64 | allowEmptyIssuePrefix: true, 65 | confirmColorize: true, 66 | maxHeaderLength: Infinity, 67 | maxSubjectLength: Infinity, 68 | minSubjectLength: 0, 69 | scopeOverrides: undefined, 70 | defaultBody: '', 71 | defaultIssues: '', 72 | defaultScope: '', 73 | defaultSubject: '', 74 | }, 75 | } 76 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

前言

2 | 3 |

🤩 一些配置文件 ➕ 主题预览 ➕ 字体推荐

4 | 5 | > VS Code 6 | 7 | - [settings.json](./2-vscode/settings.json) · 系统配置文件 8 | - [keybindings.json](./2-vscode/keybindings.json) · 键盘快捷键映射配置文件 9 | 10 | > 系统 11 | 12 | - [nvim](./1-system/.nvim.vim) | [vimrc](./1-system/.vimrc) | [zimrc](./1-system/.zimrc) | [zshrc](./1-system/main.zsh) 13 | - [Zimfw](https://github.com/zimfw/zimfw) 一个比 oh-my-zsh 更轻量级更快的 zsh 配置框架 14 | 15 |

主题

16 | 17 | > 常用 18 | 19 | - Default Light Modern - 浅色自带。 20 | - [Maple Theme](https://marketplace.visualstudio.com/items?itemName=subframe7536.theme-maple) - 深色好看!色彩搭配超细节很舒服! 21 | 22 | > 其他 23 | 24 | - [Spacegray VSCode](https://marketplace.visualstudio.com/items?itemName=ionutvmi.spacegray-vscode) - 深色平替。 25 | - [GitHub Plus Theme](https://marketplace.visualstudio.com/items?itemName=thenikso.github-plus-theme) - 浅色,群友推荐。 26 | - [Moegi Theme](https://marketplace.visualstudio.com/items?itemName=ddiu8081.moegi-theme) - 深浅皆用,Diu 大佬写的主题。 27 | - [Github Dark Classic Theme](https://marketplace.visualstudio.com/items?itemName=BerriJ.github-vscode-theme-dark-classic) - 深色,GitHub 主题还是很舒服的。 28 | - [JetBrains Fleet Dark](https://marketplace.visualstudio.com/items?itemName=FranzGollhammer.jb-fleet-dark) - 深色,Fleet Dark,对于 Fleet 编辑器主题还原度非常高了 👍🏻 29 | - [Evondev Dracula](https://marketplace.visualstudio.com/items?itemName=evondev.dracula-high-contrast) - 深色,对比度高,定位和写代码更清晰,能给人一种极客的感觉 ⚡ 30 | - [Vitesse Theme](https://marketplace.visualstudio.com/items?itemName=antfu.theme-vitesse) - 深浅皆用,托尼写的!整体配色扁平,但是看久了感觉有点暗,部分细节需要自己处理下。 31 | - [Panda Theme](https://marketplace.visualstudio.com/items?itemName=tinkertrain.theme-panda) - 深色,也是扁平的粉青配色,但是已经很久没有更新了,有些颜色细节适配的不是特别好。 32 | 33 |

字体

34 | 35 | > 常用 36 | 37 | - [Liga SFMono Nerd Font](https://github.com/shaunsingh/SFMono-Nerd-Font-Ligaturized) - zx 哥推荐,看起来不错,体验中... 38 | - [Input Mono](https://input.djr.com/) - 托尼推荐!用了好久了。 39 | - [Maple Font](https://github.com/subframe7536/maple-font) - 带连字和控制台图标的圆角等宽字体。 40 | - [JetBrains Mono Font](https://github.com/JetBrains/JetBrainsMono) - 方方正正的,很适合写代码。 41 | 42 | > 其他 43 | 44 | - Monaco - 来源于 Mac 系统自带。 45 | - [Fira Code](https://github.com/tonsky/FiraCode) - 带连字。 46 | - [Comic Shanns Font](https://github.com/shannpersand/comic-shanns) - 很酷的字体。 47 | - [IBM Plex Mono](https://github.com/IBM/plex) 48 | 49 | > 字体工具网站 50 | 51 | - [FontFreeze](https://mutsuntsai.github.io/fontfreeze/) - 冻结字体的变体功能生成 ttf,可以导入 Input Mono 试试。 52 | - [Ligaturizer](https://github.com/ToxicFrog/Ligaturizer/) - 把连字添加到其他不支持连字的字体内。 53 | 54 |

常用主题

55 | 56 |

57 | 58 | 59 |

60 | 61 |

其他主题

62 | 63 | ![VSCode Moegi Vitesse Light.png](https://cdn.jsdelivr.net/gh/fengstats/blogcdn@main/2023/VSCode%20Meogi%20Vitesse%20Light.png) 64 | ![VSCode Github Classic Dark.png](https://cdn.jsdelivr.net/gh/fengstats/blogcdn@main/2023/VSCode%20Github%20Classic%20Dark.png) 65 | ![VSCode Moegi Vitesse Dark.png](https://cdn.jsdelivr.net/gh/fengstats/blogcdn@main/2023/VSCode%20Meogi%20Vitesse%20Dark.png) 66 | ![VSCode JetBrains Fleet Dark](https://cdn.jsdelivr.net/gh/fengstats/blogcdn@main/2023/VSCode%20JetBrains%20Fleet%20Dark.png) 67 | ![VSCode Evondev Dracula Darker.png](https://cdn.jsdelivr.net/gh/fengstats/blogcdn@main/2023/VSCode%20Evondev%20Dracula%20Darker.png) 68 | -------------------------------------------------------------------------------- /2-vscode/extensions.txt: -------------------------------------------------------------------------------- 1 | akamud.vscode-theme-onedark 2 | aminer.codegeex 3 | andrejunges.handlebars 4 | antfu.file-nesting 5 | antfu.goto-alias 6 | antfu.iconify 7 | antfu.icons-carbon 8 | antfu.theme-vitesse 9 | antfu.unocss 10 | asvetliakov.vscode-neovim 11 | atdow.vue-jumper 12 | baiducomate.comate 13 | be5invis.vscode-custom-css 14 | beardedbear.beardedtheme 15 | berrij.github-vscode-theme-dark-classic 16 | bierner.github-markdown-preview 17 | bierner.markdown-checkbox 18 | bierner.markdown-emoji 19 | bierner.markdown-footnotes 20 | bierner.markdown-mermaid 21 | bierner.markdown-preview-github-styles 22 | bierner.markdown-yaml-preamble 23 | bradlc.vscode-tailwindcss 24 | brandonkirbyson.vscode-animations 25 | capaj.vscode-standardjs-snippets 26 | catppuccin.catppuccin-vsc-icons 27 | chensuiyi.fn-map 28 | christian-kohler.npm-intellisense 29 | christian-kohler.path-intellisense 30 | cipchk.cssrem 31 | codeium.codeium 32 | csstools.postcss 33 | cuixiaorui.cvim 34 | cweijan.dbclient-jdbc 35 | cweijan.vscode-mysql-client2 36 | davidbwaters.macos-modern-theme 37 | dbaeumer.vscode-eslint 38 | ddiu8081.moegi-theme 39 | degreat.fonted 40 | donjayamanne.githistory 41 | drcika.apc-extension 42 | eamodio.gitlens 43 | ecmel.vscode-html-css 44 | ellreka.tailwindcss-highlight 45 | emmanuelbeziat.vscode-great-icons 46 | esbenp.prettier-vscode 47 | evan-buss.font-switcher 48 | evondev.dracula-high-contrast 49 | exodiusstudios.comment-anchors 50 | fabiospampinato.vscode-diff 51 | file-icons.file-icons 52 | fittentech.fitten-code 53 | formulahendry.auto-close-tag 54 | formulahendry.auto-rename-tag 55 | formulahendry.code-runner 56 | foxundermoon.shell-format 57 | franzgollhammer.jb-fleet-dark 58 | github.vscode-pull-request-github 59 | heybourn.headwind 60 | humao.rest-client 61 | intellsmi.comment-translate 62 | ionutvmi.path-autocomplete 63 | ionutvmi.spacegray-vscode 64 | jasonlhy.hungry-delete 65 | jbockle.jbockle-format-files 66 | kaiqun.tencent-cloud-translate 67 | kakumei.ts-debug 68 | kc.danmaku 69 | kevinmcgowan.typescriptimport 70 | kisstkondoros.vscode-gutter-preview 71 | leetcode.vscode-leetcode 72 | lehni.vscode-fix-checksums 73 | letrieu.expand-region 74 | lihuiwang.vue-alias-skip 75 | meganrogge.template-string-converter 76 | mgmcdermott.vscode-language-babel 77 | mhutchie.git-graph 78 | mikestead.dotenv 79 | mkxml.vscode-filesize 80 | moetype.moe-panda-theme 81 | mrcrowl.easy-less 82 | ms-azuretools.vscode-docker 83 | ms-ceintl.vscode-language-pack-zh-hans 84 | ms-vscode.live-server 85 | ms-vsliveshare.vsliveshare 86 | murloccra4ler.leap 87 | muuvmuuv.vscode-sundial 88 | naumovs.color-highlight 89 | nicoespeon.hocus-pocus 90 | octref.vetur 91 | oderwat.indent-rainbow 92 | phoenisx.cssvar 93 | pkief.material-icon-theme 94 | pmneo.tsimporter 95 | pucelle.vscode-css-navigation 96 | quick-lint.quick-lint-js 97 | redguardtoo.matchit 98 | remisa.shellman 99 | rsbondi.highlight-words 100 | shd101wyy.markdown-preview-enhanced 101 | silesky.toggle-boolean 102 | simonhe.fast-jump 103 | simonhe.lazy-install 104 | simonhe.to-tailwindcss 105 | simonhe.to-ts-type 106 | simonhe.unot 107 | simonhe.vscode-alias-jump 108 | simonhe.vscode-tailwind-magic 109 | streetsidesoftware.code-spell-checker 110 | stringham.move-ts 111 | styled-components.vscode-styled-components 112 | subframe7536.theme-maple 113 | tal7aouy.icons 114 | techer.open-in-browser 115 | thenikso.github-plus-theme 116 | tinkertrain.theme-panda 117 | tomoki1207.pdf 118 | usernamehw.errorlens 119 | visualstudioexptteam.vscodeintellicode 120 | vscodevim.vim 121 | vue.volar 122 | wejectchan.vue3-snippets-for-vscode 123 | withfig.fig 124 | wix.vscode-import-cost 125 | wraith13.bracket-lens 126 | xabikos.javascriptsnippets 127 | xadillax.viml 128 | xyz.local-history 129 | yandeu.five-server 130 | yoavbls.pretty-ts-errors 131 | yummygum.city-lights-icon-vsc 132 | yzhang.markdown-all-in-one 133 | zhuangtongfa.material-theme 134 | -------------------------------------------------------------------------------- /1-system/.zshrc: -------------------------------------------------------------------------------- 1 | # Fig pre block. Keep at the top of this file. 2 | # [[ -f "$HOME/.fig/shell/zshrc.pre.zsh" ]] && builtin source "$HOME/.fig/shell/zshrc.pre.zsh" 3 | 4 | # fzf 5 | # --------- 6 | if [[ ! "$PATH" == */opt/homebrew/opt/fzf/bin* ]]; then 7 | PATH="${PATH:+${PATH}:}/opt/homebrew/opt/fzf/bin" 8 | fi 9 | export FZF_DEFAULT_OPTS='--bind=ctrl-t:top,change:top --bind ctrl-e:down,ctrl-u:up' 10 | # export FZF_DEFAULT_OPTS='--bind ctrl-e:down,ctrl-u:up --preview "[[ $(file --mime {}) =~ binary ]] && echo {} is a binary file || (ccat --color=always {} || highlight -O ansi -l {} || cat {}) 2> /dev/null | head -500"' 11 | # export FZF_DEFAULT_COMMAND='ag --hidden --ignore .git -g ""' 12 | export FZF_DEFAULT_COMMAND='fd' 13 | export FZF_COMPLETION_TRIGGER='\' 14 | export FZF_TMUX=1 15 | export FZF_TMUX_HEIGHT='80%' 16 | export fzf_preview_cmd='[[ $(file --mime {}) =~ binary ]] && echo {} is a binary file || (ccat --color=always {} || highlight -O ansi -l {} || cat {}) 2> /dev/null | head -500' 17 | # Auto-completion 18 | # --------------- 19 | # [[ $- == *i* ]] && source "/opt/homebrew/opt/fzf/shell/completion.zsh" 2> /dev/null 20 | # Key bindings 21 | # ------------ 22 | source "/opt/homebrew/opt/fzf/shell/key-bindings.zsh" 23 | 24 | 25 | # Enable Powerlevel10k instant prompt. Should stay close to the top of ~/.zshrc. 26 | # Initialization code that may require console input (password prompts, [y/n] 27 | # confirmations, etc.) must go above this block; everything else may go below. 28 | if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then 29 | source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" 30 | fi 31 | 32 | # Remove older command from the history if a duplicate is to be added. 33 | setopt HIST_IGNORE_ALL_DUPS 34 | # Remove path separator from WORDCHARS. 35 | WORDCHARS=${WORDCHARS//[\/]} 36 | # Disable automatic widget re-binding on each precmd. This can be set when 37 | # zsh-users/zsh-autosuggestions is the last module in your ~/.zimrc. 38 | ZSH_AUTOSUGGEST_MANUAL_REBIND=1 39 | # Set what highlighters will be used. 40 | # See https://github.com/zsh-users/zsh-syntax-highlighting/blob/master/docs/highlighters.md 41 | ZSH_HIGHLIGHT_HIGHLIGHTERS=(main brackets) 42 | 43 | 44 | # Zim 45 | ZIM_HOME=${ZDOTDIR:-${HOME}}/.zim 46 | # Download zimfw plugin manager if missing. 47 | if [[ ! -e ${ZIM_HOME}/zimfw.zsh ]]; then 48 | if (( ${+commands[curl]} )); then 49 | curl -fsSL --create-dirs -o ${ZIM_HOME}/zimfw.zsh \ 50 | https://github.com/zimfw/zimfw/releases/latest/download/zimfw.zsh 51 | else 52 | mkdir -p ${ZIM_HOME} && wget -nv -O ${ZIM_HOME}/zimfw.zsh \ 53 | https://github.com/zimfw/zimfw/releases/latest/download/zimfw.zsh 54 | fi 55 | fi 56 | # Install missing modules, and update ${ZIM_HOME}/init.zsh if missing or outdated. 57 | if [[ ! ${ZIM_HOME}/init.zsh -nt ${ZDOTDIR:-${HOME}}/.zimrc ]]; then 58 | source ${ZIM_HOME}/zimfw.zsh init -q 59 | fi 60 | # Initialize modules. 61 | source ${ZIM_HOME}/init.zsh 62 | zmodload -F zsh/terminfo +p:terminfo 63 | # Bind ^[[A/^[[B manually so up/down works both before and after zle-line-init 64 | for key ('^[[A' '^P' ${terminfo[kcuu1]}) bindkey ${key} history-substring-search-up 65 | for key ('^[[B' '^N' ${terminfo[kcud1]}) bindkey ${key} history-substring-search-down 66 | for key ('k') bindkey -M vicmd ${key} history-substring-search-up 67 | for key ('j') bindkey -M vicmd ${key} history-substring-search-down 68 | unset key 69 | 70 | 71 | # fnm 72 | eval "$(fnm env --use-on-cd)" 73 | 74 | 75 | # pnpm 76 | export PNPM_HOME="/Users/feng/Library/pnpm" 77 | case ":$PATH:" in 78 | *":$PNPM_HOME:"*) ;; 79 | *) export PATH="$PNPM_HOME:$PATH" ;; 80 | esac 81 | 82 | 83 | # To customize prompt, run `p10k configure` or edit ~/.p10k.zsh. 84 | [[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh 85 | 86 | # Fig post block. Keep at the bottom of this file. 87 | # [[ -f "$HOME/.fig/shell/zshrc.post.zsh" ]] && builtin source "$HOME/.fig/shell/zshrc.post.zsh" 88 | 89 | # 加载我的 zsh 配置 90 | source ~/.config/zsh/main.zsh 91 | 92 | typeset -g POWERLEVEL9K_INSTANT_PROMPT=quiet 93 | typeset -g POWERLEVEL9K_INSTANT_PROMPT=off 94 | -------------------------------------------------------------------------------- /1-system/.vimrc: -------------------------------------------------------------------------------- 1 | " ================================================================ 2 | " 基本设置 3 | " ================================================================ 4 | " vim 时, normal/insert 模式下光标的显示状态 5 | " let &t_ut='' 6 | " let &t_SI = "\]50;CursorShape=1\x7" 7 | " let &t_SR = "\]50;CursorShape=2\x7" 8 | " let &t_EI = "\]50;CursorShape=0\x7" 9 | 10 | " NOTE: 可更改 Terminal + iTerm2 + VS Code 终端通过 vim 命令操作文件的光标样式 11 | let &t_SI = "\e[5 q" "SI = INSERT mode 12 | let &t_SR = "\e[4 q" "SR = REPLACE mode 13 | let &t_EI = "\e[1 q" "EI = NORMAL mode (ELSE) 14 | 15 | " 可以让你在 vim 编辑时使用鼠标进行操作 16 | set mouse=a 17 | " 显示普通模式未完成的指令(一般在右下角) 18 | set showcmd 19 | " 解决插入模式下删除键不能删除的问题 20 | set backspace=indent,eol,start 21 | " 命令模式按下 Tab 键, 展示候选词 22 | set wildmenu 23 | " 打通系统 cv 和 vim 24 | " 系统剪切板 -> vim 25 | set clipboard=unnamedplus 26 | " vim -> 系统剪切板 27 | set clipboard=unnamed 28 | " 解决插入模式 -> 普通模式延迟显示的问题 29 | set ttimeout ttimeoutlen=10 30 | " 位置标识记录 | 关闭文件后再次打开, 光标会回到你上一次离开的位置 31 | au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g'\"" | endif 32 | " 保留文件视图更改的状态 33 | " autocmd BufWrite * mkview 34 | " autocmd BufWinLeave * mkview 35 | " autocmd BufRead * silent loadview 36 | 37 | " ================================================================ 38 | " 编辑器设置 | editor 39 | " ================================================================ 40 | " 显示行号 41 | set number 42 | " 显示光标行和列信息 43 | " set ruler 44 | " 显示相对行号 45 | " set relativenumber 46 | " 突出当前行显示 47 | set cursorline 48 | " 底部命令行状态栏显示在底部倒数第二行位置 | 设置 0 关闭 49 | set laststatus=2 50 | " 显示语法高亮 51 | syntax enable 52 | syntax on 53 | " 显示多余的符号替换 Tab(>---), 空格(^), 换行(¬) 54 | " set list 55 | " set listchars=tab:>-,trail:^ ",eol:¬ 56 | " 开启自动缩进 57 | set autoindent 58 | " 智能缩进 59 | set smartindent 60 | " 发生错误时不要响铃, 也不要闪烁 61 | set noerrorbells 62 | set belloff=all 63 | " 单行内容超出窗口时自动换行显示 64 | set wrap 65 | " 编辑模式下时按一个 Tab 键相当于输入 2 个空格 66 | set tabstop=2 67 | " 格式化时缩进尺寸为 2 个空格, 即 >>、<< 、==(取消全部缩进)时, 每一级的字符数 68 | set shiftwidth=2 69 | " 让 vim 把连续的空格视为一个 Tab, 删除时可以一次删掉一个 Tab 的空格数量 70 | set softtabstop=2 71 | " 把制表符转换为多个空格, 具体空格数量参考 tabstop 和 shiftwidth 72 | set expandtab 73 | " 垂直滚动时, 光标距离顶部/底部的行数 | 保持在你的可视区域的行数 74 | set scrolloff=5 75 | " 在行和段的开始处智能使用 Tab 76 | set smarttab 77 | " 命令行历史记录数量 78 | set history=200 79 | " 自动切换工作目录 80 | " set autochdir 81 | " 合并两行中文时, 不在中间加空格 82 | " set formatoptions+=B 83 | " 合并行时不添加多余空格 84 | " set nojoinspaces 85 | 86 | " ================================================================ 87 | " 编码设置 88 | " ================================================================ 89 | " 设置 vim 内部默认编码 90 | set encoding=utf-8 91 | " 设置编辑文件时的编码 92 | set fileencoding=utf-8 93 | " 设置 vim 能识别的编码 94 | set fileencodings=ucs-bom,utf-8,cp936,gb18030,gb2312,big5,cuc-jp,cuc-kr,latin 95 | " 设置终端模式(非 GUI 模式)下的编码 96 | set termencoding=utf-8 97 | " 防止特殊符号无法显示 98 | " set ambiwidth=double 99 | 100 | " ================================================================ 101 | " 文件设置 102 | " ================================================================ 103 | " 自动检测文件类型和缩进格式, 并根据文件类型加载插件 104 | filetype plugin indent on 105 | " 文件被外部改动后, 自动加载 106 | set autoread 107 | " 不生成备份文件 108 | " set nobackup 109 | " 不生成临时文件 110 | " set noswapfile 111 | " 不生成 undo 文件 112 | " set noundofile 113 | " 生成 undo (缓存) 文件, 设置目录位置 | 退出文件后还能记忆之前的操作, 比如 u 114 | " 还原上次的操作更改项, 坏处是会生成很多缓存文件 115 | set undofile 116 | set undodir=~/.vim/undodir 117 | 118 | " ================================================================ 119 | " 搜索匹配 120 | " ================================================================ 121 | " 高亮显示匹配到的括号 122 | set showmatch 123 | " 高亮显示搜索到的关键字 124 | set hlsearch 125 | " 即时搜索 | 即边搜边高亮 126 | set incsearch 127 | " 智能大小敏感, 若有字母大写, 敏感, 否则不敏感 128 | set ignorecase smartcase 129 | 130 | " ================================================================ 131 | " 操作习惯 | 快捷键 132 | " ================================================================ 133 | " 将 键配置为 space | 空格 134 | let mapleader = " " 135 | " 快速上下移动 | 这里使用递归因为 jk 都被我改了 136 | map J 5j 137 | map K 5k 138 | " 对于很长的行, vim 会自动换行, 此时 j 或者 k 就会一下跳很多行 139 | " 使用 gk/gj 可以避免跳过多行, 但是不方便, 所以做了如下映射: 140 | noremap k gk 141 | noremap j gj 142 | " 光标移动到所在行开头/结尾 143 | noremap H ^ 144 | noremap L $ 145 | " 返回上次光标所在位置 | 可跨文件 146 | " nnoremap gk 147 | " 与 gk 相反 148 | " nnoremap gj 149 | " 将查找所在行内容居中显示 | 目前通过 easymotion 替代了 150 | " nnoremap n nzz 151 | " nnoremap N Nzz 152 | " 按 U 执行 redo 153 | nnoremap U 154 | " 在可视模式下使用 p 粘贴时不替换寄存器内容, 这里是利用了黑洞寄存器, 155 | " 将选中内容删除到黑洞寄存器, 然后再执行大写P, 在行尾时会有点bug, 但基本满足需求 156 | vnoremap p "_dP 157 | " 取消搜索高亮 158 | nnoremap ; :nohl 159 | " 可视模式下按 y 将内容写入系统寄存器 160 | " vnoremap y "+y 161 | " 可视模式下按 x 将内容写入(剪切到)系统寄存器 162 | " vnoremap x "+x 163 | " 按 p 将系统寄存器中的内容粘贴出来 164 | " nnoremap p "+p 165 | " 打开一个新的标签页 166 | " map tu :tabe 167 | " 切换左右标签页 168 | " map th :-tabnext 169 | " map tl :+tabnext 170 | " map tx :r !figlet 171 | " 保存 172 | " nnoremap s :w 173 | " nnoremap S :w 174 | " 退出 175 | nnoremap q :q 176 | nnoremap Q :q 177 | " 上下左右分屏 178 | " nnoremap sk; :set nosplitbelow:split 179 | " nnoremap sj; :set splitbelow:split 180 | " nnoremap sh; :set nosplitright:vsplit 181 | " nnoremap sl; :set splitright:vsplit 182 | " 聚焦上下左右分屏 183 | nnoremap l l 184 | nnoremap h h 185 | nnoremap j j 186 | nnoremap k k 187 | " 上下 -> 左右分屏 188 | " nnoremap sv tH 189 | " 上下 -> 上下分屏 190 | " nnoremap sh tK 191 | " 开启/关闭 单词拼写检查 192 | " nnoremap sc :set spell! 193 | " 通过设置一个自定义占位符, 然后按"两次空格"来快速定位更改 | placeholder 194 | " map /<++>:nohl"_c4l 195 | " 刷新全局 vimrc 配置 | 系统会根据文件等级依次往下找 196 | nnoremap R :source $MYVIMRC 197 | " 每次进入一个新文件时先执行取消高亮命令 | 防止上次在此文件的高亮结果再次显示造成视觉干扰 198 | exec "nohl" 199 | 200 | " ================================================================ 201 | " 插件引入 | vim-plug 202 | " ================================================================ 203 | call plug#begin('~/.vim/plugged') 204 | " 底部状态栏增强 205 | Plug 'itchyny/lightline.vim' 206 | " PaperColor 主题 (亮/暗) 207 | Plug 'nlknguyen/papercolor-theme' 208 | " Molokai 主题(暗色) 209 | Plug 'tomasr/molokai' 210 | " Dracula 主题(暗色), 后面的配置表示将主题装在 dracula 文件夹下 211 | Plug 'dracula/vim', { 'as': 'dracula' } 212 | " 扩展多光标功能 213 | " hint: 这个插件已经被 deprecated 了 214 | " Plug 'terryma/vim-multiple-cursors' 215 | Plug 'mg979/vim-visual-multi', {'branch': 'master'} 216 | " 扩展 . 的功能 217 | " Plug 'tpope/vim-repeat' 218 | " easymotion | 移动指令增强 219 | " Plug 'easymotion/vim-easymotion" 220 | " 通过 enter 键来快速选择包含块内容(text-objects), 再次按下会继续扩大包含块 221 | Plug 'gcmt/wildfire.vim' 222 | " 通过选中内容后按 S 快速添加成对符号, 也支持删除与更改, ds/cs, 与 wildfire 搭配有奇效 223 | Plug 'tpope/vim-surround' 224 | " hint: 这个 plug#end() 一定要记得写啊!!!坑死我啦!!!找了好久的 bug 225 | call plug#end() 226 | 227 | " ================================================================ 228 | " 插件相关设置 229 | " ================================================================ 230 | " 231 | " lightline.vim 232 | let lightline = { 233 | \ 'colorscheme': 'PaperColor', 234 | \ } 235 | 236 | " PaperColor.vim 237 | let g:PaperColor_Theme_Options = { 238 | \ 'theme': { 239 | \ 'default.dark': { 240 | \ 'transparent_background': 1 241 | \ } 242 | \ } 243 | \ } 244 | 245 | " theme 246 | set background=dark 247 | " colorscheme molokai 248 | " colorscheme dracula 249 | colorscheme PaperColor 250 | 251 | " wildfire 252 | " nmap f (wildfire-quick-select) 253 | 254 | " easymotion 255 | " 替换原生 / 查找 256 | " map / (easymotion-sn) 257 | " 替换原生 n/N 查找 258 | " map n (easymotion-next)zz 259 | " map N (easymotion-prev)zz 260 | " 实现类似 vim-sneak 的双字符查找快速移动 261 | " nmap s (easymotion-s2) 262 | " 上下方向行首字母快速移动 263 | " map j (easymotion-j) 264 | " map k (easymotion-k) 265 | 266 | " ================================================================ 267 | " ================================================================ 268 | -------------------------------------------------------------------------------- /3-js/pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '9.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | importers: 8 | 9 | .: 10 | dependencies: 11 | axios: 12 | specifier: ^1.7.2 13 | version: 1.7.2 14 | clipboardy: 15 | specifier: ^4.0.0 16 | version: 4.0.0 17 | number-precision: 18 | specifier: ^1.6.0 19 | version: 1.6.0 20 | 21 | packages: 22 | 23 | asynckit@0.4.0: 24 | resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} 25 | 26 | axios@1.7.2: 27 | resolution: {integrity: sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==} 28 | 29 | clipboardy@4.0.0: 30 | resolution: {integrity: sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w==} 31 | engines: {node: '>=18'} 32 | 33 | combined-stream@1.0.8: 34 | resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} 35 | engines: {node: '>= 0.8'} 36 | 37 | cross-spawn@7.0.3: 38 | resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} 39 | engines: {node: '>= 8'} 40 | 41 | delayed-stream@1.0.0: 42 | resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} 43 | engines: {node: '>=0.4.0'} 44 | 45 | execa@8.0.1: 46 | resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} 47 | engines: {node: '>=16.17'} 48 | 49 | follow-redirects@1.15.6: 50 | resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==} 51 | engines: {node: '>=4.0'} 52 | peerDependencies: 53 | debug: '*' 54 | peerDependenciesMeta: 55 | debug: 56 | optional: true 57 | 58 | form-data@4.0.0: 59 | resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} 60 | engines: {node: '>= 6'} 61 | 62 | get-stream@8.0.1: 63 | resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} 64 | engines: {node: '>=16'} 65 | 66 | human-signals@5.0.0: 67 | resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} 68 | engines: {node: '>=16.17.0'} 69 | 70 | is-docker@3.0.0: 71 | resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} 72 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 73 | hasBin: true 74 | 75 | is-inside-container@1.0.0: 76 | resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} 77 | engines: {node: '>=14.16'} 78 | hasBin: true 79 | 80 | is-stream@3.0.0: 81 | resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} 82 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 83 | 84 | is-wsl@3.1.0: 85 | resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} 86 | engines: {node: '>=16'} 87 | 88 | is64bit@2.0.0: 89 | resolution: {integrity: sha512-jv+8jaWCl0g2lSBkNSVXdzfBA0npK1HGC2KtWM9FumFRoGS94g3NbCCLVnCYHLjp4GrW2KZeeSTMo5ddtznmGw==} 90 | engines: {node: '>=18'} 91 | 92 | isexe@2.0.0: 93 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 94 | 95 | merge-stream@2.0.0: 96 | resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} 97 | 98 | mime-db@1.52.0: 99 | resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} 100 | engines: {node: '>= 0.6'} 101 | 102 | mime-types@2.1.35: 103 | resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} 104 | engines: {node: '>= 0.6'} 105 | 106 | mimic-fn@4.0.0: 107 | resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} 108 | engines: {node: '>=12'} 109 | 110 | npm-run-path@5.3.0: 111 | resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} 112 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 113 | 114 | number-precision@1.6.0: 115 | resolution: {integrity: sha512-05OLPgbgmnixJw+VvEh18yNPUo3iyp4BEWJcrLu4X9W05KmMifN7Mu5exYvQXqxxeNWhvIF+j3Rij+HmddM/hQ==} 116 | 117 | onetime@6.0.0: 118 | resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} 119 | engines: {node: '>=12'} 120 | 121 | path-key@3.1.1: 122 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 123 | engines: {node: '>=8'} 124 | 125 | path-key@4.0.0: 126 | resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} 127 | engines: {node: '>=12'} 128 | 129 | proxy-from-env@1.1.0: 130 | resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} 131 | 132 | shebang-command@2.0.0: 133 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 134 | engines: {node: '>=8'} 135 | 136 | shebang-regex@3.0.0: 137 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 138 | engines: {node: '>=8'} 139 | 140 | signal-exit@4.1.0: 141 | resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} 142 | engines: {node: '>=14'} 143 | 144 | strip-final-newline@3.0.0: 145 | resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} 146 | engines: {node: '>=12'} 147 | 148 | system-architecture@0.1.0: 149 | resolution: {integrity: sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA==} 150 | engines: {node: '>=18'} 151 | 152 | which@2.0.2: 153 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} 154 | engines: {node: '>= 8'} 155 | hasBin: true 156 | 157 | snapshots: 158 | 159 | asynckit@0.4.0: {} 160 | 161 | axios@1.7.2: 162 | dependencies: 163 | follow-redirects: 1.15.6 164 | form-data: 4.0.0 165 | proxy-from-env: 1.1.0 166 | transitivePeerDependencies: 167 | - debug 168 | 169 | clipboardy@4.0.0: 170 | dependencies: 171 | execa: 8.0.1 172 | is-wsl: 3.1.0 173 | is64bit: 2.0.0 174 | 175 | combined-stream@1.0.8: 176 | dependencies: 177 | delayed-stream: 1.0.0 178 | 179 | cross-spawn@7.0.3: 180 | dependencies: 181 | path-key: 3.1.1 182 | shebang-command: 2.0.0 183 | which: 2.0.2 184 | 185 | delayed-stream@1.0.0: {} 186 | 187 | execa@8.0.1: 188 | dependencies: 189 | cross-spawn: 7.0.3 190 | get-stream: 8.0.1 191 | human-signals: 5.0.0 192 | is-stream: 3.0.0 193 | merge-stream: 2.0.0 194 | npm-run-path: 5.3.0 195 | onetime: 6.0.0 196 | signal-exit: 4.1.0 197 | strip-final-newline: 3.0.0 198 | 199 | follow-redirects@1.15.6: {} 200 | 201 | form-data@4.0.0: 202 | dependencies: 203 | asynckit: 0.4.0 204 | combined-stream: 1.0.8 205 | mime-types: 2.1.35 206 | 207 | get-stream@8.0.1: {} 208 | 209 | human-signals@5.0.0: {} 210 | 211 | is-docker@3.0.0: {} 212 | 213 | is-inside-container@1.0.0: 214 | dependencies: 215 | is-docker: 3.0.0 216 | 217 | is-stream@3.0.0: {} 218 | 219 | is-wsl@3.1.0: 220 | dependencies: 221 | is-inside-container: 1.0.0 222 | 223 | is64bit@2.0.0: 224 | dependencies: 225 | system-architecture: 0.1.0 226 | 227 | isexe@2.0.0: {} 228 | 229 | merge-stream@2.0.0: {} 230 | 231 | mime-db@1.52.0: {} 232 | 233 | mime-types@2.1.35: 234 | dependencies: 235 | mime-db: 1.52.0 236 | 237 | mimic-fn@4.0.0: {} 238 | 239 | npm-run-path@5.3.0: 240 | dependencies: 241 | path-key: 4.0.0 242 | 243 | number-precision@1.6.0: {} 244 | 245 | onetime@6.0.0: 246 | dependencies: 247 | mimic-fn: 4.0.0 248 | 249 | path-key@3.1.1: {} 250 | 251 | path-key@4.0.0: {} 252 | 253 | proxy-from-env@1.1.0: {} 254 | 255 | shebang-command@2.0.0: 256 | dependencies: 257 | shebang-regex: 3.0.0 258 | 259 | shebang-regex@3.0.0: {} 260 | 261 | signal-exit@4.1.0: {} 262 | 263 | strip-final-newline@3.0.0: {} 264 | 265 | system-architecture@0.1.0: {} 266 | 267 | which@2.0.2: 268 | dependencies: 269 | isexe: 2.0.0 270 | -------------------------------------------------------------------------------- /3-js/diary-stats.js: -------------------------------------------------------------------------------- 1 | // 初始版本,请移步:https://github.com/fengstats/diary-duration-stats 2 | 3 | import fs from 'fs' 4 | import path from 'path' 5 | 6 | // 匹配模式 7 | const modeMap = { 8 | // 默认匹配,也就是所有标题都会匹配 9 | free: 'FREE', 10 | // 自定义匹配,会过滤掉除了在 includeTitleList 中的其他标题 11 | custom: 'CUSTOM', 12 | // 临时匹配,与默认匹配一样,只不过输出格式有点差别,可以在执行脚本时开启 13 | temp: 'TEMP', 14 | } 15 | // 前后缀括号映射 16 | const bracketMap = { '': '', '**': '**', '(': ')', '(': ')' } 17 | 18 | let matchMode = modeMap['free'] 19 | // 是否需要插入模板格式信息,用于匹配替换,默认开启 20 | let isInsertTemplate = true 21 | // 文件总时长 22 | let fileTotalTime = 0 23 | 24 | // 固定插件标题 25 | const insertTitle = 'Record' 26 | // 需要匹配的标题列表 27 | const includeTitleList = ['重要', '生活', '休闲'] 28 | // 需要排除的目录或者文件 29 | const excludeFileList = [] 30 | // 是否写入文件,默认开启 31 | const isSaveFile = true 32 | // 是否删除未匹配到内容的标题,默认关闭 33 | const isRemoveTitle = false 34 | 35 | // 时间转换:分钟转换为 h+min/h/min,可选前后缀参数 36 | function minToTimeStr(t, bracket = '**') { 37 | // 没有值返回空字符串 38 | if (t === 0) return '' 39 | 40 | const h = Math.floor(t / 60) 41 | const m = Math.floor(t % 60) 42 | // 0 的情况返回空字符串 43 | // 不满 10 补 0 44 | // 小时不补 0(感觉不好看,不直观) 45 | const hStr = h === 0 ? '' : h + 'h' 46 | const mStr = m === 0 ? '' : String(m).padStart(2, '0') + 'min' 47 | 48 | return bracket + hStr + mStr + bracketMap[bracket] 49 | } 50 | 51 | // 时间转换:分钟转换为 00:00 形式 52 | function minToTime(time) { 53 | const h = String(Math.floor(time / 60)).padStart(2, '0') 54 | const m = String(Math.floor(time % 60)).padStart(2, '0') 55 | return h + ':' + m 56 | } 57 | 58 | ;(function () { 59 | function setup() { 60 | const args = process.argv.slice(2) 61 | const inputPath = args[0] 62 | const filePathList = [] 63 | 64 | // 选择匹配模式,如果有值说明匹配到了 65 | if (modeMap[args[1]]) matchMode = modeMap[args[1]] 66 | 67 | // 异常处理 68 | if (!inputPath) { 69 | console.log('请先传入一个文件/文件夹') 70 | return 71 | } else if (!fs.existsSync(inputPath)) { 72 | console.log('没有找到这个文件/文件夹~') 73 | return 74 | } 75 | 76 | // 如果是文件直接执行 77 | if (fs.statSync(inputPath).isFile()) { 78 | run(inputPath) 79 | return 80 | } 81 | 82 | // TODO: 下面就是目录的情况了,目前没有支持递归扫描,只支持该目录第一层 md 文件 83 | 84 | // 读取所有文件名 85 | const files = fs.readdirSync(inputPath) 86 | for (let file of files) { 87 | // 过滤不是 md 的文件或者被排除的文件 88 | if (path.extname(file) !== '.md' || excludeFileList.includes(file)) continue 89 | // 合并为完整路径 90 | const filePath = path.join(inputPath, file) 91 | // 将扫描到的文件添加到文件列表(排除一些文件和目录) 92 | if (fs.statSync(filePath).isFile()) filePathList.push(filePath) 93 | } 94 | 95 | // 遍历文件列表开始执行 96 | filePathList.forEach((filePath) => { 97 | run(filePath) 98 | }) 99 | } 100 | 101 | // 数据初始化 102 | function initData(isTmpMode) { 103 | // 在临时模式下默认不插入 104 | isInsertTemplate = !isTmpMode 105 | fileTotalTime = 0 106 | } 107 | 108 | // 录入数据 109 | function addData(dataList, title, insertContent, matchContent, result, statsTime = 0, options = {}) { 110 | dataList.push({ 111 | // 标题 112 | title, 113 | // 插入模板需要的内容 114 | insertContent, 115 | // 替换匹配需要的内容 116 | matchContent, 117 | // 替换结果 118 | result, 119 | // 此标题下的统计时长 120 | statsTime, 121 | // 一些其他的可选参数 122 | ...options, 123 | }) 124 | } 125 | 126 | // 启动 127 | function run(filePath) { 128 | // 文件内容 129 | let text = fs.readFileSync(filePath, 'utf8') 130 | 131 | if (!text) { 132 | console.log('这是一个空文件噢~') 133 | return 134 | } 135 | 136 | // 是否为临时模式 137 | const isTmpMode = matchMode === modeMap['temp'] 138 | // 在处理前通过正则校验提取旧日记的总时长 139 | const oldTotalTimeList = text.match(/\n> 总时长:\*\*(\d+h)?(\d+min)?.*\*\*/) ?? [] 140 | const oldTotalTime = parseInt(oldTotalTimeList[1] || '0') * 60 + parseInt(oldTotalTimeList[2] || '0') 141 | // 数据列表 142 | const dataList = [] 143 | 144 | // 初始化 145 | initData(isTmpMode) 146 | // 核心处理 147 | parseFileContent(dataList, text) 148 | 149 | // 是否插入模板 150 | if (isInsertTemplate) text = insertRecordTemplate(dataList, text, insertTitle) 151 | // 根据不同的正则,替换文件中的内容 152 | if (dataList.length) text = matchContentReplace(dataList, text) 153 | 154 | // 将内容写入到『Record』中 155 | // 优化:新总时长对比旧总时长,不一致时进行写入更新 156 | if (oldTotalTime !== fileTotalTime && isSaveFile) saveFile(filePath, text) 157 | // saveFile(filePath, text) 158 | 159 | // 之总时长超过或等于 24h 一律认为已经完成,就不打印了,但是会存在最后一次超过或等于的情况 160 | // 这时候我们还是要打印的,所以两个总时长取一个较小的 161 | if (Math.min(oldTotalTime, fileTotalTime) < 24 * 60) { 162 | // 开始打印!去除 .md 的后缀名 163 | let index = 1 164 | let bracket = '' 165 | let printContent = `${path.parse(filePath).name}` 166 | // 关于睡眠数据特殊处理 167 | for (let item of dataList) { 168 | if (item.title === '睡眠') { 169 | printContent += ` 💤 ${minToTimeStr(item.statsTime, '')}` 170 | break 171 | } 172 | } 173 | // 加上总时长 174 | printContent += ` 🕛 ${isTmpMode ? minToTimeStr(fileTotalTime, '') : minToTime(fileTotalTime)}\n` 175 | // 剩余标题数据 176 | for (let item of dataList) { 177 | const { title, statsTime } = item 178 | // 不包含睡眠和总时长 179 | if (['睡眠', '总时长'].includes(title) || statsTime === 0) continue 180 | printContent += `\n${index++}. ${title} ${minToTimeStr(statsTime, bracket)}` 181 | } 182 | console.log(printContent, '\n') 183 | } 184 | } 185 | 186 | // 解析文件内容,根据匹配正则录入数据 187 | function parseFileContent(dataList, text) { 188 | // 睡眠时长 189 | addSleepTimeData(dataList, text) 190 | // 内容时长 191 | addTitleTimeData(dataList, text) 192 | // 总时长 193 | addTotalTimeData(dataList, fileTotalTime) 194 | } 195 | 196 | // 根据匹配正则添加睡眠时长数据 197 | function addSleepTimeData(dataList, text, match, sleepTitle = '睡眠') { 198 | const sleepTimeRegex = /(\d{2}):(\d{2})-(\d{2}):(\d{2})/g 199 | while ((match = sleepTimeRegex.exec(text)) !== null) { 200 | // 开始与结束时间,默认当前时间 201 | const start = new Date() 202 | const end = new Date() 203 | const matchContent = match[0] 204 | const startHour = parseInt(match[1], 10) 205 | const startMinute = parseInt(match[2], 10) 206 | const endHour = parseInt(match[3], 10) 207 | const endMinute = parseInt(match[4], 10) 208 | start.setHours(startHour, startMinute) 209 | end.setHours(endHour, endMinute) 210 | // 如果结束时间在开始时间之前,表示跨天 211 | if (end < start) { 212 | // 将结束时间调整为第二天 213 | end.setDate(end.getDate() + 1) 214 | } 215 | // 计算时间差 216 | const duration = end.getTime() - start.getTime() 217 | const statsTime = duration / 1000 / 60 218 | // 累加给文件总时长 219 | fileTotalTime += statsTime 220 | // 录入数据 221 | addData( 222 | dataList, 223 | sleepTitle, 224 | `- [x] ${sleepTitle}:${matchContent}`, 225 | matchContent + '.*', 226 | `${matchContent} 💤 ${minToTimeStr(statsTime)}`, 227 | statsTime, 228 | ) 229 | } 230 | } 231 | 232 | // 根据匹配正则添加标题为主的内容数据时长 233 | function addTitleTimeData(dataList, text, match) { 234 | const contentRegex = /## (.+?)\n([\s\S]*?)(?=\n## |\n*$)/g 235 | const contentTimeRegex = /- \[x\].*\*\*(.*)\*\*/g 236 | // NOTE: 后面的 \+? 为了兼容旧笔记数据,如 1h+、25min+ 等等 237 | const timeRegex = /\*\*(\d+h)?(\d+min)?\+?\*\*/ 238 | 239 | while ((match = contentRegex.exec(text)) !== null) { 240 | const title = match[1] 241 | const matchContent = match[2].trim() 242 | const matchContentList = matchContent.match(contentTimeRegex) || [] 243 | 244 | // 该文件中已有插入标题,无需自动插入 245 | if (title === insertTitle) { 246 | isInsertTemplate = false 247 | continue 248 | } 249 | // 过滤不满足 custom 模式内包含的标题 250 | if (matchMode === modeMap['custom'] && !includeTitleList.includes(title)) { 251 | continue 252 | } 253 | // 没有匹配到内容的标题 254 | if (!matchContent) { 255 | // 顺便看看要不要删除 256 | isRemoveTitle && addData(dataList, title, '', `\n## ${title}\n*`, '') 257 | continue 258 | } 259 | 260 | // OK,校验都结束了,那我们下面开始匹配时间数据并计算 261 | 262 | // 插入内容 263 | let insertContent = `- [x] ${title}:` 264 | // 匹配标题 265 | let matchTitle = `${title}:.*` 266 | // 当前标题下的总时长 267 | let statsTime = 0 268 | for (let content of matchContentList) { 269 | // 每个任务的统计时长 270 | let taskMinTime = 0 271 | const matchTimeList = content.match(new RegExp(timeRegex, 'g')) || [] 272 | // NOTE: 兼容单个任务内出现多个时长的情况 273 | for (let taskContent of matchTimeList) { 274 | const item = taskContent.match(timeRegex) || [] 275 | const hour = parseInt(item[1]) || 0 276 | const minute = parseInt(item[2]) || 0 277 | taskMinTime += hour * 60 + minute 278 | } 279 | // 累加到标题总时长 280 | statsTime += taskMinTime 281 | } 282 | // 标题总时长累加到文件总时长上 283 | fileTotalTime += statsTime 284 | // 添加数据,后续统一处理 285 | addData(dataList, title, insertContent, matchTitle, `${title}:${minToTimeStr(statsTime)}`, statsTime, { 286 | matchContentList, 287 | }) 288 | } 289 | } 290 | 291 | // 录入总时长 292 | function addTotalTimeData(dataList, totalTime, title = '总时长') { 293 | // 根据总时长给原有标题时长添加百分比信息 294 | dataList.forEach((item) => { 295 | if (item.statsTime !== 0) { 296 | item.percentage = Math.round((item.statsTime / totalTime) * 100) 297 | // NOTE: 这里百分比是四舍五入的,可能会存在总和不为 100 的情况 298 | item.result += `(${item.percentage}%)` 299 | } 300 | }) 301 | 302 | addData(dataList, title, `\n> ${title}:\n`, `${title}:.*`, `${title}:${minToTimeStr(totalTime)}`, totalTime) 303 | } 304 | 305 | // 根据扫描标题动态插入格式模板 306 | function insertRecordTemplate(dataList, text, title) { 307 | let insertTemplate = `## ${title}\n\n` 308 | dataList.forEach(({ insertContent }) => { 309 | // 插入内容为空就不用插入了 310 | if (insertContent) { 311 | insertTemplate += insertContent + '\n' 312 | } 313 | }) 314 | return insertTemplate + text 315 | } 316 | 317 | // 根据内容匹配正则替换数据(返回替换后的数据,不影响原数据) 318 | function matchContentReplace(dataList, text) { 319 | dataList.forEach(({ matchContent: match, result }) => { 320 | text = text.replace(new RegExp(match), result) 321 | }) 322 | return text 323 | } 324 | 325 | // 保存文件内容 326 | function saveFile(filePath, text) { 327 | fs.writeFileSync(filePath, text, 'utf8') 328 | } 329 | 330 | // salute! 331 | setup() 332 | })() 333 | -------------------------------------------------------------------------------- /3-js/diary-stats-utools.js: -------------------------------------------------------------------------------- 1 | // 首先感谢你点开了这个文件,其次我劝你别看了,这代码写的跟屎一样 🙏 2 | // 建议移步:https://github.com/fengstats/diary-duration-stats 可能会好点 3 | 4 | import fs from 'fs' 5 | import path from 'path' 6 | import clipboardy from 'clipboardy' 7 | import NP from 'number-precision' 8 | 9 | const year = '2024' 10 | const month = '01' 11 | let inputPath = `/Users/feng/codebase/private/diary/${year}/${month}月` 12 | 13 | const isRemoveTitle = false 14 | const recordTitle = 'Record' 15 | const includeTitleList = ['重要', '生活', '休闲'] 16 | const excludeFileList = [] 17 | const bracketMap = { '': '', '**': '**', '(': ')', '(': ')' } 18 | const typeMap = { 19 | title: 'title', 20 | quote: 'quote', 21 | money: 'money', 22 | } 23 | // 生活: '', 24 | const colorMap = { 25 | 重要: ['#3eb370', '#44c47b'], 26 | 出行: ['#3eb370', '#44c47b'], 27 | 睡眠: ['#91c5b9', '#91c5b9'], 28 | 生活: ['#4e99de', '#1f99ed'], 29 | // 休闲: ["#f09665", "#FC8D2A"], 30 | 休闲: ['#ff6b81', '#ff4757'], 31 | 其他: ['#a5b1c2', '#a5b1c2'], 32 | } 33 | const modeMap = { 34 | free: 'FREE', 35 | custom: 'CUSTOM', 36 | temp: 'TEMP', 37 | } 38 | const style = { 39 | // fontFamily: 'font-family: Input Mono Freeze', 40 | // fontFamily: 'font-family: Comic Sans MS', 41 | // fontFamily: 'font-family: Maple UI', 42 | fontFamily: '', 43 | fontWeight: 'font-weight: 700', 44 | fontSize: 'font-size: 16px', 45 | autoCenter: 'width: fit-content; margin: 0 auto;', 46 | } 47 | 48 | let matchMode = modeMap['free'] 49 | let isSaveFile = true 50 | let isInsertTemplate = true 51 | // 月支出 52 | let monthSpend = 0 53 | // 月收入 54 | let monthEarn = 0 55 | // 单文件总时长 56 | let fileTotalTime = 0 57 | 58 | function generateMoneyHtml(title, money, text, emoji) { 59 | return ` 60 |
61 | 这个月${text} 62 | ${money} 元了 ${emoji} 70 |
` 71 | } 72 | 73 | // 生成任务模板 74 | function generateTaskHtml(title, content = '') { 75 | return ` 76 |
77 |

${title}

85 |
    ${content}
92 |
93 | ` 94 | } 95 | 96 | // 生成单个任务 HTML 模板 97 | function generateTaskItemHtml(title, statsTime) { 98 | //
99 | const progressHeight = `height: 18px` 100 | const progressRadius = `border-radius: 9px` 101 | const [color1, color2] = colorMap[title] || colorMap['生活'] 102 | const percentage = Math.round((100 * statsTime) / fileTotalTime) 103 | // 单独处理百分比小于 10% 的进度小球大小和位置 104 | const circleBoxSize = percentage >= 10 ? 40 : 34 105 | const circleBoxTop = percentage >= 10 ? 0.88 : 0.64 // 大往上,小往下 106 | const circleTextTop = percentage >= 10 ? 0.32 : 0.06 // 大往下,小往上 107 | const titleFlex = matchMode === modeMap['temp'] ? 0.3 : 0.08 108 | const isMinPercentage = percentage >= 2 109 | return ` 110 |
  • 118 |
    ${title}
    127 |
    138 |
    146 | ${ 147 | isMinPercentage 148 | ? `
    ${percentage}%
    163 | ` 164 | : '' 165 | } 166 |
    167 |
    168 |
    ${minToTimeStr(statsTime, '')}
    174 |
  • ` 175 | } 176 | 177 | function minToTime(time, separator = ':') { 178 | const h = String(Math.floor(time / 60)).padStart(2, '0') 179 | const m = String(Math.floor(time % 60)).padStart(2, '0') 180 | return h + separator + m 181 | } 182 | 183 | function minToTimeStr(t, bracket = '**') { 184 | if (t === 0) return '' 185 | const h = Math.floor(t / 60) 186 | const m = Math.floor(t % 60) 187 | const hStr = h === 0 ? '' : h + 'h' 188 | const mStr = m === 0 ? '' : String(m).padStart(2, '0') + 'min' 189 | return bracket + hStr + mStr + bracketMap[bracket] 190 | } 191 | 192 | function initData() { 193 | fileTotalTime = 0 194 | } 195 | 196 | function addData(dataList, type, data) { 197 | const id = dataList.length + 1 198 | const { title = '', matchRegex = '', result = '' } = data 199 | // 公有参数 200 | const item = { id, type, title, matchRegex, result } 201 | switch (type) { 202 | case typeMap['title']: 203 | const { insert = '', statsTime = 0, matchList = [] } = data 204 | item.insert = insert 205 | item.statsTime = statsTime 206 | item.matchList = matchList 207 | break 208 | case typeMap['quote']: 209 | // ... 210 | break 211 | default: 212 | break 213 | } 214 | dataList.push(item) 215 | } 216 | 217 | function addSleepTimeData(dataList, text, match, title = '睡眠') { 218 | const sleepTimeRegex = /(\d{2}):(\d{2})-(\d{2}):(\d{2})/g 219 | while ((match = sleepTimeRegex.exec(text)) !== null) { 220 | const start = new Date() 221 | const end = new Date() 222 | const matchContent = match[0] 223 | const startHour = parseInt(match[1], 10) 224 | const startMinute = parseInt(match[2], 10) 225 | const endHour = parseInt(match[3], 10) 226 | const endMinute = parseInt(match[4], 10) 227 | start.setHours(startHour, startMinute) 228 | end.setHours(endHour, endMinute) 229 | if (end < start) { 230 | end.setDate(end.getDate() + 1) 231 | } 232 | const duration = end.getTime() - start.getTime() 233 | const statsTime = duration / 1000 / 60 234 | fileTotalTime += statsTime 235 | addData(dataList, typeMap['title'], { 236 | title, 237 | insert: `- [x] ${title}:${matchContent}`, 238 | matchRegex: `${matchContent}.*`, 239 | statsTime, 240 | result: `${matchContent} 💤 ${minToTimeStr(statsTime)}`, 241 | }) 242 | } 243 | } 244 | 245 | function addTitleTimeData(dataList, text, match) { 246 | const contentRegex = /## (.+?)\n([\s\S]*?)(?=\n## |\n*$)/g 247 | const contentTimeRegex = /- \[x\].*\*\*(.*)\*\*/g 248 | const timeRegex = /\*\*(\d+h)?(\d+min)?\+?\*\*/ 249 | 250 | while ((match = contentRegex.exec(text)) !== null) { 251 | const title = match[1] 252 | const matchContent = match[2].trim() 253 | const matchContentList = matchContent.match(contentTimeRegex) || [] 254 | 255 | if (title === recordTitle) { 256 | isInsertTemplate = false 257 | continue 258 | } 259 | if (matchMode === modeMap['custom'] && !includeTitleList.includes(title)) { 260 | continue 261 | } 262 | if (!matchContent) { 263 | isRemoveTitle && 264 | addData(dataList, typeMap['title'], { 265 | title, 266 | matchRegex: `\n## ${title}\n*`, 267 | result: '', 268 | }) 269 | continue 270 | } 271 | // 自动计算 272 | if (title === '生活') { 273 | monthSpend = NP.plus(addMoneyData(dataList, matchContent, '支出小记'), monthSpend) 274 | monthEarn = NP.plus(addMoneyData(dataList, matchContent, '收入小记'), monthEarn) 275 | addMoneyData(dataList, matchContent, '人情世故') 276 | } 277 | 278 | const insert = `- [x] ${title}:` 279 | const matchRegex = `${title}:.*` 280 | let statsTime = 0 281 | for (const content of matchContentList) { 282 | let taskMinTime = 0 283 | const matchTimeList = content.match(new RegExp(timeRegex, 'g')) || [] 284 | for (const taskContent of matchTimeList) { 285 | const item = taskContent.match(timeRegex) || [] 286 | const hour = parseInt(item[1]) || 0 287 | const minute = parseInt(item[2]) || 0 288 | taskMinTime += hour * 60 + minute 289 | } 290 | statsTime += taskMinTime 291 | } 292 | fileTotalTime += statsTime 293 | addData(dataList, typeMap['title'], { 294 | title, 295 | insert, 296 | matchRegex, 297 | statsTime, 298 | result: `${title}:${minToTimeStr(statsTime)}`, 299 | matchList: matchContentList, 300 | }) 301 | } 302 | } 303 | 304 | function addTotalTimeData(dataList, title = '总时长') { 305 | addData(dataList, typeMap['quote'], { 306 | title, 307 | insert: `\n> ${title}:\n`, 308 | matchRegex: `${title}:.*`, 309 | result: `${title}:${minToTimeStr(fileTotalTime)}`, 310 | }) 311 | } 312 | 313 | function addMoneyData(dataList, text, title) { 314 | // NOTE: \\s\\S 这里是因为字符串形式需要转移 315 | // /> 支出小记:.*\n([\s\S]*?)(?=\n{2}|$)' 316 | const regex = new RegExp(`> ${title}:.*\n([\\s\\S]*?)(?=\n{2}|$)`) 317 | const moneyRegex = /-.*((.*?) 元.*)/g 318 | 319 | let money = 0 320 | const match = regex.exec(text) 321 | if (match) { 322 | const matchContent = match[1] 323 | const moneyList = [] 324 | let matchMoney 325 | while ((matchMoney = moneyRegex.exec(matchContent)) !== null) { 326 | moneyList.push(matchMoney[1]) 327 | } 328 | let result = `${title}:` 329 | if (moneyList.length) { 330 | const spend = NP.plus(...moneyList) 331 | money = NP.plus(spend, money) 332 | result += `${moneyList.join('+')}(${spend} 元)` 333 | } else { 334 | result += '0 元' 335 | } 336 | addData(dataList, typeMap['money'], { 337 | title, 338 | matchRegex: `${title}:.*`, 339 | result, 340 | moneyList, 341 | }) 342 | } 343 | return money 344 | } 345 | 346 | function insertRecordTemplate(dataList, text, title) { 347 | let insertTemplate = `## ${title}\n\n` 348 | for (const { insert } of dataList) { 349 | if (insert) insertTemplate += insert + '\n' 350 | } 351 | return insertTemplate + text 352 | } 353 | 354 | function matchContentReplace(dataList, text) { 355 | for (const { matchRegex, result } of dataList) { 356 | if (matchRegex === '') continue 357 | const regex = new RegExp(matchRegex) 358 | text = text.replace(regex, result) 359 | } 360 | return text 361 | } 362 | 363 | function parseFileContent(dataList, text) { 364 | addSleepTimeData(dataList, text) 365 | addTitleTimeData(dataList, text) 366 | addTotalTimeData(dataList) 367 | } 368 | 369 | function saveFile(filePath, data) { 370 | fs.writeFile(filePath, data, (err) => { 371 | if (err) { 372 | console.error('❌ 文件更新失败', err) 373 | } else { 374 | // console.log('✅ 文件更新成功') 375 | } 376 | }) 377 | } 378 | 379 | function run(filePath) { 380 | let text = fs.readFileSync(filePath, 'utf8') 381 | if (!text) { 382 | generateTaskHtml('这是一个空文件嗷~') 383 | return 384 | } 385 | 386 | const oldTotalTimeList = text.match(/\n> 总时长:\*\*(\d+h)?(\d+min)?.*\*\*/) ?? [] 387 | const oldTotalTime = parseInt(oldTotalTimeList[1] || '0') * 60 + parseInt(oldTotalTimeList[2] || '0') 388 | const dataList = [] 389 | initData() 390 | parseFileContent(dataList, text) 391 | 392 | if (isInsertTemplate) text = insertRecordTemplate(dataList, text, recordTitle) 393 | if (dataList.length) text = matchContentReplace(dataList, text) 394 | if (oldTotalTime !== fileTotalTime && isSaveFile) saveFile(filePath, text) 395 | // 手动更新 396 | // saveFile(filePath, text) 397 | 398 | if (Math.min(oldTotalTime, fileTotalTime) < 24 * 60) { 399 | let title = path.parse(filePath).name 400 | let content = '' 401 | if (fileTotalTime === 0) { 402 | // printTip(`${title}:`) 403 | console.log(generateTaskHtml(title, '暂无时长可统计,可先添加二级标题 → 任务列表 → 尾部追加时间')) 404 | return 405 | } 406 | 407 | title += `
    🕛
    ` 408 | title += `${minToTime(fileTotalTime)}` 409 | 410 | // 临时模式将标题替换为总时长,将总时长写入到系统剪贴板中 411 | if (matchMode === modeMap['temp']) { 412 | title = `总时长:${minToTimeStr(fileTotalTime, '')}` 413 | clipboardy.write(minToTimeStr(fileTotalTime, '')) 414 | } else { 415 | clipboardy.write(minToTime(fileTotalTime)) 416 | } 417 | for (const { type, title, statsTime } of dataList) { 418 | // 过滤 419 | if (type !== typeMap['title'] || title === '睡眠' || statsTime === 0) continue 420 | // 加入输出模板中 421 | content += generateTaskItemHtml(title, statsTime) 422 | } 423 | 424 | // 添加睡眠时间,注意可能有多个睡眠数据 425 | let sleepTime = 0 426 | for (const { title, statsTime } of dataList) { 427 | if (title === '睡眠') sleepTime += statsTime 428 | } 429 | if (sleepTime) { 430 | // title += ` 💤 ${minToTimeStr(sleepTime, '')}` 431 | content += generateTaskItemHtml('睡眠', sleepTime) 432 | } 433 | 434 | // 输出 435 | console.log(generateTaskHtml(title, content)) 436 | } 437 | } 438 | 439 | function setup(inputPath) { 440 | // 如果有值就按照临时模式匹配 441 | const forceInputPath = process.argv.slice(2)[0] 442 | if (forceInputPath) { 443 | matchMode = modeMap['temp'] 444 | inputPath = forceInputPath 445 | // 不需要插入标题和保存 446 | isInsertTemplate = false 447 | isSaveFile = false 448 | } 449 | if (!inputPath) { 450 | generateTaskHtml('请先传入一个文件/文件夹') 451 | return 452 | } 453 | if (!fs.existsSync(inputPath)) { 454 | generateTaskHtml('没有找到这个文件/文件夹~') 455 | return 456 | } 457 | if (fs.statSync(inputPath).isFile()) { 458 | run(inputPath) 459 | return 460 | } 461 | 462 | // 执行 463 | const files = fs.readdirSync(inputPath) 464 | for (const file of files) { 465 | if (path.extname(file) !== '.md' || excludeFileList.includes(file)) continue 466 | const filePath = path.join(inputPath, file) 467 | if (fs.statSync(filePath).isFile()) { 468 | run(filePath) 469 | } 470 | } 471 | 472 | console.log(generateMoneyHtml('重要', monthEarn, '赚了', '🎉')) 473 | console.log(generateMoneyHtml('生活', monthSpend, '花了', '💢')) 474 | } 475 | 476 | setup(inputPath) 477 | -------------------------------------------------------------------------------- /2-vscode/keybindings.json: -------------------------------------------------------------------------------- 1 | [ 2 | // Vim or NeoVim 3 | // 增量范围选中扩大、缩小 4 | { 5 | "key": "enter", 6 | "command": "expand_region", 7 | "when": "editorTextFocus && (vim.mode == 'Normal' || vim.mode == 'Visual') && !suggestWidgetVisible" 8 | }, 9 | { 10 | "key": "backspace", 11 | "command": "undo_expand_region", 12 | "when": "editorTextFocus && editorHasSelection && vim.mode == 'Visual'" 13 | }, 14 | // 在 Vim INSERT 模式下的 Ctrl+d/u 滚动半屏 15 | { 16 | "key": "ctrl+d", 17 | "command": "cursorMove", 18 | "when": "editorTextFocus && vim.mode == 'Insert'", 19 | "args": { 20 | "to": "down", 21 | "by": "line", 22 | "value": 22, 23 | "revealCursor": true 24 | } 25 | }, 26 | { 27 | "key": "ctrl+u", 28 | "command": "cursorMove", 29 | "when": "editorTextFocus && vim.mode == 'Insert'", 30 | "args": { 31 | "to": "up", 32 | "by": "line", 33 | "value": 22, 34 | "revealCursor": true 35 | } 36 | }, 37 | // Copilot 编辑器内联聊天 38 | { 39 | "key": "cmd+l", 40 | "command": "inlineChat.startWithCurrentLine", 41 | "when": "editorFocus && github.copilot.chat.editor.enableLineTrigger && inlineChatHasProvider && !editorReadonly && !inlineChatVisible" 42 | }, 43 | // 与上面的指令效果差不多,不过是由另外的参数控制的: 44 | // editorScroll 和 halfPage 45 | // { 46 | // "key": "ctrl+d", 47 | // "when": "editorTextFocus && vim.mode == 'Insert'", 48 | // "command": "editorScroll", 49 | // "args": { 50 | // "to": "down", 51 | // "value": 1, 52 | // "by": "halfPage", 53 | // "revealCursor": true 54 | // } 55 | // }, 56 | 57 | // Basic 58 | // { 59 | // "key": "cmd+l", 60 | // "command": "markdown.extension.checkTaskList", 61 | // "when": "editorTextFocus && editorLangId =~ /^markdown$|^rmd$|^quarto$/" 62 | // }, 63 | // 选择最近的文件工作区 64 | { 65 | "key": "cmd+r", 66 | "command": "workbench.action.openRecent" 67 | // 只能在聚焦文件管理、编辑器、Panel 时使用 68 | // "when": "filesExplorerFocus || editorFocus || panelFocus" 69 | }, 70 | // 搜索面板刷新搜索结果,需要聚焦侧边栏以及搜索面板可见 71 | { 72 | "key": "cmd+r", 73 | "command": "search.action.refreshSearchResults", 74 | "when": "sideBarFocus && searchViewletVisible" 75 | }, 76 | // 清空扩展输入信息(就当我没事给自己找点事干好了,这个配置挺鸡肋的,直接 cmd+a 然后 del 就行哈哈哈哈) 77 | { 78 | "key": "cmd+k", 79 | "command": "workbench.extensions.action.clearExtensionsSearchResults", 80 | "when": "sideBarFocus" 81 | }, 82 | // 搜索面板调出替换输入框的快捷键 83 | { 84 | "key": "cmd+g", 85 | "command": "workbench.action.replaceInFiles", 86 | "when": "sideBarFocus" 87 | }, 88 | // 替换单个文件内的某处匹配(在搜索面板中使用,需聚焦具体匹配项) 89 | { 90 | "key": "enter", 91 | "command": "search.action.replace", 92 | "when": "matchFocus && replaceActive && searchViewletVisible" 93 | }, 94 | // 切换左右 panel 95 | { 96 | "key": "cmd+[", 97 | "command": "workbench.action.previousPanelView", 98 | "when": "panelFocus" 99 | }, 100 | { 101 | "key": "cmd+]", 102 | "command": "workbench.action.nextPanelView", 103 | "when": "panelFocus" 104 | }, 105 | // 打开一个新窗口 106 | { 107 | "key": "cmd+ctrl+n", 108 | "command": "workbench.action.newWindow" 109 | }, 110 | // 打开当前文件所在访达位置 111 | { 112 | "key": "cmd+shift+r", 113 | "command": "revealFileInOS" 114 | // "when": "!editorFocus" 115 | }, 116 | // 在不同的面板(组件)之间进行聚焦 117 | { 118 | "key": "cmd+shift+h", 119 | "command": "workbench.action.navigateLeft" 120 | }, 121 | { 122 | "key": "cmd+shift+l", 123 | "command": "workbench.action.navigateRight" 124 | }, 125 | { 126 | "key": "cmd+shift+k", 127 | "command": "workbench.action.navigateUp" 128 | }, 129 | { 130 | "key": "cmd+shift+j", 131 | "command": "workbench.action.navigateDown" 132 | }, 133 | // 聚焦文件管理面板 134 | { 135 | "key": "cmd+shift+;", 136 | "command": "workbench.view.explorer", 137 | "when": "viewContainer.workbench.view.explorer.enabled" 138 | }, 139 | // 聚焦全局搜索面板 140 | { 141 | "key": "cmd+shift+f", 142 | "command": "workbench.action.findInFiles" 143 | }, 144 | // 聚焦 gitlens 145 | { 146 | "key": "cmd+shift+g", 147 | "command": "workbench.view.scm", 148 | "when": "workbench.scm.active" 149 | }, 150 | // 断点调试 151 | { 152 | "key": "cmd+5", 153 | "command": "workbench.action.debug.start", 154 | "when": "debuggersAvailable && debugState == 'inactive'" 155 | }, 156 | { 157 | "key": "cmd+5", 158 | "command": "workbench.action.debug.continue", 159 | "when": "debugState == 'stopped'" 160 | }, 161 | // Run Code 162 | // { 163 | // "key": "cmd+alt+n", 164 | // "command": "code-runner.run" 165 | // }, 166 | // 切换随机背景图(暂时不用了,影响写代码速度) 167 | // { 168 | // "key": "shift+cmd+7", 169 | // "command": "extension.backgroundCover.refresh" 170 | // }, 171 | // 让你的 Esc 优先执行取消提示建议的操作,然后才会识别进入 normal 模式 172 | // { 173 | // "key": "escape", 174 | // "command": "hideSuggestWidget", 175 | // "when": "suggestWidgetVisible && textInputFocus" 176 | // }, 177 | // VSC 调用 Vim 指令 178 | // { 179 | // "key": "cmd+shift+h", 180 | // "command": "vim.remap", 181 | // "when": "vim.mode == 'Normal'", 182 | // "args": { 183 | // "after": ["", "h"] 184 | // } 185 | // }, 186 | 187 | // File 188 | // NOTE: 没什么问题(去掉了 !explorerResourceIsRoot 达到了聚焦资源管理器根目录中新建的功能,但不知道可能会有什么隐患,先观望一下) 189 | { 190 | "key": "cmd+n", 191 | "command": "explorer.newFile" 192 | }, 193 | // 新建未命名文件 194 | { 195 | "key": "cmd+t", 196 | "command": "workbench.action.files.newUntitledFile" 197 | }, 198 | // 在文件管理器中搜索 199 | { 200 | "key": "f", 201 | "command": "list.find", 202 | "when": "listFocus && listSupportsFind && !inputFocus" 203 | }, 204 | { 205 | "key": "/", 206 | "command": "list.find", 207 | "when": "listFocus && listSupportsFind && !inputFocus" 208 | }, 209 | // 新建文件/文件夹 210 | { 211 | "key": "a", 212 | "command": "explorer.newFile", 213 | "when": "explorerViewletVisible && filesExplorerFocus && !explorerResourceReadonly && !inputFocus" 214 | }, 215 | { 216 | "key": "shift+a", 217 | "command": "explorer.newFolder", 218 | "when": "explorerViewletVisible && filesExplorerFocus && !explorerResourceReadonly && !inputFocus" 219 | }, 220 | // 复制/剪切/粘贴 221 | { 222 | "key": "y", 223 | "command": "filesExplorer.copy", 224 | "when": "explorerViewletVisible && filesExplorerFocus && !explorerResourceIsRoot && !explorerResourceReadonly && !inputFocus" 225 | }, 226 | { 227 | "key": "x", 228 | "command": "filesExplorer.cut", 229 | "when": "explorerViewletVisible && filesExplorerFocus && !explorerResourceIsRoot && !explorerResourceReadonly && !inputFocus" 230 | }, 231 | { 232 | "key": "p", 233 | "command": "filesExplorer.paste", 234 | "when": "explorerViewletVisible && filesExplorerFocus && !explorerResourceIsRoot && !explorerResourceReadonly && !inputFocus" 235 | }, 236 | // 重命名/删除 237 | { 238 | "key": "r", 239 | "command": "renameFile", 240 | "when": "explorerViewletVisible && filesExplorerFocus && !explorerResourceIsRoot && !explorerResourceReadonly && !inputFocus" 241 | }, 242 | { 243 | "key": "d", 244 | "command": "deleteFile", 245 | "when": "explorerViewletVisible && filesExplorerFocus && !explorerResourceReadonly && !inputFocus" 246 | }, 247 | 248 | // Tabs 249 | // 在当前编辑组内切换左右文件(将当前文件与左右文件换位置) 250 | { 251 | "key": "cmd+[", 252 | "command": "workbench.action.moveEditorLeftInGroup", 253 | // 解决和 panel 切换快捷键冲突的问题 254 | "when": "!panelFocus" 255 | }, 256 | { 257 | "key": "cmd+]", 258 | "command": "workbench.action.moveEditorRightInGroup", 259 | "when": "!panelFocus" 260 | }, 261 | // 在当前编辑组内左右聚焦文件 262 | { 263 | "key": "cmd+shift+[", 264 | "command": "workbench.action.previousEditorInGroup" 265 | }, 266 | { 267 | "key": "cmd+shift+]", 268 | "command": "workbench.action.nextEditorInGroup" 269 | }, 270 | // 将当前编辑组的文件移动到上一个/下一个编辑组中 | << and >> 271 | { 272 | "key": "cmd+shift+, cmd+shift+,", 273 | "command": "workbench.action.moveEditorToPreviousGroup" 274 | }, 275 | { 276 | "key": "cmd+shift+. cmd+shift+.", 277 | "command": "workbench.action.moveEditorToNextGroup" 278 | }, 279 | 280 | // Editor 281 | // Codeium 的 Command 面板 282 | // TODO: 找了一圈没看到怎么用键盘快捷方式 cancel 掉这个 command,ESC 直接切 Vim 的 normal 模式了 283 | // 先鼠标点掉吧…… 284 | { 285 | "key": "alt+i", 286 | "command": "codeium.openCodeiumCommand", 287 | "when": "codeium.commandEnabled && editorTextFocus && !inlineSuggestionsVisible" 288 | }, 289 | // 替换当前行和上/下行 290 | { 291 | "key": "alt+k", 292 | "command": "editor.action.moveLinesUpAction", 293 | "when": "editorTextFocus && !editorReadonly" 294 | }, 295 | { 296 | "key": "alt+j", 297 | "command": "editor.action.moveLinesDownAction", 298 | "when": "editorTextFocus && !editorReadonly" 299 | }, 300 | // 查找替换 301 | { 302 | "key": "cmd+g", 303 | "command": "editor.action.startFindReplaceAction", 304 | "when": "editorFocus" 305 | }, 306 | // 向下/上寻找当前文件出现的提示提示/警告/错误 307 | { 308 | "key": "cmd+8", 309 | "command": "editor.action.marker.next", 310 | "when": "editorFocus" 311 | }, 312 | { 313 | "key": "cmd+shift+8", 314 | "command": "editor.action.marker.prev", 315 | "when": "editorFocus" 316 | }, 317 | // 调整编辑组区域宽度大小(缩小、放大、恢复) 318 | { 319 | "key": "cmd+shift+-", 320 | "command": "workbench.action.decreaseViewWidth" 321 | // "when": "editorTextFocus && !editorReadonly" 322 | }, 323 | { 324 | "key": "cmd+shift+=", 325 | "command": "workbench.action.increaseViewWidth" 326 | }, 327 | { 328 | "key": "cmd+shift+0", 329 | "command": "workbench.action.evenEditorWidths" 330 | }, 331 | // 垂直分屏 332 | { 333 | "key": "cmd+shift+\\", 334 | "command": "workbench.action.splitEditorToBelowGroup" 335 | }, 336 | // { 337 | // "key": "ctrl+o", 338 | // "command": "workbench.action.navigateBack" 339 | // }, 340 | // { 341 | // "key": "ctrl+i", 342 | // "command": "workbench.action.navigateForward" 343 | // }, 344 | 345 | // Terminal 346 | { 347 | "key": "cmd+w", 348 | "command": "workbench.action.terminal.kill", 349 | // "args": ["workbench.action.terminal.kill", "workbench.action.terminal.focus"], 350 | "when": "terminalFocus" 351 | }, 352 | // 创建终端(根据当前编辑区聚焦文件的位置) 353 | { 354 | "key": "ctrl+`", 355 | "command": "openInIntegratedTerminal" 356 | // 打开外部终端:具体看 settings.json 中 osxExec 设置的 357 | // "command": "openInTerminal" 358 | }, 359 | // 创建终端(水平方向) 360 | { 361 | "key": "cmd+d", 362 | "command": "workbench.action.terminal.split", 363 | "when": "terminalFocus && terminalProcessSupported || terminalFocus && terminalWebExtensionContributedProfile" 364 | }, 365 | // 创建终端(垂直方向) 366 | { 367 | "key": "cmd+shift+d", 368 | "command": "workbench.action.terminal.new", 369 | "when": "terminalFocus && terminalProcessSupported || terminalWebExtensionContributedProfile" 370 | }, 371 | { 372 | "key": "cmd+shift+n", 373 | "command": "workbench.action.terminal.new", 374 | "when": "terminalProcessSupported || terminalWebExtensionContributedProfile" 375 | }, 376 | // 从任意地方聚焦到终端,i = iTerm 377 | { 378 | "key": "cmd+shift+i", 379 | "command": "workbench.action.terminal.focus" 380 | }, 381 | // 最大化终端 382 | { 383 | "key": "cmd+shift+enter", 384 | "command": "workbench.action.toggleMaximizedPanel", 385 | "when": "terminalFocus" 386 | }, 387 | // 上下拉伸终端(快捷键原本是编辑器整体放大缩小, 被我禁用了) 388 | { 389 | "key": "cmd+shift+-", 390 | "command": "workbench.action.terminal.resizePaneDown", 391 | "when": "panelFocus" 392 | // "when": "terminalFocus && terminalHasBeenCreated || terminalFocus && terminalProcessSupported" 393 | }, 394 | { 395 | "key": "cmd+shift+=", 396 | "command": "workbench.action.terminal.resizePaneUp", 397 | "when": "panelFocus" 398 | // "when": "terminalFocus && terminalHasBeenCreated || terminalFocus && terminalProcessSupported" 399 | }, 400 | // 左右终端聚焦 401 | { 402 | "key": "cmd+shift+h", 403 | "command": "workbench.action.terminal.focusPreviousPane", 404 | "when": "terminalFocus && terminalHasBeenCreated || terminalFocus && terminalProcessSupported" 405 | }, 406 | { 407 | "key": "cmd+shift+l", 408 | "command": "workbench.action.terminal.focusNextPane", 409 | "when": "terminalFocus && terminalHasBeenCreated || terminalFocus && terminalProcessSupported" 410 | }, 411 | // 可以从终端返回编辑区中而不关闭终端 412 | { 413 | "key": "cmd+shift+k", 414 | "command": "workbench.action.navigateUp", 415 | "when": "terminal.active && terminalFocus" 416 | }, 417 | // TODO: 上下终端聚焦,用来覆盖 Tabs 中设置左右聚焦 tab 功能,后续再看看能不能优化 418 | { 419 | "key": "cmd+shift+[", 420 | "command": "workbench.action.terminal.focusPrevious", 421 | "when": "terminalFocus && terminalHasBeenCreated && !terminalEditorFocus || terminalFocus && terminalProcessSupported && !terminalEditorFocus" 422 | }, 423 | { 424 | "key": "cmd+shift+]", 425 | "command": "workbench.action.terminal.focusNext", 426 | "when": "terminalFocus && terminalHasBeenCreated && !terminalEditorFocus || terminalFocus && terminalProcessSupported && !terminalEditorFocus" 427 | }, 428 | 429 | // Setting Default 430 | { 431 | "key": "ctrl+shift+`", 432 | "command": "-workbench.action.terminal.new", 433 | "when": "terminalProcessSupported || terminalWebExtensionContributedProfile" 434 | }, 435 | { 436 | "key": "alt+cmd+h", 437 | "command": "-rest-client.history" 438 | }, 439 | { 440 | "key": "ctrl+f", 441 | "command": "-cursorRight", 442 | "when": "textInputFocus" 443 | }, 444 | { 445 | "key": "ctrl+f", 446 | "command": "-extension.vim_ctrl+f", 447 | "when": "editorTextFocus && vim.active && vim.use && !inDebugRepl && vim.mode != 'Insert'" 448 | }, 449 | { 450 | "key": "ctrl+cmd+f", 451 | "command": "-workbench.action.toggleFullScreen", 452 | "when": "!isIOS" 453 | }, 454 | { 455 | "key": "ctrl+f", 456 | "command": "workbench.view.search", 457 | "when": "workbench.view.search.active && neverMatch =~ /doesNotMatch/" 458 | }, 459 | { 460 | "key": "ctrl+f", 461 | "command": "workbench.action.terminal.searchWorkspace", 462 | "when": "terminalFocus && terminalProcessSupported && terminalTextSelected" 463 | }, 464 | 465 | // Setting Disabled 466 | { 467 | "key": "shift+cmd+f", 468 | "command": "-workbench.view.search", 469 | "when": "workbench.view.search.active && neverMatch =~ /doesNotMatch/" 470 | }, 471 | { 472 | "key": "shift+cmd+f", 473 | "command": "-workbench.action.terminal.searchWorkspace", 474 | "when": "terminalFocus && terminalProcessSupported && terminalTextSelected" 475 | }, 476 | { 477 | "key": "shift+cmd+f", 478 | "command": "-workbench.action.findInFiles" 479 | }, 480 | { 481 | "key": "shift+cmd+h", 482 | "command": "-workbench.action.replaceInFiles" 483 | }, 484 | { 485 | "key": "ctrl+`", 486 | "command": "-workbench.action.terminal.toggleTerminal", 487 | "when": "terminal.active" 488 | }, 489 | { 490 | "key": "ctrl+k", 491 | "command": "-deleteAllRight", 492 | "when": "textInputFocus && !editorReadonly" 493 | }, 494 | { 495 | "key": "shift+cmd+=", 496 | "command": "-workbench.action.zoomIn" 497 | }, 498 | { 499 | "key": "shift+cmd+-", 500 | "command": "-workbench.action.zoomOut" 501 | }, 502 | { 503 | "key": "cmd+-", 504 | "command": "-workbench.action.zoomOut" 505 | }, 506 | { 507 | "key": "cmd+=", 508 | "command": "-workbench.action.zoomIn" 509 | }, 510 | { 511 | "key": "ctrl+r", 512 | "command": "-shell.runCommand" 513 | }, 514 | { 515 | "key": "ctrl+o", 516 | "command": "-lineBreakInsert", 517 | "when": "textInputFocus && !editorReadonly" 518 | }, 519 | { 520 | "key": "alt+cmd+f", 521 | "command": "-editor.action.startFindReplaceAction", 522 | "when": "editorFocus || editorIsOpen" 523 | }, 524 | { 525 | "key": "alt+cmd+up", 526 | "command": "-extension.vim_cmd+alt+up", 527 | "when": "editorTextFocus && vim.active && !inDebugRepl" 528 | }, 529 | { 530 | "key": "alt+cmd+down", 531 | "command": "-extension.vim_cmd+alt+down", 532 | "when": "editorTextFocus && vim.active && !inDebugRepl" 533 | }, 534 | { 535 | "key": "cmd+n", 536 | "command": "-workbench.action.files.newUntitledFile" 537 | }, 538 | { 539 | "key": "cmd+t", 540 | "command": "-workbench.action.showAllSymbols" 541 | }, 542 | { 543 | "key": "ctrl+alt+n", 544 | "command": "-code-runner.run" 545 | }, 546 | { 547 | "key": "ctrl+shift+f7", 548 | "command": "-extension.backgroundCover.refresh" 549 | }, 550 | { 551 | "key": "cmd+l cmd+o", 552 | "command": "-fiveServer.start", 553 | "when": "editorTextFocus" 554 | }, 555 | { 556 | "key": "cmd+l cmd+c", 557 | "command": "-fiveServer.close", 558 | "when": "editorTextFocus" 559 | }, 560 | { 561 | "key": "cmd+5", 562 | "command": "-workbench.action.focusFifthEditorGroup" 563 | }, 564 | { 565 | "key": "cmd+i", 566 | "command": "-codeium.openCodeiumCommand", 567 | "when": "codeium.commandEnabled && editorTextFocus && !inlineSuggestionsVisible" 568 | }, 569 | { 570 | "key": "alt+escape", 571 | "command": "-editor.action.triggerSuggest", 572 | "when": "editorHasCompletionItemProvider && textInputFocus && !editorReadonly && !suggestWidgetVisible" 573 | }, 574 | { 575 | "key": "cmd+e", 576 | "command": "-editor.action.toggleScreenReaderAccessibilityMode", 577 | "when": "accessibilityHelpIsShown" 578 | }, 579 | { 580 | "key": "cmd+i", 581 | "command": "-inlineChat.startWithCurrentLine", 582 | "when": "editorFocus && github.copilot.chat.editor.enableLineTrigger && inlineChatHasProvider && !editorReadonly && !inlineChatVisible" 583 | }, 584 | { 585 | "key": "cmd+l", 586 | "command": "inlineChat.start", 587 | "when": "editorFocus && inlineChatHasProvider && inlineChatPossible && !editorReadonly" 588 | }, 589 | { 590 | "key": "cmd+i", 591 | "command": "-inlineChat.start", 592 | "when": "editorFocus && inlineChatHasProvider && inlineChatPossible && !editorReadonly" 593 | } 594 | ] -------------------------------------------------------------------------------- /2-vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | // Basic 3 | "update.mode": "default", 4 | "breadcrumbs.icons": false, 5 | "database-client.autoSync": true, 6 | "explorer.confirmDragAndDrop": false, 7 | "explorer.confirmPasteNative": false, 8 | "explorer.openEditors.visible": 20, 9 | "explorer.confirmDelete": false, 10 | "security.workspace.trust.untrustedFiles": "open", 11 | "files.eol": "\n", 12 | "files.autoSave": "off", 13 | // 是否在尾部插入一个新行 14 | "files.insertFinalNewline": true, 15 | "files.simpleDialog.enable": false, 16 | "files.associations": { 17 | ".zimrc": "shellscript", 18 | // "*.json": "jsonc", 19 | "*.conf": "plaintext" 20 | }, 21 | 22 | // Search 23 | "search.smartCase": true, 24 | "search.collapseResults": "auto", 25 | "search.seedOnFocus": true, 26 | "search.showLineNumbers": true, 27 | "search.useGlobalIgnoreFiles": true, 28 | "search.useParentIgnoreFiles": true, 29 | "search.quickAccess.preserveInput": true, 30 | "search.searchEditor.defaultNumberOfContextLines": null, 31 | "search.searchEditor.singleClickBehaviour": "peekDefinition", 32 | "search.exclude": { 33 | "**/.git": true, 34 | "**/.github": true, 35 | "**/.nuxt": true, 36 | "**/.output": true, 37 | "**/.pnpm": true, 38 | "**/.vscode": true, 39 | "**/.yarn": true, 40 | "**/bower_components": true, 41 | "**/dist/**": true, 42 | "**/logs": true, 43 | "**/node_modules": true, 44 | "**/out/**": true, 45 | "**/package-lock.json": true, 46 | "**/pnpm-lock.yaml": true, 47 | "**/tmp": true, 48 | "**/yarn.lock": true 49 | }, 50 | 51 | // Sundial 52 | "workbench.preferredLightColorTheme": "Default Light Modern", 53 | "workbench.preferredDarkColorTheme": "Default Dark+", 54 | "workbench.colorTheme": "Default Dark+", 55 | "sundial.sunrise": "07:00", 56 | "sundial.sunset": "17:00", 57 | "sundial.interval": 20, 58 | // "Color": "#d484818f" 59 | // "sundial.daySettings": { 60 | // "animations.CursorAnimationOptions": { 61 | // "Color": "#0000006f" 62 | // } 63 | // }, 64 | // "sundial.nightSettings": { 65 | // "animations.CursorAnimationOptions": { 66 | // "Color": "#ffffff4f" 67 | // } 68 | // }, 69 | 70 | // Window 71 | "window.nativeTabs": false, 72 | "window.dialogStyle": "custom", 73 | "window.newWindowDimensions": "offset", 74 | "window.zoomLevel": 1, 75 | "window.commandCenter": false, 76 | "workbench.activityBar.location": "top", 77 | "workbench.tree.indent": 10, 78 | "workbench.tree.enableStickyScroll": true, 79 | "workbench.tree.renderIndentGuides": "always", 80 | "workbench.iconTheme": "material-icon-theme", 81 | "workbench.startupEditor": "none", 82 | "workbench.productIconTheme": "icons-carbon", 83 | "workbench.list.smoothScrolling": true, 84 | "workbench.editor.pinnedTabsOnSeparateRow": true, 85 | "workbench.editor.focusRecentEditorAfterClose": false, 86 | "workbench.editor.highlightModifiedTabs": true, 87 | "workbench.editor.limit.value": 12, 88 | "workbench.editor.limit.perEditorGroup": true, 89 | "workbench.editor.limit.enabled": true, 90 | "workbench.commandPalette.experimental.suggestCommands": true, 91 | // 自动恢复上次使用过的命令 92 | // "workbench.commandPalette.preserveInput": true, 93 | // 字体像素级和次像素级平滑 94 | // "workbench.fontAliasing": "antialiased", 95 | "workbench.colorCustomizations": { 96 | // 终端提示命令 97 | "terminal.ansiBrightBlack": "#0000008f", 98 | // "editor.lineHighlightBackground": "#ffffff00", 99 | // 底部控制栏 100 | // "statusBar.background": "#0000002f", 101 | "[Maple Dark]": { 102 | "editorCursor.background": "#ffffff", 103 | "editor.selectionHighlightBackground": "#8adcf14f" 104 | }, 105 | "[Default Dark+][GitHub Dark Classic]": { 106 | "terminal.ansiBlue": "#8adcf1", 107 | "terminal.ansiRed": "#ff6b81", 108 | "terminal.ansiBrightRed": "#ff7675" 109 | } 110 | }, 111 | 112 | // Editor 113 | "fonted.font": "Arial", 114 | "editor.fontSize": 13, 115 | "editor.lineNumbers": "interval", 116 | "editor.lineHeight": 1.45, 117 | "editor.gotoLocation.multipleDefinitions": "goto", 118 | "editor.fontFamily": "Input Mono, monospace", 119 | // "editor.fontFamily": "Maple Mono SC NF, monospace", 120 | // "editor.fontFamily": "JetBrains Mono, monospace", 121 | // "editor.fontFamily": "Monaco, monospace", 122 | // "editor.fontFamily": "Liga SFMono Nerd Font, monospace", 123 | "editor.fontLigatures": "'ss01', 'ss02', 'ss03', 'ss06', 'ss12', 'ss13'", 124 | "editor.cursorSurroundingLines": 5, 125 | "editor.accessibilitySupport": "auto", 126 | "editor.renderLineHighlight": "all", 127 | "editor.cursorBlinking": "expand", 128 | "editor.cursorSmoothCaretAnimation": "on", 129 | // 配置选中文本时的截断分隔符 130 | // "editor.wordSeparators": "`~!@%^&*()=+[{]}\\|;:'\",.<>/?(),。;:_-", 131 | // 不好用,输入比较快的时候就抽风了 132 | "editor.linkedEditing": false, 133 | // TODO: 关闭缩进猜测 134 | "editor.detectIndentation": false, 135 | "editor.tabSize": 2, 136 | // auto close brackets 137 | "editor.autoClosingBrackets": "beforeWhitespace", 138 | "editor.autoClosingDelete": "always", 139 | "editor.autoClosingOvertype": "always", 140 | "editor.autoClosingQuotes": "beforeWhitespace", 141 | // smart suggest 142 | "editor.suggest.snippetsPreventQuickSuggestions": true, 143 | "editor.acceptSuggestionOnEnter": "smart", 144 | "editor.inlineSuggest.showToolbar": "always", 145 | "editor.hover.above": false, 146 | "editor.hover.delay": 220, 147 | "editor.hover.hidingDelay": 0, 148 | "editor.padding.top": 2, 149 | "editor.smoothScrolling": true, 150 | // TODO: 父级代码吸附置顶,显示嵌套作用域 151 | "editor.stickyScroll.enabled": false, 152 | "editor.stickyScroll.scrollWithEditor": false, 153 | "editor.scrollbar.ignoreHorizontalScrollbarInContentHeight": true, 154 | "editor.scrollbar.horizontalScrollbarSize": 6, 155 | "editor.scrollbar.verticalScrollbarSize": 24, 156 | "editor.scrollBeyondLastLine": true, 157 | "editor.find.addExtraSpaceOnTop": false, 158 | "editor.minimap.renderCharacters": false, 159 | "editor.minimap.showSlider": "always", 160 | "editor.minimap.size": "fit", 161 | "editor.minimap.maxColumn": 60, 162 | // bracket pair color 163 | "editor.guides.bracketPairs": true, 164 | "editor.bracketPairColorization.enabled": true, 165 | "editor.bracketPairColorization.independentColorPoolPerBracketType": true, 166 | "editor.quickSuggestions": { 167 | "strings": "on" 168 | }, 169 | "editor.unicodeHighlight.allowedLocales": { 170 | "zh-hant": true 171 | }, 172 | "editor.semanticTokenColorCustomizations": { 173 | "enabled": true 174 | }, 175 | "editor.codeActionsOnSave": { 176 | "source.fixAll": "never", 177 | "source.fixAll.eslint": "explicit" 178 | }, 179 | "editor.tokenColorCustomizations": { 180 | // "[Default Light Modern][Moegi Light Vitesse]": { "comments": "#95a5a6" }, 181 | "[Fleet Dark Modern][Fleet Dark][Fleet Ocean][Maple Dark]": { 182 | "comments": "#a1a7a1df" 183 | }, 184 | "[Default Light Modern][Moegi Light]": { 185 | "comments": "#218c74" 186 | }, 187 | "[Evondev Dracula Darker Contrast]": { 188 | "comments": "#95a5a6" 189 | }, 190 | "[GitHub Dark Classic][Atom One Dark]": { 191 | "comments": "#95a5a6" 192 | }, 193 | "[Default Dark+]": { 194 | "comments": "#adb5ad" 195 | }, 196 | "[Moegi Dark Vitesse]": { 197 | "comments": "#a1a7a1" 198 | }, 199 | "[Maple Dark]": { 200 | "textMateRules": [ 201 | // 重置斜体关键字 202 | { 203 | "scope": [ 204 | // import/export/for/if/for/while/continue/break/switch/return 205 | "keyword.control", 206 | // function/let/const 207 | "storage.type", 208 | // async/await 209 | "storage.modifier", 210 | // this 211 | "variable.language.this" 212 | // 下面这个 scope 选择器貌似没起作用 213 | // "keyword.function" 214 | ], 215 | "settings": { 216 | "fontStyle": "" 217 | } 218 | }, 219 | // 去除无效值的删除线 220 | { 221 | "scope": "invalid", 222 | "settings": { 223 | "fontStyle": "" 224 | } 225 | } 226 | ] 227 | }, 228 | // 一般的斜体矫正 229 | "textMateRules": [ 230 | { 231 | "name": "Comment Italics", 232 | "scope": ["comment.line.double-slash", "comment.block.documentation"], 233 | "settings": { 234 | "fontStyle": "" 235 | } 236 | } 237 | ] 238 | }, 239 | 240 | // Terminal 241 | "terminal.external.osxExec": "iTerm", 242 | "terminal.integrated.gpuAcceleration": "on", 243 | "terminal.integrated.fontSize": 13, 244 | "terminal.integrated.lineHeight": 1.1, 245 | "terminal.integrated.confirmOnKill": "never", 246 | "terminal.integrated.copyOnSelection": true, 247 | "terminal.integrated.cursorBlinking": true, 248 | "terminal.integrated.fontFamily": "Maple Mono SC NF, Hack Nerd Font Mono, monospace", 249 | "terminal.integrated.tabs.defaultColor": "terminal.ansiGreen", 250 | "terminal.integrated.tabs.defaultIcon": "terminal-bash", 251 | "terminal.integrated.smoothScrolling": true, 252 | "terminal.integrated.env.osx": { 253 | "FIG_NEW_SESSION": "1", 254 | "NO_COLOR": null 255 | }, 256 | // "terminal.integrated.fontFamily": "Maple Mono SC NF Freeze, JetBrains Mono, Monaco, Input Mono Freeze, Hack Nerd Font Mono, monospace", 257 | 258 | // Formatter 259 | "editor.formatOnSave": true, 260 | "prettier.semi": false, 261 | "prettier.singleQuote": true, 262 | "prettier.trailingComma": "all", 263 | "prettier.proseWrap": "preserve", 264 | "prettier.printWidth": 100, 265 | "[json]": { 266 | "editor.defaultFormatter": "vscode.json-language-features" 267 | }, 268 | "[markdown][jsonc][javascript][typescript][vue][html][css][less]": { 269 | "editor.defaultFormatter": "esbenp.prettier-vscode" 270 | }, 271 | "[javascriptreact][typescriptreact]": { 272 | "editor.defaultFormatter": "esbenp.prettier-vscode" 273 | }, 274 | "[handlebars]": { 275 | "editor.defaultFormatter": "esbenp.prettier-vscode" 276 | }, 277 | "[dotenv]": { 278 | "editor.defaultFormatter": "foxundermoon.shell-format" 279 | }, 280 | 281 | // Vue 282 | "vue.inlayHints.missingProps": true, 283 | "vue.autoInsert.dotValue": true, 284 | 285 | // JS/TS 关闭验证,用 quick-lint-js 看看 286 | "typescript.validate.enable": true, 287 | "javascript.validate.enable": true, 288 | 289 | // DEBUG 290 | "debug.javascript.autoAttachFilter": "onlyWithFlag", 291 | 292 | // CSS 293 | "css.lint.duplicateProperties": "warning", 294 | "less.lint.duplicateProperties": "warning", 295 | "scss.lint.duplicateProperties": "warning", 296 | "css.lint.unknownAtRules": "ignore", 297 | "scss.lint.unknownAtRules": "ignore", 298 | "tailwindMagic.variantGroup": true, 299 | 300 | // Vim 301 | "vim.leader": "", 302 | "vim.useSystemClipboard": true, 303 | "vim.hlsearch": true, 304 | "vim.foldfix": true, 305 | "vim.easymotion": false, 306 | "vim.highlightedyank.enable": true, 307 | "vim.highlightedyank.duration": 100, 308 | "vim.highlightedyank.color": "#00000000", 309 | "vim.highlightedyank.textColor": "white", 310 | "vim.flash.enable": true, 311 | // Vimium-C 312 | // "vim.flash.labels": "sadjklewcmpgho", 313 | // mini.jump2d 314 | // "vim.flash.labels": "abcdefghijklmnopqrstuvwxyz", 315 | // hop.nvim 316 | "vim.flash.labels": "etovxqpdygfblzhckisuran", 317 | "vim.flash.marker.nextMatchBackgroundColor": "#fdff6c", 318 | "vim.flash.marker.backgroundColor": "#3eb370", 319 | "vim.operatorPendingModeKeyBindings": [ 320 | { "before": ["H"], "after": ["^"] }, 321 | { "before": ["L"], "after": ["g", "_"] } 322 | ], 323 | "vim.visualModeKeyBindingsNonRecursive": [ 324 | // 还原原生的 f 命令 325 | // 设置 fash.nvim 查找键 326 | { "before": ["f"], "after": ["\\"] }, 327 | { "before": ["s"], "after": ["f"] }, 328 | { "before": ["`"], "after": ["S", "`", "e"] }, 329 | { "before": ["\""], "after": ["S", "\"", "e"] }, 330 | { "before": ["'"], "after": ["S", "'", "e"] }, 331 | { "before": ["("], "after": ["S", ")", "e"] }, 332 | { "before": ["p"], "after": ["p", "g", "v", "y"] }, 333 | { "before": ["j"], "after": ["g", "j"] }, 334 | { "before": ["k"], "after": ["g", "k"] }, 335 | { "before": ["J"], "after": ["4", "j"] }, 336 | { "before": ["K"], "after": ["4", "k"] }, 337 | { "before": ["H"], "after": ["^"] }, 338 | { "before": ["L"], "after": ["g", "_"] }, 339 | { "before": ["g", "h"], "commands": ["editor.action.showHover"] }, 340 | { "before": ["leader", "i", "w"], "after": ["V", "$", "%", "o"] }, 341 | { "before": ["leader", "d", "f"], "after": ["V", "$", "%", "d"] } 342 | ], 343 | "vim.normalModeKeyBindingsNonRecursive": [ 344 | // NOTE: 会覆盖原生的 Ctrl+D 命令,修复 Ctrl+D/U 在顶部代码折叠后失效 + 遇到折叠代码自动展开的问题 345 | { "before": [""], "after": ["2", "2", "g", "j", "z", "z"] }, 346 | { "before": [""], "after": ["2", "2", "g", "k", "z", "z"] }, 347 | // 通过 matchit 插件代替原生 % 功能,匹配范围更精确且支持匹配 html 标签 348 | { "before": ["s"], "commands": ["extension.matchitJumpItems"] }, 349 | { "before": ["f"], "after": ["\\"] }, 350 | { "before": [";"], "after": ["f"] }, 351 | { "before": ["="], "after": [""] }, 352 | { "before": ["-"], "after": [""] }, 353 | { "before": ["j"], "after": ["g", "j"] }, 354 | { "before": ["k"], "after": ["g", "k"] }, 355 | { "before": ["J"], "after": ["4", "g", "j"] }, 356 | { "before": ["K"], "after": ["4", "g", "k"] }, 357 | { "before": ["H"], "after": ["^"] }, 358 | { "before": ["L"], "after": ["g", "_"] }, 359 | { "before": ["U"], "after": [""] }, 360 | { "before": ["n"], "after": ["n", "z", "z"] }, 361 | { "before": ["N"], "after": ["N", "z", "z"] }, 362 | { "before": ["["], "after": ["{"] }, 363 | { "before": ["]"], "after": ["}"] }, 364 | // 解决按快了没 365 | { "before": ["v", "w", "i"], "after": ["v", "i", "w"] }, 366 | { "before": [",", ","], "after": ["A", ",", "esc"] }, 367 | { "before": ["`", "`"], "after": ["v", "i", "w", "S", "`", "e", "l"] }, 368 | { "before": ["'", "'"], "after": ["v", "i", "w", "S", "'", "e", "l"] }, 369 | { "before": ["\"", "\""], "after": ["v", "i", "w", "S", "\"", "e", "l"] }, 370 | { "before": ["g", "r"], "commands": ["editor.action.goToReferences"] }, 371 | { "before": ["z", "C"], "commands": ["editor.foldAll"] }, 372 | { "before": ["z", "O"], "commands": ["editor.unfoldAll"] }, 373 | { "before": ["leader", ";"], "commands": [":noh"] }, 374 | { "before": ["leader", "o"], "commands": ["extension.toggleBool"] }, 375 | { "before": ["leader", "l"], "commands": ["workbench.action.toggleAuxiliaryBar"] }, 376 | { "before": ["leader", "e"], "commands": ["workbench.action.toggleSidebarVisibility"] }, 377 | { "before": ["leader", "q"], "commands": ["workbench.action.closeActiveEditor"] }, 378 | { "before": ["leader", "w"], "commands": ["workbench.action.files.saveWithoutFormatting"] }, 379 | { "before": ["leader", "["], "after": ["[", "{"] }, 380 | { "before": ["leader", "]"], "after": ["]", "}"] }, 381 | { "before": ["leader", "r", "n"], "commands": ["editor.action.rename"] }, 382 | { "before": ["leader", "i", "w"], "after": ["V", "$", "%", "o"] }, 383 | { "before": ["leader", "i", "y"], "after": ["V", "$", "%", "o", "y"] }, 384 | { "before": ["leader", "d", "f"], "after": ["V", "$", "%", "o", "d"] } 385 | ], 386 | 387 | // Git 388 | "git.autofetch": true, 389 | "git.confirmSync": false, 390 | "git.enableSmartCommit": true, 391 | "git.openRepositoryInParentFolders": "never", 392 | "git.ignoreRebaseWarning": true, 393 | "git.autoStash": true, 394 | "diffEditor.ignoreTrimWhitespace": false, 395 | "diffEditor.hideUnchangedRegions.enabled": true, 396 | "scm.showActionButton": false, 397 | "scm.showInputActionButton": false, 398 | "scm.diffDecorationsGutterPattern": { 399 | "modified": false 400 | }, 401 | 402 | // GitLens 403 | "gitlens.plusFeatures.enabled": false, 404 | "gitlens.graph.minimap.enabled": false, 405 | "githubPullRequests.pullBranch": "never", 406 | 407 | // Markdown 408 | "markdown-preview-github-styles.colorTheme": "light", 409 | "markdown-preview-github-styles.lightTheme": "light_tritanopia", 410 | "markdown-preview-github-styles.darkTheme": "dark_dimmed", 411 | 412 | // ErrorLens 413 | "errorLens.enabledDiagnosticLevels": ["error", "warning", "info"], 414 | "errorLens.excludeBySource": ["cSpell", "Grammarly"], 415 | 416 | // LeetCode 417 | "leetcode.endpoint": "leetcode-cn", 418 | "leetcode.defaultLanguage": "typescript", 419 | "leetcode.workspaceFolder": "/Users/feng/codebase/public/leetcode", 420 | "leetcode.hint.commandShortcut": false, 421 | "leetcode.hint.commentDescription": false, 422 | "leetcode.hint.configWebviewMarkdown": false, 423 | 424 | // Comment Anchors 425 | "commentAnchors.tags.anchors": { 426 | "BUG": { 427 | "isBold": false, 428 | "iconColor": "red", 429 | "highlightColor": "#F44336", 430 | "scope": "workspace" 431 | }, 432 | "TODO": { 433 | "isBold": false, 434 | "iconColor": "red", 435 | "highlightColor": "#3ea8ff", 436 | "scope": "workspace" 437 | }, 438 | "FIXME": { 439 | "isBold": false, 440 | "iconColor": "red", 441 | "highlightColor": "#F44336", 442 | "scope": "workspace" 443 | }, 444 | "REVIEW": { 445 | "isBold": false, 446 | "iconColor": "orange", 447 | "highlightColor": "#FFB300", 448 | "scope": "workspace" 449 | }, 450 | "NOTE": { 451 | "isBold": false, 452 | "iconColor": "green", 453 | "highlightColor": "#2ecc71", 454 | "scope": "file" 455 | }, 456 | "DONE": { 457 | "isBold": false, 458 | "iconColor": "green", 459 | "highlightColor": "#2ecc71", 460 | "scope": "file" 461 | } 462 | }, 463 | 464 | // Code Spell Checker 465 | "cSpell.enableFiletypes": ["vimrc"], 466 | "cSpell.userWords": [ 467 | "antfu", 468 | "astro", 469 | "asvetliakov", 470 | "autofetch", 471 | "axios", 472 | "Behaviour", 473 | "bilibili", 474 | "Callout", 475 | "catppuccin", 476 | "clipboardy", 477 | "Codegeex", 478 | "codeium", 479 | "cofounder", 480 | "colour", 481 | "composables", 482 | "concat", 483 | "daisyui", 484 | "douyin", 485 | "Downie", 486 | "easymotion", 487 | "esno", 488 | "Evondev", 489 | "excalidraw", 490 | "feng", 491 | "fengstats", 492 | "filesize", 493 | "Fira", 494 | "fittencode", 495 | "flvjs", 496 | "foldfix", 497 | "fonted", 498 | "fullscreen", 499 | "Gitee", 500 | "Grammarly", 501 | "highlightedyank", 502 | "hlsearch", 503 | "iconfont", 504 | "IINA", 505 | "incsearch", 506 | "Innei", 507 | "juejin", 508 | "karabiner", 509 | "Keka", 510 | "Kirbyson", 511 | "lcpr", 512 | "leetcode", 513 | "Liga", 514 | "Logi", 515 | "logto", 516 | "macwk", 517 | "matchit", 518 | "MBTI", 519 | "Moegi", 520 | "mysqld", 521 | "naiveui", 522 | "Navicat", 523 | "neovim", 524 | "nestjs", 525 | "nums", 526 | "nuxt", 527 | "nuxtjs", 528 | "nvim", 529 | "peachpuff", 530 | "picgo", 531 | "pinia", 532 | "powermode", 533 | "PTSD", 534 | "Raycast", 535 | "rgba", 536 | "Rubick", 537 | "Shanns", 538 | "Shikiji", 539 | "Snipaste", 540 | "Sonoma", 541 | "soundmark", 542 | "streamurl", 543 | "strs", 544 | "SVIP", 545 | "tabao", 546 | "tailwindcss", 547 | "Taze", 548 | "tencent", 549 | "timi", 550 | "unocss", 551 | "unplugin", 552 | "utools", 553 | "Vimium", 554 | "vimrc", 555 | "Vite", 556 | "Vitesse", 557 | "vscodevim", 558 | "vueuse", 559 | "webrtc", 560 | "wechat", 561 | "weibo", 562 | "Windi", 563 | "xattr", 564 | "yuque", 565 | "zhihu", 566 | "zimfw", 567 | "zimrc", 568 | "zmodule", 569 | "Zolplay" 570 | ], 571 | 572 | // File Nesting 573 | "explorer.fileNesting.enabled": true, 574 | "explorer.fileNesting.expand": false, 575 | "explorer.fileNesting.patterns": { 576 | "//": "Last update at 2024/12/5 19:35:26", 577 | ".clang-tidy": ".clang-format, .clangd, compile_commands.json", 578 | ".env": "*.env, .env.*, .envrc, env.d.ts", 579 | ".gitignore": ".gitattributes, .gitmodules, .gitmessage, .mailmap, .git-blame*", 580 | ".project": ".classpath", 581 | "+layout.svelte": "+layout.ts,+layout.ts,+layout.js,+layout.server.ts,+layout.server.js,+layout.gql", 582 | "+page.svelte": "+page.server.ts,+page.server.js,+page.ts,+page.js,+page.gql", 583 | "ansible.cfg": "ansible.cfg, .ansible-lint, requirements.yml", 584 | "app.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, capacitor.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, i18n.config.*, ionic.config.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, panda.config.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, sst.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, vuetify.config.*, webpack.config.*, windi.config.*", 585 | "artisan": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, capacitor.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, i18n.config.*, ionic.config.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, panda.config.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, server.php, sst.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, vuetify.config.*, webpack.config.*, webpack.mix.js, windi.config.*", 586 | "astro.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, capacitor.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, i18n.config.*, ionic.config.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, panda.config.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, sst.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, vuetify.config.*, webpack.config.*, windi.config.*", 587 | "build-wrapper.log": "build-wrapper*.log, build-wrapper-dump*.json, build-wrapper-win*.exe, build-wrapper-linux*, build-wrapper-macosx*", 588 | "BUILD.bazel": "*.bzl, *.bazel, *.bazelrc, bazel.rc, .bazelignore, .bazelproject, WORKSPACE", 589 | "Cargo.toml": ".clippy.toml, .rustfmt.toml, cargo.lock, clippy.toml, cross.toml, rust-toolchain.toml, rustfmt.toml", 590 | "CMakeLists.txt": "*.cmake, *.cmake.in, .cmake-format.yaml, CMakePresets.json, CMakeCache.txt", 591 | "composer.json": ".php*.cache, composer.lock, phpunit.xml*, psalm*.xml", 592 | "default.nix": "shell.nix", 593 | "deno.json*": "*.env, .env.*, .envrc, api-extractor.json, deno.lock, env.d.ts, import-map.json, import_map.json, jsconfig.*, tsconfig.*, tsdoc.*", 594 | "Dockerfile": "*.dockerfile, .devcontainer.*, .dockerignore, captain-definition, compose.*, docker-compose.*, dockerfile*", 595 | "flake.nix": "flake.lock", 596 | "gatsby-config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, capacitor.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, gatsby-browser.*, gatsby-node.*, gatsby-ssr.*, gatsby-transformer.*, histoire.config.*, htmlnanorc.*, i18n.config.*, ionic.config.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, panda.config.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, sst.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, vuetify.config.*, webpack.config.*, windi.config.*", 597 | "gemfile": ".ruby-version, gemfile.lock", 598 | "go.mod": ".air*, go.sum", 599 | "go.work": "go.work.sum", 600 | "hatch.toml": ".editorconfig, .flake8, .isort.cfg, .python-version, hatch.toml, requirements*.in, requirements*.pip, requirements*.txt, tox.ini", 601 | "I*.cs": "$(capture).cs", 602 | "Makefile": "*.mk", 603 | "mix.exs": ".credo.exs, .dialyzer_ignore.exs, .formatter.exs, .iex.exs, .tool-versions, mix.lock", 604 | "next.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, capacitor.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, i18n.config.*, ionic.config.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, next-env.d.ts, next-i18next.config.*, panda.config.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, sst.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, vuetify.config.*, webpack.config.*, windi.config.*", 605 | "nuxt.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .nuxtignore, .nuxtrc, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, capacitor.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, i18n.config.*, ionic.config.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, panda.config.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, sst.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, vuetify.config.*, webpack.config.*, windi.config.*", 606 | "package.json": "*.code-workspace, .browserslist*, .circleci*, .commitlint*, .cursorrules, .cz-config.js, .czrc, .dlint.json, .dprint.json*, .editorconfig, .eslint*, .firebase*, .flowconfig, .github*, .gitlab*, .gitmojirc.json, .gitpod*, .huskyrc*, .jslint*, .knip.*, .lintstagedrc*, .markdownlint*, .node-version, .nodemon*, .npm*, .nvmrc, .pm2*, .pnp.*, .pnpm*, .prettier*, .pylintrc, .release-please*.json, .releaserc*, .ruff.toml, .sentry*, .simple-git-hooks*, .stackblitz*, .styleci*, .stylelint*, .tazerc*, .textlint*, .tool-versions, .travis*, .versionrc*, .vscode*, .watchman*, .xo-config*, .yamllint*, .yarnrc*, Procfile, apollo.config.*, appveyor*, azure-pipelines*, biome.json*, bower.json, build.config.*, bun.lockb, bunfig.toml, colada.options.ts, commitlint*, crowdin*, dangerfile*, dlint.json, dprint.json*, electron-builder.*, eslint*, firebase.json, grunt*, gulp*, jenkins*, knip.*, lerna*, lint-staged*, nest-cli.*, netlify*, nixpacks*, nodemon*, npm-shrinkwrap.json, nx.*, package-lock.json, package.nls*.json, phpcs.xml, pm2.*, pnpm*, prettier*, pullapprove*, pyrightconfig.json, release-please*.json, release-tasks.sh, release.config.*, renovate*, rollup.config.*, rspack*, ruff.toml, sentry.*.config.ts, simple-git-hooks*, sonar-project.properties, stylelint*, tslint*, tsup.config.*, turbo*, typedoc*, unlighthouse*, vercel*, vetur.config.*, webpack*, workspace.json, wrangler.toml, xo.config.*, yarn*", 607 | "Pipfile": ".editorconfig, .flake8, .isort.cfg, .python-version, Pipfile, Pipfile.lock, requirements*.in, requirements*.pip, requirements*.txt, tox.ini", 608 | "pubspec.yaml": ".metadata, .packages, all_lint_rules.yaml, analysis_options.yaml, build.yaml, pubspec.lock, pubspec_overrides.yaml", 609 | "pyproject.toml": ".commitlint*, .dlint.json, .dprint.json*, .editorconfig, .eslint*, .flake8, .flowconfig, .isort.cfg, .jslint*, .lintstagedrc*, .markdownlint*, .pdm-python, .pdm.toml, .prettier*, .pylintrc, .python-version, .ruff.toml, .stylelint*, .textlint*, .xo-config*, .yamllint*, MANIFEST.in, Pipfile, Pipfile.lock, biome.json*, commitlint*, dangerfile*, dlint.json, dprint.json*, eslint*, hatch.toml, lint-staged*, pdm.lock, phpcs.xml, poetry.lock, poetry.toml, prettier*, pyproject.toml, pyrightconfig.json, requirements*.in, requirements*.pip, requirements*.txt, ruff.toml, setup.cfg, setup.py, stylelint*, tox.ini, tslint*, uv.lock, uv.toml, xo.config.*", 610 | "quasar.conf.js": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, capacitor.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, i18n.config.*, ionic.config.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, panda.config.*, playwright.config.*, postcss.config.*, puppeteer.config.*, quasar.extensions.json, rspack.config.*, sst.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, vuetify.config.*, webpack.config.*, windi.config.*", 611 | "readme*": "AUTHORS, Authors, BACKERS*, Backers*, CHANGELOG*, CITATION*, CODEOWNERS, CODE_OF_CONDUCT*, CONTRIBUTING*, CONTRIBUTORS, COPYING*, CREDITS, Changelog*, Citation*, Code_Of_Conduct*, Codeowners, Contributing*, Contributors, Copying*, Credits, GOVERNANCE.MD, Governance.md, HISTORY.MD, History.md, LICENSE*, License*, MAINTAINERS, Maintainers, README-*, README_*, RELEASE_NOTES*, ROADMAP.MD, Readme-*, Readme_*, Release_Notes*, Roadmap.md, SECURITY.MD, SPONSORS*, Security.md, Sponsors*, authors, backers*, changelog*, citation*, code_of_conduct*, codeowners, contributing*, contributors, copying*, credits, governance.md, history.md, license*, maintainers, readme-*, readme_*, release_notes*, roadmap.md, security.md, sponsors*", 612 | "Readme*": "AUTHORS, Authors, BACKERS*, Backers*, CHANGELOG*, CITATION*, CODEOWNERS, CODE_OF_CONDUCT*, CONTRIBUTING*, CONTRIBUTORS, COPYING*, CREDITS, Changelog*, Citation*, Code_Of_Conduct*, Codeowners, Contributing*, Contributors, Copying*, Credits, GOVERNANCE.MD, Governance.md, HISTORY.MD, History.md, LICENSE*, License*, MAINTAINERS, Maintainers, README-*, README_*, RELEASE_NOTES*, ROADMAP.MD, Readme-*, Readme_*, Release_Notes*, Roadmap.md, SECURITY.MD, SPONSORS*, Security.md, Sponsors*, authors, backers*, changelog*, citation*, code_of_conduct*, codeowners, contributing*, contributors, copying*, credits, governance.md, history.md, license*, maintainers, readme-*, readme_*, release_notes*, roadmap.md, security.md, sponsors*", 613 | "README*": "AUTHORS, Authors, BACKERS*, Backers*, CHANGELOG*, CITATION*, CODEOWNERS, CODE_OF_CONDUCT*, CONTRIBUTING*, CONTRIBUTORS, COPYING*, CREDITS, Changelog*, Citation*, Code_Of_Conduct*, Codeowners, Contributing*, Contributors, Copying*, Credits, GOVERNANCE.MD, Governance.md, HISTORY.MD, History.md, LICENSE*, License*, MAINTAINERS, Maintainers, README-*, README_*, RELEASE_NOTES*, ROADMAP.MD, Readme-*, Readme_*, Release_Notes*, Roadmap.md, SECURITY.MD, SPONSORS*, Security.md, Sponsors*, authors, backers*, changelog*, citation*, code_of_conduct*, codeowners, contributing*, contributors, copying*, credits, governance.md, history.md, license*, maintainers, readme-*, readme_*, release_notes*, roadmap.md, security.md, sponsors*", 614 | "remix.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, capacitor.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, i18n.config.*, ionic.config.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, panda.config.*, playwright.config.*, postcss.config.*, puppeteer.config.*, remix.*, rspack.config.*, sst.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, vuetify.config.*, webpack.config.*, windi.config.*", 615 | "requirements.txt": ".editorconfig, .flake8, .isort.cfg, .python-version, requirements*.in, requirements*.pip, requirements*.txt, tox.ini", 616 | "rush.json": "*.code-workspace, .browserslist*, .circleci*, .commitlint*, .cursorrules, .cz-config.js, .czrc, .dlint.json, .dprint.json*, .editorconfig, .eslint*, .firebase*, .flowconfig, .github*, .gitlab*, .gitmojirc.json, .gitpod*, .huskyrc*, .jslint*, .knip.*, .lintstagedrc*, .markdownlint*, .node-version, .nodemon*, .npm*, .nvmrc, .pm2*, .pnp.*, .pnpm*, .prettier*, .pylintrc, .release-please*.json, .releaserc*, .ruff.toml, .sentry*, .simple-git-hooks*, .stackblitz*, .styleci*, .stylelint*, .tazerc*, .textlint*, .tool-versions, .travis*, .versionrc*, .vscode*, .watchman*, .xo-config*, .yamllint*, .yarnrc*, Procfile, apollo.config.*, appveyor*, azure-pipelines*, biome.json*, bower.json, build.config.*, bun.lockb, bunfig.toml, colada.options.ts, commitlint*, crowdin*, dangerfile*, dlint.json, dprint.json*, electron-builder.*, eslint*, firebase.json, grunt*, gulp*, jenkins*, knip.*, lerna*, lint-staged*, nest-cli.*, netlify*, nixpacks*, nodemon*, npm-shrinkwrap.json, nx.*, package-lock.json, package.nls*.json, phpcs.xml, pm2.*, pnpm*, prettier*, pullapprove*, pyrightconfig.json, release-please*.json, release-tasks.sh, release.config.*, renovate*, rollup.config.*, rspack*, ruff.toml, sentry.*.config.ts, simple-git-hooks*, sonar-project.properties, stylelint*, tslint*, tsup.config.*, turbo*, typedoc*, unlighthouse*, vercel*, vetur.config.*, webpack*, workspace.json, wrangler.toml, xo.config.*, yarn*", 617 | "sanity.config.*": "sanity.cli.*, sanity.types.ts, schema.json", 618 | "setup.cfg": ".editorconfig, .flake8, .isort.cfg, .python-version, MANIFEST.in, requirements*.in, requirements*.pip, requirements*.txt, setup.cfg, tox.ini", 619 | "setup.py": ".editorconfig, .flake8, .isort.cfg, .python-version, MANIFEST.in, requirements*.in, requirements*.pip, requirements*.txt, setup.cfg, setup.py, tox.ini", 620 | "shims.d.ts": "*.d.ts", 621 | "svelte.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, capacitor.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, houdini.config.*, htmlnanorc.*, i18n.config.*, ionic.config.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, mdsvex.config.js, panda.config.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, sst.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vite.config.*, vitest.config.*, vuetify.config.*, webpack.config.*, windi.config.*", 622 | "vite.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, capacitor.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, i18n.config.*, ionic.config.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, panda.config.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, sst.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, vuetify.config.*, webpack.config.*, windi.config.*", 623 | "vue.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, capacitor.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, i18n.config.*, ionic.config.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, panda.config.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, sst.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, vuetify.config.*, webpack.config.*, windi.config.*", 624 | "*.asax": "$(capture).*.cs, $(capture).*.vb", 625 | "*.ascx": "$(capture).*.cs, $(capture).*.vb", 626 | "*.ashx": "$(capture).*.cs, $(capture).*.vb", 627 | "*.aspx": "$(capture).*.cs, $(capture).*.vb", 628 | "*.axaml": "$(capture).axaml.cs", 629 | "*.bloc.dart": "$(capture).event.dart, $(capture).state.dart", 630 | "*.c": "$(capture).h", 631 | "*.cc": "$(capture).hpp, $(capture).h, $(capture).hxx, $(capture).hh", 632 | "*.cjs": "$(capture).cjs.map, $(capture).*.cjs, $(capture)_*.cjs", 633 | "*.component.ts": "$(capture).component.html, $(capture).component.spec.ts, $(capture).component.css, $(capture).component.scss, $(capture).component.sass, $(capture).component.less", 634 | "*.cpp": "$(capture).hpp, $(capture).h, $(capture).hxx, $(capture).hh", 635 | "*.cs": "$(capture).*.cs", 636 | "*.cshtml": "$(capture).cshtml.cs", 637 | "*.csproj": "*.config, *proj.user, appsettings.*, bundleconfig.json", 638 | "*.css": "$(capture).css.map, $(capture).*.css", 639 | "*.cxx": "$(capture).hpp, $(capture).h, $(capture).hxx, $(capture).hh", 640 | "*.dart": "$(capture).freezed.dart, $(capture).g.dart", 641 | "*.db": "*.db-shm, *.db-wal", 642 | "*.ex": "$(capture).html.eex, $(capture).html.heex, $(capture).html.leex", 643 | "*.fs": "$(capture).fs.js, $(capture).fs.js.map, $(capture).fs.jsx, $(capture).fs.ts, $(capture).fs.tsx, $(capture).fs.rs, $(capture).fs.php, $(capture).fs.dart", 644 | "*.go": "$(capture)_test.go", 645 | "*.java": "$(capture).class", 646 | "*.js": "$(capture).js.map, $(capture).*.js, $(capture)_*.js, $(capture).d.ts, $(capture).js.flow", 647 | "*.jsx": "$(capture).js, $(capture).*.jsx, $(capture)_*.js, $(capture)_*.jsx, $(capture).module.css, $(capture).less, $(capture).module.less, $(capture).module.less.d.ts, $(capture).scss, $(capture).module.scss, $(capture).module.scss.d.ts", 648 | "*.master": "$(capture).*.cs, $(capture).*.vb", 649 | "*.md": "$(capture).*", 650 | "*.mjs": "$(capture).mjs.map, $(capture).*.mjs, $(capture)_*.mjs", 651 | "*.module.ts": "$(capture).resolver.ts, $(capture).controller.ts, $(capture).service.ts", 652 | "*.mts": "$(capture).mts.map, $(capture).*.mts, $(capture)_*.mts", 653 | "*.pubxml": "$(capture).pubxml.user", 654 | "*.py": "$(capture).pyi", 655 | "*.razor": "$(capture).razor.cs, $(capture).razor.css, $(capture).razor.scss", 656 | "*.resx": "$(capture).*.resx, $(capture).designer.cs, $(capture).designer.vb", 657 | "*.tex": "$(capture).acn, $(capture).acr, $(capture).alg, $(capture).aux, $(capture).bbl, $(capture).bbl-SAVE-ERROR, $(capture).bcf, $(capture).blg, $(capture).fdb_latexmk, $(capture).fls, $(capture).glg, $(capture).glo, $(capture).gls, $(capture).idx, $(capture).ind, $(capture).ist, $(capture).lof, $(capture).log, $(capture).lot, $(capture).nav, $(capture).out, $(capture).run.xml, $(capture).snm, $(capture).synctex.gz, $(capture).toc, $(capture).xdv", 658 | "*.ts": "$(capture).js, $(capture).d.ts.map, $(capture).*.ts, $(capture)_*.js, $(capture)_*.ts", 659 | "*.tsx": "$(capture).ts, $(capture).*.tsx, $(capture)_*.ts, $(capture)_*.tsx, $(capture).module.css, $(capture).less, $(capture).module.less, $(capture).module.less.d.ts, $(capture).scss, $(capture).module.scss, $(capture).module.scss.d.ts, $(capture).css.ts", 660 | "*.vbproj": "*.config, *proj.user, appsettings.*, bundleconfig.json", 661 | "*.vue": "$(capture).*.ts, $(capture).*.js, $(capture).story.vue", 662 | "*.w": "$(capture).*.w, I$(capture).w", 663 | "*.wat": "$(capture).wasm", 664 | "*.xaml": "$(capture).xaml.cs" 665 | }, 666 | 667 | // Translate 668 | "commentTranslate.hover.string": true, 669 | "commentTranslate.hover.enabled": true, 670 | "commentTranslate.hover.variable": true, 671 | "commentTranslate.multiLineMerge": true, 672 | "commentTranslate.hover.content": false, 673 | "commentTranslate.maxTranslationLength": 1000, 674 | "commentTranslate.targetLanguage": "zh-CN", 675 | "commentTranslate.source": "Kaiqun.tencent-cloud-translate-tencentCloud", 676 | 677 | // Extensions 678 | "gotoAlias.closeDts": true, 679 | "fnMap.registrationCode": "flm7F9uEfVXhX8rtQpZ3kGRm9UE/Bb5Nj2t/q5msz4tQqR7WrbFDnhdtuCOUQ7DFYLSKCqh7oNqylVWdoXsiNpZo112c1KWI7U8Y+hehQmYpQbdaylIdyBbVb+gvhJ3x774vaJ7327UzyoqBlC54x+HQREYOJsdUbWKSdQ67/0sFtZL+6aumQEDJObPqQDuxQHQbT1pAjz15FnsEGADsThjgAg+toQ8TJtFx0f5cU4E+twFRpIS1O4td8OpwJDxm0OcEMfFRHsw3JzmrxxNITTRPv3lHiWr9CBMYYm0HBL61je7veCMrwDoRv9jgoTJYy1Ds7JKkqVEKK8pKe8Ez9Q==", 680 | "timeline.pageOnScroll": true, 681 | "extensions.ignoreRecommendations": true, 682 | "extensions.experimental.affinity": { 683 | "cuixiaorui.cvim": 1, 684 | "be5invis.vscode-custom-css": 2 685 | // "BrandonKirbyson.vscode-animations": 2, 686 | // "drcika.apc-extension": 2, 687 | // "vscodevim.vim": 1, 688 | // "asvetliakov.vscode-neovim": 2 689 | } 690 | } 691 | --------------------------------------------------------------------------------