←返回網站更新紀錄
Site Changelog
提交原始紀錄
fix(search): match mixed Latin and CJK queries (#397)
Split mixed-script search terms and allow CJK phrase matches across indexed spaces.
- SHA
d6681989d460fe5513bbd9695b4329bce0c4916c
- 提交時間
- 作者
- neo · 125815713+nnneeeooo-nnneeeooo@users.noreply.github.com
- 提交者
- GitHub · noreply@github.com
變更檔案(2)
-
static/search.js
modified · +16 / −1
-
tests/test_search.py
modified · +31 / −0
完整差異
diff --git a/static/search.js b/static/search.js\nindex e266e355e..afc712963 100644\n--- a/static/search.js\n+++ b/static/search.js\n@@ -12,10 +12,24 @@\n .trim();\n }\n \n+ function queryTerms(value) {\n+ var normalized = normalize(value);\n+ return normalized.match(\n+ /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}]+|[^\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\s]+/gu\n+ ) || [];\n+ }\n+\n function termMatches(haystack, term) {\n if (/^[a-z0-9]{1,3}$/.test(term)) {\n return haystack.split(/\s+/).indexOf(term) !== -1;\n }\n+ if (/[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}]/u.test(term)) {\n+ var compactCjk = haystack.replace(\n+ /([\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}])\s+(?=[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}])/gu,\n+ "$1"\n+ );\n+ return compactCjk.indexOf(term) !== -1;\n+ }\n return haystack.indexOf(term) !== -1;\n }\n \n@@ -149,7 +163,7 @@\n var modelQuery = parseModelQuery(records, textQuery.normalize("NFKC"));\n if (modelQuery) textQuery = modelQuery.remainder;\n var normalizedQuery = normalize(textQuery);\n- var terms = normalizedQuery.split(/\s+/).filter(Boolean);\n+ var terms = queryTerms(textQuery);\n var criteria = {\n normalizedQuery: normalizedQuery,\n terms: terms,\n@@ -184,6 +198,7 @@\n if (typeof module !== "undefined" && module.exports) {\n module.exports = {\n normalize: normalize,\n+ queryTerms: queryTerms,\n termMatches: termMatches,\n parseAirlineCodeQuery: parseAirlineCodeQuery,\n searchRecords: searchRecords\ndiff --git a/tests/test_search.py b/tests/test_search.py\nindex 683b38edf..2d95ddc5a 100644\n--- a/tests/test_search.py\n+++ b/tests/test_search.py\n@@ -3,6 +3,7 @@ from __future__ import annotations\n \n import json\n import re\n+import subprocess\n import sys\n import tempfile\n import unicodedata\n@@ -164,6 +165,36 @@ def main() -> None:\n assert payload["airlineCodes"]["icao"]["ASV"] == "ASV"\n assert "9S" not in payload["airlineCodes"]["iata"]\n items_by_id = {row["id"]: row for row in payload["items"]}\n+ client_search = subprocess.run(\n+ [\n+ "node",\n+ "-e",\n+ r"""\n+const assert = require("assert").strict;\n+const search = require("./static/search.js");\n+const index = require("./site/search-index.json");\n+const result = search.searchRecords(\n+ index.items,\n+ "SAS SK916折返紐瓦克",\n+ index.airlineCodes,\n+ "zh"\n+);\n+assert.ok(\n+ result.matches.some(({record}) => record.id === "a-sas-sk916-jfk-turnback-20261025"),\n+ JSON.stringify({\n+ queryTerms: search.queryTerms("SAS SK916折返紐瓦克"),\n+ matchIds: result.matches.map(({record}) => record.id)\n+ })\n+);\n+""",\n+ ],\n+ cwd=ROOT,\n+ capture_output=True,\n+ text=True,\n+ check=False,\n+ )\n+ assert client_search.returncode == 0, (\n+ client_search.stdout + client_search.stderr)\n live_condor = items_by_id[\n "a-20260915-0811-simple-flying-reports-condor-a320-missed"]\n beyond_borders = items_by_id[