diff --git a/.gitignore b/.gitignore index 01b9bb4..9241667 100644 --- a/.gitignore +++ b/.gitignore @@ -1,25 +1,26 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - /src/words/raw-words.ts -# dependencies -/node_modules -/.pnp -.pnp.js - -# testing -/coverage - -# production -/build - -# misc -.DS_Store -.env.local -.env.development.local -.env.test.local -.env.production.local - +# Logs +logs +*.log npm-debug.log* yarn-debug.log* yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/public/index.html b/index.html similarity index 60% rename from public/index.html rename to index.html index d3201be..0086e83 100644 --- a/public/index.html +++ b/index.html @@ -2,7 +2,7 @@ - + - - - - - + + + + + - - + + - + @@ -30,12 +30,12 @@ - + LingDocs Pashto Grammar -
+ diff --git a/netlify.toml b/netlify.toml index f4a934a..b2add86 100644 --- a/netlify.toml +++ b/netlify.toml @@ -1,3 +1,3 @@ [build] - command = "node scripts/get-words.js && yarn build" - publish = "build/" + command = "yarn build" + publish = "dist/" diff --git a/notes b/notes deleted file mode 100644 index f692e11..0000000 --- a/notes +++ /dev/null @@ -1,5 +0,0 @@ -adjectives can be used like nouns - -وبخښه، ته **استرحات** وې - -زه **عادت** یم diff --git a/package.json b/package.json index 1bb7379..88ef173 100644 --- a/package.json +++ b/package.json @@ -1,81 +1,66 @@ { - "name": "lingdocs-grammar", - "version": "0.1.0", - "private": true, + "name": "lingdocs-pashto-grammar", + "version": "0.0.0", "homepage": "https://grammar.lingdocs.com", - "dependencies": { - "@formkit/auto-animate": "^1.0.0-beta.1", - "@fortawesome/fontawesome-free": "^5.15.4", - "@lingdocs/lingdocs-main": "^0.3.3", - "@lingdocs/ps-react": "^5.5.1", - "@testing-library/jest-dom": "^5.11.4", - "@testing-library/react": "^11.1.0", - "@testing-library/user-event": "^12.1.10", - "@types/cron": "^1.7.3", - "@types/react-router-dom": "^5.3.1", - "algoliasearch": "^4.14.1", - "bootstrap": "4.5.3", - "classnames": "^2.3.1", - "cron": "^1.8.2", - "fast-deep-equal": "^3.1.3", - "froebel": "^0.21.3", - "lokijs": "^1.5.12", - "markdown-to-jsx": "^7.1.3", - "react": "^17.0.2", - "react-bootstrap": "^1.6.4", - "react-countdown-circle-timer": "^3.0.9", - "react-dom": "^17.0.2", - "react-ga": "^3.3.0", - "react-instantsearch-dom": "^6.30.2", - "react-media": "^1.10.0", - "react-player": "^2.10.1", - "react-rewards": "^1.1.2", - "react-router-dom": "^5.3.0", - "react-router-hash-link": "^2.4.3", - "react-scripts": "4.0.3", - "react-scrollspy": "^3.4.3", - "react-select": "^5.1.0", - "react-smooth-collapse": "^2.1.0", - "react-swipeable": "^6.2.0", - "unist-util-visit": "^4.1.0", - "web-vitals": "^1.0.1" - }, + "type": "module", "scripts": { + "dev": "vite", + "dev-w-user": "REACT_APP_ENV=dev vite", + "build": "yarn get-words && 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", - "start": "react-scripts start", - "start-w-user": "REACT_APP_ENV=dev react-scripts start", - "build": "react-scripts build", - "test": "react-scripts test", - "eject": "react-scripts eject", "get-words": "node scripts/get-words.js" }, - "eslintConfig": { - "extends": [ - "react-app", - "react-app/jest" - ] - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] + "dependencies": { + "@formkit/auto-animate": "^1.0.0-beta.6", + "@fortawesome/fontawesome-free": "5.15.4", + "@lingdocs/lingdocs-main": "^0.3.3", + "@lingdocs/ps-react": "^5.7.13", + "@mdx-js/rollup": "^2.2.1", + "@stefanprobst/rehype-extract-toc": "^2.2.0", + "@types/mdx": "^2.0.3", + "bootstrap": "4.5.3", + "classnames": "^2.3.2", + "cron": "^2.2.0", + "fast-deep-equal": "^3.1.3", + "froebel": "^0.23.2", + "lokijs": "^1.5.12", + "markdown-to-jsx": "^7.1.9", + "react": "^18.2.0", + "react-bootstrap": "1.6.4", + "react-countdown-circle-timer": "3.0.9", + "react-dom": "^18.2.0", + "react-ga": "3.3.0", + "react-media": "1", + "react-player": "2.10.1", + "react-rewards": "1.1.2", + "react-router-dom": "6.8.0", + "react-router-hash-link": "2.4.3", + "react-scrollspy": "^3.4.3", + "react-select": "5.1.0", + "react-smooth-collapse": "^2.1.2", + "rehype-autolink-headings": "^6.1.1", + "rehype-slug": "^5.1.0", + "remark-frontmatter": "^4.0.1", + "remark-gfm": "^3.0.1", + "remark-mdx-frontmatter": "^2.1.1" }, "devDependencies": { - "@lingdocs/mdx-loader": "^0.1.6", - "@types/jest": "^27.0.2", - "@types/node": "^16.10.3", - "@types/react": "^17.0.27", - "@types/react-dom": "^17.0.9", - "babel-loader": "8.1.0", - "node-fetch": "^2.6.1", - "typescript": "^4.4.3" + "@testing-library/jest-dom": "^5.16.5", + "@testing-library/react": "^13.4.0", + "@testing-library/user-event": "^14.4.3", + "@types/cron": "^2.0.0", + "@types/react": "^18.0.26", + "@types/react-dom": "^18.0.9", + "@types/react-router-dom": "^5.3.3", + "@types/react-router-hash-link": "^2.4.5", + "@types/react-scrollspy": "^3.3.5", + "@types/react-swipeable": "^5.2.0", + "@vitejs/plugin-react": "^3.0.0", + "node-fetch": "2.6.1", + "typescript": "^4.9.3", + "vite": "^4.0.0", + "vite-plugin-pwa": "^0.14.1" } } diff --git a/public/manifest.json b/public/manifest.json deleted file mode 100644 index 6ebe984..0000000 --- a/public/manifest.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "short_name": "Pashto Grammar", - "name": "LingDocs Pashto Grammar", - "icons": [ - { - "src": "icons/android-chrome-36x36.png", - "sizes": "36x36", - "type": "image/png" - }, - { - "src": "icons/android-chrome-48x48.png", - "sizes": "48x48", - "type": "image/png" - }, - { - "src": "icons/android-chrome-72x72.png", - "sizes": "72x72", - "type": "image/png" - }, - { - "src": "icons/android-chrome-96x96.png", - "sizes": "96x96", - "type": "image/png" - }, - { - "src": "icons/android-chrome-144x144.png", - "sizes": "144x144", - "type": "image/png" - }, - { - "src": "icons/android-chrome-192x192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "icons/android-chrome-256x256.png", - "sizes": "256x256", - "type": "image/png" - }, - { - "src": "icons/android-chrome-384x384.png", - "sizes": "384x384", - "type": "image/png" - }, - { - "src": "icons/android-chrome-512x512.png", - "sizes": "512x512", - "type": "image/png" - } - ], - "start_url": "./table-of-contents", - "display": "minimal-ui", - "theme_color": "#DEE1E6", - "background_color": "#ffffff" -} diff --git a/scripts/get-words.js b/scripts/get-words.js index bea0574..272f0c0 100644 --- a/scripts/get-words.js +++ b/scripts/get-words.js @@ -1,30 +1,13 @@ -const fs = require("fs"); -const fetch = require("node-fetch"); -const path = require("path"); -const wordsPath = path.join(".", "src", "words"); -const wordsFile = "raw-words.ts"; +import fs from "fs"; +import fetch from "node-fetch"; -const verbCollectionPath = path.join(wordsPath, "verb-categories"); -const nounAdjCollectionPath = path.join(wordsPath, "noun-adj-categories"); -const adverbCollectionPath = path.join(wordsPath, "adverbs"); +import nounAdjTs from "../src/words/nouns-adjs.js"; +import verbs from "../src/words/verbs.js"; +import adverbs from "../src/words/adverbs.js"; -const verbTsFiles = fs.readdirSync(verbCollectionPath); -const nounAdjTsFiles = fs.readdirSync(nounAdjCollectionPath); -const adverbTsFiles = fs.readdirSync(adverbCollectionPath); +const wordsFile = "./src/words/raw-words.ts"; -const allVerbTsS = verbTsFiles.flatMap(fileName => [ - ...require(path.join("..", verbCollectionPath, fileName)) -]).filter((v, i, a) => a.findIndex(x => x === v) === i); - -const allNounAdjTsS = nounAdjTsFiles.flatMap(fileName => [ - ...require(path.join("..", nounAdjCollectionPath, fileName)) -]).filter((v, i, a) => a.findIndex(x => x === v) === i); - -const allAdverbTsS = adverbTsFiles.flatMap(fileName => [ - ...require(path.join("..", adverbCollectionPath, fileName)) -]).filter((v, i, a) => a.findIndex(x => x === v) === i); - -const allTs = [...allVerbTsS, ...allAdverbTsS, ...allNounAdjTsS]; +const allTs = [...nounAdjTs, ...verbs, ...adverbs]; console.log("getting words from dictionary..."); fetch("https://account.lingdocs.com/dictionary/entries", { @@ -38,7 +21,7 @@ fetch("https://account.lingdocs.com/dictionary/entries", { // @ts-ignore const words: Word[] = ${JSON.stringify(data.results)}; export default words;`; - fs.writeFileSync(path.join(wordsPath, wordsFile), content); + fs.writeFileSync(wordsFile, content); const missingEc = data.results.filter(x => "entry" in x && !x.entry.ec); if (missingEc.length) { console.log("verbs missing ec"); diff --git a/src/App.tsx b/src/App.tsx index 6dffe75..0ac5ff7 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -7,7 +7,7 @@ */ import { useState } from "react"; -import { Route, withRouter, Switch, RouteComponentProps } from "react-router-dom"; +import { Route, Routes, useNavigate } from "react-router-dom"; import "./App.css"; import Page404 from "./pages/404"; import Chapter from "./components/Chapter"; @@ -34,8 +34,9 @@ if (isProd) { ReactGA.set({ anonymizeIp: true }); } -function App(props: RouteComponentProps) { +function App(props: any) { const [navOpen, setNavOpen] = useState(false); + const navigate = useNavigate(); const { user } = useUser(); function logAnalytics() { if (isProd && !(user?.admin)) { @@ -44,9 +45,9 @@ function App(props: RouteComponentProps) { } useEffect(() => { logAnalytics(); - if (props.location.pathname === "/") { + if (window.location.pathname === "/") { if (localStorage.getItem("visitedOnce")) { - props.history.replace("/table-of-contents"); + navigate("/table-of-contents", { replace: true }) } else { localStorage.setItem("visitedOnce", "true"); } @@ -57,7 +58,7 @@ function App(props: RouteComponentProps) { window.scroll(0, 0); logAnalytics(); // eslint-disable-next-line - }, [props.location.pathname]); + }, [window.location.pathname]); return ( <>
@@ -67,32 +68,38 @@ function App(props: RouteComponentProps) { content={content} navOpen={navOpen} setNavOpen={setNavOpen} - pathname={props.location.pathname} + pathname={window.location.pathname} /> - - - - - - - - - - + + } + /> + } + /> + } + /> {chapters.map((chapter: any) => ( - - {chapter} - + {chapter}} + /> ))} - - - - - + } + /> + } /> + ); } -export default withRouter(App); +export default App; diff --git a/src/components/Chapter.js b/src/components/Chapter.jsx similarity index 100% rename from src/components/Chapter.js rename to src/components/Chapter.jsx diff --git a/src/components/EquativeFormChoice.js b/src/components/EquativeFormChoice.jsx similarity index 100% rename from src/components/EquativeFormChoice.js rename to src/components/EquativeFormChoice.jsx diff --git a/src/components/Footer.js b/src/components/Footer.jsx similarity index 100% rename from src/components/Footer.js rename to src/components/Footer.jsx diff --git a/src/components/GenderTable.js b/src/components/GenderTable.jsx similarity index 100% rename from src/components/GenderTable.js rename to src/components/GenderTable.jsx diff --git a/src/components/Header.js b/src/components/Header.jsx similarity index 100% rename from src/components/Header.js rename to src/components/Header.jsx diff --git a/src/components/InlineInflectionButton.js b/src/components/InlineInflectionButton.jsx similarity index 100% rename from src/components/InlineInflectionButton.js rename to src/components/InlineInflectionButton.jsx diff --git a/src/components/Link.js b/src/components/Link.tsx similarity index 84% rename from src/components/Link.js rename to src/components/Link.tsx index 5002f22..6d93fd8 100644 --- a/src/components/Link.js +++ b/src/components/Link.tsx @@ -8,9 +8,15 @@ import { HashLink } from 'react-router-hash-link'; import { Link } from "react-router-dom"; +import type { CSSProperties } from 'react'; // import scrollWithOffset from "../../lib/scroll-with-offset.js"; -export default function L(props) { +export default function L(props: { + to: string, + style?: CSSProperties, + children: string | JSX.Element, + className?: string, +}) { const { to } = props || ""; const toA = (to.includes("#") && to.split("#")[0] === window.location.pathname) ? ("#" + to.split("#")[1]) diff --git a/src/components/Sidebar.js b/src/components/Sidebar.jsx similarity index 100% rename from src/components/Sidebar.js rename to src/components/Sidebar.jsx diff --git a/src/components/Table.js b/src/components/Table.jsx similarity index 100% rename from src/components/Table.js rename to src/components/Table.jsx diff --git a/src/components/TableOfContents.jsx b/src/components/TableOfContents.tsx similarity index 72% rename from src/components/TableOfContents.jsx rename to src/components/TableOfContents.tsx index 0a24010..118f96d 100644 --- a/src/components/TableOfContents.jsx +++ b/src/components/TableOfContents.tsx @@ -8,23 +8,23 @@ import { NavHashLink } from 'react-router-hash-link'; import Scrollspy from 'react-scrollspy'; - - function TableOfContents({ tableOfContents }) { - return ( + +function TableOfContents({ tableOfContents }: { tableOfContents: TableOfContents }) { + return (