Skip to content

Commit ccb8c25

Browse files
ieduerclaude
andcommitted
fix: clean _x000D_ artifacts from idiom sections + bump version to r33
Apply unified _clean() to all 11 idiom section fields extracted from raw_json (previously only source_text was cleaned). Update cache busters and version to 2026.03.26-r33. Add README entry for idiom dict + s2t. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent dd8df77 commit ccb8c25

8 files changed

Lines changed: 66 additions & 40 deletions

File tree

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,18 @@
3030

3131
---
3232

33+
## 🧭 2026-03-26 教育部成语典接入与简繁转换
34+
35+
### 本轮已完成的关键更新
36+
37+
- 接入教育部《成語典》5,489 条成语,高中/初中查典页均可查询,结果按释义、典故说明、典源、注解、语义、例句、书证、近反义词分区展示
38+
- 新增简繁转换(opencc-python-reimplemented):用户输入简体字时自动转为正体查询教育部《重编国语辞典修订本》与《成語典》,正体输入不受影响
39+
- AI 对话上下文增强:查典 AI 对话现在同时携带教育部修订本与成语典的匹配条目作为证据
40+
- 成语典数据源为教育部公开 XLSX 资料,以 CC BY-ND 3.0 TW 授权只读展示,不拆改原文
41+
- 修复成语典内容中残留的 `_x000D_` XML 转义符号
42+
43+
---
44+
3345
## 🧭 2026-03-11 实虚词典真题页上线与公开约束
3446

3547
### 本轮已完成的关键更新

backend/main.py

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5891,48 +5891,57 @@ def _parse_idiom_sections(raw_json_str: str) -> dict:
58915891
raw = json.loads(raw_json_str) if raw_json_str else {}
58925892
except (json.JSONDecodeError, TypeError):
58935893
return {}
5894+
5895+
import re as _re_local
5896+
5897+
def _clean(val: str) -> str:
5898+
"""Remove XML escape artifacts from raw XLSX cell values."""
5899+
t = (val or "").strip()
5900+
if not t:
5901+
return ""
5902+
t = _re_local.sub(r"_x[0-9A-Fa-f]{4}_", "", t)
5903+
t = _re_local.sub(r"\*\d+\*", "", t)
5904+
t = _re_local.sub(r"#", "", t)
5905+
return t.strip()
5906+
58945907
sections = {}
58955908
if raw.get("釋義"):
5896-
sections["definition"] = raw["釋義"].strip()
5909+
sections["definition"] = _clean(raw["釋義"])
58975910
if raw.get("典故說明"):
5898-
sections["story"] = raw["典故說明"].strip()
5911+
sections["story"] = _clean(raw["典故說明"])
58995912
source_name = (raw.get("典源文獻名稱") or "").strip()
5900-
source_text = (raw.get("典源文獻內容") or "").strip()
5913+
source_text = _clean(raw.get("典源文獻內容") or "")
59015914
if source_text:
5902-
import re as _re_local
5903-
source_text = _re_local.sub(r"\*\d+\*", "", source_text)
5904-
source_text = _re_local.sub(r"#", "", source_text)
5905-
source_text = _re_local.sub(r"_x[0-9A-Fa-f]{4}_", "", source_text)
59065915
source_text = _re_local.sub(r"\n(?!\n)", "", source_text)
59075916
source_text = _re_local.sub(r"\n{2,}", "\n", source_text)
59085917
sections["source_text"] = source_text.strip()
59095918
if source_name:
59105919
sections["source_name"] = source_name
5911-
source_notes = (raw.get("典源注解") or "").strip()
5920+
source_notes = _clean(raw.get("典源注解") or "")
59125921
if source_notes:
59135922
sections["source_notes"] = source_notes
5914-
usage_cat = (raw.get("用法說明-使用類別") or "").strip()
5923+
usage_cat = _clean(raw.get("用法說明-使用類別") or "")
59155924
if usage_cat:
59165925
sections["usage_category"] = usage_cat
5917-
usage_desc = (raw.get("用法說明-語義說明") or "").strip()
5926+
usage_desc = _clean(raw.get("用法說明-語義說明") or "")
59185927
if usage_desc:
59195928
sections["usage_description"] = usage_desc
5920-
usage_examples = (raw.get("用法說明-例句") or "").strip()
5929+
usage_examples = _clean(raw.get("用法說明-例句") or "")
59215930
if usage_examples:
59225931
sections["usage_examples"] = usage_examples
5923-
citations = (raw.get("書證") or "").strip()
5932+
citations = _clean(raw.get("書證") or "")
59245933
if citations:
59255934
sections["citations"] = citations
5926-
synonyms = (raw.get("近義成語") or "").strip()
5935+
synonyms = _clean(raw.get("近義成語") or "")
59275936
if synonyms:
59285937
sections["synonyms"] = synonyms
5929-
antonyms = (raw.get("反義成語") or "").strip()
5938+
antonyms = _clean(raw.get("反義成語") or "")
59305939
if antonyms:
59315940
sections["antonyms"] = antonyms
5932-
discrimination = (raw.get("辨似") or raw.get("辨識") or "").strip()
5941+
discrimination = _clean(raw.get("辨似") or raw.get("辨識") or "")
59335942
if discrimination:
59345943
sections["discrimination"] = discrimination
5935-
ref_words = (raw.get("參考詞語") or "").strip()
5944+
ref_words = _clean(raw.get("參考詞語") or "")
59365945
if ref_words:
59375946
sections["ref_words"] = ref_words
59385947
return sections

frontend/assets/version.json

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
{
2-
"frontend_refactor_version": "2026.03.17-r32",
3-
"updated_at": "2026-03-17",
2+
"frontend_refactor_version": "2026.03.26-r33",
3+
"updated_at": "2026-03-26",
44
"history": [
5+
{
6+
"version": "2026.03.26-r33",
7+
"date": "2026-03-26",
8+
"summary": "integrated MOE idiom dictionary (5489 entries) for both 初中/高中 dict pages, added simplified↔traditional Chinese conversion (opencc) so simplified queries match MOE traditional-only entries, structured idiom display with sections (释义/典故/典源/注解/语义/例句/书证/近反义), fixed _x000D_ XML artifacts in idiom content, enhanced AI chat context with MOE revised + idiom evidence"
9+
},
510
{
611
"version": "2026.03.17-r32",
712
"date": "2026-03-17",

frontend/chuzhong-dict.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
<link
1717
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&family=Noto+Serif+SC:wght@400;600;700&display=swap"
1818
rel="stylesheet">
19-
<link rel="stylesheet" href="assets/style.css?v=20260315a">
20-
<link rel="stylesheet" href="assets/dict.css?v=20260315a">
19+
<link rel="stylesheet" href="assets/style.css?v=20260326a">
20+
<link rel="stylesheet" href="assets/dict.css?v=20260326a">
2121
</head>
2222

2323
<body class="dict-page" data-phase="初中">
@@ -187,7 +187,7 @@ <h2>AI 学习助手</h2>
187187
</div>
188188
</footer>
189189
</div>
190-
<script src="assets/dict.js?v=20260315a"></script>
190+
<script src="assets/dict.js?v=20260326a"></script>
191191
</body>
192192

193193
</html>

frontend/chuzhong.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
<script defer src="https://unpkg.com/katex@0.16.9/dist/contrib/auto-render.min.js"></script>
2424
<script src="https://d3js.org/d3.v7.min.js"></script>
2525

26-
<link rel="stylesheet" href="assets/style.css?v=20260315a">
26+
<link rel="stylesheet" href="assets/style.css?v=20260326a">
2727
</head>
2828

2929
<body data-phase="初中">
@@ -202,7 +202,7 @@ <h2>🔗 知识图谱</h2>
202202
</div>
203203
</footer>
204204
</div>
205-
<script src="assets/app.js?v=20260315a"></script>
205+
<script src="assets/app.js?v=20260326a"></script>
206206
</body>
207207

208208
</html>

frontend/dict.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
<link
1717
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&family=Noto+Serif+SC:wght@400;600;700&display=swap"
1818
rel="stylesheet">
19-
<link rel="stylesheet" href="assets/style.css?v=20260315a">
20-
<link rel="stylesheet" href="assets/dict.css?v=20260315a">
19+
<link rel="stylesheet" href="assets/style.css?v=20260326a">
20+
<link rel="stylesheet" href="assets/dict.css?v=20260326a">
2121
</head>
2222

2323
<body class="dict-page" data-phase="高中">
@@ -188,7 +188,7 @@ <h2>AI 学习助手</h2>
188188
</div>
189189
</footer>
190190
</div>
191-
<script src="assets/dict.js?v=20260315a"></script>
191+
<script src="assets/dict.js?v=20260326a"></script>
192192
</body>
193193

194194
</html>

frontend/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
<script defer src="https://unpkg.com/katex@0.16.9/dist/contrib/auto-render.min.js"></script>
2424
<script src="https://d3js.org/d3.v7.min.js"></script>
2525

26-
<link rel="stylesheet" href="assets/style.css?v=20260315a">
26+
<link rel="stylesheet" href="assets/style.css?v=20260326a">
2727
</head>
2828

2929
<body data-phase="高中">
@@ -276,7 +276,7 @@ <h2>🔗 知识图谱</h2>
276276
</div>
277277
</footer>
278278
</div>
279-
<script src="assets/app.js?v=20260315a"></script>
279+
<script src="assets/app.js?v=20260326a"></script>
280280
</body>
281281

282282
</html>

release_manifest.json

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"schema_version": 1,
3-
"generated_at": "2026-03-26T04:57:07.214481+00:00",
4-
"git_head": "ba5b7b255a43e8857f7352cadbbf64b4851c6dda",
5-
"frontend_version": "2026.03.17-r32",
3+
"generated_at": "2026-03-26T08:23:48.317852+00:00",
4+
"git_head": "dd8df77eaac44b9db2f8f134f25daa558bfbc6cd",
5+
"frontend_version": "2026.03.26-r33",
66
"source_of_truth": {
77
"local_workspace": "authoritative",
88
"github": "authoritative_for_code_only_after_push",
@@ -31,8 +31,8 @@
3131
{
3232
"kind": "source",
3333
"logical_path": "backend/main.py",
34-
"size": 363473,
35-
"sha256": "a8589aa81ce49bfcb8a918b534ad5322e87acb6533fd0992f6018483dc11ee0f"
34+
"size": 363615,
35+
"sha256": "66fad8c7f12d0bdc9c0fb22cbbf97682684f3ced1102efdd4a37b5f790795699"
3636
},
3737
{
3838
"kind": "source",
@@ -92,25 +92,25 @@
9292
"kind": "source",
9393
"logical_path": "frontend/index.html",
9494
"size": 13900,
95-
"sha256": "a1e96ab7ff33b08d903631f2c957186bc867310d78acf8bc7d710cd5c528675f"
95+
"sha256": "3cdb2c795717ecb0cd2bd54ec72d98c6bd6a9b22c767ceb3a5d48a530e72a647"
9696
},
9797
{
9898
"kind": "source",
9999
"logical_path": "frontend/dict.html",
100100
"size": 10344,
101-
"sha256": "a0cc01c46c758c12a12f24f1e5d8efd0ca247d26618b0d8897a8021ad0fcb7aa"
101+
"sha256": "01370a5f4a0793841bb41219604d6ba7e91b10325bbd30624f1c3319beec7b4f"
102102
},
103103
{
104104
"kind": "source",
105105
"logical_path": "frontend/chuzhong.html",
106106
"size": 10519,
107-
"sha256": "a0367a8574d905c344f75d52f0af2123af2d6873b987bde76c95c61068829c63"
107+
"sha256": "b987e80195aaff9d7c645c44de775c9eefe466d7f17b4b7080cb1a69dd7e642d"
108108
},
109109
{
110110
"kind": "source",
111111
"logical_path": "frontend/chuzhong-dict.html",
112112
"size": 10305,
113-
"sha256": "24365cac54ea6b4c719409bfffd69edf5b4f8b29df8c3923a88183d97035bb09"
113+
"sha256": "c9a2289279b493a10d0e8f724bf5f8ee18e3b0c5ca8f1f64e1dfd2f375ef7bce"
114114
},
115115
{
116116
"kind": "source",
@@ -139,8 +139,8 @@
139139
{
140140
"kind": "source",
141141
"logical_path": "frontend/assets/version.json",
142-
"size": 8200,
143-
"sha256": "1f1d7c0a7d68097dd53c3fe19e1aaa2ad43857033fc3ee90f5f8071e99d4a122"
142+
"size": 8700,
143+
"sha256": "121d37d3cd0debb1330f20048f4da6d237bf2156fde6f7a83038d37d870d4615"
144144
},
145145
{
146146
"kind": "source",
@@ -178,7 +178,7 @@
178178
"kind": "runtime",
179179
"logical_path": "data/index/textbook_mineru_fts.db",
180180
"size": 80961536,
181-
"sha256": "a13055b47cb07da2edf78295a26abcc626d9e246fa250a4df03bf998ff7552b2",
181+
"sha256": "9454c4f0cc79d4a6c0cb933d7461590c09fc773ed2169e9d27d7f72ac3e5e7b3",
182182
"source_path": "data/index/textbook_mineru_fts.db",
183183
"runtime_identity": {
184184
"type": "sqlite_textbook_runtime_identity_v1",

0 commit comments

Comments
 (0)