From 9fa1c31cc4442a75975a4149fb8f013fdbf4f12c Mon Sep 17 00:00:00 2001 From: chumanic Date: Wed, 11 Nov 2026 18:48:27 +0800 Subject: [PATCH] Reject oversized pastes before the browser can truncate the document --- README.md | 2 +- browser/main.ts | 26 ++++++++++++++++++++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6a6bd24..c7936e7 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ ## 快速开始 -使用 Node.js 24 和 npm,在示例目录上做一次只读检查。 +CLI 支持 Node.js 20 及以上版本。下面使用 Node.js 24 和 npm,在示例目录做一次只读检查。桌面打包所需的运行时见[构建说明](docs/build.md)。 ```sh git clone https://github.com/Chumaniac/skillsync.git diff --git a/browser/main.ts b/browser/main.ts index 68b4370..0113c82 100644 --- a/browser/main.ts +++ b/browser/main.ts @@ -4,6 +4,28 @@ const status = document.querySelector("#status")!; const message = document.querySelector("#message")!; const fields = document.querySelector("#fields")!; const example = "---\nname: inventory-check\ndescription: 对照清单核对库存。\n---\n\n先读取清单,再逐项核对应有与实收数量。"; +const byteLimit = 24 * 1024; +const encoder = new TextEncoder(); +function tooLarge(value: string) { + return value.length > byteLimit || encoder.encode(value).length > byteLimit; +} +function oversized() { + fields.replaceChildren(); + status.textContent = "文档过大"; + message.textContent = "最多可检查 24 KiB。请缩短文档后重试。"; +} +function checkInsertion(event: Event, text: string | null) { + if (!text) return; + if (text.length > byteLimit || tooLarge(input.value.slice(0, input.selectionStart) + text + input.value.slice(input.selectionEnd))) { + event.preventDefault(); + oversized(); + message.textContent = "本次输入超过 24 KiB,原文已保留。"; + } +} +input.addEventListener("paste", event => checkInsertion(event, event.clipboardData?.getData("text/plain") ?? null)); +input.addEventListener("beforeinput", event => { + if (event.cancelable && event.inputType.startsWith("insert")) checkInsertion(event, event.data); +}); function clear() { status.textContent = "等待检查"; message.textContent = "文档已更新,请重新检查。"; @@ -11,8 +33,8 @@ function clear() { } function check() { fields.replaceChildren(); - if (new TextEncoder().encode(input.value).length > 24576) { - status.textContent = "文档过大"; message.textContent = "请缩短至 24 KiB 后重试。"; return; + if (tooLarge(input.value)) { + oversized(); return; } const parsed = parseSkillDocument(input.value); if (!parsed.ok) {