fix sitemap
This commit is contained in:
parent
35a093c14d
commit
f914f3470b
|
@ -227,8 +227,10 @@ async function upload(content: Buffer | string, filename: string) {
|
||||||
metadata: {
|
metadata: {
|
||||||
contentType: isBuffer
|
contentType: isBuffer
|
||||||
? "application/octet-stream"
|
? "application/octet-stream"
|
||||||
: filename.slice(-5) === ".json"
|
: filename.endsWith(".json")
|
||||||
? "application/json"
|
? "application/json"
|
||||||
|
: filename.endsWith(".xml")
|
||||||
|
? "application/xml"
|
||||||
: "text/plain; charset=UTF-8",
|
: "text/plain; charset=UTF-8",
|
||||||
cacheControl: "no-cache",
|
cacheControl: "no-cache",
|
||||||
},
|
},
|
||||||
|
@ -274,14 +276,21 @@ async function uploadDictionaryToStorage(dictionary: T.Dictionary) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeSitemap(dictionary: T.Dictionary): string {
|
function makeSitemap(dictionary: T.Dictionary): string {
|
||||||
|
const pages = [
|
||||||
|
...["", "/about", "/settings", "/account", "/phrase-builder"],
|
||||||
|
...dictionary.entries.map((x) => `/word?id=${x.ts}`),
|
||||||
|
];
|
||||||
return `<?xml version="1.0" encoding="UTF-8"?>
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||||
${dictionary.entries.map(
|
${pages
|
||||||
(entry) =>
|
.map(
|
||||||
` <url>
|
(page) =>
|
||||||
<loc>https://dictionary.lingdocs.com/word?id=${entry.ts}</loc>
|
`
|
||||||
|
<url>
|
||||||
|
<loc>https://dictionary.lingdocs.com${page}}</loc>
|
||||||
</url>`
|
</url>`
|
||||||
)}
|
)
|
||||||
|
.join("")}
|
||||||
</urlset>
|
</urlset>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,9 +36,11 @@ function Entry({
|
||||||
data-testid="entry"
|
data-testid="entry"
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<strong>
|
<dt>
|
||||||
<InlinePs opts={textOptions}>{{ p: entry.p, f: entry.f }}</InlinePs>
|
<strong>
|
||||||
</strong>
|
<InlinePs opts={textOptions}>{{ p: entry.p, f: entry.f }}</InlinePs>
|
||||||
|
</strong>
|
||||||
|
</dt>
|
||||||
{` `}
|
{` `}
|
||||||
<em>{entry.c}</em>
|
<em>{entry.c}</em>
|
||||||
{entry.a && !nonClickable && (
|
{entry.a && !nonClickable && (
|
||||||
|
@ -49,7 +51,9 @@ function Entry({
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<ExtraEntryInfo entry={entry} textOptions={textOptions} />
|
<ExtraEntryInfo entry={entry} textOptions={textOptions} />
|
||||||
<div className="entry-definition">{entry.e}</div>
|
<dd>
|
||||||
|
<div className="entry-definition">{entry.e}</div>
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
import { Types as T, InlinePs } from "@lingdocs/ps-react";
|
||||||
|
import { getAudioPath } from "./PlayStorageAudio";
|
||||||
|
|
||||||
|
export function EntryAudioDisplay({
|
||||||
|
entry,
|
||||||
|
opts,
|
||||||
|
}: {
|
||||||
|
entry: T.DictionaryEntry;
|
||||||
|
opts: T.TextOptions;
|
||||||
|
}) {
|
||||||
|
if (!entry.a) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<figure>
|
||||||
|
<figcaption className="mb-1">
|
||||||
|
Listen to <InlinePs opts={opts}>{{ p: entry.p, f: entry.f }}</InlinePs>
|
||||||
|
</figcaption>
|
||||||
|
<audio
|
||||||
|
controls
|
||||||
|
controlsList="nofullscreen"
|
||||||
|
src={getAudioPath(entry.ts)}
|
||||||
|
preload="auto"
|
||||||
|
>
|
||||||
|
<a href={getAudioPath(entry.ts)}>
|
||||||
|
Download audio for{" "}
|
||||||
|
<InlinePs opts={opts}>{{ p: entry.p, f: entry.f }}</InlinePs>
|
||||||
|
</a>
|
||||||
|
</audio>
|
||||||
|
</figure>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,6 +1,10 @@
|
||||||
|
export function getAudioPath(ts: number): string {
|
||||||
|
return `https://storage.lingdocs.com/audio/${ts}.mp3`;
|
||||||
|
}
|
||||||
|
|
||||||
export default function playStorageAudio(ts: number, callback: () => void) {
|
export default function playStorageAudio(ts: number, callback: () => void) {
|
||||||
if (!ts) return;
|
if (!ts) return;
|
||||||
let audio = new Audio(`https://storage.lingdocs.com/audio/${ts}.mp3`);
|
let audio = new Audio(getAudioPath(ts));
|
||||||
audio.addEventListener("ended", () => {
|
audio.addEventListener("ended", () => {
|
||||||
callback();
|
callback();
|
||||||
audio.remove();
|
audio.remove();
|
||||||
|
|
|
@ -34,7 +34,7 @@ import { Modal } from "react-bootstrap";
|
||||||
import { getTextOptions } from "../lib/get-text-options";
|
import { getTextOptions } from "../lib/get-text-options";
|
||||||
import { entryFeeder } from "../lib/dictionary";
|
import { entryFeeder } from "../lib/dictionary";
|
||||||
import { State, DictionaryAPI } from "../types/dictionary-types";
|
import { State, DictionaryAPI } from "../types/dictionary-types";
|
||||||
import playStorageAudio from "../components/PlayStorageAudio";
|
import { EntryAudioDisplay } from "../components/EntryAudioDisplay";
|
||||||
|
|
||||||
function IsolatedEntry({
|
function IsolatedEntry({
|
||||||
state,
|
state,
|
||||||
|
@ -46,7 +46,6 @@ function IsolatedEntry({
|
||||||
isolateEntry: (ts: number) => void;
|
isolateEntry: (ts: number) => void;
|
||||||
}) {
|
}) {
|
||||||
const [exploded, setExploded] = useState<boolean>(false);
|
const [exploded, setExploded] = useState<boolean>(false);
|
||||||
const [playing, setPlaying] = useState<boolean>(false);
|
|
||||||
const [editing, setEditing] = useState<boolean>(false);
|
const [editing, setEditing] = useState<boolean>(false);
|
||||||
const [comment, setComment] = useState<string>("");
|
const [comment, setComment] = useState<string>("");
|
||||||
const [editSubmitted, setEditSubmitted] = useState<boolean>(false);
|
const [editSubmitted, setEditSubmitted] = useState<boolean>(false);
|
||||||
|
@ -57,7 +56,6 @@ function IsolatedEntry({
|
||||||
setEditing(false);
|
setEditing(false);
|
||||||
setComment("");
|
setComment("");
|
||||||
setEditSubmitted(false);
|
setEditSubmitted(false);
|
||||||
setPlaying(false);
|
|
||||||
}, [state]);
|
}, [state]);
|
||||||
function flashClippedMessage(m: string) {
|
function flashClippedMessage(m: string) {
|
||||||
setShowClipped(m);
|
setShowClipped(m);
|
||||||
|
@ -154,17 +152,14 @@ function IsolatedEntry({
|
||||||
navigator.clipboard.writeText(JSON.stringify(entry));
|
navigator.clipboard.writeText(JSON.stringify(entry));
|
||||||
flashClippedMessage("entry data copied to clipboard");
|
flashClippedMessage("entry data copied to clipboard");
|
||||||
}
|
}
|
||||||
function handlePlayStorageAudio() {
|
|
||||||
if (!entry) return;
|
|
||||||
setPlaying(true);
|
|
||||||
playStorageAudio(entry.ts, () => {
|
|
||||||
setPlaying(false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<div className="wide-width-limiter">
|
<div className="wide-width-limiter">
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>{entry.p} - LingDocs Pashto Dictionary</title>
|
<title>{entry.p} - LingDocs Pashto Dictionary</title>
|
||||||
|
<link
|
||||||
|
rel="canonical"
|
||||||
|
href={`https://dictionary.lingdocs.com/word?id=${entry.ts}`}
|
||||||
|
/>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-8">
|
<div className="col-8">
|
||||||
|
@ -177,13 +172,6 @@ function IsolatedEntry({
|
||||||
</div>
|
</div>
|
||||||
<div className="col-4">
|
<div className="col-4">
|
||||||
<div className="d-flex flex-row justify-content-end">
|
<div className="d-flex flex-row justify-content-end">
|
||||||
{entry.a && (
|
|
||||||
<div className="clickable mr-3" onClick={handlePlayStorageAudio}>
|
|
||||||
<i
|
|
||||||
className={`fas fa-lg fa-volume-${playing ? "down" : "off"}`}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div
|
<div
|
||||||
className="clickable mr-3"
|
className="clickable mr-3"
|
||||||
onClick={() => setExploded((os) => !os)}
|
onClick={() => setExploded((os) => !os)}
|
||||||
|
@ -239,6 +227,7 @@ function IsolatedEntry({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<EntryAudioDisplay entry={entry} opts={textOptions} />
|
||||||
{wordlistWord && (
|
{wordlistWord && (
|
||||||
<>
|
<>
|
||||||
{hasAttachment(wordlistWord, "audio") && (
|
{hasAttachment(wordlistWord, "audio") && (
|
||||||
|
|
Loading…
Reference in New Issue