diff --git a/.github/workflows/node-js.yml b/.github/workflows/node-js.yml index 7aa081d8..d4bf9418 100644 --- a/.github/workflows/node-js.yml +++ b/.github/workflows/node-js.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [14.x, 16.x] + node-version: [16.x, 21.x] steps: - name: Checkout diff --git a/.github/workflows/pr-deploy-preview.yml b/.github/workflows/pr-deploy-preview.yml new file mode 100644 index 00000000..8adedb90 --- /dev/null +++ b/.github/workflows/pr-deploy-preview.yml @@ -0,0 +1,40 @@ +name: Netlify PR Preview + +on: + pull_request: + branches: + - "develop/**" + - "feature/**" + types: + - opened + - reopened + - synchronize + +jobs: + deploy-draft: + name: Deploy draft to Netlify + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v1 + + - name: Set up Node.js + uses: actions/setup-node@master + with: + node-version: 16.x + + - name: Install dependencies + run: yarn install + + - name: Build page + run: yarn build + + - name: Deploy draft to Netlify + uses: evnex/netlify-deploy@v1.0.4 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + netlify-auth-token: ${{ secrets.NETLIFY_AUTH_TOKEN }} + netlify-site-id: ${{ secrets.NETLIFY_SITE_ID }} + build-dir: "./build" + draft: true + comment-on-pull-request: true diff --git a/src/components/mdx-searchbar/searchbar.js b/src/components/mdx-searchbar/searchbar.js index af10cf43..46f68a64 100644 --- a/src/components/mdx-searchbar/searchbar.js +++ b/src/components/mdx-searchbar/searchbar.js @@ -6,12 +6,79 @@ export default function SearchBar() { function handleKeyPress(event) { // event.preventDefault(); - if(event.key === 'Enter'){ - console.log(document.getElementById('search-input').value); - // Working on here.. + if (event.key === 'Enter') { + // console.log(document.getElementById('search-input').value); + handleSearch(); } } + function handleSearch() { + if (!searchString || searchString.trim().length < 2) { + alert("2글자 이상 입력해주십쇼 ㅡㅅㅡ\nPlz type more than 2 characters."); + return; + } + // convert to lowercase & whitespace to dash + const normalizedSearch = searchString.trim().toLowerCase().replace(/\s+/g, '-'); + + // query all anchor ids in the page + const anchors = Array.from(document.querySelectorAll('[id]')); + + // search anchor id with normalized keyword + const matchedAnchor = anchors.find(anchor => { + const anchorId = anchor.id.toLowerCase(); + return anchorId.includes(normalizedSearch); + }); + + if (matchedAnchor) { + /* Allow navigation to the same hash URL even if already at that position */ + // Remove existing hash then re-set + // Synchronously changing the hash twice may cause browsers to ignore the first or override with the second + // -> no navigation + // -> so we have to cheat the browser + const tempHash = '#_temp'; + // set fake hash: reload x scroll x -> only change URL + // -> to cheat the browser to think it's in a different state + history.replaceState(null, null, tempHash); + + // set real hash in the next event loop tick + setTimeout(() => { + // Type A. move directly + // location.hash = '#' + matchedAnchor.id; + + // Type B. scroll animation + matchedAnchor.scrollIntoView({ + behavior: 'smooth', + block: 'start' + }); + + // update browser url state + history.replaceState(null, null, '#' + matchedAnchor.id); + + // highlight target anchor + highlightElement(matchedAnchor); + }, 0); + } else { + alert('그런 단어는 없는뎁쇼 ㅇㅅㅇ\nSowwy~ no such word here!'); + } + } + + function highlightElement(el) { + // reset + el.classList.remove('highlight-active', 'highlight-fade-out'); + void el.offsetWidth; // reflow + + // highlight for 1.5s then fadeout for .5s + el.classList.add('highlight-active'); + + setTimeout(() => { + el.classList.add('highlight-fade-out'); + }, 1500); + + setTimeout(() => { // 1.5s + .5s -> 2s + el.classList.remove('highlight-active', 'highlight-fade-out'); + }, 2000); + } + return (
@@ -20,9 +87,9 @@ export default function SearchBar() {
- setSearchString(event.target.value)} /> -
+ setSearchString(event.target.value)} /> +