dsh-fonttune 0.2.4 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.en.md +12 -16
- package/CHANGELOG.md +12 -16
- package/lib/index.js +43 -1
- package/package.json +1 -1
package/CHANGELOG.en.md
CHANGED
|
@@ -2,27 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to **dsh-fonttune** are documented here. Chinese version: [CHANGELOG.md](CHANGELOG.md).
|
|
4
4
|
|
|
5
|
+
## [0.2.5] - 2026-09-23
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- **Installed as a link to the source directory, the card and the fonts disappeared together on 0.1.5-rc.x**: the plugin used the copy of the schema library in its own directory instead of the one DSH provides, and the newer copy marked the configuration in a way the rc line's settings controller cannot handle — the settings namespace was therefore never registered: no card in the settings sheet, an empty injected stylesheet, no typography change at all. It now always uses the copy DSH ships, so a linked install and a normal install behave identically.
|
|
9
|
+
|
|
5
10
|
## [0.2.4] - 2026-09-23
|
|
6
11
|
|
|
7
12
|
### Added
|
|
8
|
-
- **One package
|
|
9
|
-
- **
|
|
10
|
-
- **Claiming the settings namespace now waits, then matches by signature**: the alpha's `configForms.describe()` is asynchronous, and the old code guessed a candidate by name before it answered, so the guess could land on somebody else's namespace and every write was refused by the host (on a real machine: the card opens, and the first edit reports "The setting was not saved"). With no candidate the scope is now `null` and a pending stand-in (the whole `getSnapshot`/`subscribe`/`set`/`unset` surface) is adopted once the describe view arrives, recognized by a **schema that carries both `uiFollowsDialog` and `stackDialog`** (real log: `served namespaces []` → `matched by served schema: fonttune`).
|
|
11
|
-
- **The host side unwraps volatile references**: on the alpha every field of `ctx.fiber.config` is a cosmokit volatile reference (`{ get(), [Symbol.for("cosmokit.volatile.write")](v) }`, frozen), and reading it as a plain object yields nothing — on a real machine the card's **first render was a column of empty controls and the injected stylesheet was 0 bytes**. `plainConfigValue()` now unwraps it deeply, so `styleRow()` sees an ordinary object (measured: a 973 B rule set with `Georgia` / `520`).
|
|
12
|
-
- **`inject` narrowed to the services both lines have** (`slots` / `locale`): declaring one that a line does not have (say the rc-only `settingsScope`) **parks the whole package** (`pending (waiting for service: …)`) and the web never boots. The settings scope is looked up at runtime with `ctx.get()`, and a missing host layer degrades to browser-local storage.
|
|
13
|
-
- **Both shapes of a write result are understood**: the rc line's `mutate` resolves `undefined` even when it failed, while the alpha's `set`/`unset` resolve a boolean (`false` = the host refused). `followWrite` now reports a synchronous `false`, a thenable resolving `false`, and a rejection in that same note beside the preset row.
|
|
14
|
-
- **`test/host-line-probe.mjs`, a live probe that is independent of the host line.** It asserts only what must hold on every line — the page boots without errors, the plugin owns exactly **one** stylesheet element and it is connected, the settings really reach the document (with `DFP_EXPECT_FAMILY` / `DFP_EXPECT_WEIGHT` set it also asserts the computed values), the configuration card is reachable from the settings sheet and renders (`.dfp-card`, whichever seat that line declares) and a control on it really writes through to the host. It joined the read-only group of `npm run verify:browser`. `DFP_PROBE=1` makes the plugin log its diagnostics (which namespaces are served, which one was claimed, what state the seat is in); `DFP_DUMP=1` makes the probe print the Plugins page grouped as the host renders it.
|
|
13
|
+
- **One package for both host lines**: it installs and works as-is on **DSH 0.1.5-rc.1 – rc.3** and on **0.1.7-alpha.1 – alpha.2**, with no version to pick. At runtime the plugin uses whichever settings interface the host offers (the rc line's and the alpha's are different); when neither is there it only injects the font and shows no card.
|
|
14
|
+
- **A configuration entry point on the alpha**: on 0.1.7-alpha.x the card lives in the sidebar's Plugins page, under the plugin entry "Font tune"; on rc.x it stays in Settings → Plugins → Plugin configuration.
|
|
15
15
|
|
|
16
|
-
###
|
|
17
|
-
- **
|
|
18
|
-
- **
|
|
19
|
-
- The compatibility table gained 0.2.4, and both READMEs describe how the runtime handles the two dialects.
|
|
16
|
+
### Fixed
|
|
17
|
+
- **On the alpha the card's first render was a column of empty controls**: it was reading the host's internal references instead of the values, so the injected stylesheet came out empty; the first frame now carries the right family and readouts.
|
|
18
|
+
- **On the alpha an edit reported "The setting was not saved"**: the plugin could write to a place that was not its own; it now writes only after confirming the configuration is its own.
|
|
20
19
|
|
|
21
|
-
###
|
|
22
|
-
-
|
|
23
|
-
- `test/render-card.mjs` (23 checks): rendering resolves its seat as `settings.plugin.item` and falls back to `plugins.item`, so both lines' shapes are exercised.
|
|
24
|
-
- Live (managed instance + headless Edge): `host-line-probe` passes on `0.1.5-rc.2`, `0.1.5-rc.3` and `0.1.7-alpha.2` (insert-style loading), and once more on alpha.2 loaded as a bundle. On the alpha the `codeLigatures: 2` driven from the card lands in `profiles/dfp/cordis.patch.yml`; on the rc line it lands in `settings.yaml`.
|
|
25
|
-
- **CI caught a case the local dialect cannot show**: three schema cases in `test/run.mjs` read fields straight off `schema({…}).sans`. The release CI installs the newest schemastery (3.18.4, which has `.volatile()`), and a resolved field is then a **reference** rather than a value — all three were green locally (3.18.2) and red in CI. The host half now exports `plainConfigValue`, those cases read the config **the way the plugin reads it**, and each dialect's shape is asserted: with the modifier a field is a reference that has to be unwrapped, without it the field is the value. The devDependency moved to `^3.18.4` so local and CI exercise the same dialect (the rc line's unmarked shape is covered live on rc.2 / rc.3 by the probe).
|
|
20
|
+
### Changed
|
|
21
|
+
- The compatibility statement and the compatibility table in both READMEs are updated to 0.2.4, listing the five host lines that were actually tested (0.1.5-rc.1 / rc.2 / rc.3 and 0.1.7-alpha.1 / alpha.2) and where each line's settings live.
|
|
26
22
|
|
|
27
23
|
## [0.2.3] - 2026-09-22
|
|
28
24
|
|
package/CHANGELOG.md
CHANGED
|
@@ -2,27 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
**dsh-fonttune** 的重要变更都记录在这里。英文版见 [CHANGELOG.en.md](CHANGELOG.en.md)。
|
|
4
4
|
|
|
5
|
+
## [0.2.5] - 2026-09-23
|
|
6
|
+
|
|
7
|
+
### 修复
|
|
8
|
+
- **以「链接到源码目录」的方式安装时,0.1.5-rc.x 上的配置卡片与字体一起消失**:插件会用自己目录里的 schema 库副本,而不是 DSH 自带的那一份;副本的较新版本给配置加了 rc 线宿主处理不了的标记,设置命名空间因此根本没有注册出去——设置页看不到卡片、注入的样式是空的、字体毫无变化。现在插件始终使用 DSH 自带的那一份,链接安装与正常安装在行为上完全一致。
|
|
9
|
+
|
|
5
10
|
## [0.2.4] - 2026-09-23
|
|
6
11
|
|
|
7
12
|
### 新增
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
- **认领命名空间改成「先等、再按签名认」**:alpha 的 `configForms.describe()` 是异步的,以前抢在它应答前按名字猜候选,猜错就会落在别的命名空间上、每次写入都被宿主拒绝(真机表现:卡片能开、一改就报「设置没有保存成功」)。现在候选为空就返回 `null`,并挂一个「待定作用域」占位(`getSnapshot`/`subscribe`/`set`/`unset` 全套),等 describe 的视图到达后按 **schema 里同时含 `uiFollowsDialog` 与 `stackDialog`** 认出自己那一个再接管(真机日志:`served namespaces []` → `matched by served schema: fonttune`)。
|
|
11
|
-
- **宿主侧拆掉 volatile 引用**:alpha 的 `ctx.fiber.config` 里每个字段都是 cosmokit 的 volatile 引用(`{ get(), [Symbol.for("cosmokit.volatile.write")](v) }`,且被冻结),当普通对象读只会拿到空值——真机表现是**卡片第一次渲染是一整排空控件、注入的样式表 0 字节**。现在统一走 `plainConfigValue()` 深拆,`styleRow()` 拿到的是普通对象(实测样式行 973 B、`Georgia` / `520`)。
|
|
12
|
-
- **`inject` 收窄到两条线都有的服务**(`slots` / `locale`):声明一个某条线上不存在的服务(例如 rc 才有的 `settingsScope`)会把**整包 park 住**(`pending (waiting for service: …)`),Web 直接起不来。设置作用域改为运行时用 `ctx.get()` 免声明查找,找不到就按「没有宿主层」降级。
|
|
13
|
-
- **写设置的结果两种形状都认**:rc 的 `mutate` 即使失败也 resolve `undefined`,alpha 的 `set`/`unset` resolve 布尔(`false` = 宿主拒绝)。`followWrite` 现在把同步 `false`、resolve 成 `false` 的 thenable、以及 rejection 三种都报到预设行右侧那句提示里。
|
|
14
|
-
- **`test/host-line-probe.mjs`:与宿主线无关的真机探针**。只断言两条线都必须成立的事——页面无报错、插件只维护**一份**样式表且已接入文档、设置真的作用到文档(设了 `DFP_EXPECT_FAMILY` / `DFP_EXPECT_WEIGHT` 就顺带断言计算样式)、设置页里能找到并渲染出 `.dfp-card`(哪条线的座位都行)、以及从卡片上改一个值真的写进宿主。已并入 `npm run verify:browser` 的只读组。设 `DFP_PROBE=1` 时插件会往控制台打诊断行(服务了哪些命名空间、认领了哪个、座位当前状态),`DFP_DUMP=1` 时探针额外按分组打印插件页的条目。
|
|
13
|
+
- **同一个安装包同时支持两条宿主线**:DSH **0.1.5-rc.1 – rc.3** 与 **0.1.7-alpha.1 – alpha.2** 上都能直接安装使用,不需要挑版本。插件在运行时按宿主实际提供的那一套设置接口工作(rc 线一套、alpha 线一套),两条都不在时只注入字体、不显示卡片。
|
|
14
|
+
- **alpha 上的配置入口**:在 0.1.7-alpha.x 上,卡片出现在侧栏「插件」页的插件条目「字体增强」里;rc.x 上仍在 设置 → 插件 → 插件配置。
|
|
15
15
|
|
|
16
|
-
###
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
- 兼容表补 0.2.4(中英两份 README 都改了运行时双方言的处理说明)。
|
|
16
|
+
### 修复
|
|
17
|
+
- **alpha 上卡片第一次打开是一排空控件**:此前读到的是宿主的内部引用而不是配置值,注入的样式因此为空;现在首帧就是正确的字体与读数。
|
|
18
|
+
- **alpha 上改设置提示「设置没有保存成功」**:插件有几率把改动写到不属于自己的位置;现在只在确认是自己的配置之后才写入。
|
|
20
19
|
|
|
21
|
-
###
|
|
22
|
-
-
|
|
23
|
-
- `test/render-card.mjs`(23 项):渲染取值改为「`settings.plugin.item` 不在就取 `plugins.item`」,两条线的座位各跑一遍。
|
|
24
|
-
- 真机(受管实例 + 无头 Edge):`0.1.5-rc.2`、`0.1.5-rc.3`、`0.1.7-alpha.2` 各跑一次 `host-line-probe` 通过(插入式装载);alpha.2 另跑一次 bundle 式装载通过。alpha 上确认从卡片改的 `codeLigatures: 2` 真的写进 `profiles/dfp/cordis.patch.yml`,rc 上确认落在 `settings.yaml`。
|
|
25
|
-
- **CI 抓到一条本地测不出来的用例**:`test/run.mjs` 里三条 schema 用例直接读 `schema({…}).sans` 这类字段。发布 CI 装的是最新的 schemastery(3.18.4,带 `.volatile()`),于是解析出来的字段是**引用**而不是值,三条在本地(3.18.2)全绿、在 CI 全红。现在宿主半把 `plainConfigValue` 导出,这三条按**插件读配置的同一方式**取值,并断言两种方言各自的形态:有修饰符时字段是引用、拆开后才是值;没有修饰符时字段本身就是值。devDependency 同时抬到 `^3.18.4`,让本地与 CI 跑同一个方言(rc 线那套无修饰符的形态由真机探针在 rc.2 / rc.3 上覆盖)。
|
|
20
|
+
### 变更
|
|
21
|
+
- 兼容声明与中英 README 的兼容表更新到 0.2.4,逐条列出五条实测过的宿主线(0.1.5-rc.1 / rc.2 / rc.3、0.1.7-alpha.1 / alpha.2),并写清两条线各自的设置入口。
|
|
26
22
|
|
|
27
23
|
## [0.2.3] - 2026-09-22
|
|
28
24
|
|
package/lib/index.js
CHANGED
|
@@ -20,12 +20,54 @@
|
|
|
20
20
|
*
|
|
21
21
|
* @module dsh-fonttune
|
|
22
22
|
*/
|
|
23
|
-
import
|
|
23
|
+
import { createRequire } from "node:module";
|
|
24
|
+
import { dirname, sep } from "node:path";
|
|
25
|
+
import { fileURLToPath } from "node:url";
|
|
24
26
|
// Default import, not named: `shared.cjs` is a CommonJS module, and Node's
|
|
25
27
|
// CJS-to-ESM interop only guarantees `module.exports` as the default binding
|
|
26
28
|
// (statically-detected named exports would break this half at boot).
|
|
27
29
|
import shared from "./shared.cjs";
|
|
28
30
|
|
|
31
|
+
/**
|
|
32
|
+
* The schema library, taken from the HOST whenever the host can be reached.
|
|
33
|
+
*
|
|
34
|
+
* `@deepseek-ai/schemastery` is an optional peer dependency — DSH supplies the
|
|
35
|
+
* schema library, this package never ships its own copy into a profile. Node's
|
|
36
|
+
* bare-specifier resolution does not know that: when this package is linked or
|
|
37
|
+
* junctioned into a profile (the development setup) the specifier resolves
|
|
38
|
+
* inside this package's own `node_modules`, i.e. to the devDependency. That is
|
|
39
|
+
* a SECOND instance of the library, and — worse — a newer one than the running
|
|
40
|
+
* host may carry: its `.volatile()` marking lands on a schema the rc line's
|
|
41
|
+
* settings controller cannot digest, so the namespace is never served (no card
|
|
42
|
+
* in the settings sheet, an empty first-frame stylesheet). Measured on
|
|
43
|
+
* 0.1.5-rc.3: linked → nothing, installed → works.
|
|
44
|
+
*
|
|
45
|
+
* Resolving from the host first keeps one instance and one dialect, which is
|
|
46
|
+
* exactly what an installed package gets. `process.argv[1]` is the host's own
|
|
47
|
+
* entry (its `node_modules` holds the authoritative copy); anything resolving
|
|
48
|
+
* back inside THIS package is skipped, so the offline suites — which have no
|
|
49
|
+
* host — still fall through to the devDependency.
|
|
50
|
+
* @returns {object} the schemastery export.
|
|
51
|
+
*/
|
|
52
|
+
function loadSchemastery() {
|
|
53
|
+
const own = dirname(dirname(fileURLToPath(import.meta.url))) + sep;
|
|
54
|
+
const bases = [process.argv[1], fileURLToPath(import.meta.url)];
|
|
55
|
+
for (const base of bases) {
|
|
56
|
+
if (typeof base !== "string" || base === "") continue;
|
|
57
|
+
try {
|
|
58
|
+
const from = createRequire(base);
|
|
59
|
+
if (!from.resolve("@deepseek-ai/schemastery").startsWith(own)) {
|
|
60
|
+
return from("@deepseek-ai/schemastery");
|
|
61
|
+
}
|
|
62
|
+
} catch {
|
|
63
|
+
// Not resolvable from that anchor: try the next one.
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return createRequire(import.meta.url)("@deepseek-ai/schemastery");
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const z = loadSchemastery();
|
|
70
|
+
|
|
29
71
|
const {
|
|
30
72
|
buildFontCss,
|
|
31
73
|
CODE_LINE_HEIGHT_FIELD,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-fonttune",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "Font plugin for the DeepSeek Harness Web GUI: the conversation gets its own font, size, line height and weight, the interface font and weight follow it, code keeps its own axis with ligature control, and whole setups save as presets.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|