mirror of
https://github.com/hectorqin/reader.git
synced 2026-11-11 21:41:02 +08:00
服务端仍在做排版:`chapter-html:<n>` 自己断段、自己提升标题、自己吐 `<p>`。于是 reader 设置里的缩进和段间距只能作用于服务端已经渲染好的那一份, 流式那条路(`chapter:<n>`)拿不到段落,同一本书因为走哪条传输而看起来不一样。 客户端的 `retypePlainText` 于是把服务端断好的段落再拆一遍——同一个判断被两个 地方执行,两次的结果就会分歧。 `POST /api/v1/sync` 的响应本来就是合并后的状态(服务端在两个接口上返回同一份 `pull`),但客户端把它丢掉,然后又为同一份数据发一个 `GET`。读者每翻一页都发 一个 POST 加一个 GET,网络面板里成对出现。另外 `setState` 每次调用都广播,而 阅读页的状态监听会重绘整棵 chrome 树,一个同步循环通知三次。 现在服务端只把整章字符交出来(`text/plain`,`chapter-html:` 不截断),断段、 去段前空格、提升标题全部由 `web/src/formats/segments.ts` 一处决定;push 的返回 值直接喂给 `applyPulled`,空闲轮询才真的发 GET;`setState` 值未变就不广播。 「这一章是不是纯文本」改由 manifest 声明(item 的 `format: 'html'` → `Section.plainText` → `isPlainText()`),不再靠 `.txt-body` 嗅探:服务端现在发 裸字符,嗅探对一章节全是纯文本的章节会答「不是」,读者会看到一本没有段落、 没有缩进、样式表也没挂上的小说。`.txt-body` 标记降级为旧服务端/旧缓存的兜底。 放弃的方案:保留服务端渲染、只在客户端覆盖样式。缩进和段间距是阅读偏好,服务端 渲染就等于把每次调整变成一次往返,而这个往返正是问题本身。也考虑过让 `chapter-html:` 直接返回服务端渲染的裸 `<p>`(不带 wrapper),但那仍然有两个 地方在判断「一段是什么」。 Ref: #34
21 lines
952 B
TypeScript
21 lines
952 B
TypeScript
import assert from 'node:assert/strict';
|
|
import { test, describe } from 'node:test';
|
|
import { escapeHtml } from '../src/indexer/formats/text-html.ts';
|
|
|
|
/**
|
|
* The escaping helper is all that is left of the server's TXT rendition.
|
|
*
|
|
* The paragraph split that used to be tested here moved to the client
|
|
* (`web/src/formats/segments.ts`, tested in `web/test/segments.test.ts`), because
|
|
* deciding where a paragraph is is a *reading* decision and not a property of the
|
|
* file. What is left on the server is the one mechanical thing: making a chapter's
|
|
* characters safe to put in a page, for the paths that still need it.
|
|
*/
|
|
describe('escapeHtml', () => {
|
|
test('escapes the characters that would otherwise rewrite the page', () => {
|
|
assert.equal(escapeHtml('<script>alert(1)</script>'), '<script>alert(1)</script>');
|
|
assert.equal(escapeHtml('a & b'), 'a & b');
|
|
assert.equal(escapeHtml(`"'`), '"'');
|
|
});
|
|
});
|