Browse Source

feat: 译文评估标注 evaluate 复用旁注方式显示

扫描经文中的 <span class="evaluate"> 标注,保留背景色高亮,
在其后注入 Tufte marginnote(label/checkbox/marginnote 三件套),
把 title 中的问题简述与建议分行显示。桌面端浮于右栏,手机端
点击展开,复用现有旁注 CSS,无需新增样式。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
visuddhinanda 1 tháng trước cách đây
mục cha
commit
4fa887a70c
1 tập tin đã thay đổi với 48 bổ sung0 xóa
  1. 48 0
      api-v13/resources/js/modules/reader.js

+ 48 - 0
api-v13/resources/js/modules/reader.js

@@ -2,6 +2,7 @@
 
 export function initReader() {
     injectCommentaryMarkers();
+    injectEvaluateMarkers();
     initTocToggle();
 }
 
@@ -72,6 +73,53 @@ function injectCommentaryMarkers() {
         });
 }
 
+// 译文质量评估标注:把 <span class="evaluate evaluate-级别" title="…"> 就地
+// 升级为 Tufte 旁注。保留原 span(含背景色高亮)不动,在其后注入
+//   span.evaluate → label.margin-toggle → input.margin-toggle → span.marginnote
+// 复用既有旁注样式:桌面端 marginnote 自动浮到右栏,手机端点击 label 展开。
+// 用 marginnote(而非 sidenote)以避免 ::before 计数器的 [N] 编号。
+function injectEvaluateMarkers() {
+    let counter = 0;
+
+    document
+        .querySelectorAll('article.reader-body span.evaluate[title]')
+        .forEach((evalEl) => {
+            const info = evalEl.getAttribute('title').trim();
+            if (info === '') {
+                return;
+            }
+
+            counter++;
+            const id = `evaluate-${counter}`;
+
+            // label:手机端点击触发(桌面隐藏,marginnote 自动浮动)
+            const label = document.createElement('label');
+            label.htmlFor = id;
+            label.className = 'margin-toggle';
+            label.innerHTML = '<i class="ti ti-alert-triangle"></i>';
+
+            // checkbox:控制手机端展开
+            const checkbox = document.createElement('input');
+            checkbox.type = 'checkbox';
+            checkbox.className = 'margin-toggle';
+            checkbox.id = id;
+
+            // 旁注内容:取自 title,| 分隔的「问题简述/建议」分行显示
+            const note = document.createElement('span');
+            note.className = 'marginnote evaluate-note';
+            info.split('|').forEach((part, index) => {
+                if (index > 0) {
+                    note.appendChild(document.createElement('br'));
+                }
+                note.appendChild(document.createTextNode(part.trim()));
+            });
+
+            // 顺序:span.evaluate → label → input → span.marginnote
+            // (input 与 marginnote 相邻,CSS :checked + .marginnote 依赖此顺序)
+            evalEl.after(label, checkbox, note);
+        });
+}
+
 async function fetchCommentary(noteEl) {
     const uuid = noteEl.dataset.uuid;