Compare commits
No commits in common. "master" and "context-store" have entirely different histories.
master
...
context-st
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,6 +1,4 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
build/
|
build/
|
||||||
tmp/
|
tmp/
|
||||||
books/
|
books/
|
||||||
cache/
|
|
||||||
data/
|
|
1
data/gutenberg.json
Normal file
1
data/gutenberg.json
Normal file
File diff suppressed because one or more lines are too long
1
data/stats_language.json
Normal file
1
data/stats_language.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"en": 48484, "la": 121, "es": 628, "de": 1751, "fr": 2959, "it": 752, "ja": 22, "zh": 441, "sv": 193, "da": 68, "cy": 13, "bg": 6, "pt": 552, "nl": 800, "el": 220, "he": 6, "ru": 9, "hu": 183, "ko": 1, "pl": 31, "fi": 1994, "eo": 118, "enm": 6, "sa": 1, "ang": 4, "ale": 1, "yi": 1, "lt": 1, "nai": 3, "sr": 4, "no": 19, "ca": 33, "ro": 2, "nah": 3, "kha": 1, "cs": 10, "tl": 60, "is": 7, "myn": 2, "ilo": 3, "ia": 1, "ga": 2, "fur": 7, "af": 4, "kld": 1, "oc": 1, "nap": 1, "fy": 2, "ceb": 3, "gl": 2, "mi": 2, "nav": 3, "br": 1, "arp": 2, "iu": 1, "bgs": 1, "csb": 1, "gla": 2, "rmr": 1, "sl": 1, "te": 6, "oji": 1, "grc": 3, "ar": 1, "et": 1, "fa": 1, "brx": 2}
|
1
data/stats_rights.json
Normal file
1
data/stats_rights.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"Public domain in the USA.": 58354, "Copyrighted. Read the copyright notice inside this book for details.": 955, "None": 69}
|
1
data/stats_subject.json
Normal file
1
data/stats_subject.json
Normal file
File diff suppressed because one or more lines are too long
@ -1,21 +0,0 @@
|
|||||||
const path = require('path')
|
|
||||||
const Axios = require('axios')
|
|
||||||
const { readFile, cacheDir, mkdirAndWriteFile } = require('../paths')
|
|
||||||
|
|
||||||
async function getMetadata() {
|
|
||||||
const cacheFile = path.join(cacheDir, 'gutenberg-metadata.json')
|
|
||||||
try {
|
|
||||||
const fileContents = await readFile(cacheFile)
|
|
||||||
return JSON.parse(fileContents)
|
|
||||||
} catch (err) {}
|
|
||||||
|
|
||||||
console.log('Downloading metadata from GitHub')
|
|
||||||
const metadata = await Axios.get(
|
|
||||||
'https://hugovk.github.io/gutenberg-metadata/gutenberg-metadata.json'
|
|
||||||
).then(res => res.data)
|
|
||||||
|
|
||||||
await mkdirAndWriteFile(cacheFile, JSON.stringify(metadata))
|
|
||||||
return metadata
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { getMetadata }
|
|
@ -1,37 +0,0 @@
|
|||||||
const path = require('path')
|
|
||||||
|
|
||||||
const { getMetadata } = require('./getMetadata')
|
|
||||||
const { parseMetadata } = require('./parseMetadata')
|
|
||||||
const { mkdirAndWriteFile, dataDir } = require('../paths')
|
|
||||||
|
|
||||||
async function main() {
|
|
||||||
const parsedData = [...parseMetadata(await getMetadata())]
|
|
||||||
const tsvData = parsedData.map(entryToRow)
|
|
||||||
|
|
||||||
mkdirAndWriteFile(
|
|
||||||
path.join(dataDir, 'PG-meta.json'),
|
|
||||||
JSON.stringify(parsedData, undefined, 2)
|
|
||||||
)
|
|
||||||
mkdirAndWriteFile(path.join(dataDir, 'PG-meta.tsv'), formatTsv(tsvData))
|
|
||||||
}
|
|
||||||
|
|
||||||
function entryToRow(entry) {
|
|
||||||
return [
|
|
||||||
entry.id,
|
|
||||||
(entry.title[0] || '').replace(/[\r\n]+/gm, ''),
|
|
||||||
entry.author.join('|'),
|
|
||||||
entry.language.join('|'),
|
|
||||||
entry.subject.join('|'),
|
|
||||||
entry.textUris.join('|'),
|
|
||||||
entry.pictures.join('|')
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatTsv(array2D) {
|
|
||||||
return array2D
|
|
||||||
.map(row => row.join('\t'))
|
|
||||||
.join('\n')
|
|
||||||
.replace(/"/gm, '\\"')
|
|
||||||
}
|
|
||||||
|
|
||||||
main()
|
|
@ -1,22 +0,0 @@
|
|||||||
function* parseMetadata(metadata) {
|
|
||||||
for (const [key, entry] of Object.entries(metadata)) {
|
|
||||||
entry.textUris = entry.formaturi
|
|
||||||
.filter(uri => extensionIn(uri, ['.txt', '.utf-8']))
|
|
||||||
.map(stripPGHost)
|
|
||||||
entry.pictures = entry.formaturi
|
|
||||||
.filter(uri => extensionIn(uri, ['.jpg', 'png']))
|
|
||||||
.map(stripPGHost)
|
|
||||||
delete entry.formaturi
|
|
||||||
entry.id = key
|
|
||||||
yield entry
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function extensionIn(path, endings) {
|
|
||||||
return endings.some(ending => path.endsWith(ending))
|
|
||||||
}
|
|
||||||
function stripPGHost(uri) {
|
|
||||||
return uri.replace('http://www.gutenberg.org', '')
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { parseMetadata }
|
|
@ -1,31 +0,0 @@
|
|||||||
const fs = require('fs')
|
|
||||||
const util = require('util')
|
|
||||||
const path = require('path')
|
|
||||||
|
|
||||||
const projectRoot = path.join(__dirname, '..')
|
|
||||||
const cacheDir = path.join(projectRoot, 'cache')
|
|
||||||
const dataDir = path.join(projectRoot, 'data')
|
|
||||||
|
|
||||||
const readFile = util.promisify(fs.readFile)
|
|
||||||
const writeFile = util.promisify(fs.writeFile)
|
|
||||||
const mkdir = util.promisify(fs.mkdir)
|
|
||||||
|
|
||||||
async function mkdirAndWriteFile(filepath, data) {
|
|
||||||
try {
|
|
||||||
// create directory
|
|
||||||
await mkdir(path.dirname(filepath))
|
|
||||||
} catch (err) {
|
|
||||||
// ignore "directory exists errors"
|
|
||||||
if (err.code !== 'EEXIST') throw err
|
|
||||||
}
|
|
||||||
return writeFile(filepath, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
projectRoot,
|
|
||||||
cacheDir,
|
|
||||||
dataDir,
|
|
||||||
readFile,
|
|
||||||
writeFile,
|
|
||||||
mkdirAndWriteFile
|
|
||||||
}
|
|
@ -17,5 +17,4 @@ header {
|
|||||||
|
|
||||||
footer {
|
footer {
|
||||||
background-color: antiquewhite;
|
background-color: antiquewhite;
|
||||||
margin-top: 2em;
|
|
||||||
}
|
}
|
||||||
|
18
src/App.js
18
src/App.js
@ -13,8 +13,6 @@ import { Options } from 'components/Options'
|
|||||||
import { TextInput } from 'components/TextInput'
|
import { TextInput } from 'components/TextInput'
|
||||||
import { TextOutput } from 'components/TextOutput'
|
import { TextOutput } from 'components/TextOutput'
|
||||||
import { TotalTime } from 'components/TotalTime'
|
import { TotalTime } from 'components/TotalTime'
|
||||||
import { Div } from 'styles/Div'
|
|
||||||
import { BookSelect } from 'components/BookSelect'
|
|
||||||
|
|
||||||
export const App = () => {
|
export const App = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
@ -34,25 +32,21 @@ export const App = () => {
|
|||||||
<main>
|
<main>
|
||||||
<Container>
|
<Container>
|
||||||
<h2>Widget</h2>
|
<h2>Widget</h2>
|
||||||
<Div maxWidth="600px" margin="0 auto">
|
<RsvpWidget />
|
||||||
<RsvpWidget />
|
<Flex>
|
||||||
</Div>
|
<FlexMain padding="10px">
|
||||||
<h2>Text Cursor</h2>
|
|
||||||
<TextOutput />
|
|
||||||
<Flex flexWrap="wrap">
|
|
||||||
<FlexMain padding="10px" minWidth="300px">
|
|
||||||
<h2>Options</h2>
|
<h2>Options</h2>
|
||||||
<Options />
|
<Options />
|
||||||
</FlexMain>
|
</FlexMain>
|
||||||
<FlexMain padding="10px" minWidth="300px">
|
<FlexMain>
|
||||||
<h2>Text input</h2>
|
<h2>Text input</h2>
|
||||||
<TextInput />
|
<TextInput />
|
||||||
</FlexMain>
|
</FlexMain>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
<h2>Text Output</h2>
|
||||||
|
<TextOutput />
|
||||||
<h2>Time needed</h2>
|
<h2>Time needed</h2>
|
||||||
<TotalTime />
|
<TotalTime />
|
||||||
<h2>Select from Project Gutenberg Top 100</h2>
|
|
||||||
<BookSelect />
|
|
||||||
</Container>
|
</Container>
|
||||||
</main>
|
</main>
|
||||||
<footer>
|
<footer>
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
import React, { useState, useCallback } from 'react'
|
|
||||||
|
|
||||||
import bookIndex from '../../books/index.json'
|
|
||||||
import { Flex, FlexMain } from 'styles/Flex.js'
|
|
||||||
import Axios from 'axios'
|
|
||||||
import { useDispatch } from 'store'
|
|
||||||
|
|
||||||
const bookList = Object.entries(bookIndex).sort()
|
|
||||||
|
|
||||||
export const BookSelect = () => {
|
|
||||||
const [bookId, setBookId] = useState(bookList[0][0])
|
|
||||||
const { setText } = useDispatch()
|
|
||||||
|
|
||||||
const loadBook = useCallback(() => {
|
|
||||||
Axios.get(`/books/${bookId}.txt`)
|
|
||||||
.then(res => res.data)
|
|
||||||
.then(setText)
|
|
||||||
}, [bookId, setText])
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Flex>
|
|
||||||
<FlexMain>
|
|
||||||
<select
|
|
||||||
style={{ width: '100%' }}
|
|
||||||
value={bookId}
|
|
||||||
onChange={evt => setBookId(evt.target.value)}
|
|
||||||
>
|
|
||||||
{/* <option value={0}>Select from Project Gutenberg Top 100</option> */}
|
|
||||||
{bookList.map(([id, title]) => (
|
|
||||||
<option key={id} value={id}>
|
|
||||||
{title}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</select>
|
|
||||||
</FlexMain>
|
|
||||||
<button onClick={loadBook}>Load</button>
|
|
||||||
</Flex>
|
|
||||||
<span>
|
|
||||||
<a href="https://www.gutenberg.org/browse/scores/top">Source</a>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
@ -32,8 +32,8 @@ export const SearchBar = () => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const handleSelect = async idx => {
|
const handleSelect = async idx => {
|
||||||
const { textUris, language } = results[idx]
|
const { id, language } = results[idx]
|
||||||
setText(await getBook(textUris[0]))
|
setText(await getBook(id))
|
||||||
setLang(language[0])
|
setLang(language[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import Axios from 'axios'
|
|||||||
export async function search(searchTerm, maxResults = Infinity) {
|
export async function search(searchTerm, maxResults = Infinity) {
|
||||||
const regex = new RegExp(searchTerm, 'i')
|
const regex = new RegExp(searchTerm, 'i')
|
||||||
const result = []
|
const result = []
|
||||||
const data = await import('../../data/PG-meta.json').then(
|
const data = await import('../../data/gutenberg.json').then(
|
||||||
module => module.default
|
module => module.default
|
||||||
)
|
)
|
||||||
for (let entry of data) {
|
for (let entry of data) {
|
||||||
@ -16,8 +16,8 @@ export async function search(searchTerm, maxResults = Infinity) {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getBook(textUri) {
|
export async function getBook(bookId) {
|
||||||
const url = `https://aleph.gutenberg.org${textUri}`
|
const url = `https://gutenberg.muperfredi.de/texts/${bookId}/stripped-body`
|
||||||
const text = await Axios.get(url).then(res => res.data.body)
|
const text = await Axios.get(url).then(res => res.data.body)
|
||||||
return text
|
return text
|
||||||
}
|
}
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
|
|
||||||
/** A generic div. Mainly for development. Try to use as sparse as possible */
|
|
||||||
export const Div = ({ children, ...rest }) => {
|
|
||||||
return <div style={rest}>{children}</div>
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user