feat(web): name the source publisher instead of printing its URL

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.
This commit is contained in:
tiennm99 committed 2026-08-14 14:02:20 +07:00
1 parent b38965dc4b
commit 92d13048f2
2 files changed
+21 -5

No files matched your search

+17 -3
View File
@@ -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_<id>.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)) {
+4 -2
View File
@@ -207,12 +207,14 @@
{/if}
</main>
<footer class="mt-12 border-t border-line pt-4 text-center text-sm break-words text-ink-subtle">
<footer class="mt-12 border-t border-line pt-4 text-center text-sm text-ink-subtle">
<p>
Nguồn:
<!-- An off-site article URL, so there is no route for resolve() to take. -->
<!-- eslint-disable-next-line svelte/no-navigation-without-resolve -->
<a href={dataset.source} target="_blank" rel="noopener noreferrer">{dataset.source}</a>
<a href={dataset.source} title={dataset.source} target="_blank" rel="noopener noreferrer"
>{dataset.sourceName}</a
>
· {dataset.rows.toLocaleString("vi-VN")} thí sinh · Dữ liệu chỉ mang tính tham khảo
</p>
</footer>