update base

This commit is contained in:
lingdocs 2021-10-10 20:39:59 -04:00
parent b591379a59
commit 2d87556184
26 changed files with 4348 additions and 3959 deletions

View File

@ -1,11 +1,3 @@
{ {
"presets": ["babel-preset-react-app"], "presets": ["babel-preset-react-app"]
"plugins": [
[
"@babel/plugin-transform-react-jsx",
{
"pragmaFrag": "React.Fragment"
}
]
]
} }

View File

@ -1,5 +0,0 @@
{
"rules": {
"jsx-a11y/accessible-emoji": "off"
}
}

View File

@ -1,23 +0,0 @@
name: CI
on:
push:
branches: [ '*' ]
pull_request:
branches: [ '*' ]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
env:
LINGDOCS_NPM_TOKEN: ${{ secrets.LINGDOCS_NPM_TOKEN }}
LINGDOCS_DICTIONARY_URL: ${{ secrets.LINGDOCS_DICTIONARY_URL }}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 12
- run: yarn install
- run: yarn build

4
.gitignore vendored
View File

@ -1,9 +1,5 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dictionary entries fetched during build
/src/words/**/verbs.js
/src/words/**/nouns-adjs.js
# dependencies # dependencies
/node_modules /node_modules
/.pnp /.pnp

2
.npmrc
View File

@ -1,2 +0,0 @@
@lingdocs:registry=https://npm.lingdocs.com
//npm.lingdocs.com/:_authToken=${LINGDOCS_NPM_TOKEN}

View File

@ -1,9 +1,21 @@
# LingDocs Pashto Grammar # Create React App w/ MDX Starter
[![Netlify Status](https://api.netlify.com/api/v1/badges/150beb8b-aae1-4cef-a05c-2add5d8904f7/deploy-status)](https://app.netlify.com/sites/pashto-grammar/deploys) A boilerplate for Create React App projects w/ MDX import functionality
![build](https://github.com/lingdocs/grammar.lingdocs.com/actions/workflows/main.yml/badge.svg)
The source code of this app is licensed under an MIT license. Bootstrapped with:
The contents of the book, however, (found in `/src/content`) are licensed under a [Attribution-ShareAlike 4.0 International License (CC BY-SA 4.0)]( - [Create React App](https://reactjs.org/docs/create-a-new-react-app.html)
https://creativecommons.org/licenses/by-sa/4.0/). - [@lingdocs/mdx-loader](https://github.com/lingdocs/mdx-loader)
### Development
```
yarn install
yarn start
```
### Building
```
yarn build
```

View File

@ -1 +0,0 @@
[0122/001738.459:ERROR:directory_reader_win.cc(43)] FindFirstFile: The system cannot find the path specified. (0x3)

View File

@ -1,51 +1,45 @@
{ {
"name": "lingdocs-pashto-grammar", "name": "lingdocs-grammar",
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-free": "^5.15.2", "@fortawesome/fontawesome-free": "^5.15.4",
"@lingdocs/lingdocs-main": "^0.1.8", "@lingdocs/lingdocs-main": "^0.2.0",
"@lingdocs/pashto-inflector": "^1.1.9", "@lingdocs/pashto-inflector": "^1.1.9",
"@testing-library/jest-dom": "^4.2.4", "@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^9.3.2", "@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^7.1.2", "@testing-library/user-event": "^12.1.10",
"@types/jest": "^27.0.2", "@types/cron": "^1.7.3",
"@types/node": "^14.14.35", "@types/react-router-dom": "^5.3.1",
"@types/react": "^17.0.3",
"@types/react-dom": "^17.0.2",
"@types/react-router-dom": "^5.1.9",
"bootstrap": "4.5.3", "bootstrap": "4.5.3",
"classnames": "^2.2.6",
"cron": "^1.8.2", "cron": "^1.8.2",
"markdown-to-jsx": "^7.1.3", "markdown-to-jsx": "^7.1.3",
"react": "^17.0.1", "react": "^17.0.2",
"react-bootstrap": "^1.5.2", "react-bootstrap": "^1.6.4",
"react-countdown-circle-timer": "^2.5.4", "react-countdown-circle-timer": "^2.5.4",
"react-dom": "^17.0.1", "react-dom": "^17.0.2",
"react-ga": "^3.3.0", "react-ga": "^3.3.0",
"react-media": "^1.10.0", "react-media": "^1.10.0",
"react-rewards": "^1.1.2", "react-rewards": "^1.1.2",
"react-router-dom": "^5.2.0", "react-router-dom": "^5.3.0",
"react-router-hash-link": "^2.3.1", "react-router-hash-link": "^2.4.3",
"react-scripts": "3.4.3", "react-scripts": "4.0.3",
"react-scrollspy": "^3.4.3", "react-scrollspy": "^3.4.3",
"react-smooth-collapse": "^2.1.0", "react-smooth-collapse": "^2.1.0",
"react-swipeable": "^6.1.0", "react-swipeable": "^6.2.0",
"typescript": "^4.2.3" "web-vitals": "^1.0.1"
}, },
"scripts": { "scripts": {
"start": "react-scripts start", "start": "react-scripts start",
"start-w-user": "REACT_APP_ENV=dev react-scripts start", "build": "react-scripts build",
"build": "node scripts/get-words.js && react-scripts build",
"test": "react-scripts test", "test": "react-scripts test",
"eject": "react-scripts eject", "eject": "react-scripts eject"
"get-words": "node scripts/get-words.js"
}, },
"eslintConfig": { "eslintConfig": {
"extends": "react-app", "extends": [
"rules": { "react-app",
"jsx-a11y/accessible-emoji": "off" "react-app/jest"
} ]
}, },
"browserslist": { "browserslist": {
"production": [ "production": [
@ -60,9 +54,13 @@
] ]
}, },
"devDependencies": { "devDependencies": {
"@babel/plugin-transform-react-jsx": "^7.14.5", "@lingdocs/mdx-loader": "^0.0.8",
"@types/cron": "^1.7.3", "@types/jest": "^27.0.2",
"mdx-loader": "^3.0.2", "@types/node": "^16.10.3",
"node-fetch": "^2.6.1" "@types/react": "^17.0.27",
"@types/react-dom": "^17.0.9",
"babel-loader": "8.1.0",
"node-fetch": "^3.0.0",
"typescript": "^4.4.3"
} }
} }

View File

@ -1,17 +1,8 @@
/** import { render, screen } from '@testing-library/react';
* Copyright (c) 2021 lingdocs.com
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
import React from 'react';
import { render } from '@testing-library/react';
import App from './App'; import App from './App';
test('renders', () => { test('renders learn react link', () => {
const { getByText } = render(<App />); render(<App />);
const linkElement = getByText(/pashto grammar/i); const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument(); expect(linkElement).toBeInTheDocument();
}); });

View File

@ -6,7 +6,7 @@
* *
*/ */
import React, { useState } from "react"; import { useState } from "react";
// eslint-disable-next-line // eslint-disable-next-line
import { BrowserRouter as Router, Route, withRouter, Switch, RouteComponentProps } from "react-router-dom"; import { BrowserRouter as Router, Route, withRouter, Switch, RouteComponentProps } from "react-router-dom";
import "./App.css"; import "./App.css";

View File

@ -6,7 +6,7 @@
* *
*/ */
import React, { useState } from "react"; import { useState } from "react";
import { useSwipeable } from "react-swipeable"; import { useSwipeable } from "react-swipeable";
import leftChevron from "./chevron_left-24px.svg"; import leftChevron from "./chevron_left-24px.svg";
import rightChevron from "./chevron_right-24px.svg"; import rightChevron from "./chevron_right-24px.svg";
@ -16,7 +16,7 @@ const chevStyle = {
width: "3.5rem", width: "3.5rem",
}; };
export default function(props) { export default function Carousel(props) {
// console.log("pppp"); // console.log("pppp");
// console.log(props.items); // console.log(props.items);
const [current, setCurrent] = useState(0); const [current, setCurrent] = useState(0);

View File

@ -6,12 +6,11 @@
* *
*/ */
import React from "react";
import { HashLink } from 'react-router-hash-link'; import { HashLink } from 'react-router-hash-link';
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
// import scrollWithOffset from "../../lib/scroll-with-offset.js"; // import scrollWithOffset from "../../lib/scroll-with-offset.js";
export default function(props) { export default function L(props) {
const { to } = props || ""; const { to } = props || "";
if (to.includes("#")) { if (to.includes("#")) {
// If it's a hash link return the special hash link // If it's a hash link return the special hash link

View File

@ -8,75 +8,75 @@
/* eslint-disable import/no-webpack-loader-syntax */ /* eslint-disable import/no-webpack-loader-syntax */
// @ts-ignore // @ts-ignore
import * as intro from "!babel-loader!mdx-loader!./intro.mdx"; import * as intro from "!babel-loader!@lingdocs/mdx-loader!./intro.mdx";
// @ts-ignore // @ts-ignore
import * as presentEquative from "!babel-loader!mdx-loader!./equatives/present-equative.mdx" import * as presentEquative from "!babel-loader!@lingdocs/mdx-loader!./equatives/present-equative.mdx"
// @ts-ignore // @ts-ignore
import * as subjunctiveHabitualEquative from "!babel-loader!mdx-loader!./equatives/subjunctive-habitual-equative.mdx"; import * as subjunctiveHabitualEquative from "!babel-loader!@lingdocs/mdx-loader!./equatives/subjunctive-habitual-equative.mdx";
// @ts-ignore // @ts-ignore
import * as otherEquatives from "!babel-loader!mdx-loader!./equatives/other-equatives.mdx"; import * as otherEquatives from "!babel-loader!@lingdocs/mdx-loader!./equatives/other-equatives.mdx";
// @ts-ignore // @ts-ignore
import * as equativeExplorer from "!babel-loader!mdx-loader!./equatives/equative-explorer.mdx"; import * as equativeExplorer from "!babel-loader!@lingdocs/mdx-loader!./equatives/equative-explorer.mdx";
// @ts-ignore // @ts-ignore
import * as nounsGender from "!babel-loader!mdx-loader!./nouns/nouns-gender.mdx"; import * as nounsGender from "!babel-loader!@lingdocs/mdx-loader!./nouns/nouns-gender.mdx";
// @ts-ignore // @ts-ignore
import * as nounsUnisex from "!babel-loader!mdx-loader!./nouns/nouns-unisex.mdx"; import * as nounsUnisex from "!babel-loader!@lingdocs/mdx-loader!./nouns/nouns-unisex.mdx";
// @ts-ignore // @ts-ignore
import * as nounsPlural from "!babel-loader!mdx-loader!./nouns/nouns-plural.mdx"; import * as nounsPlural from "!babel-loader!@lingdocs/mdx-loader!./nouns/nouns-plural.mdx";
// @ts-ignore // @ts-ignore
import * as arabicPlurals from "!babel-loader!mdx-loader!./nouns/arabic-plurals.mdx"; import * as arabicPlurals from "!babel-loader!@lingdocs/mdx-loader!./nouns/arabic-plurals.mdx";
// @ts-ignore // @ts-ignore
import * as bundledPlurals from "!babel-loader!mdx-loader!./nouns/bundled-plurals.mdx"; import * as bundledPlurals from "!babel-loader!@lingdocs/mdx-loader!./nouns/bundled-plurals.mdx";
// @ts-ignore // @ts-ignore
import * as verbAspect from "!babel-loader!mdx-loader!./verbs/verb-aspect.mdx"; import * as verbAspect from "!babel-loader!@lingdocs/mdx-loader!./verbs/verb-aspect.mdx";
// @ts-ignore // @ts-ignore
import * as verbsIntro from "!babel-loader!mdx-loader!./verbs/verbs-intro.mdx"; import * as verbsIntro from "!babel-loader!@lingdocs/mdx-loader!./verbs/verbs-intro.mdx";
// @ts-ignore // @ts-ignore
import * as presentVerbs from "!babel-loader!mdx-loader!./verbs/present-verbs.mdx"; import * as presentVerbs from "!babel-loader!@lingdocs/mdx-loader!./verbs/present-verbs.mdx";
// @ts-ignore // @ts-ignore
import * as subjunctiveVerbs from "!babel-loader!mdx-loader!./verbs/subjunctive-verbs.mdx"; import * as subjunctiveVerbs from "!babel-loader!@lingdocs/mdx-loader!./verbs/subjunctive-verbs.mdx";
// @ts-ignore // @ts-ignore
import * as futureVerbs from "!babel-loader!mdx-loader!./verbs/future-verbs.mdx"; import * as futureVerbs from "!babel-loader!@lingdocs/mdx-loader!./verbs/future-verbs.mdx";
// @ts-ignore // @ts-ignore
import * as imperativeVerbs from "!babel-loader!mdx-loader!./verbs/imperative-verbs.mdx"; import * as imperativeVerbs from "!babel-loader!@lingdocs/mdx-loader!./verbs/imperative-verbs.mdx";
// @ts-ignore // @ts-ignore
import * as verbEndings from "!babel-loader!mdx-loader!./verbs/verb-endings.mdx"; import * as verbEndings from "!babel-loader!@lingdocs/mdx-loader!./verbs/verb-endings.mdx";
// @ts-ignore // @ts-ignore
import * as rootsAndStems from "!babel-loader!mdx-loader!./verbs/roots-and-stems.mdx"; import * as rootsAndStems from "!babel-loader!@lingdocs/mdx-loader!./verbs/roots-and-stems.mdx";
// @ts-ignore // @ts-ignore
import * as sentenceStructure from "!babel-loader!mdx-loader!./verbs/sentence-structure.mdx"; import * as sentenceStructure from "!babel-loader!@lingdocs/mdx-loader!./verbs/sentence-structure.mdx";
// @ts-ignore // @ts-ignore
import * as pronounsBasic from "!babel-loader!mdx-loader!./pronouns/pronouns-basic.mdx"; import * as pronounsBasic from "!babel-loader!@lingdocs/mdx-loader!./pronouns/pronouns-basic.mdx";
// @ts-ignore // @ts-ignore
import * as pronounsMini from "!babel-loader!mdx-loader!./pronouns/pronouns-mini.mdx"; import * as pronounsMini from "!babel-loader!@lingdocs/mdx-loader!./pronouns/pronouns-mini.mdx";
// @ts-ignore // @ts-ignore
import * as directionalPronouns from "!babel-loader!mdx-loader!./pronouns/pronouns-directional.mdx"; import * as directionalPronouns from "!babel-loader!@lingdocs/mdx-loader!./pronouns/pronouns-directional.mdx";
// @ts-ignore // @ts-ignore
import * as inflectionIntro from "!babel-loader!mdx-loader!./inflection/inflection-intro.mdx"; import * as inflectionIntro from "!babel-loader!@lingdocs/mdx-loader!./inflection/inflection-intro.mdx";
// @ts-ignore // @ts-ignore
import * as inflectionPatterns from "!babel-loader!mdx-loader!./inflection/inflection-patterns.mdx"; import * as inflectionPatterns from "!babel-loader!@lingdocs/mdx-loader!./inflection/inflection-patterns.mdx";
// @ts-ignore // @ts-ignore
import * as feminineInflection from "!babel-loader!mdx-loader!./inflection/feminine-inflection.mdx"; import * as feminineInflection from "!babel-loader!@lingdocs/mdx-loader!./inflection/feminine-inflection.mdx";
// @ts-ignore // @ts-ignore
import * as sandwiches from "!babel-loader!mdx-loader!./sandwiches/sandwiches.mdx"; import * as sandwiches from "!babel-loader!@lingdocs/mdx-loader!./sandwiches/sandwiches.mdx";
// @ts-ignore // @ts-ignore
import * as phonetics from "!babel-loader!mdx-loader!./writing/phonetics.mdx"; import * as phonetics from "!babel-loader!@lingdocs/mdx-loader!./writing/phonetics.mdx";
// @ts-ignore // @ts-ignore
import * as diacritics from "!babel-loader!mdx-loader!./writing/diacritics.mdx"; import * as diacritics from "!babel-loader!@lingdocs/mdx-loader!./writing/diacritics.mdx";
// @ts-ignore // @ts-ignore
import * as theFiveYeys from "!babel-loader!mdx-loader!./writing/the-five-yeys.mdx"; import * as theFiveYeys from "!babel-loader!@lingdocs/mdx-loader!./writing/the-five-yeys.mdx";
// @ts-ignore // @ts-ignore
import * as typingIssues from "!babel-loader!mdx-loader!./writing/typing-issues.mdx"; import * as typingIssues from "!babel-loader!@lingdocs/mdx-loader!./writing/typing-issues.mdx";
// @ts-ignore // @ts-ignore
import * as games from "!babel-loader!mdx-loader!./games.mdx"; import * as games from "!babel-loader!@lingdocs/mdx-loader!./games.mdx";
const contentTree = [ const contentTree = [
{ {
@ -327,29 +327,3 @@ export const content = contentTree.map((item) => {
)), )),
} }
}); });
// // Now that the paths are made, go through and make the next and previous page information for each chapter
// // STEP #2
// content.sections.forEach((section, i) => {
// section.chapters.forEach((chapter, j) => {
// // See if there's a next chapter
// let nextChapter = j === section.chapters.length - 1 ? null : section.chapters[j + 1];
// if (!nextChapter) {
// // No? maybe there's something a section ahead (if that exists)
// nextChapter = i === content.sections.length - 1 ? null : content.sections[i + 1].chapters[0];
// }
// if (nextChapter) {
// chapter.next = { frontMatter: nextChapter, path: nextChapter.path };
// }
// // See if there's a previous chapter
// let prevChapter = j === 0 ? null : section.chapters[j - 1];
// if (!prevChapter) {
// // No? maybe there's something a section behind (if that exists)
// prevChapter = i === 0 ? null : content.sections[i - 1].chapters[content.sections[i - 1].chapters.length - 1];
// }
// if (prevChapter) {
// chapter.previous = { frontMatter: prevChapter, path: prevChapter.path };
// }
// });
// });

View File

@ -1,4 +1,4 @@
import React, { useState, useRef } from "react"; import { useState, useRef } from "react";
import { CountdownCircleTimer } from "react-countdown-circle-timer"; import { CountdownCircleTimer } from "react-countdown-circle-timer";
import Reward, { RewardElement } from 'react-rewards'; import Reward, { RewardElement } from 'react-rewards';
import Link from "../components/Link"; import Link from "../components/Link";
@ -16,14 +16,14 @@ import {
getTimestamp, getTimestamp,
} from "@lingdocs/lingdocs-main"; } from "@lingdocs/lingdocs-main";
import { import {
Types as T, Types,
} from "@lingdocs/pashto-inflector"; } from "@lingdocs/pashto-inflector";
const errorVibration = 200; const errorVibration = 200;
function GameCore<T>({ questions, Display, timeLimit, Instructions, studyLink, id }:{ function GameCore<T>({ questions, Display, timeLimit, Instructions, studyLink, id }:{
id: string, id: string,
studyLink: string, studyLink: string,
Instructions: (props: { opts?: T.TextOptions }) => JSX.Element, Instructions: (props: { opts?: Types.TextOptions }) => JSX.Element,
questions: () => QuestionGenerator<T>, questions: () => QuestionGenerator<T>,
Display: (props: QuestionDisplayProps<T>) => JSX.Element, Display: (props: QuestionDisplayProps<T>) => JSX.Element,
timeLimit: number; timeLimit: number;

View File

@ -50,7 +50,7 @@ const exceptions: Record<string, CategorySet> = {
const amount = 35; const amount = 35;
export default function({level, id, link}: { level: 1 | 2, id: string, link: string }) { export default function GenderGame({level, id, link}: { level: 1 | 2, id: string, link: string }) {
function* questions () { function* questions () {
const wordPool = {...types}; const wordPool = {...types};
const exceptionsPool = {...exceptions}; const exceptionsPool = {...exceptions};

View File

@ -34,7 +34,7 @@ const amount = 20;
type Question = { entry: T.DictionaryEntry, gender: T.Gender }; type Question = { entry: T.DictionaryEntry, gender: T.Gender };
export default function({ id, link }: { id: string, link: string }) { export default function UnisexNounGame({ id, link }: { id: string, link: string }) {
function* questions (): Generator<Current<Question>> { function* questions (): Generator<Current<Question>> {
let pool = [...nouns]; let pool = [...nouns];
for (let i = 0; i < amount; i++) { for (let i = 0; i < amount; i++) {

View File

@ -1,19 +1,12 @@
/**
* Copyright (c) 2021 lingdocs.com
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import App from './App'; import App from './App';
import * as serviceWorkerRegistration from './serviceWorkerRegistration';
import { BrowserRouter as Router } from "react-router-dom"; import { BrowserRouter as Router } from "react-router-dom";
import { UserProvider} from "./user-context"; import { UserProvider} from "./user-context";
import * as serviceWorker from './serviceWorker';
import "bootstrap/dist/css/bootstrap.min.css"; import "bootstrap/dist/css/bootstrap.min.css";
import "@fortawesome/fontawesome-free/css/all.css"; import "@fortawesome/fontawesome-free/css/all.css";
import reportWebVitals from './reportWebVitals';
ReactDOM.render( ReactDOM.render(
<React.StrictMode> <React.StrictMode>
@ -28,17 +21,10 @@ ReactDOM.render(
// If you want your app to work offline and load faster, you can change // If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls. // unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA // Learn more about service workers: https://cra.link/PWA
serviceWorker.register(); serviceWorkerRegistration.unregister();
// serviceWorker.register({
// onUpdate: registration => {
// const ready = window.confirm("New version available! Update?");
// if (registration && registration.waiting) {
// registration.waiting.postMessage({ type: 'SKIP_WAITING' });
// }
// if (ready) {
// window.location.reload();
// }
// }
// });
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

View File

@ -1,4 +1,6 @@
export default { const gc = {
m: "#C1D5F4", m: "#C1D5F4",
f: "#FFECEF", f: "#FFECEF",
} };
export default gc;

View File

@ -6,9 +6,7 @@
* *
*/ */
import React from "react"; export default function FourOFour() {
export default function() {
return <main className="col bg-faded py-3"> return <main className="col bg-faded py-3">
<h1>404 PAGE NOT FOUND</h1> <h1>404 PAGE NOT FOUND</h1>
</main>; </main>;

13
src/reportWebVitals.js Normal file
View File

@ -0,0 +1,13 @@
const reportWebVitals = onPerfEntry => {
if (onPerfEntry && onPerfEntry instanceof Function) {
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry);
getFID(onPerfEntry);
getFCP(onPerfEntry);
getLCP(onPerfEntry);
getTTFB(onPerfEntry);
});
}
};
export default reportWebVitals;

72
src/service-worker.js Normal file
View File

@ -0,0 +1,72 @@
/* eslint-disable no-restricted-globals */
// This service worker can be customized!
// See https://developers.google.com/web/tools/workbox/modules
// for the list of available Workbox modules, or add any other
// code you'd like.
// You can also remove this file if you'd prefer not to use a
// service worker, and the Workbox build step will be skipped.
import { clientsClaim } from 'workbox-core';
import { ExpirationPlugin } from 'workbox-expiration';
import { precacheAndRoute, createHandlerBoundToURL } from 'workbox-precaching';
import { registerRoute } from 'workbox-routing';
import { StaleWhileRevalidate } from 'workbox-strategies';
clientsClaim();
// Precache all of the assets generated by your build process.
// Their URLs are injected into the manifest variable below.
// This variable must be present somewhere in your service worker file,
// even if you decide not to use precaching. See https://cra.link/PWA
precacheAndRoute(self.__WB_MANIFEST);
// Set up App Shell-style routing, so that all navigation requests
// are fulfilled with your index.html shell. Learn more at
// https://developers.google.com/web/fundamentals/architecture/app-shell
const fileExtensionRegexp = new RegExp('/[^/?]+\\.[^/]+$');
registerRoute(
// Return false to exempt requests from being fulfilled by index.html.
({ request, url }) => {
// If this isn't a navigation, skip.
if (request.mode !== 'navigate') {
return false;
} // If this is a URL that starts with /_, skip.
if (url.pathname.startsWith('/_')) {
return false;
} // If this looks like a URL for a resource, because it contains // a file extension, skip.
if (url.pathname.match(fileExtensionRegexp)) {
return false;
} // Return true to signal that we want to use the handler.
return true;
},
createHandlerBoundToURL(process.env.PUBLIC_URL + '/index.html')
);
// An example runtime caching route for requests that aren't handled by the
// precache, in this case same-origin .png requests like those from in public/
registerRoute(
// Add in any other file extensions or routing criteria as needed.
({ url }) => url.origin === self.location.origin && url.pathname.endsWith('.png'), // Customize this strategy as needed, e.g., by changing to CacheFirst.
new StaleWhileRevalidate({
cacheName: 'images',
plugins: [
// Ensure that once this runtime cache reaches a maximum size the
// least-recently used images are removed.
new ExpirationPlugin({ maxEntries: 50 }),
],
})
);
// This allows the web app to trigger skipWaiting via
// registration.waiting.postMessage({type: 'SKIP_WAITING'})
self.addEventListener('message', (event) => {
if (event.data && event.data.type === 'SKIP_WAITING') {
self.skipWaiting();
}
});
// Any other custom service worker logic can go here.

View File

@ -8,16 +8,14 @@
// resources are updated in the background. // resources are updated in the background.
// To learn more about the benefits of this model and instructions on how to // To learn more about the benefits of this model and instructions on how to
// opt-in, read https://bit.ly/CRA-PWA // opt-in, read https://cra.link/PWA
const isLocalhost = Boolean( const isLocalhost = Boolean(
window.location.hostname === 'localhost' || window.location.hostname === 'localhost' ||
// [::1] is the IPv6 localhost address. // [::1] is the IPv6 localhost address.
window.location.hostname === '[::1]' || window.location.hostname === '[::1]' ||
// 127.0.0.0/8 are considered localhost for IPv4. // 127.0.0.0/8 are considered localhost for IPv4.
window.location.hostname.match( window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/)
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
); );
export function register(config) { export function register(config) {
@ -43,7 +41,7 @@ export function register(config) {
navigator.serviceWorker.ready.then(() => { navigator.serviceWorker.ready.then(() => {
console.log( console.log(
'This web app is being served cache-first by a service ' + 'This web app is being served cache-first by a service ' +
'worker. To learn more, visit https://bit.ly/CRA-PWA' 'worker. To learn more, visit https://cra.link/PWA'
); );
}); });
} else { } else {
@ -57,7 +55,7 @@ export function register(config) {
function registerValidSW(swUrl, config) { function registerValidSW(swUrl, config) {
navigator.serviceWorker navigator.serviceWorker
.register(swUrl) .register(swUrl)
.then(registration => { .then((registration) => {
registration.onupdatefound = () => { registration.onupdatefound = () => {
const installingWorker = registration.installing; const installingWorker = registration.installing;
if (installingWorker == null) { if (installingWorker == null) {
@ -71,7 +69,7 @@ function registerValidSW(swUrl, config) {
// content until all client tabs are closed. // content until all client tabs are closed.
console.log( console.log(
'New content is available and will be used when all ' + 'New content is available and will be used when all ' +
'tabs for this page are closed. See https://bit.ly/CRA-PWA.' 'tabs for this page are closed. See https://cra.link/PWA.'
); );
// Execute callback // Execute callback
@ -93,7 +91,7 @@ function registerValidSW(swUrl, config) {
}; };
}; };
}) })
.catch(error => { .catch((error) => {
console.error('Error during service worker registration:', error); console.error('Error during service worker registration:', error);
}); });
} }
@ -103,7 +101,7 @@ function checkValidServiceWorker(swUrl, config) {
fetch(swUrl, { fetch(swUrl, {
headers: { 'Service-Worker': 'script' }, headers: { 'Service-Worker': 'script' },
}) })
.then(response => { .then((response) => {
// Ensure service worker exists, and that we really are getting a JS file. // Ensure service worker exists, and that we really are getting a JS file.
const contentType = response.headers.get('content-type'); const contentType = response.headers.get('content-type');
if ( if (
@ -111,7 +109,7 @@ function checkValidServiceWorker(swUrl, config) {
(contentType != null && contentType.indexOf('javascript') === -1) (contentType != null && contentType.indexOf('javascript') === -1)
) { ) {
// No service worker found. Probably a different app. Reload the page. // No service worker found. Probably a different app. Reload the page.
navigator.serviceWorker.ready.then(registration => { navigator.serviceWorker.ready.then((registration) => {
registration.unregister().then(() => { registration.unregister().then(() => {
window.location.reload(); window.location.reload();
}); });
@ -122,19 +120,17 @@ function checkValidServiceWorker(swUrl, config) {
} }
}) })
.catch(() => { .catch(() => {
console.log( console.log('No internet connection found. App is running in offline mode.');
'No internet connection found. App is running in offline mode.'
);
}); });
} }
export function unregister() { export function unregister() {
if ('serviceWorker' in navigator) { if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready navigator.serviceWorker.ready
.then(registration => { .then((registration) => {
registration.unregister(); registration.unregister();
}) })
.catch(error => { .catch((error) => {
console.error(error.message); console.error(error.message);
}); });
} }

View File

@ -2,4 +2,4 @@
// allows you to do things like: // allows you to do things like:
// expect(element).toHaveTextContent(/react/i) // expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom // learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom/extend-expect'; import '@testing-library/jest-dom';

2
src/words/verbs.js Normal file

File diff suppressed because one or more lines are too long

View File

@ -17,7 +17,8 @@
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true, "isolatedModules": true,
"noEmit": true, "noEmit": true,
"jsx": "react" "jsx": "react-jsx",
"noFallthroughCasesInSwitch": true
}, },
"include": [ "include": [
"src" "src"

7890
yarn.lock

File diff suppressed because it is too large Load Diff