Sadsnake1/word-smith
GitHub: Sadsnake1/word-smith
一款为 Obsidian 打造的全功能无干扰写作套件,提供 zen 模式、打字机滚动、前向写作锁定、可编程状态栏和写作报告等丰富功能。
Stars: 12 | Forks: 0
# Word-Smith
一款为 Obsidian 打造的无干扰写作套件:zen 模式、信箱遮罩、打字机滚动、仅向前写入锁定、语法着色、写作检查、智能排版,以及可配置的状态栏——每一项均可独立开启,互不干扰。
## 展示
## 功能
设置被组织为七个标签页:**Retro Bar**、**Zen**、**Typewriter**、**Hemingway**、**Syntax**、**Text Options** 和 **Misc**。
### 作用范围
Word-Smith 可以在双向限制于特定的文件夹和笔记——*仅限于这些* 或 *除了这些之外的所有地方*。将列表留空,它就会应用于所有笔记。
单个笔记可以通过其 frontmatter 覆盖所有设置,并且 frontmatter 的优先级高于列表:
```
---
wordsmith: off # ignore this note entirely
ws-zen: true # or override one thing at a time
ws-typewriter: false
ws-hemingway: true
ws-syntax: true
ws-markers: false
ws-typography: false
ws-font: Literata # font for this note only
ws-goal: 2000 # word target for this note
---
```
此外还有一个可选的 **恢复光标位置** 功能,它会在你上次留下插入符号的地方重新打开笔记——包括滚动位置,无论你在哪个窗格打开它。
设计上,所有功能仅限于笔记本身:当你打开画布、Base、PDF 或空白标签页时,状态栏会自动隐藏,Obsidian 原生的界面元素会回归;而当你切回笔记的瞬间,这一切又会再次切换。
### Retro bar
固定在屏幕底部的状态栏,其宽度与打开的笔记相匹配(而非整个窗口)。**一至三行堆叠排列**,每一行都有独立格式化的 **左侧**、**居中** 和 **右侧** 插槽,每个插槽可以接受任意 token 的组合。
新建的 vault 默认使用 **Mash** 状态栏。除此之外还内置了五种样式——**Plain**、**DOS**、**Zero**、**Echo**、**Slant**——你可以保存、分享并加载自己的样式(参见下文的 *Presets*)。
#### 读数
| Token | 显示内容 |
|---|---|
| `{file}` | 当前文件——完整路径或仅文件名(可配置) |
| `{words}` | 字数(如果选中了文本,则为选中文本的字数) |
| `{chars}` | 字符数(如果选中了文本,则为选中文本的字符数) |
| `{ln:col}` | 插入符号位置 |
| `{paragraph}` | 当前段落 / 总段落数 |
| `{readtime}` | 预计阅读时间,可根据每分钟可配置字数进行计算 |
| `{mode}` | 激活的模式徽章:**T** 打字机,**H** Hemingway,**Z** zen |
| `{time}` | 以文本形式显示的当前时间 |
| `{clock}` | 同样的时间,但绘制为表盘样式 |
| `{dd}` `{mm}` `{yyyy}` `{yy}` | 日期部分——你可以使用任何喜欢的分隔符组合它们 |
| `{battery}` | 电池电量(充电时显示 ⚡︎) |
| `{caps}` | 开启时双行显示的 `CAPS LOCK` |
| `{num}` | 开启时双行显示的 `NUM LOCK` |
| `{vim}` | 当前的 vim 模式:`-- NORMAL --`、`-- INSERT --`、`-- VISUAL --`、`-- REPLACE --`,以及在由按键驱动界面而非文本的地方显示 `-- COMMAND --`——vim 的 `:` 命令行、命令面板、搜索、快速切换器 |
| `{obsidian}` | 一个微小的 Obsidian 水晶图标,使用其所在区段当前的文本颜色绘制 |
#### 按钮
这些在被点击时会执行操作,并且当状态栏空间不足时它们永远不会被隐藏。
| Token | 操作 |
|---|---|
| `{goal}` | 写作目标仪表。点击可设置目标或重置基准 |
| `{filegoal}` | 当前笔记的字数目标。点击进行设置 |
| `{foldergoal}` | 当前文件夹的字数目标,会统计其下所有笔记的字数 |
| `{syntax}` | 五种词类的选择器,每种旁边都有其专属颜色 |
| `{prose}` | 所有七项写作检查的选择器,以及该组的总开关 |
| `{markers}` | 空格、制表符、段落和行尾标记的选择器 |
| `{font}` | 字体选择器——以你当前选用的字体显示 `Aa` |
| `{report}` | 打开写作报告 |
点击 `{mode}` 徽章可切换对应模式;未激活的徽章会变淡。**Z** 徽章可移动整个 Zen 界面的两个部分。
#### 间隔符
`{s}`、`{ss}`、`{sss}`… —— 每一个 `s` 代表四分之一个空格。仅仅是空白空间,仅此而已。如果为其指定颜色(`{s}:3`),它就会变成一条实心窄条:作为区段旁边的边缘着色。
#### Powerline
开启 powerline 后,token 之间的标点符号就会变成各种形状。**字符即为分隔符:**
| | |
|---|---|
| `>` `<` | 箭头 |
| `\|` | 直线 |
| `)` `(` | 圆角 |
| `~` | 波浪线 |
| `/` `\` | 两种斜切角 |
输入 `\|` 来表示字面意义上的管道符。在一行的最开头或最末尾,`<` 和 `>` 还可以决定端盖的指向——`<{file}` 表示向左指,`{words}>` 表示向右指。
分隔符以 SVG 形式绘制,因此无需依赖任何修补过的 Nerd Font,并且它们会随状态栏的高度自动缩放。
**区段颜色** —— 包含七种背景色和四种文本颜色的调色板,每种都有深色和浅色两种变体:
| 写法 | 作用 |
|---|---|
| `{words}:N` | 背景 N(1–7,循环使用) |
| `{words}:N;M` | `;M` 选择文本 M(1–4);否则文本颜色会自动根据对比度推导 |
| `{ln:col}:vim` | 背景跟随实时的 vim 模式——`{vim}` 区段会自动执行此操作 |
| `{words};vim` | *文本* 跟随模式——可单独使用,或与任何 `:N` 搭配 |
| `{file}:b1` `{file}:b2` | 主题的页面 / 面板颜色——一种与状态栏融为一体的区段 |
| `{file};t1` `{file};t2` | 主题的常规 / 弱化文本颜色——`:b1`/`:b2` 的孪生兄弟 |
**状态栏本身** 采用相同的语法,写在第 1 行左侧插槽的最开头:`:b1` `:b2` `:N` `:vim` 设置其背景,`;t1` `;t2` `;N` `;vim` 设置其文本。可以单独使用其中一种或同时使用两种,顺序不限。如果使用了 `:N` 或 `:vim` 而未指定文本颜色,文本颜色会自动推导,以确保状态栏在任何背景下都能保持清晰可读。
```
:vim {vim} > {file} :: {ln:col}
```
**渐变** —— 阶梯式渐变,通过 `{g}` 书写:
```
{file}:3 | {g}{g}{g}{g} | {words}:5
```
一连串本身没有颜色的 `{g}` 会在其相邻元素的颜色之间渐变——或者在一组元素的末尾渐变到状态栏本身的颜色。每个 token 代表一条色带,因此 `{g}{g}{g}` 会形成三个狭窄的阶梯,而 `{ggg}` 则是一个宽阔的阶梯;你可以自由掌握颗粒度。将分隔符放在 `{g}` token *之间*,它们就能保持形状,并贯穿一条连续的渐变色带:
```
{file}:3 > {g}>{g}>{g} > {words}:5
```
**柔和标记** 位于单个区段内部,使用其自身颜色绘制,而非位于两个区块之间:`::` 是一条细短的辅助线,`>>` 和 `<<` 是与箭头角度相匹配的全高尖角符号。
#### Presets
可将任何状态栏保存为命名的预设,并一键重新加载。每个预设都携带了完整的视觉样式——行数、颜色、分隔符样式、尺寸——并能生成一串 **分享代码**,你可以将其粘贴给他人,或在开始尝试前作为备份保留。
#### 尺寸与行为
可配置行高、字体大小、顶部和底部内边距,以及两侧边缘的分割线样式与粗细。状态栏的排版也可以 **匹配笔记自身的文本大小**,因此它会跟随 Ctrl+滚轮 缩放,整个视图保持一致。
当窗口变窄时,状态栏会按照固定的顺序裁剪内容,而不是换行或缩小字体:首先缩短文件路径,然后从边缘向内移除读数。按钮始终会保留。
默认情况下,它遵循主题的背景和文本颜色,并可选自定义颜色覆盖(深色/浅色选择器分开),同时采用你通过 `{font}` 挑选的任何字体。激活时它会自动隐藏 Obsidian 原生状态栏,并为 vim 的 `:` 命令行让路,确保其可见。
**目标仪表。** 三种目标的绘制方式相同:一个随你的写作进度填充的进度条(垂直或水平),旁边显示百分比或分数——或者只显示标签而无进度条。厚度、长度和颜色均可配置,每个目标可以设定专属颜色。文件目标和文件夹目标都没有基准线;它们只是根据设定的目标来统计字数。
### Zen
一个控制两部分的统一总开关。
**Focus mode** 隐藏 UI 界面(标签页、视图标题、侧边栏、属性、滚动条、反向链接、原生状态栏),折叠双侧边栏,并支持进入全屏。可选的专注文件模式会隐藏所有其他窗格,仅保留当前活动的笔记。每一个被隐藏的元素都有独立的开关。Obsidian 自身的标题栏也可以被绘制成与编辑器一致的颜色,从而让窗口毫无缝隙。按下 `Escape` 退出(兼容 vim 模式和 Excalidraw)。
**Letterbox** 使用顶部和底部的遮罩来框定写作区域——可调整高度、水平内边距、箭头样式(实心/空心三角形、标准箭头、单/双尖角符号或自定义字符)、箭头数量和比例,可选择在行两端加上箭头端盖,以及分割线样式与粗细。箭头和线条的深色/浅色颜色相互独立。拖动分割线可调整遮罩大小;拖动箭头行可调整内边距——所有操作均直接在编辑器中实时进行。遮罩区域依然是窗口的拖拽手柄,因此隐藏标题栏对你毫无损失。
Letterbox 功能与打字机滚动相互独立:你可以单独使用其中一个,而无需开启另一个。
### Typewriter
在你打字时保持光标所在行垂直固定。可配置在光标 **上方** 和 **下方** 保留多少行上下文(数值相等时光标将完全居中)。
- **当前行高亮** —— 为光标所在行着色,深色/浅色颜色分开,并提供透明度滑块。
- **焦点淡化** —— 在你写作时淡化焦点区域之外的所有内容。可选择 **段落** 或 **句子** 颗粒度(在句子模式下,即使是同一行内的其他句子也会被淡化),并设置淡化透明度。当编辑器失去焦点时,淡化效果会自动解除。
两者均通过 CodeMirror 自身的装饰 pipeline 渲染,因此在打字时绝无闪烁。
### Hemingway
阻挡你用来回退和修改的按键,确保草稿只能向前推进。每一个锁定均可独立切换:
**删除文本** —— 退格键(及其删除单词/行的变体)、向前删除键、撤销、重做、剪切、粘贴。
**移动光标** —— 方向键、Home/End/Page Up/Page Down、全选、鼠标点击。
按键被锁定时,可单独闪烁 **H 徽章**、**retro bar**、**屏幕**、屏幕和状态栏,或不闪烁。所有锁定均非永久——随时可在标签页或状态栏的 `H` 徽章处关闭。
锁定机制在两个层面起作用:一个是处理按键的高优先级 keymap,另一个是 `beforeinput` 层,同样能拦截编辑菜单、右键菜单、IME 和移动端键盘操作。
### 写作报告
`{report}` 会打开一个包含两个标签页的面板——当前笔记及其文件夹——各自展示十项数据:
**词数**、**字符数**、**无空格字符数**、**音节数**、**句子数**、**段落数**、**行数**、**页数**、**阅读时间**,以及 **Flesch–Kincaid 年级水平**。
数据上方是一个进度仪表,显示你相对于该笔记或文件夹目标的进度,颜色随进度填充由红变绿。将鼠标悬停在每个数据上都会有详细说明——排除了什么、如何计算、以什么标准界定一页。
达到目标时,报告会为你放烟花庆祝。
### Syntax
包含两组功能,且全部在你的设备本地运行。
**Word classes** —— 名词、动词、形容词、副词、连词,每种都有专属颜色和开关。可选择淡化其他所有词汇,突出某一类词。一次开启一种可以专门针对该类词阅读段落;全部开启则会呈现五颜六色的效果。
**Writing checks** —— 值得重读的模式,而非错误:
| 检查项 | 捕捉目标 |
|---|---|
| Filler words | 模棱两可的词和强调词——*very*、*really*、*basically*、*kind of*、*in order to* |
| Passive voice | *to be* 的某种形式加上过去分词——*was written*、*is being considered* |
| Lexical illusions | 同一个词连续出现两次。肉眼容易忽略,这也是它们能逃过校对的原因 |
| Commonly misused | 人们常常用错的一对词——*affect/effect*、*its/it's*、*fewer/less* |
| Loose pronoun | 句子开头的代词,读者必须猜测其指代对象 |
| Sentence rhythm | 根据阅读难度为句子着色,单调的文笔会显示为单一颜色的色块墙 |
| Repetition radar | 两个相同且不常用的词挨得太近——你写下却从未察觉的重复 |
两组功能均可独立选择渲染为 **彩色文本**、**高亮**、**波浪线** 或 **下划线**。代码、frontmatter 和数学公式会被跳过。
易错词对无论你使用了哪一个半边都会被标记——究竟哪个才是对的取决于具体句子,重点在于提醒你留意,而非强行纠正。
### 文本选项
两个互相独立的总开关。
**Text options**
- **限制行宽** —— 无论窗口宽度如何,将文本列限制在固定的字符宽度。
- **水平内边距** —— 左右文本内边距,应用于所有地方。
- **段落缩进** —— 首行缩进,由空行或每一行触发,宽度可调。仅应用于段落:列表、任务、标题、引用、表格和代码均不受影响。
- **行间距** —— 行高倍数。
- **文本两端对齐** —— 在编辑和阅读视图中均实现两端完全对齐。
- **隐藏标记** —— 显示不可见字符,每个都有独立的开关:空格 (`·`)、制表符 (`→`)、段落换行符 (`¶`) 和行尾符 (`↵`)。
**Typography** —— 在你写作时将输入的简写替换为真正的字符:弯引号和撇号、省略号、短/长破折号、箭头、尖括号引号、比较运算符和分数。每个组别均可单独切换。绝不在代码、数学公式或 frontmatter 中触发,并且撤销操作会精确还原你的原始输入。
引号字符本身是可配置的,因此 `"` 和 `'` 可以打出德语的 „…“、法语的 « … » 或任何其他格式。撇号的设置与右单引号分开,插件会通过回溯未闭合的引号来自行判断你的意图——因此 *don't* 和 *'word'* 都能被正确转换。
### Right-to-left
如果 Obsidian 或笔记被设置为从右向左(RTL)书写,文本选项就会发生镜像翻转:缩进和内边距会跟随文本方向,两端对齐的文本将其最后一行设为向右对齐,制表符和行尾标记也会指向相反的方向。词数统计已支持希伯来语、阿拉伯语和波斯语。
语法着色和写作检查仅支持英文。在从右向左书写的文本中,它们不会标记任何内容,从而避免标记错误。
### 杂项
**Vim** —— 一个可将 `j`、`k`、0 和 `$` 映射到带 `g` 前缀形式的选项,使得移动操作遵循自动换行后的行而非原段落。
**Word goals** —— 写作目标,加上你设置的所有文件和文件夹目标,均可在同一个列表中编辑。它们与你点击 `{filegoal}` 和 `{foldergoal}` token 时设置的目标完全一致。
文件管理器(汇总到文件夹)中可选的单文件字数统计,以及大纲面板中的单标题字数统计。
词数统计功能对 markdown 感知:会排除 frontmatter、围栏代码块、数学公式块、HTML、URL、链接目标和列表标记,同时统计标题、列表文本和链接标签。中文和日文按字符数统计;韩文按词数统计。
## 命令
- **Word-Smith: Toggle Word-Smith on/off** —— 整个插件的总开关(也可作为 “WS” 侧边栏徽章使用)
- **Word-Smith: Show or hide the retro bar** —— 滑出和滑入状态栏,而无需将其关闭
- **Word-Smith: Copy bar layout diagnostic** —— 将状态栏测得的几何布局复制到剪贴板,用于提交 bug 报告
其他所有功能均可在设置标签页或直接通过 retro bar 上的 token 访问。
## 安装说明
1. 下载 `main.js`、`styles.css` 和 `manifest.json`(或 clone 本仓库)。
2. 在你的 vault 的 `.obsidian/plugins/` 目录下创建一个名为 `word-smith` 的文件夹。
3. 将文件复制到该文件夹中。
4. 重新加载 Obsidian(或将其重启),然后在 **Settings → Community plugins** 下启用 **Word-Smith**。
更新时请复制全部三个文件,而不仅是 `main.js` —— 插件会检查样式表是否与脚本匹配,若不匹配会在启动时发出警告。
## 隐私
Word-Smith 完全在本地运行。
- **无网络访问。** 插件中没有任何 `fetch`、`XMLHttpRequest`、`WebSocket` 或 `requestUrl` 调用。源代码中唯一的 URL 是 SVG 命名空间字符串。
- **无遥测、数据分析或崩溃报告。**
- **无第三方依赖。** 没有任何打包模块。仅有的导入项是 `obsidian` 和 `@codemirror/*`,且均由 Obsidian 自身提供。
- **无 Obsidian 自身 API 之外的文件系统访问。** 没有 `require('fs')`,没有 `child_process`,没有 Electron 转义。
### 它会读取什么
在笔记打开期间读取内存中的笔记内容——用于字数统计、语法着色和段落检测。它们从编辑器读取后即被丢弃。绝不会被复制、缓存或写入任何地方。
写作报告还会在你打开对应标签页时读取文件夹中的笔记,以进行汇总。这些总计数据保存在内存中,并在文件发生更改时重新计算。
它还会读取笔记的 frontmatter,以执行 `wordsmith:` 和 `ws-*` 覆盖指令。
### 它会存储什么
仅有一个文件:`data.json`,位于你 vault 内的插件专属文件夹中。
它存储你的设置、已保存的状态栏预设,以及你设置的任何文件和文件夹字数目标。如果你开启了 **恢复光标位置**,它还会为每个笔记路径存储行号、列和滚动偏移量——最多保留最近 300 个笔记。存储的仅仅是文件 *路径* 和 *位置*,绝不包含文件内容。关闭该设置并删除 `data.json` 即可将其清除。
除此之外,没有任何信息被存储在任何地方。
### 自行验证
该插件是一个单可读文件。切勿仅听信我的一面之词:
```
grep -nE "fetch\(|XMLHttpRequest|WebSocket|requestUrl|sendBeacon" main.js
```
该命令什么也不返回。Word-Smith 采用 MIT 许可协议,完整源代码均在本仓库中。
## 语法高亮是如何工作的
没有 API,没有模型,也没有打包任何 NLP 库——它是一个完全在你 vault 内部运行的手写词性标注器。
每个可见行都通过三遍处理进行标注。
**1. 词汇表。** 一张包含约 800 个单词的表格,这些单词无法信任后缀规则:限定词、代词、介词、连词、助动词和情态动词、不规则动词,以及如果不特判就会被误标的常见名词和形容词。如 `the`、`is`、`went`、`difficult`。
**2. 后缀规则。** 任何不在词汇表中的词都会根据其结尾进行猜测,按可靠性排序:
| 结尾 | 标签 | 备注 |
|---|---|---|
| `-ly` | 副词 | 排除约 90 个例外——`family`、`reply`、`early`、`friendly` |
| `-ing` `-ed` | 动词 | |
| `-est` | 形容词 | |
| `-tion` `-ment` `-ness` `-ity` `-ism` `-ology` | 名词 | |
| `-ous` `-ful` `-less` `-ive` `-able` `-ical` `-ish` | 形容词 | |
| `-ize` `-ate` `-ify` | 动词 | |
| `-s` | 名词或动词 | 取决于其单数形式是否为已知动词 |
**3. 上下文。** 这一过程利用两侧的单词来修正前两步犯的错误:
- 在限定词或介词之后,动词会变成名词——*the **work***、*in **place***。一个以 `-ing` 结尾的词会变成动名词(*the **meeting***),除非后面跟着名词,此时它变成修饰语(*the **running** water*)。
- 介于限定词和名词之间的未知词会填补形容词的位置——*her **difficult** book*。
- 在 `to` 之后,候选词会变成不定式——*to **write***。
- `to` 本身是介词,除非后面跟着动词,以此来区分 *to **the** shop* 和 *to **write***。
- 句首单词后跟着限定词时,会被判定为祈使语气动词——***Check** the file*。
这五种结果——名词、动词、形容词、副词、连词——会作为 CodeMirror 装饰进行渲染,因此它们会在编辑器自身的 pipeline 中呈现,且在你打字时绝不会闪烁。
写作检查基于同一套被标注的 token 运行。被动语态、填充词等均基于列表和规则;句子节奏通过 Flesch–Kincaid 为每个句子打分;重复雷达则维护着一个不常用词的滑动窗口。
### 它刻意不着色的内容
冠词和物主限定词。高亮形容词不应该点亮每一个 `the`、`a` 和 `her`——它们的行为类似于冠词,而非描述词。
代词被作为名词统计,介词被作为连词统计。
### 准确率
根据我自己的测试,在普通文本上大约十词能中九词——这并没有使用标记语料库进行基准测试。它在对白密集的小说和句子片段中表现最弱,因为上下文规则能利用的信息较少,对于不常见的专有名词也是如此。
这就是为什么它是一款写作辅助工具,而不是语法检查器:颜色旨在提醒你再次审视句子,而不是下定论。一次只开启一个词类——比如显示你所有的动词,或者所有的形容词——才是它的正确用法。
### 性能
仅对当前屏幕上显示的行进行标注,代码块、frontmatter 和数学公式将被完全跳过。在一篇 11 万词的笔记上,每次重绘耗时约 2ms,因此完全不会造成打字卡顿。
## 反馈
发现 bug 或有想法?欢迎提交 issue!
## 定价
Word-Smith 100% 免费。
如果你想支持这个项目并帮助我持续推出更新,非常欢迎请我喝杯咖啡。你的支持对我来说意义非凡。万分感谢!
## 许可协议
MIT
## 功能
设置被组织为七个标签页:**Retro Bar**、**Zen**、**Typewriter**、**Hemingway**、**Syntax**、**Text Options** 和 **Misc**。
### 作用范围
Word-Smith 可以在双向限制于特定的文件夹和笔记——*仅限于这些* 或 *除了这些之外的所有地方*。将列表留空,它就会应用于所有笔记。
单个笔记可以通过其 frontmatter 覆盖所有设置,并且 frontmatter 的优先级高于列表:
```
---
wordsmith: off # ignore this note entirely
ws-zen: true # or override one thing at a time
ws-typewriter: false
ws-hemingway: true
ws-syntax: true
ws-markers: false
ws-typography: false
ws-font: Literata # font for this note only
ws-goal: 2000 # word target for this note
---
```
此外还有一个可选的 **恢复光标位置** 功能,它会在你上次留下插入符号的地方重新打开笔记——包括滚动位置,无论你在哪个窗格打开它。
设计上,所有功能仅限于笔记本身:当你打开画布、Base、PDF 或空白标签页时,状态栏会自动隐藏,Obsidian 原生的界面元素会回归;而当你切回笔记的瞬间,这一切又会再次切换。
### Retro bar
固定在屏幕底部的状态栏,其宽度与打开的笔记相匹配(而非整个窗口)。**一至三行堆叠排列**,每一行都有独立格式化的 **左侧**、**居中** 和 **右侧** 插槽,每个插槽可以接受任意 token 的组合。
新建的 vault 默认使用 **Mash** 状态栏。除此之外还内置了五种样式——**Plain**、**DOS**、**Zero**、**Echo**、**Slant**——你可以保存、分享并加载自己的样式(参见下文的 *Presets*)。
#### 读数
| Token | 显示内容 |
|---|---|
| `{file}` | 当前文件——完整路径或仅文件名(可配置) |
| `{words}` | 字数(如果选中了文本,则为选中文本的字数) |
| `{chars}` | 字符数(如果选中了文本,则为选中文本的字符数) |
| `{ln:col}` | 插入符号位置 |
| `{paragraph}` | 当前段落 / 总段落数 |
| `{readtime}` | 预计阅读时间,可根据每分钟可配置字数进行计算 |
| `{mode}` | 激活的模式徽章:**T** 打字机,**H** Hemingway,**Z** zen |
| `{time}` | 以文本形式显示的当前时间 |
| `{clock}` | 同样的时间,但绘制为表盘样式 |
| `{dd}` `{mm}` `{yyyy}` `{yy}` | 日期部分——你可以使用任何喜欢的分隔符组合它们 |
| `{battery}` | 电池电量(充电时显示 ⚡︎) |
| `{caps}` | 开启时双行显示的 `CAPS LOCK` |
| `{num}` | 开启时双行显示的 `NUM LOCK` |
| `{vim}` | 当前的 vim 模式:`-- NORMAL --`、`-- INSERT --`、`-- VISUAL --`、`-- REPLACE --`,以及在由按键驱动界面而非文本的地方显示 `-- COMMAND --`——vim 的 `:` 命令行、命令面板、搜索、快速切换器 |
| `{obsidian}` | 一个微小的 Obsidian 水晶图标,使用其所在区段当前的文本颜色绘制 |
#### 按钮
这些在被点击时会执行操作,并且当状态栏空间不足时它们永远不会被隐藏。
| Token | 操作 |
|---|---|
| `{goal}` | 写作目标仪表。点击可设置目标或重置基准 |
| `{filegoal}` | 当前笔记的字数目标。点击进行设置 |
| `{foldergoal}` | 当前文件夹的字数目标,会统计其下所有笔记的字数 |
| `{syntax}` | 五种词类的选择器,每种旁边都有其专属颜色 |
| `{prose}` | 所有七项写作检查的选择器,以及该组的总开关 |
| `{markers}` | 空格、制表符、段落和行尾标记的选择器 |
| `{font}` | 字体选择器——以你当前选用的字体显示 `Aa` |
| `{report}` | 打开写作报告 |
点击 `{mode}` 徽章可切换对应模式;未激活的徽章会变淡。**Z** 徽章可移动整个 Zen 界面的两个部分。
#### 间隔符
`{s}`、`{ss}`、`{sss}`… —— 每一个 `s` 代表四分之一个空格。仅仅是空白空间,仅此而已。如果为其指定颜色(`{s}:3`),它就会变成一条实心窄条:作为区段旁边的边缘着色。
#### Powerline
开启 powerline 后,token 之间的标点符号就会变成各种形状。**字符即为分隔符:**
| | |
|---|---|
| `>` `<` | 箭头 |
| `\|` | 直线 |
| `)` `(` | 圆角 |
| `~` | 波浪线 |
| `/` `\` | 两种斜切角 |
输入 `\|` 来表示字面意义上的管道符。在一行的最开头或最末尾,`<` 和 `>` 还可以决定端盖的指向——`<{file}` 表示向左指,`{words}>` 表示向右指。
分隔符以 SVG 形式绘制,因此无需依赖任何修补过的 Nerd Font,并且它们会随状态栏的高度自动缩放。
**区段颜色** —— 包含七种背景色和四种文本颜色的调色板,每种都有深色和浅色两种变体:
| 写法 | 作用 |
|---|---|
| `{words}:N` | 背景 N(1–7,循环使用) |
| `{words}:N;M` | `;M` 选择文本 M(1–4);否则文本颜色会自动根据对比度推导 |
| `{ln:col}:vim` | 背景跟随实时的 vim 模式——`{vim}` 区段会自动执行此操作 |
| `{words};vim` | *文本* 跟随模式——可单独使用,或与任何 `:N` 搭配 |
| `{file}:b1` `{file}:b2` | 主题的页面 / 面板颜色——一种与状态栏融为一体的区段 |
| `{file};t1` `{file};t2` | 主题的常规 / 弱化文本颜色——`:b1`/`:b2` 的孪生兄弟 |
**状态栏本身** 采用相同的语法,写在第 1 行左侧插槽的最开头:`:b1` `:b2` `:N` `:vim` 设置其背景,`;t1` `;t2` `;N` `;vim` 设置其文本。可以单独使用其中一种或同时使用两种,顺序不限。如果使用了 `:N` 或 `:vim` 而未指定文本颜色,文本颜色会自动推导,以确保状态栏在任何背景下都能保持清晰可读。
```
:vim {vim} > {file} :: {ln:col}
```
**渐变** —— 阶梯式渐变,通过 `{g}` 书写:
```
{file}:3 | {g}{g}{g}{g} | {words}:5
```
一连串本身没有颜色的 `{g}` 会在其相邻元素的颜色之间渐变——或者在一组元素的末尾渐变到状态栏本身的颜色。每个 token 代表一条色带,因此 `{g}{g}{g}` 会形成三个狭窄的阶梯,而 `{ggg}` 则是一个宽阔的阶梯;你可以自由掌握颗粒度。将分隔符放在 `{g}` token *之间*,它们就能保持形状,并贯穿一条连续的渐变色带:
```
{file}:3 > {g}>{g}>{g} > {words}:5
```
**柔和标记** 位于单个区段内部,使用其自身颜色绘制,而非位于两个区块之间:`::` 是一条细短的辅助线,`>>` 和 `<<` 是与箭头角度相匹配的全高尖角符号。
#### Presets
可将任何状态栏保存为命名的预设,并一键重新加载。每个预设都携带了完整的视觉样式——行数、颜色、分隔符样式、尺寸——并能生成一串 **分享代码**,你可以将其粘贴给他人,或在开始尝试前作为备份保留。
#### 尺寸与行为
可配置行高、字体大小、顶部和底部内边距,以及两侧边缘的分割线样式与粗细。状态栏的排版也可以 **匹配笔记自身的文本大小**,因此它会跟随 Ctrl+滚轮 缩放,整个视图保持一致。
当窗口变窄时,状态栏会按照固定的顺序裁剪内容,而不是换行或缩小字体:首先缩短文件路径,然后从边缘向内移除读数。按钮始终会保留。
默认情况下,它遵循主题的背景和文本颜色,并可选自定义颜色覆盖(深色/浅色选择器分开),同时采用你通过 `{font}` 挑选的任何字体。激活时它会自动隐藏 Obsidian 原生状态栏,并为 vim 的 `:` 命令行让路,确保其可见。
**目标仪表。** 三种目标的绘制方式相同:一个随你的写作进度填充的进度条(垂直或水平),旁边显示百分比或分数——或者只显示标签而无进度条。厚度、长度和颜色均可配置,每个目标可以设定专属颜色。文件目标和文件夹目标都没有基准线;它们只是根据设定的目标来统计字数。
### Zen
一个控制两部分的统一总开关。
**Focus mode** 隐藏 UI 界面(标签页、视图标题、侧边栏、属性、滚动条、反向链接、原生状态栏),折叠双侧边栏,并支持进入全屏。可选的专注文件模式会隐藏所有其他窗格,仅保留当前活动的笔记。每一个被隐藏的元素都有独立的开关。Obsidian 自身的标题栏也可以被绘制成与编辑器一致的颜色,从而让窗口毫无缝隙。按下 `Escape` 退出(兼容 vim 模式和 Excalidraw)。
**Letterbox** 使用顶部和底部的遮罩来框定写作区域——可调整高度、水平内边距、箭头样式(实心/空心三角形、标准箭头、单/双尖角符号或自定义字符)、箭头数量和比例,可选择在行两端加上箭头端盖,以及分割线样式与粗细。箭头和线条的深色/浅色颜色相互独立。拖动分割线可调整遮罩大小;拖动箭头行可调整内边距——所有操作均直接在编辑器中实时进行。遮罩区域依然是窗口的拖拽手柄,因此隐藏标题栏对你毫无损失。
Letterbox 功能与打字机滚动相互独立:你可以单独使用其中一个,而无需开启另一个。
### Typewriter
在你打字时保持光标所在行垂直固定。可配置在光标 **上方** 和 **下方** 保留多少行上下文(数值相等时光标将完全居中)。
- **当前行高亮** —— 为光标所在行着色,深色/浅色颜色分开,并提供透明度滑块。
- **焦点淡化** —— 在你写作时淡化焦点区域之外的所有内容。可选择 **段落** 或 **句子** 颗粒度(在句子模式下,即使是同一行内的其他句子也会被淡化),并设置淡化透明度。当编辑器失去焦点时,淡化效果会自动解除。
两者均通过 CodeMirror 自身的装饰 pipeline 渲染,因此在打字时绝无闪烁。
### Hemingway
阻挡你用来回退和修改的按键,确保草稿只能向前推进。每一个锁定均可独立切换:
**删除文本** —— 退格键(及其删除单词/行的变体)、向前删除键、撤销、重做、剪切、粘贴。
**移动光标** —— 方向键、Home/End/Page Up/Page Down、全选、鼠标点击。
按键被锁定时,可单独闪烁 **H 徽章**、**retro bar**、**屏幕**、屏幕和状态栏,或不闪烁。所有锁定均非永久——随时可在标签页或状态栏的 `H` 徽章处关闭。
锁定机制在两个层面起作用:一个是处理按键的高优先级 keymap,另一个是 `beforeinput` 层,同样能拦截编辑菜单、右键菜单、IME 和移动端键盘操作。
### 写作报告
`{report}` 会打开一个包含两个标签页的面板——当前笔记及其文件夹——各自展示十项数据:
**词数**、**字符数**、**无空格字符数**、**音节数**、**句子数**、**段落数**、**行数**、**页数**、**阅读时间**,以及 **Flesch–Kincaid 年级水平**。
数据上方是一个进度仪表,显示你相对于该笔记或文件夹目标的进度,颜色随进度填充由红变绿。将鼠标悬停在每个数据上都会有详细说明——排除了什么、如何计算、以什么标准界定一页。
达到目标时,报告会为你放烟花庆祝。
### Syntax
包含两组功能,且全部在你的设备本地运行。
**Word classes** —— 名词、动词、形容词、副词、连词,每种都有专属颜色和开关。可选择淡化其他所有词汇,突出某一类词。一次开启一种可以专门针对该类词阅读段落;全部开启则会呈现五颜六色的效果。
**Writing checks** —— 值得重读的模式,而非错误:
| 检查项 | 捕捉目标 |
|---|---|
| Filler words | 模棱两可的词和强调词——*very*、*really*、*basically*、*kind of*、*in order to* |
| Passive voice | *to be* 的某种形式加上过去分词——*was written*、*is being considered* |
| Lexical illusions | 同一个词连续出现两次。肉眼容易忽略,这也是它们能逃过校对的原因 |
| Commonly misused | 人们常常用错的一对词——*affect/effect*、*its/it's*、*fewer/less* |
| Loose pronoun | 句子开头的代词,读者必须猜测其指代对象 |
| Sentence rhythm | 根据阅读难度为句子着色,单调的文笔会显示为单一颜色的色块墙 |
| Repetition radar | 两个相同且不常用的词挨得太近——你写下却从未察觉的重复 |
两组功能均可独立选择渲染为 **彩色文本**、**高亮**、**波浪线** 或 **下划线**。代码、frontmatter 和数学公式会被跳过。
易错词对无论你使用了哪一个半边都会被标记——究竟哪个才是对的取决于具体句子,重点在于提醒你留意,而非强行纠正。
### 文本选项
两个互相独立的总开关。
**Text options**
- **限制行宽** —— 无论窗口宽度如何,将文本列限制在固定的字符宽度。
- **水平内边距** —— 左右文本内边距,应用于所有地方。
- **段落缩进** —— 首行缩进,由空行或每一行触发,宽度可调。仅应用于段落:列表、任务、标题、引用、表格和代码均不受影响。
- **行间距** —— 行高倍数。
- **文本两端对齐** —— 在编辑和阅读视图中均实现两端完全对齐。
- **隐藏标记** —— 显示不可见字符,每个都有独立的开关:空格 (`·`)、制表符 (`→`)、段落换行符 (`¶`) 和行尾符 (`↵`)。
**Typography** —— 在你写作时将输入的简写替换为真正的字符:弯引号和撇号、省略号、短/长破折号、箭头、尖括号引号、比较运算符和分数。每个组别均可单独切换。绝不在代码、数学公式或 frontmatter 中触发,并且撤销操作会精确还原你的原始输入。
引号字符本身是可配置的,因此 `"` 和 `'` 可以打出德语的 „…“、法语的 « … » 或任何其他格式。撇号的设置与右单引号分开,插件会通过回溯未闭合的引号来自行判断你的意图——因此 *don't* 和 *'word'* 都能被正确转换。
### Right-to-left
如果 Obsidian 或笔记被设置为从右向左(RTL)书写,文本选项就会发生镜像翻转:缩进和内边距会跟随文本方向,两端对齐的文本将其最后一行设为向右对齐,制表符和行尾标记也会指向相反的方向。词数统计已支持希伯来语、阿拉伯语和波斯语。
语法着色和写作检查仅支持英文。在从右向左书写的文本中,它们不会标记任何内容,从而避免标记错误。
### 杂项
**Vim** —— 一个可将 `j`、`k`、0 和 `$` 映射到带 `g` 前缀形式的选项,使得移动操作遵循自动换行后的行而非原段落。
**Word goals** —— 写作目标,加上你设置的所有文件和文件夹目标,均可在同一个列表中编辑。它们与你点击 `{filegoal}` 和 `{foldergoal}` token 时设置的目标完全一致。
文件管理器(汇总到文件夹)中可选的单文件字数统计,以及大纲面板中的单标题字数统计。
词数统计功能对 markdown 感知:会排除 frontmatter、围栏代码块、数学公式块、HTML、URL、链接目标和列表标记,同时统计标题、列表文本和链接标签。中文和日文按字符数统计;韩文按词数统计。
## 命令
- **Word-Smith: Toggle Word-Smith on/off** —— 整个插件的总开关(也可作为 “WS” 侧边栏徽章使用)
- **Word-Smith: Show or hide the retro bar** —— 滑出和滑入状态栏,而无需将其关闭
- **Word-Smith: Copy bar layout diagnostic** —— 将状态栏测得的几何布局复制到剪贴板,用于提交 bug 报告
其他所有功能均可在设置标签页或直接通过 retro bar 上的 token 访问。
## 安装说明
1. 下载 `main.js`、`styles.css` 和 `manifest.json`(或 clone 本仓库)。
2. 在你的 vault 的 `.obsidian/plugins/` 目录下创建一个名为 `word-smith` 的文件夹。
3. 将文件复制到该文件夹中。
4. 重新加载 Obsidian(或将其重启),然后在 **Settings → Community plugins** 下启用 **Word-Smith**。
更新时请复制全部三个文件,而不仅是 `main.js` —— 插件会检查样式表是否与脚本匹配,若不匹配会在启动时发出警告。
## 隐私
Word-Smith 完全在本地运行。
- **无网络访问。** 插件中没有任何 `fetch`、`XMLHttpRequest`、`WebSocket` 或 `requestUrl` 调用。源代码中唯一的 URL 是 SVG 命名空间字符串。
- **无遥测、数据分析或崩溃报告。**
- **无第三方依赖。** 没有任何打包模块。仅有的导入项是 `obsidian` 和 `@codemirror/*`,且均由 Obsidian 自身提供。
- **无 Obsidian 自身 API 之外的文件系统访问。** 没有 `require('fs')`,没有 `child_process`,没有 Electron 转义。
### 它会读取什么
在笔记打开期间读取内存中的笔记内容——用于字数统计、语法着色和段落检测。它们从编辑器读取后即被丢弃。绝不会被复制、缓存或写入任何地方。
写作报告还会在你打开对应标签页时读取文件夹中的笔记,以进行汇总。这些总计数据保存在内存中,并在文件发生更改时重新计算。
它还会读取笔记的 frontmatter,以执行 `wordsmith:` 和 `ws-*` 覆盖指令。
### 它会存储什么
仅有一个文件:`data.json`,位于你 vault 内的插件专属文件夹中。
它存储你的设置、已保存的状态栏预设,以及你设置的任何文件和文件夹字数目标。如果你开启了 **恢复光标位置**,它还会为每个笔记路径存储行号、列和滚动偏移量——最多保留最近 300 个笔记。存储的仅仅是文件 *路径* 和 *位置*,绝不包含文件内容。关闭该设置并删除 `data.json` 即可将其清除。
除此之外,没有任何信息被存储在任何地方。
### 自行验证
该插件是一个单可读文件。切勿仅听信我的一面之词:
```
grep -nE "fetch\(|XMLHttpRequest|WebSocket|requestUrl|sendBeacon" main.js
```
该命令什么也不返回。Word-Smith 采用 MIT 许可协议,完整源代码均在本仓库中。
## 语法高亮是如何工作的
没有 API,没有模型,也没有打包任何 NLP 库——它是一个完全在你 vault 内部运行的手写词性标注器。
每个可见行都通过三遍处理进行标注。
**1. 词汇表。** 一张包含约 800 个单词的表格,这些单词无法信任后缀规则:限定词、代词、介词、连词、助动词和情态动词、不规则动词,以及如果不特判就会被误标的常见名词和形容词。如 `the`、`is`、`went`、`difficult`。
**2. 后缀规则。** 任何不在词汇表中的词都会根据其结尾进行猜测,按可靠性排序:
| 结尾 | 标签 | 备注 |
|---|---|---|
| `-ly` | 副词 | 排除约 90 个例外——`family`、`reply`、`early`、`friendly` |
| `-ing` `-ed` | 动词 | |
| `-est` | 形容词 | |
| `-tion` `-ment` `-ness` `-ity` `-ism` `-ology` | 名词 | |
| `-ous` `-ful` `-less` `-ive` `-able` `-ical` `-ish` | 形容词 | |
| `-ize` `-ate` `-ify` | 动词 | |
| `-s` | 名词或动词 | 取决于其单数形式是否为已知动词 |
**3. 上下文。** 这一过程利用两侧的单词来修正前两步犯的错误:
- 在限定词或介词之后,动词会变成名词——*the **work***、*in **place***。一个以 `-ing` 结尾的词会变成动名词(*the **meeting***),除非后面跟着名词,此时它变成修饰语(*the **running** water*)。
- 介于限定词和名词之间的未知词会填补形容词的位置——*her **difficult** book*。
- 在 `to` 之后,候选词会变成不定式——*to **write***。
- `to` 本身是介词,除非后面跟着动词,以此来区分 *to **the** shop* 和 *to **write***。
- 句首单词后跟着限定词时,会被判定为祈使语气动词——***Check** the file*。
这五种结果——名词、动词、形容词、副词、连词——会作为 CodeMirror 装饰进行渲染,因此它们会在编辑器自身的 pipeline 中呈现,且在你打字时绝不会闪烁。
写作检查基于同一套被标注的 token 运行。被动语态、填充词等均基于列表和规则;句子节奏通过 Flesch–Kincaid 为每个句子打分;重复雷达则维护着一个不常用词的滑动窗口。
### 它刻意不着色的内容
冠词和物主限定词。高亮形容词不应该点亮每一个 `the`、`a` 和 `her`——它们的行为类似于冠词,而非描述词。
代词被作为名词统计,介词被作为连词统计。
### 准确率
根据我自己的测试,在普通文本上大约十词能中九词——这并没有使用标记语料库进行基准测试。它在对白密集的小说和句子片段中表现最弱,因为上下文规则能利用的信息较少,对于不常见的专有名词也是如此。
这就是为什么它是一款写作辅助工具,而不是语法检查器:颜色旨在提醒你再次审视句子,而不是下定论。一次只开启一个词类——比如显示你所有的动词,或者所有的形容词——才是它的正确用法。
### 性能
仅对当前屏幕上显示的行进行标注,代码块、frontmatter 和数学公式将被完全跳过。在一篇 11 万词的笔记上,每次重绘耗时约 2ms,因此完全不会造成打字卡顿。
## 反馈
发现 bug 或有想法?欢迎提交 issue!
## 定价
Word-Smith 100% 免费。
如果你想支持这个项目并帮助我持续推出更新,非常欢迎请我喝杯咖啡。你的支持对我来说意义非凡。万分感谢!
## 许可协议
MIT标签:Markdown, Obsidian插件, 写作工具, 打字机模式, 无干扰写作, 笔记辅助, 自定义脚本