diff --git a/.env.local b/.env.local index 8b04d2c7..48bf046f 100644 --- a/.env.local +++ b/.env.local @@ -1,2 +1,2 @@ # 环境变量 @see https://www.nextjs.cn/docs/basic-features/environment-variables -NEXT_PUBLIC_VERSION=3.6.0 \ No newline at end of file +NEXT_PUBLIC_VERSION=3.6.1 \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js index 6cf90e91..4b95adcd 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -16,7 +16,10 @@ module.exports = { ecmaVersion: 12, sourceType: 'module' }, - plugins: ['react'], + plugins: [ + 'react', + 'react-hooks' + ], settings: { react: { version: 'detect' @@ -24,7 +27,8 @@ module.exports = { }, rules: { 'react/prop-types': 'off', - 'space-before-function-paren': 0 + 'space-before-function-paren': 0, + 'react-hooks/rules-of-hooks': 'error' // Checks rules of Hooks }, globals: { React: true diff --git a/README.md b/README.md index 14c81beb..df20f48e 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,9 @@ yarn run start # 本地启动NextJS服务 ifyz
ifyz

🔧 🐛 + SwwweetOrange
SwwweetOrange

🔧 🐛 + + diff --git a/components/Busuanzi.js b/components/Busuanzi.js index 12e592d8..fec41e5f 100644 --- a/components/Busuanzi.js +++ b/components/Busuanzi.js @@ -4,26 +4,23 @@ import { useGlobal } from '@/lib/global' // import { useRouter } from 'next/router' import React from 'react' +let path = '' + export default function Busuanzi () { const { theme } = useGlobal() - const router = useRouter() - - // 切换文章时更新 - React.useEffect(() => { - const busuanziRouteChange = url => { + const Router = useRouter() + Router.events.on('routeChangeComplete', (url, option) => { + if (url !== path) { + path = url busuanzi.fetch() } - router.events.on('routeChangeComplete', busuanziRouteChange) - return () => { - router.events.off('routeChangeComplete', busuanziRouteChange) - } - }, [router.events]) + }) // 更换主题时更新 React.useEffect(() => { if (theme) { busuanzi.fetch() } - }) + }, [theme]) return null } diff --git a/components/Comment.js b/components/Comment.js index d362e047..c1ae3d2b 100644 --- a/components/Comment.js +++ b/components/Comment.js @@ -43,9 +43,6 @@ const ValineComponent = dynamic(() => import('@/components/ValineComponent'), { }) const Comment = ({ frontMatter }) => { - if (!frontMatter) { - return <>Loading... - } const { isDarkMode } = useGlobal() const router = useRouter() @@ -61,6 +58,10 @@ const Comment = ({ frontMatter }) => { }, 200) }, []) + if (!frontMatter) { + return <>Loading... + } + return (
diff --git a/components/Live2D.js b/components/Live2D.js index c763349a..cb53df89 100644 --- a/components/Live2D.js +++ b/components/Live2D.js @@ -2,26 +2,27 @@ import BLOG from '@/blog.config' import { useGlobal } from '@/lib/global' import { loadExternalResource } from '@/lib/utils' -import { useEffect } from 'react' +import React from 'react' export default function Live2D() { - if (!BLOG.WIDGET_PET || !JSON.parse(BLOG.WIDGET_PET)) { - return <> - } const { switchTheme } = useGlobal() + React.useEffect(() => { + window.addEventListener('scroll', initLive2D) + return () => { + window.removeEventListener('scroll', initLive2D) + } + }, []) + function handleClick() { if (BLOG.WIDGET_PET_SWITCH_THEME) { switchTheme() } } - useEffect(() => { - window.addEventListener('scroll', initLive2D) - return () => { - window.removeEventListener('scroll', initLive2D) - } - }, []) + if (!BLOG.WIDGET_PET || !JSON.parse(BLOG.WIDGET_PET)) { + return <> + } return } diff --git a/components/NotionPage.js b/components/NotionPage.js index e9a4025e..e195e24d 100644 --- a/components/NotionPage.js +++ b/components/NotionPage.js @@ -7,8 +7,8 @@ import { isBrowser } from '@/lib/utils' import Image from 'next/image' import Link from 'next/link' import { Code } from 'react-notion-x/build/third-party/code' -import { Pdf } from 'react-notion-x/build/third-party/pdf' -import { Equation } from 'react-notion-x/build/third-party/equation' +// import { Pdf } from 'react-notion-x/build/third-party/pdf' +// import { Equation } from 'react-notion-x/build/third-party/equation' import 'prismjs/components/prism-bash.js' import 'prismjs/components/prism-markup-templating.js' @@ -43,10 +43,19 @@ import 'prismjs/components/prism-wasm.js' import 'prismjs/components/prism-yaml.js' import 'prismjs/components/prism-r.js' -// 化学方程式 -import '@/lib/mhchem' -// 页面渲染观察者 -let observer +const Equation = dynamic(() => + import('react-notion-x/build/third-party/equation').then(async (m) => { + // 化学方程式 + await import('@/lib/mhchem') + return m.Equation + }) +) +const Pdf = dynamic( + () => import('react-notion-x/build/third-party/pdf').then((m) => m.Pdf), + { + ssr: false + } +) // https://github.com/txs // import PrismMac from '@/components/PrismMac' @@ -63,10 +72,6 @@ const Modal = dynamic( ) const NotionPage = ({ post }) => { - if (!post || !post.blockMap) { - return <>{post?.summary || ''} - } - const zoom = isBrowser() && mediumZoom({ container: '.notion-viewport', background: 'rgba(0, 0, 0, 0.2)', @@ -76,10 +81,6 @@ const NotionPage = ({ post }) => { const zoomRef = React.useRef(zoom ? zoom.clone() : null) - if (isBrowser() && !observer) { - addWatch4Dom() - } - React.useEffect(() => { setTimeout(() => { if (window.location.hash) { @@ -109,8 +110,11 @@ const NotionPage = ({ post }) => { }, 800) }, []) + if (!post || !post.blockMap) { + return <>{post?.summary || ''} + } + return
- { nextImage: Image, nextLink: Link }} /> + + +
} @@ -154,61 +161,4 @@ function getMediumZoomMargin() { } } -/** - * 监听DOM变化 - * @param {*} element - */ -// eslint-disable-next-line no-unused-vars -function addWatch4Dom(element) { - // 选择需要观察变动的节点 - const targetNode = element || document?.getElementById('container') - // 观察器的配置(需要观察什么变动) - const config = { - attributes: true, - childList: true, - subtree: true - } - - // 创建一个观察器实例并传入回调函数 - observer = new MutationObserver(mutationCallback) - // console.log('观察节点变化', observer) - // 以上述配置开始观察目标节点 - if (targetNode) { - observer.observe(targetNode, config) - } - - // observer.disconnect() -} - -// 当页面发生时会调用此函数 -const mutationCallback = (mutations) => { - for (const mutation of mutations) { - const type = mutation.type - switch (type) { - case 'childList': - // console.log('A child node has been added or removed.', mutation) - if (mutation.addedNodes.length > 0) { - if (mutation?.target?.parentElement?.nodeName === 'PRE' || mutation?.target?.parentElement?.nodeName === 'CODE') { - if (mutation.addedNodes[0].nodeName === '#text' && mutation.target.childElementCount > 0) { - mutation.addedNodes[0].remove() // 移除新增的内容 - } - } - if (mutation?.target?.className === 'language-mermaid') { - // mermaid重刷新bug TODO - } - } - break - case 'attributes': - // console.log(`The ${mutation.attributeName} attribute was modified.`, mutation.target) - // console.log(mutation.attributeName) - break - case 'subtree': - // console.log('The subtree was modified.', mutation.target) - break - default: - break - } - } -} - export default NotionPage diff --git a/components/PrismMac.js b/components/PrismMac.js index 0a2bf4ec..9193cfa6 100644 --- a/components/PrismMac.js +++ b/components/PrismMac.js @@ -9,33 +9,15 @@ import 'prismjs/plugins/line-numbers/prism-line-numbers.css' // mermaid图 import mermaid from 'mermaid' -import { useGlobal } from '@/lib/global' -import { useRouter } from 'next/router' -import { isBrowser } from '@/lib/utils' -// 页面渲染观察者 -let observer /** * @author https://github.com/txs/ * @returns */ const PrismMac = () => { - const router = useRouter() - const { isDarkMode } = useGlobal() - const scrollTop = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop - - if (isBrowser() && !observer) { - addWatch4Dom() - } - React.useEffect(() => { renderPrismMac() - window.scrollTo(0, scrollTop) - router.events.on('routeChangeComplete', renderPrismMac) - return () => { - router.events.off('routeChangeComplete', renderPrismMac) - } - }, [isDarkMode]) + }) return <> } @@ -62,41 +44,18 @@ function renderPrismMac() { }) } - setTimeout(() => { - // Add pre-mac element for Mac Style UI - if (codeToolBars) { - Array.from(codeToolBars).forEach(item => { - const existPreMac = item.getElementsByClassName('pre-mac') - if (existPreMac.length < codeToolBars.length) { - const preMac = document.createElement('div') - preMac.classList.add('pre-mac') - preMac.innerHTML = '' - item?.appendChild(preMac, item) - } - }) - } - }, 10) - - // 重新渲染之前检查所有的多余text - - try { - Prism.highlightAll() - } catch (err) { - console.log('代码渲染', err) - } - // 支持 Mermaid const mermaids = document.querySelectorAll('.notion-code .language-mermaid') if (mermaids) { for (const e of mermaids) { - e.parentElement.parentElement.classList.remove('code-toolbar') + e.parentElement.classList.remove('code-toolbar') const chart = e.firstChild.textContent if (e.firstElementChild) { - e.parentElement.parentElement.remove() + e.parentElement.remove() continue } if (chart) { - e.parentElement.parentElement.innerHTML = `
${chart}
` + e.parentElement.innerHTML = `
${chart}
` } } } @@ -109,59 +68,26 @@ function renderPrismMac() { } } } -} -/** - * 监听DOM变化 - * @param {*} element - */ -// eslint-disable-next-line no-unused-vars -function addWatch4Dom(element) { - // 选择需要观察变动的节点 - const targetNode = element || document?.getElementById('container') - // 观察器的配置(需要观察什么变动) - const config = { - attributes: true, - childList: true, - subtree: true + // 重新渲染之前检查所有的多余text + + try { + Prism.highlightAll() + } catch (err) { + console.log('代码渲染', err) } - // 创建一个观察器实例并传入回调函数 - observer = new MutationObserver(mutationCallback) - // console.log('观察节点变化', observer) - // 以上述配置开始观察目标节点 - if (targetNode) { - observer.observe(targetNode, config) - } - - // observer.disconnect() -} - -// 当页面发生时会调用此函数 -const mutationCallback = (mutations) => { - for (const mutation of mutations) { - const type = mutation.type - switch (type) { - case 'childList': - // console.log('A child node has been added or removed.', mutation) - if (mutation.addedNodes.length > 0) { - if (mutation?.target?.parentElement?.nodeName === 'PRE' || mutation?.target?.parentElement?.nodeName === 'CODE') { - if (mutation.addedNodes[0].nodeName === '#text') { - mutation.addedNodes[0].remove() // 移除新增的内容 - } - } - } - break - case 'attributes': - // console.log(`The ${mutation.attributeName} attribute was modified.`, mutation.target) - // console.log(mutation.attributeName) - break - case 'subtree': - // console.log('The subtree was modified.', mutation.target) - break - default: - break - } + // Add pre-mac element for Mac Style UI + if (codeToolBars) { + Array.from(codeToolBars).forEach(item => { + const existPreMac = item.getElementsByClassName('pre-mac') + if (existPreMac.length < codeToolBars.length) { + const preMac = document.createElement('div') + preMac.classList.add('pre-mac') + preMac.innerHTML = '' + item?.appendChild(preMac, item) + } + }) } } diff --git a/components/Tabs.js b/components/Tabs.js index f3b0477a..9057f20e 100644 --- a/components/Tabs.js +++ b/components/Tabs.js @@ -6,6 +6,8 @@ import React, { useState } from 'react' * @returns */ const Tabs = ({ className, children }) => { + const [currentTab, setCurrentTab] = useState(0) + if (!children) { return <> } @@ -29,8 +31,6 @@ const Tabs = ({ className, children }) => { } - const [currentTab, setCurrentTab] = useState(0) - function tabClickHandle (i) { setCurrentTab(i) } diff --git a/components/WalineComponent.js b/components/WalineComponent.js index 2bff99f1..a47999c7 100644 --- a/components/WalineComponent.js +++ b/components/WalineComponent.js @@ -3,28 +3,34 @@ import { init } from '@waline/client' import BLOG from '@/blog.config' import { useRouter } from 'next/router' +const path = '' +let waline = null /** * @see https://waline.js.org/guide/get-started.html * @param {*} props * @returns */ const WalineComponent = (props) => { - const walineInstanceRef = React.useRef(null) const containerRef = React.createRef() const router = useRouter() const updateWaline = url => { - walineInstanceRef.current?.update(props) + if (url !== path) { + waline.update(props) + } } React.useEffect(() => { - walineInstanceRef.current = init({ - ...props, - el: containerRef.current, - serverURL: BLOG.COMMENT_WALINE_SERVER_URL - }) - router.events.on('routeChangeComplete', updateWaline) + if (!waline) { + waline = init({ + ...props, + el: containerRef.current, + serverURL: BLOG.COMMENT_WALINE_SERVER_URL + }) + } + // 跳转评论 + router.events.on('routeChangeComplete', updateWaline) const anchor = window.location.hash if (anchor) { // 选择需要观察变动的节点 @@ -54,7 +60,8 @@ const WalineComponent = (props) => { } return () => { - walineInstanceRef.current?.destroy() + waline.destroy() + waline = null router.events.off('routeChangeComplete', updateWaline) } }, []) diff --git a/lib/busuanzi.js b/lib/busuanzi.js index df0564c4..9255485a 100644 --- a/lib/busuanzi.js +++ b/lib/busuanzi.js @@ -55,7 +55,7 @@ bszCaller = { const fetch = () => { bszTag && bszTag.hides() bszCaller.fetch('//busuanzi.ibruce.info/busuanzi?jsonpCallback=BusuanziCallback', function (t) { - // console.log('不蒜子请求结果',t) + // console.log('不蒜子',t) bszTag.texts(t), bszTag.shows() }) } diff --git a/lib/notion/getPageProperties.js b/lib/notion/getPageProperties.js index 771915e9..1eced850 100644 --- a/lib/notion/getPageProperties.js +++ b/lib/notion/getPageProperties.js @@ -79,8 +79,8 @@ export default async function getPageProperties(id, block, schema, authToken, ta properties.createdTime = formatDate(new Date(value.created_time).toString(), BLOG.LANG) properties.lastEditedTime = formatDate(new Date(value?.last_edited_time).toString(), BLOG.LANG) properties.fullWidth = value.format?.page_full_width ?? false - properties.pageIcon = getPageIcon(id, block) ?? '' - properties.page_cover = getPostCover(id, block) ?? siteInfo?.pageCover + properties.pageIcon = getImageUrl(block[id].value?.format?.page_icon, block[id].value) ?? '' + properties.page_cover = getImageUrl(block[id].value?.format?.page_cover, block[id].value) ?? siteInfo?.pageCover properties.content = value.content ?? [] properties.tagItems = properties?.tags?.map(tag => { return { name: tag, color: tagOptions?.find(t => t.value === tag)?.color || 'gray' } @@ -89,20 +89,23 @@ export default async function getPageProperties(id, block, schema, authToken, ta return properties // 从Block获取封面图;优先取PageCover,否则取内容图片 - function getPostCover(id, block) { - const pageCover = block[id].value?.format?.page_cover - if (pageCover) { - if (pageCover.startsWith('/')) return 'https://www.notion.so' + pageCover - if (pageCover.startsWith('http')) return defaultMapImageUrl(pageCover, block[id].value) + function getImageUrl(imgObj, blockVal) { + if (!imgObj) { + return null + } + if (imgObj.startsWith('/')) { + return 'https://www.notion.so' + imgObj // notion内部图片转相对路径为绝对路径 } - } -} -function getPageIcon(id, block) { - const pageIcon = block[id].value?.format?.page_icon - if (pageIcon) { - if (pageIcon.startsWith('/')) return 'https://www.notion.so' + pageIcon - if (pageIcon.startsWith('http')) return defaultMapImageUrl(pageIcon, block[id].value) - return pageIcon + if (imgObj.startsWith('http')) { + // 判断如果是notion上传的图片要拼接访问token + const u = new URL(imgObj) + if (u.pathname.startsWith('/secure.notion-static.com') && u.hostname.endsWith('.amazonaws.com')) { + return defaultMapImageUrl(imgObj, blockVal) // notion上传的图片需要转换请求地址 + } + } + + // 其他图片链接 或 emoji + return imgObj } } diff --git a/next.config.js b/next.config.js index 106e6aea..f2a86bc5 100644 --- a/next.config.js +++ b/next.config.js @@ -1,6 +1,7 @@ const withBundleAnalyzer = require('@next/bundle-analyzer')({ enabled: process.env.ANALYZE === 'true' }) + module.exports = withBundleAnalyzer({ future: { webpack5: true @@ -46,13 +47,13 @@ module.exports = withBundleAnalyzer({ }, webpack: (config, { dev, isServer }) => { // Replace React with Preact only in client production build - if (!dev && !isServer) { - Object.assign(config.resolve.alias, { - react: 'preact/compat', - 'react-dom/test-utils': 'preact/test-utils', - 'react-dom': 'preact/compat' - }) - } + // if (!dev && !isServer) { + // Object.assign(config.resolve.alias, { + // react: 'preact/compat', + // 'react-dom/test-utils': 'preact/test-utils', + // 'react-dom': 'preact/compat' + // }) + // } return config } }) diff --git a/package.json b/package.json index a5c72494..2f5be0dc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "notion-next", - "version": "3.6.0", + "version": "3.6.1", "homepage": "https://github.com/tangly1024/NotionNext.git", "license": "MIT", "repository": { @@ -27,10 +27,12 @@ "animejs": "^3.2.1", "axios": ">=0.21.1", "copy-to-clipboard": "^3.3.1", + "eslint-plugin-react-hooks": "^4.6.0", "feed": "^4.2.2", "gitalk": "^1.7.2", "localStorage": "^1.0.4", "lodash.throttle": "^4.1.1", + "mark.js": "^8.11.1", "memory-cache": "^0.2.0", "mermaid": "9.2.2", "mongodb": "^4.6.0", diff --git a/pages/[...slug].js b/pages/[...slug].js index 7707ca31..63eb5e51 100644 --- a/pages/[...slug].js +++ b/pages/[...slug].js @@ -20,6 +20,17 @@ const Slug = props => { const { post, siteInfo } = props const router = Router.useRouter() + // 文章锁🔐 + const [lock, setLock] = React.useState(post?.password && post?.password !== '') + + React.useEffect(() => { + if (post?.password && post?.password !== '') { + setLock(true) + } else { + setLock(false) + } + }, [post]) + if (!post) { changeLoadingState(true) setTimeout(() => { @@ -38,16 +49,6 @@ const Slug = props => { changeLoadingState(false) - // 文章锁🔐 - const [lock, setLock] = React.useState(post?.password && post?.password !== '') - React.useEffect(() => { - if (post?.password && post?.password !== '') { - setLock(true) - } else { - setLock(false) - } - }, [post]) - /** * 验证文章密码 * @param {*} result diff --git a/pages/search/[keyword]/index.js b/pages/search/[keyword]/index.js index 91b55de6..f26b77ea 100644 --- a/pages/search/[keyword]/index.js +++ b/pages/search/[keyword]/index.js @@ -120,7 +120,7 @@ async function filterByMemCache(allPosts, keyword) { const tagContent = post.tags && Array.isArray(post.tags) ? post.tags.join(' ') : '' const categoryContent = post.category && Array.isArray(post.category) ? post.category.join(' ') : '' const articleInfo = post.title + post.summary + tagContent + categoryContent - let hit = articleInfo.indexOf(keyword) > -1 + let hit = articleInfo.toLowerCase().indexOf(keyword) > -1 let indexContent = [post.summary] if (page && page.block) { const contentIds = Object.keys(page.block) diff --git a/pages/search/index.js b/pages/search/index.js index 4dd96ad5..d562d627 100644 --- a/pages/search/index.js +++ b/pages/search/index.js @@ -5,8 +5,9 @@ import * as ThemeMap from '@/themes' const Search = props => { const { posts, siteInfo } = props + const router = useRouter() let filteredPosts - const searchKey = getSearchKey() + const searchKey = getSearchKey(router) // 静态过滤 if (searchKey) { filteredPosts = posts.filter(post => { @@ -61,8 +62,7 @@ export async function getStaticProps() { } } -function getSearchKey() { - const router = useRouter() +function getSearchKey(router) { if (router.query && router.query.s) { return router.query.s } diff --git a/styles/notion.css b/styles/notion.css index b717e39a..b8912a51 100644 --- a/styles/notion.css +++ b/styles/notion.css @@ -1941,4 +1941,12 @@ pre[class*='language-'] { .pre-mac > span:nth-child(3) { background: limegreen; +} + +.notion-asset-wrapper-pdf > div { + display: block !important; +} + +::selection { + @apply bg-blue-500 text-gray-50 !important; } \ No newline at end of file diff --git a/styles/prism-mac-style.css b/styles/prism-mac-style.css index 15e2e4f7..73fbe296 100644 --- a/styles/prism-mac-style.css +++ b/styles/prism-mac-style.css @@ -4,7 +4,7 @@ .code-toolbar { position: relative; box-shadow: 0 10px 30px 0 rgba(0, 0, 0, .4); - @apply mb-8 pt-6 w-full rounded-lg bg-black + @apply mb-8 mt-4 pt-6 w-full rounded-lg bg-black } .toolbar { @@ -26,16 +26,6 @@ margin-top: -0.1rem; } -pre[class*='language-'].line-numbers { - position: relative; - padding: 3px; /*修改*/ - padding-left: 3.8em; - counter-reset: linenumber; - max-height: 400px; /*修改*/ - background: black; - border: none; -} - .notion-code > code[class*='language-'], pre[class*='language-'] { background: black; @@ -67,4 +57,9 @@ pre[class*='language-'] { .notion-code-copy{ display: none; +} + +pre[class*="language-mermaid"] { + background: transparent !important; + @apply dark:bg-gray-200 !important; } \ No newline at end of file diff --git a/themes/example/LayoutSearch.js b/themes/example/LayoutSearch.js index 984e47e7..23b10b7a 100644 --- a/themes/example/LayoutSearch.js +++ b/themes/example/LayoutSearch.js @@ -4,6 +4,7 @@ import { BlogListScroll } from './components/BlogListScroll' import { useRouter } from 'next/router' import { useEffect } from 'react' import SearchInput from './components/SearchInput' +import Mark from 'mark.js' import LayoutBase from './LayoutBase' import { isBrowser } from '@/lib/utils' @@ -15,8 +16,12 @@ export const LayoutSearch = props => { setTimeout(() => { const container = isBrowser() && document.getElementById('container') if (container && container.innerHTML) { - const re = new RegExp(`${keyword}`, 'gim') - container.innerHTML = container.innerHTML.replace(re, `${keyword}`) + const re = new RegExp(keyword, 'gim') + const instance = new Mark(container) + instance.markRegExp(re, { + element: 'span', + className: 'text-red-500 border-b border-dashed' + }) } }, 100) }, [router.events]) diff --git a/themes/fukasawa/LayoutSearch.js b/themes/fukasawa/LayoutSearch.js index 9329846d..fcfa35b2 100644 --- a/themes/fukasawa/LayoutSearch.js +++ b/themes/fukasawa/LayoutSearch.js @@ -4,6 +4,7 @@ import BlogListPage from './components/BlogListPage' import BlogListScroll from './components/BlogListScroll' import { useRouter } from 'next/router' import { useEffect } from 'react' +import Mark from 'mark.js' import { isBrowser } from '@/lib/utils' export const LayoutSearch = (props) => { @@ -14,8 +15,12 @@ export const LayoutSearch = (props) => { setTimeout(() => { const container = isBrowser() && document.getElementById('container') if (container && container.innerHTML) { - const re = new RegExp(`${currentSearch}`, 'gim') - container.innerHTML = container.innerHTML.replace(re, `${currentSearch}`) + const re = new RegExp(currentSearch, 'gim') + const instance = new Mark(container) + instance.markRegExp(re, { + element: 'span', + className: 'text-red-500 border-b border-dashed' + }) } }, 100) }) diff --git a/themes/hexo/LayoutSearch.js b/themes/hexo/LayoutSearch.js index 6454ef3a..679975cb 100644 --- a/themes/hexo/LayoutSearch.js +++ b/themes/hexo/LayoutSearch.js @@ -6,6 +6,7 @@ import BlogPostListPage from './components/BlogPostListPage' import LayoutBase from './LayoutBase' import SearchInput from './components/SearchInput' import { useGlobal } from '@/lib/global' +import Mark from 'mark.js' import TagItemMini from './components/TagItemMini' import Card from './components/Card' import Link from 'next/link' @@ -25,10 +26,12 @@ export const LayoutSearch = props => { const targets = document.getElementsByClassName('replace') for (const container of targets) { if (container && container.innerHTML) { - const re = new RegExp(`${currentSearch}`, 'gim') - container.innerHTML = container.innerHTML.replace( - re, `${currentSearch}` - ) + const re = new RegExp(currentSearch, 'gim') + const instance = new Mark(container) + instance.markRegExp(re, { + element: 'span', + className: 'text-red-500 border-b border-dashed' + }) } } } diff --git a/themes/medium/LayoutSearch.js b/themes/medium/LayoutSearch.js index 9a34bcec..76a9ddae 100644 --- a/themes/medium/LayoutSearch.js +++ b/themes/medium/LayoutSearch.js @@ -6,6 +6,7 @@ import CategoryGroup from './components/CategoryGroup' import { useEffect } from 'react' import { isBrowser } from '@/lib/utils' import BLOG from '@/blog.config' +import Mark from 'mark.js' import BlogPostListScroll from './components/BlogPostListScroll' import BlogPostListPage from './components/BlogPostListPage' @@ -16,8 +17,12 @@ export const LayoutSearch = (props) => { setTimeout(() => { const container = isBrowser() && document.getElementById('container') if (container && container.innerHTML) { - const re = new RegExp(`${keyword}`, 'gim') - container.innerHTML = container.innerHTML.replace(re, `${keyword}`) + const re = new RegExp(keyword, 'gim') + const instance = new Mark(container) + instance.markRegExp(re, { + element: 'span', + className: 'text-red-500 border-b border-dashed' + }) } }, 100) diff --git a/themes/medium/components/SearchInput.js b/themes/medium/components/SearchInput.js index a04e3345..5b037540 100644 --- a/themes/medium/components/SearchInput.js +++ b/themes/medium/components/SearchInput.js @@ -3,7 +3,6 @@ import { useImperativeHandle, useRef, useState } from 'react' let lock = false const SearchInput = ({ currentTag, currentSearch, cRef, className }) => { - // const [searchKey, setSearchKey] = useState(currentSearch || getSearchKey() || '') const [onLoading, setLoadingState] = useState(false) const router = useRouter() const searchInputRef = useRef() @@ -20,9 +19,6 @@ const SearchInput = ({ currentTag, currentSearch, cRef, className }) => { if (key && key !== '') { setLoadingState(true) - // router.push({ pathname: '/search/' + key }).then(r => { - // setLoadingState(false) - // }) location.href = '/search/' + key } else { router.push({ pathname: '/' }).then(r => { diff --git a/themes/next/LayoutSearch.js b/themes/next/LayoutSearch.js index d4ec1bb8..78664343 100644 --- a/themes/next/LayoutSearch.js +++ b/themes/next/LayoutSearch.js @@ -4,6 +4,7 @@ import { useGlobal } from '@/lib/global' import { isBrowser } from '@/lib/utils' import BlogPostListScroll from './components/BlogPostListScroll' import BlogPostListPage from './components/BlogPostListPage' +import Mark from 'mark.js' import BLOG from '@/blog.config' export const LayoutSearch = (props) => { @@ -12,8 +13,12 @@ export const LayoutSearch = (props) => { setTimeout(() => { const container = isBrowser() && document.getElementById('container') if (container && container.innerHTML) { - const re = new RegExp(`${keyword}`, 'gim') - container.innerHTML = container.innerHTML.replace(re, `${keyword}`) + const re = new RegExp(keyword, 'gim') + const instance = new Mark(container) + instance.markRegExp(re, { + element: 'span', + className: 'text-red-500 border-b border-dashed' + }) } }, 200) return (