diff --git a/web/package.json b/web/package.json
index 89235ac..fc699f1 100644
--- a/web/package.json
+++ b/web/package.json
@@ -15,6 +15,7 @@
"i18next-browser-languagedetector": "^3.0.1",
"i18next-xhr-backend": "^3.0.0",
"isomorphic-unfetch": "^3.0.0",
+ "prop-types": "^15.7.2",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-ga": "^2.6.0",
diff --git a/web/public/locales/en/translation.json b/web/public/locales/en/translation.json
index 7ed6ad5..f5df2ac 100644
--- a/web/public/locales/en/translation.json
+++ b/web/public/locales/en/translation.json
@@ -15,5 +15,5 @@
"twitter": "Twitter",
"slack": "Slack"
},
- "try": "suggestion"
+ "try": "How about"
}
diff --git a/web/src/App.js b/web/src/App.js
index d5e4950..a22758c 100644
--- a/web/src/App.js
+++ b/web/src/App.js
@@ -15,6 +15,7 @@ import PypiCard from './components/cards/PypiCard'
import S3Card from './components/cards/S3Card'
import CratesioCard from './components/cards/CratesioCard'
import RubyGemsCard from './components/cards/RubyGemsCard'
+
import { EventReporter } from './components/Analytics'
import Welcome from './components/Welcome'
import Footer from './components/Footer'
@@ -34,7 +35,7 @@ export default function App() {
const queryGiven = query && query.length > 0
useEffect(() => {
- const modifiedValue = inputValue.replace(/[\s@\+!#$%^&*()\[\]]/g, '')
+ const modifiedValue = inputValue.replace(/[\s@+!#$%^&*()[\]]/g, '')
setQuery(modifiedValue)
}, [inputValue, setQuery])
diff --git a/web/src/components/Suggestion.js b/web/src/components/Suggestion.js
index cd0eaed..9973ece 100644
--- a/web/src/components/Suggestion.js
+++ b/web/src/components/Suggestion.js
@@ -1,26 +1,85 @@
-import React from 'react'
+import React, { useEffect, useState } from 'react'
import styled from 'styled-components'
import { useTranslation } from 'react-i18next'
+import fetch from 'isomorphic-unfetch'
import { capitalize } from '../util/text'
+function modifyWord(word) {
+ const modifiers = [
+ (word) => `${capitalize(word)}ify`,
+ (word) => `lib${lower(word)}`,
+ (word) => `Omni${capitalize(word)}`,
+ (word) => `${capitalize(word)}Lab`,
+ (word) => `${capitalize(word)}Kit`,
+ (word) => `Open${capitalize(word)}`,
+ (word) => `${capitalize(word)}box`,
+ (word) => `Insta${lower(word)}`,
+ (word) => `${capitalize(word)}Hub`,
+ (word) => `Semantic ${capitalize(word)}`,
+ (word) => `Cloud${capitalize(word)}`,
+ (word) => `Deep${capitalize(word)}`,
+ (word) => `${capitalize(word)}gram`,
+ (word) => `${capitalize(word)}base`,
+ (word) => `${capitalize(word)}API`,
+ (word) => `${capitalize(word)}note`,
+ (word) => `In${capitalize(word)}`,
+ (word) => `Under${lower(word)}`,
+ (word) => `Uni${lower(word)}`,
+ (word) => `${capitalize(word)}mind`,
+ ]
+ return modifiers[Math.floor(Math.random() * modifiers.length)](word)
+}
+
+function lower(word) {
+ return word.toLowerCase()
+}
+
+async function findSynonyms(word, maximum = 10) {
+ try {
+ const response = await fetch(
+ `https://translate.googleapis.com/translate_a/single?client=gtx&sl=auto&dt=ss&ie=UTF-8&oe=UTF-8&dj=1&q=${encodeURIComponent(
+ word
+ )}`
+ )
+ const json = await response.json()
+ const synonyms = json.synsets.reduce(
+ (sum, synset) =>
+ (sum = [...sum, ...synset.entry.map((e) => e.synonym[0])]),
+ []
+ )
+ let bestWords = [
+ ...new Set(
+ synonyms
+ .filter((word) => !word.match(/[\s-]/))
+ .sort(() => Math.random() - 0.5)
+ .slice(0, maximum)
+ ),
+ ]
+ const deficit = maximum - bestWords.length
+ if (deficit > 0) {
+ bestWords = [...bestWords, ...Array(deficit).fill(word)]
+ }
+ return bestWords
+ } catch (err) {
+ return Array(maximum).fill(word)
+ }
+}
+
export default function Suggestion({ query, onSubmit }) {
const { t } = useTranslation()
- const capital = capitalize(query)
- const lower = query.toLowerCase()
+ const [synonyms, setSynonyms] = useState([])
- const suggestions = [
- `${lower}ify`,
- `insta${lower}`,
- `lib${lower}`,
- `omni${lower}`,
- `${capital}Lab`,
- `${capital}Kit`,
- `Open${capital}`,
- `${capital}box`,
- `${lower}hub`,
- ]
- .sort(() => Math.random() - 0.5)
- .slice(0, 3)
+ useEffect(() => {
+ const fn = async () => {
+ if (query && query.length > 0) {
+ const synonyms = (await findSynonyms(query, 3)).map((synonym) =>
+ modifyWord(synonym)
+ )
+ setSynonyms(synonyms)
+ }
+ }
+ fn()
+ }, [query])
function applyQuery(name) {
onSubmit(name)
@@ -30,11 +89,12 @@ export default function Suggestion({ query, onSubmit }) {
{t('try')}
- {suggestions.map((name) => (
- - applyQuery(name)}>
- {name}
-
- ))}
+ {synonyms &&
+ synonyms.map((name) => (
+ - applyQuery(name)}>
+ {name}
+
+ ))}
)
@@ -52,9 +112,6 @@ const Container = styled.div`
const Title = styled.div`
margin-top: 15px;
- border: 1px solid black;
- padding: 4px 12px;
- border-radius: 20px;
font-size: 0.6em;
`
@@ -63,10 +120,13 @@ const Items = styled.div`
margin-left: 8px;
display: flex;
flex-direction: row;
+ flex-wrap: wrap;
+ justify-content: center;
`
const Item = styled.div`
- margin-right: 8px;
+ margin-right: 10px;
cursor: pointer;
font-weight: bold;
+ font-family: monospace;
`
diff --git a/web/src/components/cards/GithubCard.js b/web/src/components/cards/GithubCard.js
index 893e40d..7dedda7 100644
--- a/web/src/components/cards/GithubCard.js
+++ b/web/src/components/cards/GithubCard.js
@@ -3,7 +3,6 @@ import { useTranslation } from 'react-i18next'
import { FaGithub } from 'react-icons/fa'
import { Card } from '../Cards'
import { DedicatedAvailability } from '../Availability'
-import { capitalize } from '../../util/text'
export default function GithubCard({ name }) {
const { t } = useTranslation()
@@ -17,7 +16,7 @@ export default function GithubCard({ name }) {
`${lowerCase}hq`,
`${lowerCase}-team`,
`${lowerCase}-org`,
- `${capitalize(name)}-js`,
+ `${lowerCase}-js`,
]}>
{(name) => (