diff --git a/frontend/src/components/PlaceCard.jsx b/frontend/src/components/PlaceCard.jsx index 84ecb6b..d12ba5d 100644 --- a/frontend/src/components/PlaceCard.jsx +++ b/frontend/src/components/PlaceCard.jsx @@ -9,6 +9,7 @@ import { useStore } from "../store" import { fetchElevation, fetchPlaceDetails, fetchPlaceByWikidata, fetchDriveTime, fetchNearbyContacts, fetchLandclass, fetchReverse } from "../api" import { hasFeature } from "../config" import { buildAddress } from "../utils/place" +import { wikipediaLink, wikivoyageLink, wikidataHref } from "../utils/wiki" // Wiki service icons (simplified monochrome versions) @@ -110,13 +111,6 @@ function wheelchairLabel(val) { return map[val.toLowerCase()] || null } -function wikiUrl(wp) { - if (!wp) return null - const [lang, ...rest] = wp.split(":") - const title = rest.join(":").replace(/ /g, "_") - return "https://" + lang + ".wikipedia.org/wiki/" + encodeURIComponent(title) -} - function wikiLabel(wp) { if (!wp) return null const [, ...rest] = wp.split(":") @@ -218,13 +212,16 @@ function EnrichmentSkeleton() { function EnrichmentSections({ details }) { if (!details) return null - const { category, extratags, wiki_url, wikivoyage_url } = details + const { category, extratags } = details const et = extratags || {} + const wp = wikipediaLink(details) + const wv = wikivoyageLink(details) + const wd = wikidataHref(et) const hasAbout = category const hasHours = et.opening_hours const hasContact = et.phone || et.website || et.email const hasDetails = et.cuisine || et.operator || et.fee || et.wheelchair || et.takeaway - const hasLinks = et.wikipedia || et.wikidata || wiki_url || wikivoyage_url + const hasLinks = wp || wv || wd if (!hasAbout && !hasHours && !hasContact && !hasDetails && !hasLinks) return null let idx = 0 return ( @@ -258,27 +255,22 @@ function EnrichmentSections({ details }) { {hasLinks && (
- {wiki_url ? ( - - - Wikipedia - (local) - - ) : et.wikipedia && wikiUrl(et.wikipedia) && ( - + {wp && ( + Wikipedia + {wp.local && (local)} )} - {wikivoyage_url && ( - + {wv && ( + Wikivoyage - (local) + {wv.local && (local)} )} - {et.wikidata && ( - + {wd && ( + Wikidata diff --git a/frontend/src/components/PlaceDetail.jsx b/frontend/src/components/PlaceDetail.jsx index a0b839b..6b42dcd 100644 --- a/frontend/src/components/PlaceDetail.jsx +++ b/frontend/src/components/PlaceDetail.jsx @@ -9,6 +9,7 @@ import { useStore } from '../store' import { fetchElevation, fetchPlaceDetails, fetchPlaceByWikidata, fetchDriveTime, fetchNearbyContacts, fetchLandclass, fetchReverse } from '../api' import { hasFeature } from '../config' import { buildAddress } from '../utils/place' +import { wikipediaLink, wikivoyageLink, wikidataHref } from '../utils/wiki' // Wiki service icons (simplified monochrome versions) @@ -120,13 +121,6 @@ function wheelchairLabel(val) { return map[val.toLowerCase()] || null } -function wikiUrl(wp) { - if (!wp) return null - const match = wp.match(/^([a-z-]+):(.+)$/) - if (!match) return null - return `https://${match[1]}.wikipedia.org/wiki/${encodeURIComponent(match[2].replace(/ /g, '_'))}` -} - function wikiLabel(wp) { if (!wp) return null const match = wp.match(/^[a-z-]+:(.+)$/) @@ -277,14 +271,17 @@ function CopyPopover({ address, selectedPlace, onClose }) { function EnrichmentSections({ details }) { if (!details) return null - const { category, extratags, wiki_url, wikivoyage_url } = details + const { category, extratags } = details const et = extratags || {} + const wp = wikipediaLink(details) + const wv = wikivoyageLink(details) + const wd = wikidataHref(et) const hasAbout = category const hasHours = et.opening_hours const hasContact = et.phone || et.website || et.email const hasDetails = et.cuisine || et.operator || et.fee || et.wheelchair || et.takeaway - const hasLinks = et.wikipedia || et.wikidata || wiki_url || wikivoyage_url + const hasLinks = wp || wv || wd if (!hasAbout && !hasHours && !hasContact && !hasDetails && !hasLinks) return null @@ -346,21 +343,9 @@ function EnrichmentSections({ details }) { {hasLinks && (
- {wiki_url ? ( + {wp && ( - - Wikipedia - (local) - - ) : et.wikipedia && wikiUrl(et.wikipedia) && ( - Wikipedia + {wp.local && (local)} )} - {wikivoyage_url && ( + {wv && ( Wikivoyage - (local) + {wv.local && (local)} )} - {et.wikidata && ( + {wd && ( 1 ? parts.slice(1).join(":") : parts[0]).replace(/ /g, "_") + if (!title) return null + return `https://en.wikivoyage.org/wiki/${encodeURIComponent(title)}` +} + +// Resolve the Wikipedia link for a place: { href, local } or null. +// Prefers the backend-rewritten extratags.wikipedia (already a full URL); only +// falls back to the public wiki-index wiki_url when there is no OSM wikipedia tag. +export function wikipediaLink(details) { + const et = (details && details.extratags) || {} + const status = details && details.sources && details.sources.wiki_rewrites + ? details.sources.wiki_rewrites.wikipedia + : undefined + if (et.wikipedia) { + const href = et.wikipedia.startsWith("http") + ? et.wikipedia + : publicWikipediaUrl(et.wikipedia) + return href ? { href, local: status === "local" } : null + } + if (details && details.wiki_url) return { href: details.wiki_url, local: false } + return null +} + +// Resolve the Wikivoyage link for a place: { href, local } or null. +export function wikivoyageLink(details) { + const et = (details && details.extratags) || {} + const status = details && details.sources && details.sources.wiki_rewrites + ? details.sources.wiki_rewrites.wikivoyage + : undefined + if (et.wikivoyage) { + const href = et.wikivoyage.startsWith("http") + ? et.wikivoyage + : publicWikivoyageUrl(et.wikivoyage) + return href ? { href, local: status === "local" } : null + } + if (details && details.wikivoyage_url) return { href: details.wikivoyage_url, local: false } + return null +} + +// Resolve the Wikidata href. extratags.wikidata is already a full URL after the +// backend rewrite; only build the URL when given a bare Q-id (rewriting disabled). +export function wikidataHref(et) { + const wd = et && et.wikidata + if (!wd) return null + return wd.startsWith("http") ? wd : `https://www.wikidata.org/wiki/${wd}` +}