add basic sitemap generator

This commit is contained in:
adueck 2023-02-09 14:26:51 +05:00
parent a6e3d24672
commit ebe039d71c
5 changed files with 225 additions and 169 deletions

1
.gitignore vendored
View File

@ -1,4 +1,5 @@
/src/words/raw-words.ts /src/words/raw-words.ts
public/sitemap.xml
# Logs # Logs
logs logs

View File

@ -6,11 +6,12 @@
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"dev-w-user": "REACT_APP_ENV=dev vite", "dev-w-user": "REACT_APP_ENV=dev vite",
"build": "yarn get-words && tsc && vite build", "build": "yarn get-words && yarn make-sitemap && tsc && vite build",
"preview": "vite preview", "preview": "vite preview",
"infup": "yarn upgrade @lingdocs/ps-react --latest", "infup": "yarn upgrade @lingdocs/ps-react --latest",
"bump-dep": "yarn install && git add . && git commit -m up && git push origin master", "bump-dep": "yarn install && git add . && git commit -m up && git push origin master",
"get-words": "node scripts/get-words.js" "get-words": "node scripts/get-words.js",
"make-sitemap": "node scripts/make-sitemap.js"
}, },
"dependencies": { "dependencies": {
"@formkit/auto-animate": "^1.0.0-beta.6", "@formkit/auto-animate": "^1.0.0-beta.6",
@ -58,6 +59,7 @@
"@types/react-scrollspy": "^3.3.5", "@types/react-scrollspy": "^3.3.5",
"@types/react-swipeable": "^5.2.0", "@types/react-swipeable": "^5.2.0",
"@vitejs/plugin-react": "^3.0.0", "@vitejs/plugin-react": "^3.0.0",
"loose-json": "^1.1.2",
"node-fetch": "2.6.1", "node-fetch": "2.6.1",
"typescript": "^4.9.3", "typescript": "^4.9.3",
"vite": "^4.0.0", "vite": "^4.0.0",

38
scripts/make-sitemap.js Normal file
View File

@ -0,0 +1,38 @@
import fs from "fs";
const base = "https://grammar.lingdocs.com";
console.log("generating sitemap.xml");
const indexText = fs.readFileSync("./src/content/index.ts", "utf-8");
const contentTreeRaw = indexText.split("/* content-tree */")[1];
const safeContentTreeText = contentTreeRaw
.split("\n")
.filter(l => !l.includes(`"import":`))
.join("\n");
const contentTree = JSON.parse(safeContentTreeText);
const urls = contentTree.reduce((acc, section) => {
if ("slug" in section) {
return [
...acc,
`${base}/${section.slug}`,
];
} else {
return [
...acc,
...section.chapters.map(x => `${base}/${section.subdirectory}/${x.slug}`),
];
}
}, [base]);
const siteMap = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${urls.map(u => ` <url>
<loc>${u}</loc>
</url>
`).join("")}
</urlset>
`
fs.writeFileSync("./public/sitemap.xml", siteMap);

View File

@ -137,288 +137,291 @@ type ChaptersSection = {
chapters: ChapterSection[], chapters: ChapterSection[],
}; };
const contentTree: (ChapterSection | ChaptersSection)[] = [ // for the super hacky sitemap generator to work this array needs to be
// - in valid JSON and surrounded by these comments
// - the import statements have to be at the top of the objects in a seperate line
export const contentTree: (ChapterSection | ChaptersSection)[] = /* content-tree */[
{ {
import: intro, "import": intro,
slug: "intro", "slug": "intro"
}, },
{ {
import: games, "import": games,
slug: "games", "slug": "games"
}, },
{ {
import: phraseBuilder, "import": phraseBuilder,
slug: "phrase-builder", "slug": "phrase-builder"
}, },
{ {
heading: "Equatives", "heading": "Equatives",
subdirectory: "equatives", "subdirectory": "equatives",
chapters: [ "chapters": [
{ {
import: presentEquative, "import": presentEquative,
slug: "present-equative", "slug": "present-equative"
}, },
{ {
import: habitualEquative, "import": habitualEquative,
slug: "habitual-equative", "slug": "habitual-equative"
}, },
{ {
import: otherEquatives, "import": otherEquatives,
slug: "other-equatives", "slug": "other-equatives"
}, }
], ]
}, },
{ {
heading: "Nouns", "heading": "Nouns",
subdirectory: "nouns", "subdirectory": "nouns",
chapters: [ "chapters": [
{ {
import: nounsGender, "import": nounsGender,
slug: "nouns-gender", "slug": "nouns-gender"
}, },
{ {
import: nounsUnisex, "import": nounsUnisex,
slug: "nouns-unisex", "slug": "nouns-unisex"
}, },
{ {
import: nounsPlural, "import": nounsPlural,
slug: "nouns-plural", "slug": "nouns-plural"
}, },
{ {
import: arabicPlurals, "import": arabicPlurals,
slug: "arabic-plurals", "slug": "arabic-plurals"
}, },
{ {
import: bundledPlurals, "import": bundledPlurals,
slug: "bundled-plurals", "slug": "bundled-plurals"
}, }
], ]
}, },
{ {
heading: "Phrase Structure 🧱", "heading": "Phrase Structure 🧱",
subdirectory: "phrase-structure", "subdirectory": "phrase-structure",
chapters: [ "chapters": [
{ {
import: BlocksAndKids, "import": BlocksAndKids,
slug: "blocks-and-kids", "slug": "blocks-and-kids"
}, },
{ {
import: NPIntro, "import": NPIntro,
slug: "np", "slug": "np"
}, },
{ {
import: APIntro, "import": APIntro,
slug: "ap", "slug": "ap"
}, },
{ {
import: EPIntro, "import": EPIntro,
slug: "ep", "slug": "ep"
}, },
{ {
import: VPIntro, "import": VPIntro,
slug: "vp", "slug": "vp"
}, },
{ {
import: Complement, "import": Complement,
slug: "complement", "slug": "complement"
}, },
{ {
import: ShorteningVPs, "import": ShorteningVPs,
slug: "shortening-vps", "slug": "shortening-vps"
}, }
], ]
}, },
{ {
heading: "Verbs", "heading": "Verbs",
subdirectory: "verbs", "subdirectory": "verbs",
chapters: [ "chapters": [
{ {
import: verbsIntro, "import": verbsIntro,
slug: "verbs-intro", "slug": "verbs-intro"
}, },
{ {
import: verbAspect, "import": verbAspect,
slug: "verb-aspect", "slug": "verb-aspect"
}, },
{ {
import: rootsAndStems, "import": rootsAndStems,
slug: "roots-and-stems", "slug": "roots-and-stems"
}, },
{ {
import: presentVerbs, "import": presentVerbs,
slug: "present-verbs", "slug": "present-verbs"
}, },
{ {
import: subjunctiveVerbs, "import": subjunctiveVerbs,
slug: "subjunctive-verbs", "slug": "subjunctive-verbs"
}, },
{ {
import: futureVerbs, "import": futureVerbs,
slug: "future-verbs", "slug": "future-verbs"
}, },
{ {
import: imperativeVerbs, "import": imperativeVerbs,
slug: "imperative-verbs", "slug": "imperative-verbs"
}, },
{ {
import: pastVerbs, "import": pastVerbs,
slug: "past-verbs", "slug": "past-verbs"
}, },
{ {
import: perfectVerbsIntro, "import": perfectVerbsIntro,
slug: "perfect-verbs-intro", "slug": "perfect-verbs-intro"
}, },
{ {
import: allPerfectVerbs, "import": allPerfectVerbs,
slug: "all-perfect-verbs", "slug": "all-perfect-verbs"
}, },
{ {
import: negativeVerbs, "import": negativeVerbs,
slug: "negative-verbs", "slug": "negative-verbs"
}, },
{ {
import: ability, "import": ability,
slug: "ability", "slug": "ability"
}, },
{ {
import: passiveVoice, "import": passiveVoice,
slug: "passive-voice", "slug": "passive-voice"
}, },
{ {
import: verbEndings, "import": verbEndings,
slug: "verb-endings", "slug": "verb-endings"
}, },
{ {
import: masterChart, "import": masterChart,
slug: "master-chart", "slug": "master-chart"
}, }
], ]
}, },
{ {
heading: "Compound Verbs", "heading": "Compound Verbs",
subdirectory: "compound-verbs", "subdirectory": "compound-verbs",
chapters: [ "chapters": [
{ {
import: compoundVerbsIntro, "import": compoundVerbsIntro,
slug: "intro", "slug": "intro"
}, },
{ {
import: helperVerbs, "import": helperVerbs,
slug: "helper-verbs", "slug": "helper-verbs"
}, },
{ {
import: stativeCompounds, "import": stativeCompounds,
slug: "stative-compounds", "slug": "stative-compounds"
}, },
{ {
import: dynamicCompounds, "import": dynamicCompounds,
slug: "dynamic-compounds", "slug": "dynamic-compounds"
}, },
{ {
import: moreOnCompounds, "import": moreOnCompounds,
slug: "more-on-compounds", "slug": "more-on-compounds"
}, }
], ]
}, },
{ {
heading: "Participles", "heading": "Participles",
subdirectory: "participles", "subdirectory": "participles",
chapters: [ "chapters": [
{ {
import: introToParticiples, "import": introToParticiples,
slug: "intro", "slug": "intro"
}, }
], ]
}, },
{ {
heading: "Pronouns", "heading": "Pronouns",
subdirectory: "pronouns", "subdirectory": "pronouns",
chapters: [ "chapters": [
{ {
import: pronounsBasic, "import": pronounsBasic,
slug: "pronouns-basic", "slug": "pronouns-basic"
}, },
{ {
import: pronounsMini, "import": pronounsMini,
slug: "pronouns-mini", "slug": "pronouns-mini"
}, },
{ {
import: directionalPronouns, "import": directionalPronouns,
slug: "pronouns-directional", "slug": "pronouns-directional"
}, }
], ]
}, },
{ {
heading: "Inflection 🔘", "heading": "Inflection 🔘",
subdirectory: "inflection", "subdirectory": "inflection",
chapters: [ "chapters": [
{ {
import: inflectionIntro, "import": inflectionIntro,
slug: "inflection-intro", "slug": "inflection-intro"
}, },
{ {
import: inflectionPatterns, "import": inflectionPatterns,
slug: "inflection-patterns", "slug": "inflection-patterns"
}, }
], ]
}, },
{ {
heading: "Sandwiches 🥪", "heading": "Sandwiches 🥪",
subdirectory: "sandwiches", "subdirectory": "sandwiches",
chapters: [ "chapters": [
{ {
import: sandwiches, "import": sandwiches,
slug: "sandwiches", "slug": "sandwiches"
}, }
], ]
}, },
{ {
heading: "Writing 🖊", "heading": "Writing 🖊",
subdirectory: "writing", "subdirectory": "writing",
chapters: [ "chapters": [
{ {
import: phonetics, "import": phonetics,
slug: "phonetics", "slug": "phonetics"
}, },
{ {
import: diacritics, "import": diacritics,
slug: "diacritics", "slug": "diacritics"
}, },
{ {
import: theFiveYeys, "import": theFiveYeys,
slug: "the-five-yeys", "slug": "the-five-yeys"
}, },
{ {
import: typingIssues, "import": typingIssues,
slug: "typing-issues", "slug": "typing-issues"
}, }
], ]
}, },
{ {
heading: "Recipes 👩‍🍳", "heading": "Recipes 👩‍🍳",
subdirectory: "recipes", "subdirectory": "recipes",
chapters: [ "chapters": [
{ {
import: unrealConditionals, "import": unrealConditionals,
slug: "unreal-conditionals", "slug": "unreal-conditionals"
}, }
], ]
}, },
{ {
heading: "Practice Tools 🔧", "heading": "Practice Tools 🔧",
subdirectory: "practice-tools", "subdirectory": "practice-tools",
chapters: [ "chapters": [
{ {
import: pronounPicker, "import": pronounPicker,
slug: "pronoun-picker", "slug": "pronoun-picker"
}, }
], ]
}, },
{ {
slug: "dictionary", "import": dictionary,
import: dictionary, "slug": "dictionary"
}, }
]; ]/* content-tree */;
export const content = contentTree.map((item) => { export const content = contentTree.map((item) => {
function prepareChapter(chp: any, subdir?: any) { function prepareChapter(chp: any, subdir?: any) {

View File

@ -2356,6 +2356,11 @@ escape-string-regexp@^5.0.0:
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8"
integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==
esprima@2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.4.1.tgz#83059c751e9e9c41d228a41aaa1eef0ccce384ba"
integrity sha512-oQ5niex1XEkpjZhmW1zsozCG515481U0s+A1n6xU9usjkLSy7ZDvfuaAR+CKAKujczvEy7sOPIiX/GO+MZPk8Q==
estree-util-attach-comments@^2.0.0: estree-util-attach-comments@^2.0.0:
version "2.1.1" version "2.1.1"
resolved "https://registry.yarnpkg.com/estree-util-attach-comments/-/estree-util-attach-comments-2.1.1.tgz#ee44f4ff6890ee7dfb3237ac7810154c94c63f84" resolved "https://registry.yarnpkg.com/estree-util-attach-comments/-/estree-util-attach-comments-2.1.1.tgz#ee44f4ff6890ee7dfb3237ac7810154c94c63f84"
@ -3272,6 +3277,13 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
dependencies: dependencies:
js-tokens "^3.0.0 || ^4.0.0" js-tokens "^3.0.0 || ^4.0.0"
loose-json@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/loose-json/-/loose-json-1.1.2.tgz#e86186d087c7ff81bc74067febfeaa747e1384e3"
integrity sha512-PzphlTCZdoR/cfXWN6TOKwxk9MibQmmQO6Rj4fblas+IbIWUwXhnad7E7qnWOE6ZuMZhwpmLWIUWiVy9C6UiMQ==
dependencies:
esprima "2.4.1"
lottie-web@^5.5.7: lottie-web@^5.5.7:
version "5.10.2" version "5.10.2"
resolved "https://registry.yarnpkg.com/lottie-web/-/lottie-web-5.10.2.tgz#a1c952b6734759fcd369eba73b6b7e3d9a76ce0b" resolved "https://registry.yarnpkg.com/lottie-web/-/lottie-web-5.10.2.tgz#a1c952b6734759fcd369eba73b6b7e3d9a76ce0b"