意味のあるシソーラス
シソーラスを使用するときに見つけた単語をすべて覚えておいてください。
SynonymSearch は、検索時にすべての検索クエリのリストを共有の定義に基づいて並べ替えることで、学んだばかりの (忘れてしまうかもしれない) 内容を復習するのに役立ちます。
SynonymSearch を使用すると、同義語を文に挿入することによって、その意味が共有する定義に応じて類似性をテストできます。このアプリは、定義を積極的に理解して、それを同義語のリポジトリと照合して確認するのに役立ちます。
このプロジェクトは、Code Institute の MS2 インタラクティブ フロント エンド モジュールの一部として開発されました。これは Merriam-Webster の Collegiate® Thesaurus の JSON 応答形式で動作するように書かれており、Next.js 経由で React で開発され、 create-next-app
でブートストラップされ、Vercel でデプロイされます。
こちらのプロジェクトにアクセスしてください: Synonyms.vercel.app
参考メモ: 以前のスキームは「synonym-chaser」という名前でした
回路図のモックアップは、異種コンポーネント間の関係を確立し、適切な責任を割り当てるために、2021 年 1 月初旬に開始されました。
このアプローチは、プロジェクトの範囲を細分化するのに役立ち、そして最も重要なことに、開発とトラブルシューティングのための参照のためのベンチマークを提供することができました。
React で考える (ドキュメント) を参照してください。
{Results} => {Root} => {Sense} => {Option}
に分類されています (結果ディレクトリを参照){Saves} => {Selection}
に分類されています (saves ディレクトリを参照){ReplaceSubStringNode}
を介して{Results} =>{Root} => {Sense}
から渡された操作された文字列を表します (string.helper.js を参照)。 {Saves} => {Selection}
に分類されました (表示を参照) {Sense} => {Option}
の間で完全に処理されるため、表示はダミー コンポーネントになりました (結果ディレクトリを参照)一貫した上下の境界線が、動的コンテンツを含むすべてのノードに適用されます。これらの個別の境界線は、メモ帳の物質的なスケールをユーザーに馴染みのあるタッチポイントとして伝えるように設計されています。これらのwordBoxes
間隔が異なるだけで、リストのリスト内の階層を視覚的に伝える役割を果たします。
ThemeProvider
、コンポーネント ツリーにスタイルを渡すためにアプリをラップします。 「マテリアル - UI テーマ」を参照してください。 デバイス/プラットフォーム/ユーザー構成に適応し、明示的な書体への依存を避けるために、フォント ファミリはシステム フォントの配列に設定されます。 theme.context.js
のcommonSettings
オブジェクトには、これらのオーバーライドのリストが含まれており、マテリアル UI のテーマ プロバイダーとマージされます。 「マテリアル-UI グローバル-CSS」を参照してください。
export const commonSettings = {
typography : {
fontFamily : [
'-apple-system' ,
'BlinkMacSystemFont' ,
'"Segoe UI"' ,
'Roboto' ,
'"Helvetica Neue"' ,
'Arial' ,
'sans-serif' ,
'"Apple Color Emoji"' ,
'"Segoe UI Emoji"' ,
'"Segoe UI Symbol"' ,
] . join ( ',' ) ,
} ,
}
このアプリには、マテリアル UI のパレット構成によって構成された明るいテーマと暗いテーマの 2 つの一次色と二次色のセットが備えられています。色の動作と状態は、マテリアル UI のデフォルト テーマ オブジェクトで定義されたプロパティに依存します。二次色は中間色に設定され、原色は単一の「特徴色」としてレンダリングされます。カラーセットへの最小限のアプローチは、メモ帳を強化することです
const lightTheme = createMuiTheme ( {
palette : {
type : 'light' ,
primary : {
main : '#ff3200' ,
} ,
secondary : {
main : grey [ 900 ] ,
} ,
} ,
... commonSettings ,
} ) ;
const darkTheme = createMuiTheme ( {
palette : {
type : 'dark' ,
primary : {
main : lightblue [ 500 ] ,
} ,
secondary : {
main : '#fafafa' ,
} ,
background : {
default : '#151515' ,
} ,
} ,
... commonSettings ,
} ) ;
この Web サイトはプログレッシブ Web アプリケーションとしてモデル化されており、ページ全体をリロードすることなくシングルページ アプリの機能をレンダリングし、ネイティブ アプリのように動作するように最適化されています。そのフレームワークにより、ブラウザー間での柔軟性が保証されます。
この Web サイトは、大きなフローティング アクション ボタン (FAB) を利用して、「検索」、「情報」、「保存」の 3 つのリモート ビュー間をすばやく移動します。視覚的なメタファーを利用して、これらのビュー モードを個別かつ効率的に表現します。
フローティングの「スピード ダイヤル」ボタンは複数のビューにわたって表示され、用語のクエリ、保存された履歴のクリア、ライト モードとダーク モードの切り替えなど、アプリのコア アクションにすばやくアクセスできます。
このアプリには、最初のページ読み込み時にカスタム起動画面が表示され、その目的を「インタラクティブなシソーラス アプリ」と簡潔に説明しています。
jsx
とjss
js
の間で機能するように構文を変換するツールチェーン コンパイラー。 (Nestjs でブートストラップ)next
開発、 next build
の準備、そしてnext start
。commit
、GitHub にpush
ために利用されます。push
時にプロジェクトのコードとディレクトリを保存するために使用されます。スタイルは jss 構文で記述され、Nextjs サーバー側レンダリングで適切に動作するように、マテリアル UI の仕様に従っています。これには、 pages/_document
カスタマイズしてサーバー側でレンダリングされたスタイルを使用直前にマークアップに挿入するロジックが含まれます。これは非公式の推奨事項であり、MUI/Gatsby 用のものと同様の Nextjs 用の公式プラグインを MUI がリリースする場合にはリファクタリングする必要があることに注意してください。
すべてのスタイル オブジェクトは MUI のmakeStyles
フックを使用して作成され、テーマ設定については MUI スタイル ドキュメントのガイドラインに従います。これには、CSS オーバーライドとメディア クエリが含まれます。主要コンポーネントのスタイル オブジェクトは、スタイル ディレクトリ内のスコープごとに分離され、必要に応じてモジュールにインポートされます。ただし、一部のコンポーネント ( Launcher
では、すべてのスタイル プロパティがコンポーネント ファイル自体で宣言されています。一貫性を保つために、最終的にはすべてのスタイルを 1 つのディレクトリからエクスポートする必要があることに注意してください。
results
ツリーは、定数を初期化せずに、API 呼び出しごとにjsx
コンポーネントをレンダリングします。 Props と条件式は、MW-Thesaurus API からの応答スキーマの反復を制御します。値と Prop-Type の検証は、このスキーマから適切なデータを取得するために特別に記述されていることに注意してください。
保存された各単語インスタンスは、単語の特定の定義、ラベル、ルート単語など、「取得」された結果ファミリーのプロパティを保持し、各インスタンスが同一であるかどうかを確認しながら、重複の値を増分し、意味定義によって単語をグループ化します。名前の値では、定義と意味が異なる場合は区別されます
React フックuseReducer
、 useContext
、 createContext
はcontext/words.context
(HistoryProvider を参照) にまとめられ、コンポーネントが同じデータを共有および消費するためのコンテキスト ラッパーを提供します。このロジックは、next.js/examples/with-context-api に設定されたサンプルから直接モデル化されていることに注意してください。
HistoryProvider
のエクスポートされたコンテキスト ラッパー フックuseHistory
とuseDispatchHstory
によって実現されることに従って、これらは上位コンポーネント、共有コンポーネント、およびhelpers/*
のヘルパー関数全体で利用され、DOM を根本的に操作します。同じロジックが複数の操作に再利用されます。 MUI の ThemeProvider を使用してカスタム ラッパーに沿ってフックします (ThemeProvider を参照)。この場合、ビュー値を設定すると、いくつか例を挙げると、どのコンポーネントでもどこからでもページを変更できるようになります。このコンテキスト レイアウト プロバイダーの包括的な性質に注意してください。
export const ThemeContextProvider = ( { children } ) => {
// Sets the theme for MUI ThemeProvider to use
const [ darkMode , setDarkMode ] = useState ( false ) ;
// Sets the current view
const [ value , setValue ] = useState ( 'launch' ) ;
// Hooks to set warning colors for searchText input
const [ meta , setMeta ] = useState ( true ) ;
const [ root , setRoot ] = useState ( '' ) ;
// Rides an MUI hook to set a memoized theme
const prefersDarkMode = useMediaQuery ( '(prefers-color-scheme: dark)' ) ;
useMemo (
( ) => ( prefersDarkMode
? setDarkMode ( true )
: setDarkMode ( false ) ) ,
[ prefersDarkMode ] ,
) ;
// Provides all values and the hooks that control them
return (
< ThemeDispatchContext . Provider
value = { {
darkMode ,
setDarkMode ,
value ,
setValue ,
meta ,
setMeta ,
root ,
setRoot ,
} }
>
< ThemeProvider
theme = {
darkMode
? darkTheme
: lightTheme
}
>
{ children }
< / ThemeProvider >
< / ThemeDispatchContext . Provider >
) ;
} ;
// All state/hooks are accessible by importing
// a catch-all export below
// Example:
// // anyFile.js
// import { useDispatchTheme } from './../theme.context'
//
// const dispatch = useDispatchTheme()
//
// Change any/all states from any component
// dispatch.setDarkMode(false)
// dispatch.setValue('search')
//
export const useDispatchTheme = ( ) => useContext ( ThemeDispatchContext ) ;
MW-Thesaurus の使用は、非営利および/または教育目的であれば無料です。情報タブの注目のブランド ロゴは、メリアム ウェブスターの開発センターから要求されたブランド ガイドラインに従っていますが、これに限定されません。
このプロジェクトにリンクされている登録済みのシソーラス API キーは現在公開されています。この議論に従うと、クライアント側で API 呼び出しを保護する取り組みは、秘密キーが常に公開されるため、目的がありません。 /pages/api
に内部エンドポイントを持つためのさらなる構成は、Nextjs API ルートに従って検討する必要があります。上記の理由とプロジェクトの教育目的により、キーは.env.local
から公開されていることに注意してください。
const axiosConfig = { baseURL : 'https://dictionaryapi.com/api/v3/references/' , } ;
function searchThesaurus ( searchText , selection ) {
const query = selection || searchText ;
// Key is processed from ignored env.local
// use this method if API endpoint is set up in /pages/api/*
const key = process . env . MW_THESAURUS_KEY ;
// @note Key is explicitly declared otherwise
// for Production/submission
return axiosGetCancellable (
`/thesaurus/json/ ${ query } ?key= ${ key } ` ,
axiosConfig ,
) ;
}
注: 非定型メソッドの説明はすべて、jsDoc 標準に準拠したコメント ブロック内にあります。
ユーザーは、サイトにアクセスしてから数秒以内に説明が表示されることを期待しています。
Launcher
の説明:useEffect
では、最初のページ読み込み時にLauncher
を 1 回実行できますuseContext
使用すると、タイムアウト後にLauncher
現在のページ ビューのvalue
「 search
」に設定できるようになります。Synonym Search An Interactive Thesaurus App
」が 2 秒半表示されます。 import React , { useEffect , useState } from 'react' ;
import { useDispatchTheme } from '../../context/theme.context' ;
const Launcher = ( ) => {
const classes = useStyles ( ) ;
const viewDispatch = useDispatchTheme ( ) ;
const [ open , setOpen ] = useState ( true ) ;
const [ showOpen , setShowOpen ] = useState ( true ) ;
useEffect ( ( ) => {
setTimeout ( ( ) => {
setShowOpen ( false ) ;
setTimeout ( ( ) => {
setOpen ( false ) ;
viewDispatch . setValue ( 'search' ) ;
} , 350 ) ;
} , 2500 ) ;
} , [ ] ) ;
return (
< >
< Backdrop
className = { classes . backdrop }
open = { open }
/ >
< Grow
in = { showOpen }
unmountOnExit
>
< Box className = { classes . launch } >
{ ... excerpt . . . }
Synonym
/Search
An Interactive Thesaurus App
{ ... excerpt . . . }
< / Box >
< / Grow >
< / >
) ;
} ;
ユーザーはビュー間を簡単に移動したいと考えています
Speed (Dial)
:onClick
で開きます。FixedBottom
(FixedBottom から分岐) を使用すると、スクロール時に下部のSpeed Dial
がモバイルの下部バーの上に応答して移動できます。useScrollTrigger
使用するとSpeed Dial
ScrollTop
と表示を切り替えることができます。 ScrollTop は、クリックすると、 id="back-to-top"
のアンカーを介してウィンドウをページの先頭までスクロールするフローティング アクション ボタンです。Search
用の小道具は、シソーラス API にクエリを送信する関数であるonSearchTextChange
アクティブにするためにSpeed Dial
に渡されます。useState
使用すると、 Search
がactive
場合を除き、 useDispatch
経由でページvalue
変更されるたびに、 useEffect
で常にSpeedDial
閉じることができます。ToggleTheme
、 Search
、 Clear
Saves
ビューにいますSpeedDial
をクリックするSpeedDial
が開いていますToggleTheme
アクションをクリックします<mode>
not
に変更されますSpeedDial
は閉じていますSaves
ビューにいますSpeedDial
をクリックするSpeedDial
が開いていますSearch
アクションをクリックしますSpeedDial
はまだ開いていますSearch
ビューにいますSpeedDial
が消えるScrollTop
ボタンが表示されますScrollTop
をクリックしますSpeedDial
が表示されますSpeedDial
アクションをクリックすることで、 x
次元とy
次元 (ビュー内で上/下、ビュー間で左/右) にすばやく移動できます。さらに、ビューごとのボタン ナビゲーションはページ ヘッダーからアクセスできます。他の 2 つのビューはSaves
とInfo
で、 SpeedDial
内のアクションと同じフローティング アクション ボタン ファミリに属します。テーマ、色、UI の一貫性と特異性は、ユーザーの衝動と、伝えられる永続的なタッチポイントへの親しみやすさに影響します。 import React , { useEffect , useState } from 'react' ;
import { useDispatchTheme } from '../../context/theme.context' ;
const Speed = ( {
children ,
value ,
index ,
searchText ,
loading ,
onSearchTextChange ,
... other
} ) => {
const trigger = useScrollTrigger ( ) ;
const classes = useStyles ( ) ;
const [ open , setOpen ] = useState ( false ) ;
const [ direction , setDirection ] = useState ( 'up' ) ;
const matches = useMediaQuery ( '(min-width:600px)' ) ;
const viewDispatch = useDispatchTheme ( ) ;
const view = viewDispatch . value ? viewDispatch . value : null ;
const handleClick = ( event ) => setOpen ( ! open ) ;
open && trigger ? setOpen ( false ) : null ;
useEffect ( ( ) => {
setTimeout ( ( ) => {
if ( viewDispatch . value !== 'search' ) {
setOpen ( false ) ;
}
} , 10 ) ;
} , [ view ] ) ;
return (
< Slide appear direction = "up" in = { ! trigger } >
< FixedBottom offset = { matches ? 16 : 48 } >
< SpeedDial
ariaLabel = "actions"
className = { classes . speedDialGroup }
FabProps = { {
className : clsx ( classes . speedDial , classes . bottom ) ,
size : matches ? 'medium' : 'small' ,
style : { padding : matches ? '12px' : '8px' } ,
} }
onClick = { handleClick }
open = { open }
direction = { direction }
>
{ ... Search action }
{ ... Toggle theme action }
{ ... Clear cache action }
/ >
< / SpeedDial >
< / FixedBottom >
< / Slide >
) ;
} ;
export default Speed ;
ユーザーは信頼できる情報源を知りたいと考えています
Brands
説明 (マテリアル-UI AvatarGroup
):useEffect
すると、ページ値が現在のview
=> Info
に設定されているときにuseState
でマージンを反転できます。これにより、ユーザーを情報デスクに歓迎するかのようにアバターが展開するようにアニメーション化され、背後にある「 SynonymStory
」を説明する短い段落が表示されます。 「 SynonymSearch
」Logo
インスタンス (各 1 つ): React
、 NextJS
、 MaterialUI
、 CodeInstitute
、 Merriam-Webster
。Search
ビューにいますInfo
をクリックInfo
ビューにいますBrands
のアバターが登場Merriam-Webster
をクリックMerriam-Webster Developer Center website
が開きますInfo
に保ちます import React , { useEffect , useState } from 'react' ;
import { useDispatchTheme } from '../../context/theme.context' ;
const Brands = ( { children } ) => {
const classes = useStyles ( ) ;
const viewDispatch = useDispatchTheme ( ) ;
const [ active , setActive ] = useState ( false ) ;
const { value } = viewDispatch ;
useEffect ( ( ) => {
if ( value === 'info' ) {
setTimeout ( ( ) => {
setActive ( true ) ;
} , 750 ) ;
}
} , [ ] ) ;
return (
< AvatarGroup
className = {
clsx (
classes . avatarGroup , active
? classes . active
: classes . inactive ,
)
}
>
< Logo
name = "React"
url = "https://react.org/"
path = "/images/reactLogo.png"
/ >
< Logo
name = "Next JS"
url = "https://nextjs.org/"
path = "/images/nextJSLogo.svg"
/ >
< Logo
name = "Material UI"
url = "https://material-ui.com/"
path = "/images/materialUILogoLight.png"
darkImage = "/images/materialUILogoDark.png"
/ >
< Logo
name = "Code Institute"
url = "https://codeinstitute.net/"
path = "/images/codeInstituteLogo.png"
/ >
< Logo
name = "Merriam-Webster"
url = "https://dictionaryapi.com/"
path = "/images/merriamWebsterLogoLight.png"
/ >
< / AvatarGroup >
) ;
} ;
ユーザーが同義語を検索したいと考えています
Search
の説明:loading
: 結果が読み込まれているかどうか、meta
: ユーザーの入力が有効な結果を生成するかどうか、root
: 結果の配列内の最初の項目がユーザーが入力した内容と一致するかどうか。useState
使用すると、これらの条件を動的に変更できます。useRef
は入力コンポーネントにアタッチされており、キー イベントとマウス イベントが上記の条件に基づいて条件付きで入力プロンプトにfocus
できるようにします。Field
、 Input
。Search
ビューにいますSearch
アクションをクリックしますimmediately successful word
を入力> を入力します。immediately successful word
の同義語による結果の更新Search
アクションをクリックしますincomplete word
を入力>real word
を入力>real word
の同義語を含む結果の更新Search
アクションをクリックしますa word with no matches
を入力>good word
を入力>new word
の同義語を含む結果の更新 const Field = ( {
label ,
onChange ,
placeHolder ,
helperText ,
loading ,
} ) => {
const theme = useTheme ( ) ;
const trigger = useScrollTrigger ( ) ;
const [ active , setActive ] = useState ( false ) ;
const textInput = useRef ( null ) ;
const metaDispatch = useDispatchTheme ( ) ;
const { meta , root } = metaDispatch ;
const handleSearchButton = ( ) => {
setActive ( true ) ;
setTimeout ( ( ) => {
textInput . current && textInput . current . focus ( ) ;
} , 100 ) ;
} ;
const handleClickAway = ( ) => setActive ( false ) ;
const handleBackDrop = ( ) => setActive ( false ) ;
const onKeyPress = ( ) => setActive ( false ) ;
const match
= textInput . current
? textInput . current . value === root
: false ;
active && trigger ? setActive ( false ) : null ;
useEffect ( ( ) => {
if ( active && match ) {
setTimeout ( ( ) => {
setActive ( false ) ;
} , 2000 ) ;
}
} , [ ] ) ;
return (
< ClickAwayListener
onClickAway = { handleClickAway }
>
< >
< Backdrop
open = { active }
onClick = { handleBackDrop }
/ >
< Fab
size = "small"
color = "primary"
aria-label = "search"
onClick = { handleSearchButton }
variant = { active ? 'extended' : 'round' }
style = { active ? {
backgroundColor :
loading
? theme . palette . warning . main
: ! meta
? theme . palette . error . main
: meta && match
? theme . palette . success . main
: theme . palette . primary . main ,
} : null }
>
< Input
label = { label }
placeHolder = { placeHolder }
helperText = { helperText }
active = { active }
match = { match }
meta = { meta }
loading = { loading }
textInput = { textInput }
onKeyPress = { onKeyPress }
onChange = { onChange }
/ >
< / Fab >
< / >
< / ClickAwayListener >
) ;
} ;
ユーザーは検索履歴を見たいと考えています
useHistory
HistoryProvider
に格納されている値にアクセスするための Context フックです。useReducer
HistoryProver
クエリされた単語を、共有する定義に基づいてグループ化できます。Selection
ユーザーは文の中で使用されている単語を確認したいと考えています
Display
の説明:sampleString
およびoptionWord
プロパティを渡すためにSense
によって使用されます。これにより、 Intersection Observer
とマウス イベントがアクティブになり、 optionWord
プロパティが動的に変更されます。{it} {/it}
ノードと{lquo} {rquo}
ノードでラップされています。正規表現置換関数は、開始タグと終了タグであるため、定義にサンプル文字列が含まれている場合に、その文字列を一貫してクリーンアップする上で信頼性が高いことが証明されています。 (Theaurus API からの応答例を参照してください)ユーザーは、繰り返し結果 (つまり、すでに保存されている単語) の隣にタグを表示したいと考えています。
HistoryProvider
にuseReducer
記述します。HistoryProvider
に保存される Word オブジェクトは、これらのプロパティを新しい単語と比較することによって検証できるプロパティとともに保存されます。Counters
で Word Type チェックを説明します。History
に保存された単語を削減、並べ替え、グループ化するためのヘルパー関数としての型定義Saves
ビューでも使用されるため、ユーザーは共有のプロパティ定義によって「繰り返し」、つまりユーザーが保存した単語を表示できます。 const [ savedWords , dispatch ] = useReducer ( ( state , action ) => {
switch ( action . type ) {
case 'add' :
const wordIndex = state . findIndex ( ( word ) => word . uuid === action . uuid
|| word . name === action . name
&& word . sense === action . sense ) ;
if ( wordIndex !== - 1 ) {
return state . map ( ( word , i ) => ( {
... word ,
value : word . value + ( wordIndex === i ? 1 : 0 ) ,
} ) ) ;
}
return [
... state ,
{
id : state . length ,
name : action . name ,
value : 1 ,
root : action . root ,
label : action . label ,
uuid : action . uuid ,
sense : action . sense ,
} ,
] ;
case 'remove' :
return state . filter ( ( word ) => word . id !== action . id ) ;
case 'clear' :
return [ ] ;
default :
return state ;
}
} , [ ] ) ;
ユーザーが保存された検索履歴を削除したいと考えています
Clear
説明:DeleteForever
アイコンが付いたボタン。これは、Context からすべてを削除するHistoryProvider
からのuseReducer
のdispatch
関数です。Chip
コンポーネントで表されるDelete
アイコンを介して個々の単語を削除できます。 // clear.button.js
// excerpt
const wordsDispatch = useDispatchHistory ( ) ;
const handleClick = ( event ) => {
wordsDispatch ( {
type : 'clear' ,
} ) ;
} ;
// words.context.js
// excerpt from reducer
// the above handler calls case 'remove'
case 'remove' :
return state . filter ( ( word ) => word . id !== action . id ) ;
最新の結果を表示
Vercel 経由の Lighthouse はパフォーマンスのテストに使用され、 git push
ごとに固有の結果が生成されます。 lighthouse-badges は、 npm i -g lighthouse-badges
をインストールし、新しいハッシュ化された URL を URL の配列にプッシュすることにより、デプロイメントごとに新しいバッジを生成するために使用されます。
lighthouse-badges
-o docs/badges -r
-u https://synonyms.vercel.app/ [... all other urls]
# Output to docs/badges
# Badges will contain the respective
average score(s) of all the urls
supplied, combined
Lighthouse の指標、つまりアクセシビリティとパフォーマンスは、監査ごとに特定のフラグを生成します。プッシュごとに、特に問題に対処する調整が行われます。
role
明確にするために HTML5 セマンティック要素を調整する変更が挙げられます。 トップに戻る
create-next-app
でブートストラップされ、Vercel でデプロイされます。これは次の手順で実現しました。commit
てpush
。select
入力を介して「Git リポジトリのインポート」にアクセスします。「プロジェクトは正常にデプロイされました。」
トップに戻る
git clone https://github.com/israelias/synonym-chaser
cd
。 cd synonym-chaser
npm install
npm run dev
# or
yarn dev
ブラウザを開いて localhost:3000 にアクセスします
info
の短い説明以外のコンテンツはすべて、Merriam-Webster の Collegiate Thesaurus を介して提供されています。トップに戻る