mirror of
https://github.com/uetchy/namae.git
synced 2025-08-20 18:08:11 +09:00
style: prettier
This commit is contained in:
@@ -1,18 +1,18 @@
|
||||
import ReactGA from 'react-ga'
|
||||
import * as Sentry from '@sentry/browser'
|
||||
import { History } from 'history'
|
||||
import ReactGA from 'react-ga';
|
||||
import * as Sentry from '@sentry/browser';
|
||||
import { History } from 'history';
|
||||
|
||||
const isProduction = process.env.NODE_ENV !== 'development'
|
||||
const isProduction = process.env.NODE_ENV !== 'development';
|
||||
|
||||
export function wrapHistoryWithGA(history: History) {
|
||||
if (isProduction) {
|
||||
ReactGA.initialize('UA-28919359-15')
|
||||
ReactGA.pageview(window.location.pathname + window.location.search)
|
||||
ReactGA.initialize('UA-28919359-15');
|
||||
ReactGA.pageview(window.location.pathname + window.location.search);
|
||||
history.listen((location) => {
|
||||
ReactGA.pageview(location.pathname + location.search)
|
||||
})
|
||||
ReactGA.pageview(location.pathname + location.search);
|
||||
});
|
||||
}
|
||||
return history
|
||||
return history;
|
||||
}
|
||||
|
||||
export function trackEvent({
|
||||
@@ -21,10 +21,10 @@ export function trackEvent({
|
||||
label = undefined,
|
||||
value = undefined,
|
||||
}: {
|
||||
category: string
|
||||
action: string
|
||||
label?: string
|
||||
value?: number
|
||||
category: string;
|
||||
action: string;
|
||||
label?: string;
|
||||
value?: number;
|
||||
}) {
|
||||
if (isProduction) {
|
||||
ReactGA.event({
|
||||
@@ -32,35 +32,35 @@ export function trackEvent({
|
||||
action,
|
||||
label,
|
||||
value,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function sendQueryEvent(query: string): void {
|
||||
trackEvent({ category: 'Search', action: 'Invoke New Search', label: query })
|
||||
trackEvent({ category: 'Search', action: 'Invoke New Search', label: query });
|
||||
}
|
||||
|
||||
export function sendGettingStartedEvent(): void {
|
||||
trackEvent({ category: 'Search', action: 'Getting Started' })
|
||||
trackEvent({ category: 'Search', action: 'Getting Started' });
|
||||
}
|
||||
|
||||
export function sendExpandEvent(): void {
|
||||
trackEvent({ category: 'Result', action: 'Expand Card' })
|
||||
trackEvent({ category: 'Result', action: 'Expand Card' });
|
||||
}
|
||||
|
||||
export function sendAcceptSuggestionEvent(): void {
|
||||
trackEvent({ category: 'Suggestion', action: 'Accept' })
|
||||
trackEvent({ category: 'Suggestion', action: 'Accept' });
|
||||
}
|
||||
|
||||
export function sendShuffleSuggestionEvent(): void {
|
||||
trackEvent({ category: 'Suggestion', action: 'Shuffle' })
|
||||
trackEvent({ category: 'Suggestion', action: 'Shuffle' });
|
||||
}
|
||||
|
||||
export function initSentry(): void {
|
||||
if (isProduction) {
|
||||
Sentry.init({
|
||||
dsn: 'https://7ab2df74aead499b950ebef190cc40b7@sentry.io/1759299',
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,16 +68,16 @@ export function sendError(
|
||||
error: Error,
|
||||
errorInfo: {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
[key: string]: any
|
||||
[key: string]: any;
|
||||
}
|
||||
): Promise<string> {
|
||||
return new Promise((resolve) => {
|
||||
if (isProduction) {
|
||||
Sentry.withScope((scope) => {
|
||||
scope.setExtras(errorInfo)
|
||||
const eventId = Sentry.captureException(error)
|
||||
resolve(eventId)
|
||||
})
|
||||
scope.setExtras(errorInfo);
|
||||
const eventId = Sentry.captureException(error);
|
||||
resolve(eventId);
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
@@ -1,25 +1,25 @@
|
||||
export function shuffleArray<T>(array: T[]): T[] {
|
||||
for (let i = array.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1))
|
||||
const temp = array[i]
|
||||
array[i] = array[j]
|
||||
array[j] = temp
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
const temp = array[i];
|
||||
array[i] = array[j];
|
||||
array[j] = temp;
|
||||
}
|
||||
return array
|
||||
return array;
|
||||
}
|
||||
|
||||
export function sampleFromArray<T>(array: T[], maximum: number): T[] {
|
||||
return shuffleArray(array).slice(0, maximum)
|
||||
return shuffleArray(array).slice(0, maximum);
|
||||
}
|
||||
|
||||
export function fillArray<T>(array: T[], filler: string, maximum: number): T[] {
|
||||
const deficit = maximum - array.length
|
||||
const deficit = maximum - array.length;
|
||||
if (deficit > 0) {
|
||||
array = [...array, ...Array(deficit).fill(filler)]
|
||||
array = [...array, ...Array(deficit).fill(filler)];
|
||||
}
|
||||
return array
|
||||
return array;
|
||||
}
|
||||
|
||||
export function compose<T>(arg: T, ...fn: ((arg: T) => T)[]): T {
|
||||
return fn.reduce((arg, f) => f(arg), arg)
|
||||
return fn.reduce((arg, f) => f(arg), arg);
|
||||
}
|
||||
|
@@ -1,14 +1,14 @@
|
||||
interface CrispWindow extends Window {
|
||||
$crisp: unknown[]
|
||||
CRISP_WEBSITE_ID: string
|
||||
$crisp: unknown[];
|
||||
CRISP_WEBSITE_ID: string;
|
||||
}
|
||||
declare let window: CrispWindow
|
||||
declare let window: CrispWindow;
|
||||
|
||||
export function initCrisp(): void {
|
||||
window.$crisp = []
|
||||
window.CRISP_WEBSITE_ID = '92b2e096-6892-47dc-bf4a-057bad52d82e'
|
||||
const s = document.createElement('script')
|
||||
s.src = 'https://client.crisp.chat/l.js'
|
||||
s.async = true
|
||||
document.getElementsByTagName('head')[0].appendChild(s)
|
||||
window.$crisp = [];
|
||||
window.CRISP_WEBSITE_ID = '92b2e096-6892-47dc-bf4a-057bad52d82e';
|
||||
const s = document.createElement('script');
|
||||
s.src = 'https://client.crisp.chat/l.js';
|
||||
s.async = true;
|
||||
document.getElementsByTagName('head')[0].appendChild(s);
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { keyframes } from 'styled-components'
|
||||
import { keyframes } from 'styled-components';
|
||||
|
||||
export const mobile = '@media screen and (max-width: 800px)'
|
||||
export const tablet = '@media screen and (max-width: 1200px)'
|
||||
export const mobile = '@media screen and (max-width: 800px)';
|
||||
export const tablet = '@media screen and (max-width: 1200px)';
|
||||
|
||||
export const slideUp = keyframes`
|
||||
from {
|
||||
@@ -10,4 +10,4 @@ from {
|
||||
to {
|
||||
transform: translateY(0) skewY(0);
|
||||
}
|
||||
`
|
||||
`;
|
||||
|
@@ -1,22 +1,22 @@
|
||||
import { render, waitFor } from '@testing-library/react'
|
||||
import 'mutationobserver-shim'
|
||||
import React from 'react'
|
||||
import { useDeferredState } from './hooks'
|
||||
import { render, waitFor } from '@testing-library/react';
|
||||
import 'mutationobserver-shim';
|
||||
import React from 'react';
|
||||
import { useDeferredState } from './hooks';
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [value, setValue] = useDeferredState(500, 0)
|
||||
const [value, setValue] = useDeferredState(500, 0);
|
||||
React.useEffect(() => {
|
||||
setValue(1)
|
||||
setValue(2)
|
||||
setValue(3)
|
||||
}, [setValue])
|
||||
return <div data-testid="root">{value}</div>
|
||||
}
|
||||
setValue(1);
|
||||
setValue(2);
|
||||
setValue(3);
|
||||
}, [setValue]);
|
||||
return <div data-testid="root">{value}</div>;
|
||||
};
|
||||
|
||||
it('provoke state flow after certain time passed', async () => {
|
||||
const { getByTestId } = render(<App />)
|
||||
expect(getByTestId('root').textContent).toBe('0')
|
||||
const { getByTestId } = render(<App />);
|
||||
expect(getByTestId('root').textContent).toBe('0');
|
||||
await waitFor(() => {
|
||||
expect(getByTestId('root').textContent).toBe('3')
|
||||
})
|
||||
})
|
||||
expect(getByTestId('root').textContent).toBe('3');
|
||||
});
|
||||
});
|
||||
|
@@ -1,24 +1,24 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Helmet } from 'react-helmet';
|
||||
|
||||
export function useDeferredState<T>(
|
||||
duration = 1000,
|
||||
initialValue: T
|
||||
): [T, React.Dispatch<React.SetStateAction<T>>] {
|
||||
const [response, setResponse] = useState(initialValue)
|
||||
const [innerValue, setInnerValue] = useState(initialValue)
|
||||
const [response, setResponse] = useState(initialValue);
|
||||
const [innerValue, setInnerValue] = useState(initialValue);
|
||||
|
||||
useEffect(() => {
|
||||
const fn = setTimeout(() => {
|
||||
setResponse(innerValue)
|
||||
}, duration)
|
||||
setResponse(innerValue);
|
||||
}, duration);
|
||||
|
||||
return (): void => {
|
||||
clearTimeout(fn)
|
||||
}
|
||||
}, [duration, innerValue])
|
||||
clearTimeout(fn);
|
||||
};
|
||||
}, [duration, innerValue]);
|
||||
|
||||
return [response, setInnerValue]
|
||||
return [response, setInnerValue];
|
||||
}
|
||||
|
||||
export function useOpenSearch(xmlPath: string) {
|
||||
@@ -31,5 +31,5 @@ export function useOpenSearch(xmlPath: string) {
|
||||
href={xmlPath}
|
||||
/>
|
||||
</Helmet>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@@ -1,11 +1,11 @@
|
||||
import i18n from 'i18next'
|
||||
import Backend from 'i18next-chained-backend'
|
||||
import LocalStorageBackend from 'i18next-localstorage-backend'
|
||||
import XHR from 'i18next-xhr-backend'
|
||||
import LanguageDetector from 'i18next-browser-languagedetector'
|
||||
import { initReactI18next } from 'react-i18next'
|
||||
import i18n from 'i18next';
|
||||
import Backend from 'i18next-chained-backend';
|
||||
import LocalStorageBackend from 'i18next-localstorage-backend';
|
||||
import XHR from 'i18next-xhr-backend';
|
||||
import LanguageDetector from 'i18next-browser-languagedetector';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
|
||||
const TRANSLATION_VERSION = '3'
|
||||
const TRANSLATION_VERSION = '3';
|
||||
|
||||
i18n
|
||||
.use(Backend)
|
||||
@@ -32,6 +32,6 @@ i18n
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
export default i18n
|
||||
export default i18n;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { isStandalone } from './pwa'
|
||||
import { isStandalone } from './pwa';
|
||||
|
||||
it('recognize standalone mode', () => {
|
||||
expect(isStandalone()).toEqual(false)
|
||||
})
|
||||
expect(isStandalone()).toEqual(false);
|
||||
});
|
||||
|
@@ -1,8 +1,8 @@
|
||||
interface CustomNavigator extends Navigator {
|
||||
standalone?: boolean
|
||||
standalone?: boolean;
|
||||
}
|
||||
|
||||
export function isStandalone(): boolean {
|
||||
const navigator: CustomNavigator = window.navigator
|
||||
return 'standalone' in navigator && navigator.standalone === true
|
||||
const navigator: CustomNavigator = window.navigator;
|
||||
return 'standalone' in navigator && navigator.standalone === true;
|
||||
}
|
||||
|
@@ -1,10 +1,10 @@
|
||||
import React, { Suspense } from 'react'
|
||||
import styled from 'styled-components'
|
||||
import BarLoader from 'react-spinners/BarLoader'
|
||||
import React, { Suspense } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import BarLoader from 'react-spinners/BarLoader';
|
||||
|
||||
export const FullScreenSuspense: React.FC = ({ children }) => {
|
||||
return <Suspense fallback={<Fallback />}>{children}</Suspense>
|
||||
}
|
||||
return <Suspense fallback={<Fallback />}>{children}</Suspense>;
|
||||
};
|
||||
|
||||
const Container = styled.div`
|
||||
width: 100vw;
|
||||
@@ -13,10 +13,10 @@ const Container = styled.div`
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
`
|
||||
`;
|
||||
|
||||
const Fallback: React.FC = () => (
|
||||
<Container>
|
||||
<BarLoader />
|
||||
</Container>
|
||||
)
|
||||
);
|
||||
|
@@ -1,9 +1,9 @@
|
||||
import { capitalize } from './text'
|
||||
import { capitalize } from './text';
|
||||
|
||||
it('capitalize text', () => {
|
||||
expect(capitalize('test')).toEqual('Test')
|
||||
expect(capitalize('Test')).toEqual('Test')
|
||||
expect(capitalize('tEST')).toEqual('Test')
|
||||
expect(capitalize('TEST')).toEqual('Test')
|
||||
expect(capitalize('')).toEqual('')
|
||||
})
|
||||
expect(capitalize('test')).toEqual('Test');
|
||||
expect(capitalize('Test')).toEqual('Test');
|
||||
expect(capitalize('tEST')).toEqual('Test');
|
||||
expect(capitalize('TEST')).toEqual('Test');
|
||||
expect(capitalize('')).toEqual('');
|
||||
});
|
||||
|
@@ -1,29 +1,29 @@
|
||||
export function capitalize(text: string): string {
|
||||
if (text.length === 0) return ''
|
||||
return text[0].toUpperCase() + text.slice(1).toLowerCase()
|
||||
if (text.length === 0) return '';
|
||||
return text[0].toUpperCase() + text.slice(1).toLowerCase();
|
||||
}
|
||||
|
||||
export function sanitize(text: string): string {
|
||||
return text
|
||||
.replace(/[\s@+!#$%^&*()[\]./<>{}]/g, '')
|
||||
.normalize('NFD')
|
||||
.replace(/[\u0300-\u036f]/g, '')
|
||||
.replace(/[\u0300-\u036f]/g, '');
|
||||
}
|
||||
|
||||
export function upper(word: string): string {
|
||||
return word.toUpperCase()
|
||||
return word.toUpperCase();
|
||||
}
|
||||
|
||||
export function lower(word: string): string {
|
||||
return word.toLowerCase()
|
||||
return word.toLowerCase();
|
||||
}
|
||||
|
||||
export function stem(word: string): string {
|
||||
return word.replace(/[aiueo]$/, '')
|
||||
return word.replace(/[aiueo]$/, '');
|
||||
}
|
||||
|
||||
export function germanify(word: string): string {
|
||||
return word.replace('c', 'k').replace('C', 'K')
|
||||
return word.replace('c', 'k').replace('C', 'K');
|
||||
}
|
||||
|
||||
export function njoin(
|
||||
@@ -33,5 +33,5 @@ export function njoin(
|
||||
): string {
|
||||
return elision
|
||||
? lhs + rhs.replace(new RegExp(`^${lhs[-1]}`, 'i'), '')
|
||||
: lhs + rhs
|
||||
: lhs + rhs;
|
||||
}
|
||||
|
@@ -1753,4 +1753,4 @@ export const zones = [
|
||||
'삼성',
|
||||
'테스트',
|
||||
'한국',
|
||||
]
|
||||
];
|
||||
|
Reference in New Issue
Block a user