From ebe039d71c85afdb24bf166c4b1311be017b9ce7 Mon Sep 17 00:00:00 2001 From: adueck Date: Thu, 9 Feb 2023 14:26:51 +0500 Subject: [PATCH] add basic sitemap generator --- .gitignore | 1 + package.json | 6 +- scripts/make-sitemap.js | 38 +++++ src/content/index.ts | 337 ++++++++++++++++++++-------------------- yarn.lock | 12 ++ 5 files changed, 225 insertions(+), 169 deletions(-) create mode 100644 scripts/make-sitemap.js diff --git a/.gitignore b/.gitignore index 9241667..dd54b8d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /src/words/raw-words.ts +public/sitemap.xml # Logs logs diff --git a/package.json b/package.json index 88ef173..2e44b8b 100644 --- a/package.json +++ b/package.json @@ -6,11 +6,12 @@ "scripts": { "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", "infup": "yarn upgrade @lingdocs/ps-react --latest", "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": { "@formkit/auto-animate": "^1.0.0-beta.6", @@ -58,6 +59,7 @@ "@types/react-scrollspy": "^3.3.5", "@types/react-swipeable": "^5.2.0", "@vitejs/plugin-react": "^3.0.0", + "loose-json": "^1.1.2", "node-fetch": "2.6.1", "typescript": "^4.9.3", "vite": "^4.0.0", diff --git a/scripts/make-sitemap.js b/scripts/make-sitemap.js new file mode 100644 index 0000000..85e37a7 --- /dev/null +++ b/scripts/make-sitemap.js @@ -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 = ` + +${urls.map(u => ` + ${u} + +`).join("")} + +` + +fs.writeFileSync("./public/sitemap.xml", siteMap); diff --git a/src/content/index.ts b/src/content/index.ts index 4446e00..ec718b7 100644 --- a/src/content/index.ts +++ b/src/content/index.ts @@ -137,288 +137,291 @@ type ChaptersSection = { 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, - slug: "intro", + "import": intro, + "slug": "intro" }, { - import: games, - slug: "games", + "import": games, + "slug": "games" }, { - import: phraseBuilder, - slug: "phrase-builder", + "import": phraseBuilder, + "slug": "phrase-builder" }, { - heading: "Equatives", - subdirectory: "equatives", - chapters: [ + "heading": "Equatives", + "subdirectory": "equatives", + "chapters": [ { - import: presentEquative, - slug: "present-equative", + "import": presentEquative, + "slug": "present-equative" }, { - import: habitualEquative, - slug: "habitual-equative", + "import": habitualEquative, + "slug": "habitual-equative" }, { - import: otherEquatives, - slug: "other-equatives", - }, - ], + "import": otherEquatives, + "slug": "other-equatives" + } + ] }, { - heading: "Nouns", - subdirectory: "nouns", - chapters: [ + "heading": "Nouns", + "subdirectory": "nouns", + "chapters": [ { - import: nounsGender, - slug: "nouns-gender", + "import": nounsGender, + "slug": "nouns-gender" }, { - import: nounsUnisex, - slug: "nouns-unisex", + "import": nounsUnisex, + "slug": "nouns-unisex" }, { - import: nounsPlural, - slug: "nouns-plural", + "import": nounsPlural, + "slug": "nouns-plural" }, { - import: arabicPlurals, - slug: "arabic-plurals", + "import": arabicPlurals, + "slug": "arabic-plurals" }, { - import: bundledPlurals, - slug: "bundled-plurals", - }, - ], + "import": bundledPlurals, + "slug": "bundled-plurals" + } + ] }, { - heading: "Phrase Structure 🧱", - subdirectory: "phrase-structure", - chapters: [ + "heading": "Phrase Structure 🧱", + "subdirectory": "phrase-structure", + "chapters": [ { - import: BlocksAndKids, - slug: "blocks-and-kids", + "import": BlocksAndKids, + "slug": "blocks-and-kids" }, { - import: NPIntro, - slug: "np", + "import": NPIntro, + "slug": "np" }, { - import: APIntro, - slug: "ap", + "import": APIntro, + "slug": "ap" }, { - import: EPIntro, - slug: "ep", + "import": EPIntro, + "slug": "ep" }, { - import: VPIntro, - slug: "vp", + "import": VPIntro, + "slug": "vp" }, { - import: Complement, - slug: "complement", + "import": Complement, + "slug": "complement" }, { - import: ShorteningVPs, - slug: "shortening-vps", - }, - ], + "import": ShorteningVPs, + "slug": "shortening-vps" + } + ] }, { - heading: "Verbs", - subdirectory: "verbs", - chapters: [ + "heading": "Verbs", + "subdirectory": "verbs", + "chapters": [ { - import: verbsIntro, - slug: "verbs-intro", + "import": verbsIntro, + "slug": "verbs-intro" }, { - import: verbAspect, - slug: "verb-aspect", + "import": verbAspect, + "slug": "verb-aspect" }, { - import: rootsAndStems, - slug: "roots-and-stems", + "import": rootsAndStems, + "slug": "roots-and-stems" }, { - import: presentVerbs, - slug: "present-verbs", + "import": presentVerbs, + "slug": "present-verbs" }, { - import: subjunctiveVerbs, - slug: "subjunctive-verbs", + "import": subjunctiveVerbs, + "slug": "subjunctive-verbs" }, { - import: futureVerbs, - slug: "future-verbs", + "import": futureVerbs, + "slug": "future-verbs" }, { - import: imperativeVerbs, - slug: "imperative-verbs", + "import": imperativeVerbs, + "slug": "imperative-verbs" }, { - import: pastVerbs, - slug: "past-verbs", + "import": pastVerbs, + "slug": "past-verbs" }, { - import: perfectVerbsIntro, - slug: "perfect-verbs-intro", + "import": perfectVerbsIntro, + "slug": "perfect-verbs-intro" }, { - import: allPerfectVerbs, - slug: "all-perfect-verbs", + "import": allPerfectVerbs, + "slug": "all-perfect-verbs" }, { - import: negativeVerbs, - slug: "negative-verbs", + "import": negativeVerbs, + "slug": "negative-verbs" }, { - import: ability, - slug: "ability", + "import": ability, + "slug": "ability" }, { - import: passiveVoice, - slug: "passive-voice", + "import": passiveVoice, + "slug": "passive-voice" }, { - import: verbEndings, - slug: "verb-endings", + "import": verbEndings, + "slug": "verb-endings" }, { - import: masterChart, - slug: "master-chart", - }, - ], + "import": masterChart, + "slug": "master-chart" + } + ] }, { - heading: "Compound Verbs", - subdirectory: "compound-verbs", - chapters: [ + "heading": "Compound Verbs", + "subdirectory": "compound-verbs", + "chapters": [ { - import: compoundVerbsIntro, - slug: "intro", + "import": compoundVerbsIntro, + "slug": "intro" }, { - import: helperVerbs, - slug: "helper-verbs", + "import": helperVerbs, + "slug": "helper-verbs" }, { - import: stativeCompounds, - slug: "stative-compounds", + "import": stativeCompounds, + "slug": "stative-compounds" }, { - import: dynamicCompounds, - slug: "dynamic-compounds", + "import": dynamicCompounds, + "slug": "dynamic-compounds" }, { - import: moreOnCompounds, - slug: "more-on-compounds", - }, - ], + "import": moreOnCompounds, + "slug": "more-on-compounds" + } + ] }, { - heading: "Participles", - subdirectory: "participles", - chapters: [ + "heading": "Participles", + "subdirectory": "participles", + "chapters": [ { - import: introToParticiples, - slug: "intro", - }, - ], + "import": introToParticiples, + "slug": "intro" + } + ] }, { - heading: "Pronouns", - subdirectory: "pronouns", - chapters: [ + "heading": "Pronouns", + "subdirectory": "pronouns", + "chapters": [ { - import: pronounsBasic, - slug: "pronouns-basic", + "import": pronounsBasic, + "slug": "pronouns-basic" }, { - import: pronounsMini, - slug: "pronouns-mini", + "import": pronounsMini, + "slug": "pronouns-mini" }, { - import: directionalPronouns, - slug: "pronouns-directional", - }, - ], + "import": directionalPronouns, + "slug": "pronouns-directional" + } + ] }, { - heading: "Inflection 🔘", - subdirectory: "inflection", - chapters: [ + "heading": "Inflection 🔘", + "subdirectory": "inflection", + "chapters": [ { - import: inflectionIntro, - slug: "inflection-intro", + "import": inflectionIntro, + "slug": "inflection-intro" }, { - import: inflectionPatterns, - slug: "inflection-patterns", - }, - ], + "import": inflectionPatterns, + "slug": "inflection-patterns" + } + ] }, { - heading: "Sandwiches 🥪", - subdirectory: "sandwiches", - chapters: [ + "heading": "Sandwiches 🥪", + "subdirectory": "sandwiches", + "chapters": [ { - import: sandwiches, - slug: "sandwiches", - }, - ], + "import": sandwiches, + "slug": "sandwiches" + } + ] }, { - heading: "Writing 🖊", - subdirectory: "writing", - chapters: [ + "heading": "Writing 🖊", + "subdirectory": "writing", + "chapters": [ { - import: phonetics, - slug: "phonetics", + "import": phonetics, + "slug": "phonetics" }, { - import: diacritics, - slug: "diacritics", + "import": diacritics, + "slug": "diacritics" }, { - import: theFiveYeys, - slug: "the-five-yeys", + "import": theFiveYeys, + "slug": "the-five-yeys" }, { - import: typingIssues, - slug: "typing-issues", - }, - ], + "import": typingIssues, + "slug": "typing-issues" + } + ] }, { - heading: "Recipes 👩‍🍳", - subdirectory: "recipes", - chapters: [ + "heading": "Recipes 👩‍🍳", + "subdirectory": "recipes", + "chapters": [ { - import: unrealConditionals, - slug: "unreal-conditionals", - }, - ], + "import": unrealConditionals, + "slug": "unreal-conditionals" + } + ] }, { - heading: "Practice Tools 🔧", - subdirectory: "practice-tools", - chapters: [ + "heading": "Practice Tools 🔧", + "subdirectory": "practice-tools", + "chapters": [ { - import: pronounPicker, - slug: "pronoun-picker", - }, - ], + "import": pronounPicker, + "slug": "pronoun-picker" + } + ] }, { - slug: "dictionary", - import: dictionary, - }, -]; + "import": dictionary, + "slug": "dictionary" + } +]/* content-tree */; export const content = contentTree.map((item) => { function prepareChapter(chp: any, subdir?: any) { diff --git a/yarn.lock b/yarn.lock index ec1d955..501b9aa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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" 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: version "2.1.1" 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: 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: version "5.10.2" resolved "https://registry.yarnpkg.com/lottie-web/-/lottie-web-5.10.2.tgz#a1c952b6734759fcd369eba73b6b7e3d9a76ce0b"