Skip to content

Commit

Permalink
Try to enable Google Snippet
Browse files Browse the repository at this point in the history
  • Loading branch information
chunlaw committed Apr 3, 2024
1 parent c42cd94 commit ce4d116
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 4 deletions.
1 change: 1 addition & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
<meta name="twitter:image" content="https://hkbus.app/img/share.png" />
<style prerender></style>
<style>body { background: black; }</style>
<script type="application/ld+json"></script>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
Expand Down
2 changes: 1 addition & 1 deletion src/i18n.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import resources from "./i18n/translation.json";
import resources from "./i18n/translation";

const getSavedLang = (): "zh" | "en" | undefined => {
const savedLang = localStorage.getItem("lang");
Expand Down
4 changes: 3 additions & 1 deletion src/i18n/translation.json → src/i18n/translation.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
const resources = {
"en": {
"translation": {
"bad-weather-text": "Services may be impacted by bad weather. Data displayed below might not be accurate. Check here to see official announcements.",
Expand Down Expand Up @@ -269,3 +269,5 @@
}
}
}

export default resources
14 changes: 13 additions & 1 deletion src/pages/RouteEta.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ import StopAccordionList from "../components/route-eta/StopAccordionList";
import StopDialog from "../components/route-eta/StopDialog";
import AppContext from "../AppContext";
import { useTranslation } from "react-i18next";
import { setSeoHeader, toProperCase, getDistance } from "../utils";
import {
setSeoHeader,
toProperCase,
getDistance,
setSeoRouteFeature,
} from "../utils";
import StrSim from "string-similarity";
import {
Company,
Expand Down Expand Up @@ -200,6 +205,12 @@ const RouteEta = () => {
description: pageDesc(),
lang: language,
});
setSeoRouteFeature({
route: routeListEntry,
stopList,
t,
lang: language,
});
}, [
AppTitle,
dest,
Expand All @@ -211,6 +222,7 @@ const RouteEta = () => {
stopList,
stopIds,
t,
routeListEntry,
]);

return (
Expand Down
64 changes: 63 additions & 1 deletion src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type {
} from "hk-bus-eta";
import type { Location as GeoLocation } from "hk-bus-eta";
import type { TransportType } from "./@types/types";
import { isRouteAvaliable } from "./timetable";
import { ServiceIds, isRouteAvaliable } from "./timetable";

export const getDistance = (a: GeoLocation, b: GeoLocation) => {
const R = 6371e3; // metres
Expand Down Expand Up @@ -184,6 +184,68 @@ export const setSeoHeader = ({
?.setAttribute("content", description);
};

export const setSeoRouteFeature = ({route, stopList, lang, t}: {route: RouteListEntry, stopList: EtaDb["stopList"], lang: string, t: any}) => {
const jsonLd = document.querySelector('script[type="application/ld+json"]')
if ( jsonLd ) {
jsonLd.textContent = JSON.stringify({
"@context": "https://schema.org",
"@type": "FAQPage",
"@name": "123",
"mainEntity": [{
"@type": "Question",
"name": lang === 'en' ? `What transport route is ${route.route}?` : `${route.route} 是甚麼路綫?`,
"acceptedAnswer": {
"@type": "Answer",
"text": lang === 'en'
? "<p>"+
`The route ${route.route} travel between ${route.orig.en} and ${route.dest.en}, with the service provided by ${route.co.map(co => t(co)).join(" and ")}. ` +
`${route.jt ? `The whole journey takes about ${route.jt} minutes. ` : ""}` +
`${route.fares ? `The segmented fares for the trip is $${route.fares
.filter((v, idx, self) => self.indexOf(v) === idx)
.map((v) => `$${v}`)}.` : ""}` +
"</p>"
: "<p>" +
`${route.route} 往來${route.orig.zh}${route.dest.zh},由${route.co.map(co => t(co)).join("和")}營運` +
`${route.jt ? `,全程${route.jt}分鐘` : ""}` +
`${route.fares ? `,分段車費為 ${route.fares
.filter((v, idx, self) => self.indexOf(v) === idx)
.map((v) => `$${v}`)}` : ""}` +
"。</p>"
}
}, {
"@type": "Question",
"name": lang === 'en' ? `What are the stops for the route ${route.route} from ${route.orig.en}?` : `由${route.orig.zh}開出的 ${route.route} 會經過甚麼站?`,
"acceptedAnswer": {
"@type": "Answer",
"text": "<ol>" +
route.stops[Object.values(route.co)[0]].map(stopId => `<li>${stopList[stopId].name[lang as "zh" | "en"]}</li>`).join("") +
"</ol>"
}
}, ...Object.entries(route.freq ?? {}).map(([serviceId, dayFreq]) => ({
"@type": "Question",
"name": lang === "en"
// @ts-ignore
? `What are the timetable for ${route.route} from ${t(ServiceIds[serviceId])}?`
// @ts-ignore
: `${route.route}${t(ServiceIds[serviceId])}的服務時間表?`,
"acceptedAnswer": {
"@type": "Answer",
"text": "<ul>" +
Object.entries(dayFreq)
.sort((a, b) => (a[0] < b[0] ? -1 : 1))
.map(([start, details]) => (
"<li>"+
`${start} ${details ? `- ${details[0]} ${parseInt(details[1], 10) / 60}${t("分鐘")}` : ""}` +
"</li>"
)) +
"</ul>"
}
}))
]
})
}
}

export const toProperCase = (txt: string) => {
return txt.replace(/\w\S*/g, function (txt) {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
Expand Down

0 comments on commit ce4d116

Please sign in to comment.