mirror of
https://github.com/uetchy/namae.git
synced 2025-03-17 04:30:31 +09:00
feat: smart suggestion
This commit is contained in:
parent
f4b6140aa6
commit
3982fb5cc4
@ -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",
|
||||
|
@ -15,5 +15,5 @@
|
||||
"twitter": "Twitter",
|
||||
"slack": "Slack"
|
||||
},
|
||||
"try": "suggestion"
|
||||
"try": "How about"
|
||||
}
|
||||
|
@ -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])
|
||||
|
||||
|
@ -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 }) {
|
||||
<Container>
|
||||
<Title>{t('try')}</Title>
|
||||
<Items>
|
||||
{suggestions.map((name) => (
|
||||
<Item key={name} onClick={() => applyQuery(name)}>
|
||||
{name}
|
||||
</Item>
|
||||
))}
|
||||
{synonyms &&
|
||||
synonyms.map((name) => (
|
||||
<Item key={name} onClick={() => applyQuery(name)}>
|
||||
{name}
|
||||
</Item>
|
||||
))}
|
||||
</Items>
|
||||
</Container>
|
||||
)
|
||||
@ -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;
|
||||
`
|
||||
|
@ -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) => (
|
||||
<DedicatedAvailability
|
||||
|
@ -8291,7 +8291,7 @@ prompts@^2.0.1:
|
||||
kleur "^3.0.2"
|
||||
sisteransi "^1.0.0"
|
||||
|
||||
prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.6.2:
|
||||
prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.6.2, prop-types@^15.7.2:
|
||||
version "15.7.2"
|
||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
|
||||
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
|
||||
|
Loading…
x
Reference in New Issue
Block a user