From 92d13048f2b3398319e16ec36da49019bc668591 Mon Sep 17 00:00:00 2001 From: tiennm99 Date: Fri, 14 Aug 2026 13:59:02 +0700 Subject: [PATCH] feat(web): name the source publisher instead of printing its URL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The footer printed the full article URL, which runs to 120 characters and wrapped across three lines on a phone — the reason that footer carried an overflow-wrap rule at all. It now shows who published the article: "Trường Phổ thông DTNT tỉnh Bắc Ninh" for 2016 and "Báo Tin tức và Dân tộc - TTXVN" for 2017. The link still points at the article and its title attribute still carries the URL, so nothing is hidden from anyone who wants to know where it goes. The wrap rule is gone with the reason for it. sourceName joins the fields every dataset must define, checked at module load alongside the registry cross-check — with the types gone, a missing one would otherwise render as an empty link. --- web/src/lib/datasets.js | 20 +++++++++++++++++--- web/src/routes/[dataset]/+page.svelte | 6 ++++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/web/src/lib/datasets.js b/web/src/lib/datasets.js index 3283cc4..89d4440 100644 --- a/web/src/lib/datasets.js +++ b/web/src/lib/datasets.js @@ -19,10 +19,15 @@ const SUBTITLE = "Dữ liệu thí sinh toàn quốc · Hỗ trợ truy vấn SQ /** * Presentation, keyed by the ids declared in datasets.json. * - * `source` is the full article URL the dataset's spreadsheets come from, shown - * in the footer as a link. The canonical copy is the crawler's `Article` field + * `source` is the full article URL the dataset's spreadsheets come from. The + * canonical copy is the crawler's `Article` field * (crawler/internal/sources/source_.go); it is duplicated here because a Go - * module and a Vite app cannot share a constant. Keep the two in step. + * module and the web app cannot share a constant. Keep the two in step. + * + * `sourceName` is who published that article, and is what the footer shows — + * the URLs run to 120 characters and used to wrap across three lines on a + * phone. The link still points at the article, and its title attribute still + * carries the URL for anyone who wants to see where it goes. */ const CONTENT = { 2016: { @@ -33,6 +38,7 @@ const CONTENT = { // ministry — hence the unexpected domain. source: "https://dtnt.bacninh.edu.vn/tin-tuc/tin-tuc-su-kien/cong-bo-diem-thi-thptqg-2016-toan-bo-120-cum-thi-da-co-diem.html", + sourceName: "Trường Phổ thông DTNT tỉnh Bắc Ninh", examples: ["TKG002747", "Nguyễn Bửu Lộc"], presets: PRESETS_2016, }, @@ -42,6 +48,7 @@ const CONTENT = { subtitle: SUBTITLE, source: "https://baotintuc.vn/tuyen-sinh/tra-cuu-diem-thi-thpt-2017-cua-63-tinh-thanh-pho-tren-baotintucvn-20170706073512672.htm", + sourceName: "Báo Tin tức và Dân tộc - TTXVN", examples: ["49008235", "Nguyễn Minh Tiến"], presets: PRESETS_2017, }, @@ -54,6 +61,13 @@ for (const { id } of registry.datasets) { if (!CONTENT[id]) { throw new Error(`datasets.json declares "${id}" but web/src/datasets.js has no content for it`); } + // The footer renders sourceName as the link text, so a missing one is an + // empty link rather than a visible mistake. + for (const field of ["title", "label", "source", "sourceName", "examples", "presets"]) { + if (!CONTENT[id][field]) { + throw new Error(`web/src/lib/datasets.js: dataset "${id}" is missing ${field}`); + } + } } for (const id of Object.keys(CONTENT)) { if (!registry.datasets.some((d) => d.id === id)) { diff --git a/web/src/routes/[dataset]/+page.svelte b/web/src/routes/[dataset]/+page.svelte index e77d48e..64d5b71 100644 --- a/web/src/routes/[dataset]/+page.svelte +++ b/web/src/routes/[dataset]/+page.svelte @@ -207,12 +207,14 @@ {/if} -