<commit_before>import React from 'react';
import R from 'ramda';
import debounce from 'lodash.debounce';

import normalizeWordData from '../../core/normalizeWordData/normalizeWordData';
import composeWordData from '../../core/composeWordData/composeWordData';
import makeCard from '../../core/makeCard/makeCard'

import splitByWord from '../../utils/splitByWord/splitByWord';
import maybePluralize from '../../utils/maybePluralize/maybePluralize';
import composeQuery from '../../utils/composeQuery/composeQuery';

import Header from '../Header/Header';
import ImportOptions from '../ImportOptions/ImportOptions';
import DownloadButton from '../DownloadButton/DownloadButton';
import ResultCards from '../ResultCards/ResultCards';
import UserWords from '../UserWords/UserWords';

import './App.css';

const wordToData = R.memoize(async word => {
	const query = composeQuery(word);
	const markup = await fetch(query).then(response => response.text());
	const wordData = composeWordData(markup);

	return wordData;
})

const sanitizeForFilename = R.pipe(
	R.replace(/ /g, ''),
	R.replace(/,/g, '_')
);

export default class App extends React.Component {
	state = {
		inputValue: '',
		wordsDataArr: [],
		showImportOptions: false
	}

	handleInputChange = async (event) => {
		const inputValue = event.target.value;

		this.setState({
			inputValue
		})

		this.debouncedComposeCards();
	}

	debouncedComposeCards = debounce(
		async () => {
			const words = splitByWord(this.state.inputValue);

			let wordsDataArr = [];
			let i = 0;

			for (let word of words) {
				const wordData = await wordToData(word)
				wordsDataArr[i] = wordData;

				this.setState({
					wordsDataArr
				});

				i++;
			}
		}, 500
	)

	handleDownload = () => {
		this.setState({
			showImportOptions: true
		})
	}

	render() {
		const cardsArr = R.pipe(
			R.map(normalizeWordData),
			R.flatten,
			R.reject(R.isEmpty),
			R.map(makeCard)
		)(this.state.wordsDataArr);

		const cards = R.join('\n')(cardsArr);

		const wordsTotalNumber = this.state.wordsDataArr.length
		const cardsTotalNumber = cardsArr.length;

		const wordsTotal = maybePluralize(wordsTotalNumber, 'word');
		const cardsTotal = maybePluralize(cardsTotalNumber, 'card');

		const totals = `${wordsTotal}, ${cardsTotal}`;

		const date = new Date().toISOString().slice(0, 10);

		return (
			<div className='App'>
				<Header />

				<UserWords
					value={this.state.inputValue}
					onChange={this.handleInputChange}
				/>

				<ResultCards
					value={cards}
				/><commit_msg>feature: send all requests in parallel (fix #52)<commit_after>import React from 'react';
import R from 'ramda';
import debounce from 'lodash.debounce';

import normalizeWordData from '../../core/normalizeWordData/normalizeWordData';
import composeWordData from '../../core/composeWordData/composeWordData';
import makeCard from '../../core/makeCard/makeCard'

import splitByWord from '../../utils/splitByWord/splitByWord';
import maybePluralize from '../../utils/maybePluralize/maybePluralize';
import composeQuery from '../../utils/composeQuery/composeQuery';

import Header from '../Header/Header';
import ImportOptions from '../ImportOptions/ImportOptions';
import DownloadButton from '../DownloadButton/DownloadButton';
import ResultCards from '../ResultCards/ResultCards';
import UserWords from '../UserWords/UserWords';

import './App.css';

const wordToData = R.memoize(async word => {
	const query = composeQuery(word);
	const markup = await fetch(query).then(response => response.text());
	const wordData = composeWordData(markup);

	return wordData;
})

const sanitizeForFilename = R.pipe(
	R.replace(/ /g, ''),
	R.replace(/,/g, '_')
);

export default class App extends React.Component {
	state = {
		inputValue: '',
		wordsDataArr: [],
		showImportOptions: false
	}

	handleInputChange = async (event) => {
		const inputValue = event.target.value;

		this.setState({
			inputValue
		})

		this.debouncedComposeCards();
	}

	debouncedComposeCards = debounce(
		() => {
			const words = splitByWord(this.state.inputValue);
			words
				.map(wordToData)
				.forEach(async (request, i) => {
					const wordData = await request;

					this.setState(prevState => {
						const newWordsDataArr = [...prevState.wordsDataArr];
						newWordsDataArr[i] = wordData;
						return {
							wordsDataArr: newWordsDataArr
						}
					})
				});
		}, 500
	)

	handleDownload = () => {
		this.setState({
			showImportOptions: true
		})
	}

	render() {
		const cardsArr = R.pipe(
			R.filter(Boolean), // reject items from wordsDataArr, which didn't recieve response yet
			R.map(normalizeWordData),
			R.flatten,
			R.reject(R.isEmpty),
			R.map(makeCard)
		)(this.state.wordsDataArr);

		const cards = R.join('\n')(cardsArr);

		const wordsTotalNumber = this.state.wordsDataArr.length
		const cardsTotalNumber = cardsArr.length;

		const wordsTotal = maybePluralize(wordsTotalNumber, 'word');
		const cardsTotal = maybePluralize(cardsTotalNumber, 'card');

		const totals = `${wordsTotal}, ${cardsTotal}`;

		const date = new Date().toISOString().slice(0, 10);

		return (
			<div className='App'>
				<Header />

				<UserWords
					value={this.state.inputValue}
					onChange={this.handleInputChange}
				/>

				<ResultCards
					value={cards}
				/>
{'fraction_non_alphanumeric': 0.1431818181818182, 'fraction_numerical': 0.002840909090909091, 'mean_word_length': 3.7965485921889193, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4301127', 'n_tokens_mistral': 1902, 'n_tokens_neox': 1640, 'n_words': 365}