mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-13 23:16:47 +00:00
精减 markjs ,精减 animate.css
This commit is contained in:
31
components/Mark.js
Normal file
31
components/Mark.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import { loadExternalResource } from '@/lib/utils'
|
||||
|
||||
/**
|
||||
* 将搜索结果的关键词高亮
|
||||
*/
|
||||
export default async function replaceSearchResult({ doms, search, target }) {
|
||||
if (!doms || !search || !target) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const url = await loadExternalResource('https://cdnjs.cloudflare.com/ajax/libs/mark.js/8.11.1/mark.min.js', 'js')
|
||||
console.log('markjs 加载成功', url, window.Mark)
|
||||
console.log('------', doms)
|
||||
|
||||
const Mark = window.Mark
|
||||
if (doms instanceof HTMLCollection) {
|
||||
for (const container of doms) {
|
||||
const re = new RegExp(search, 'gim')
|
||||
const instance = new Mark(container)
|
||||
instance.markRegExp(re, target)
|
||||
}
|
||||
} else {
|
||||
const re = new RegExp(search, 'gim')
|
||||
const instance = new Mark(doms)
|
||||
instance.markRegExp(re, target)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('markjs 加载失败', error)
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,9 @@ import React, { useEffect, useRef } from 'react'
|
||||
// import { Code } from 'react-notion-x/build/third-party/code'
|
||||
import TweetEmbed from 'react-tweet-embed'
|
||||
|
||||
import BLOG from '@/blog.config'
|
||||
import 'katex/dist/katex.min.css'
|
||||
import { mapImgUrl } from '@/lib/notion/mapImage'
|
||||
import BLOG from '@/blog.config'
|
||||
import { isBrowser } from '@/lib/utils'
|
||||
|
||||
const Code = dynamic(() =>
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
"@headlessui/react": "^1.7.15",
|
||||
"@next/bundle-analyzer": "^12.1.1",
|
||||
"@vercel/analytics": "^1.0.0",
|
||||
"animate.css": "^4.1.1",
|
||||
"animejs": "^3.2.1",
|
||||
"aos": "^3.0.0-beta.6",
|
||||
"axios": ">=0.21.1",
|
||||
@@ -35,7 +34,6 @@
|
||||
"js-md5": "^0.7.3",
|
||||
"localStorage": "^1.0.4",
|
||||
"lodash.throttle": "^4.1.1",
|
||||
"mark.js": "^8.11.1",
|
||||
"memory-cache": "^0.2.0",
|
||||
"mongodb": "^4.6.0",
|
||||
"next": "13.3.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useEffect } from 'react'
|
||||
|
||||
import 'animate.css'
|
||||
import '@/styles/animate.css' // @see https://animate.style/
|
||||
import '@/styles/globals.css'
|
||||
import '@/styles/nprogress.css'
|
||||
import '@/styles/utility-patterns.css'
|
||||
|
||||
503
styles/animate.css
vendored
Normal file
503
styles/animate.css
vendored
Normal file
@@ -0,0 +1,503 @@
|
||||
@charset "UTF-8";/*!
|
||||
* animate.css - https://animate.style/
|
||||
* Version - 4.1.1
|
||||
* Licensed under the MIT license - http://opensource.org/licenses/MIT
|
||||
* https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css
|
||||
* 这里做了精减,后续不再使用animate.css,因为占用体积太大,不如手写动画
|
||||
* Copyright (c) 2020 Animate.css
|
||||
*/
|
||||
:root {
|
||||
--animate-duration: 1s;
|
||||
--animate-delay: 1s;
|
||||
--animate-repeat: 1;
|
||||
}
|
||||
.animate__animated {
|
||||
-webkit-animation-duration: 1s;
|
||||
animation-duration: 1s;
|
||||
-webkit-animation-duration: var(--animate-duration);
|
||||
animation-duration: var(--animate-duration);
|
||||
-webkit-animation-fill-mode: both;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
|
||||
.animate__animated.animate__faster {
|
||||
-webkit-animation-duration: calc(1s / 2);
|
||||
animation-duration: calc(1s / 2);
|
||||
-webkit-animation-duration: calc(var(--animate-duration) / 2);
|
||||
animation-duration: calc(var(--animate-duration) / 2);
|
||||
}
|
||||
.animate__animated.animate__fast {
|
||||
-webkit-animation-duration: calc(1s * 0.8);
|
||||
animation-duration: calc(1s * 0.8);
|
||||
-webkit-animation-duration: calc(var(--animate-duration) * 0.8);
|
||||
animation-duration: calc(var(--animate-duration) * 0.8);
|
||||
}
|
||||
|
||||
|
||||
@media print, (prefers-reduced-motion: reduce) {
|
||||
.animate__animated {
|
||||
-webkit-animation-duration: 1ms !important;
|
||||
animation-duration: 1ms !important;
|
||||
-webkit-transition-duration: 1ms !important;
|
||||
transition-duration: 1ms !important;
|
||||
-webkit-animation-iteration-count: 1 !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
}
|
||||
|
||||
.animate__animated[class*='Out'] {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@-webkit-keyframes shakeX {
|
||||
from,
|
||||
to {
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
10%,
|
||||
30%,
|
||||
50%,
|
||||
70%,
|
||||
90% {
|
||||
-webkit-transform: translate3d(-10px, 0, 0);
|
||||
transform: translate3d(-10px, 0, 0);
|
||||
}
|
||||
|
||||
20%,
|
||||
40%,
|
||||
60%,
|
||||
80% {
|
||||
-webkit-transform: translate3d(10px, 0, 0);
|
||||
transform: translate3d(10px, 0, 0);
|
||||
}
|
||||
}
|
||||
@keyframes shakeX {
|
||||
from,
|
||||
to {
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
10%,
|
||||
30%,
|
||||
50%,
|
||||
70%,
|
||||
90% {
|
||||
-webkit-transform: translate3d(-10px, 0, 0);
|
||||
transform: translate3d(-10px, 0, 0);
|
||||
}
|
||||
|
||||
20%,
|
||||
40%,
|
||||
60%,
|
||||
80% {
|
||||
-webkit-transform: translate3d(10px, 0, 0);
|
||||
transform: translate3d(10px, 0, 0);
|
||||
}
|
||||
}
|
||||
.animate__shakeX {
|
||||
-webkit-animation-name: shakeX;
|
||||
animation-name: shakeX;
|
||||
}
|
||||
@-webkit-keyframes shakeY {
|
||||
from,
|
||||
to {
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
10%,
|
||||
30%,
|
||||
50%,
|
||||
70%,
|
||||
90% {
|
||||
-webkit-transform: translate3d(0, -10px, 0);
|
||||
transform: translate3d(0, -10px, 0);
|
||||
}
|
||||
|
||||
20%,
|
||||
40%,
|
||||
60%,
|
||||
80% {
|
||||
-webkit-transform: translate3d(0, 10px, 0);
|
||||
transform: translate3d(0, 10px, 0);
|
||||
}
|
||||
}
|
||||
@keyframes shakeY {
|
||||
from,
|
||||
to {
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
10%,
|
||||
30%,
|
||||
50%,
|
||||
70%,
|
||||
90% {
|
||||
-webkit-transform: translate3d(0, -10px, 0);
|
||||
transform: translate3d(0, -10px, 0);
|
||||
}
|
||||
|
||||
20%,
|
||||
40%,
|
||||
60%,
|
||||
80% {
|
||||
-webkit-transform: translate3d(0, 10px, 0);
|
||||
transform: translate3d(0, 10px, 0);
|
||||
}
|
||||
}
|
||||
.animate__shakeY {
|
||||
-webkit-animation-name: shakeY;
|
||||
animation-name: shakeY;
|
||||
}
|
||||
@-webkit-keyframes headShake {
|
||||
0% {
|
||||
-webkit-transform: translateX(0);
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
6.5% {
|
||||
-webkit-transform: translateX(-6px) rotateY(-9deg);
|
||||
transform: translateX(-6px) rotateY(-9deg);
|
||||
}
|
||||
|
||||
18.5% {
|
||||
-webkit-transform: translateX(5px) rotateY(7deg);
|
||||
transform: translateX(5px) rotateY(7deg);
|
||||
}
|
||||
|
||||
31.5% {
|
||||
-webkit-transform: translateX(-3px) rotateY(-5deg);
|
||||
transform: translateX(-3px) rotateY(-5deg);
|
||||
}
|
||||
|
||||
43.5% {
|
||||
-webkit-transform: translateX(2px) rotateY(3deg);
|
||||
transform: translateX(2px) rotateY(3deg);
|
||||
}
|
||||
|
||||
50% {
|
||||
-webkit-transform: translateX(0);
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
@keyframes headShake {
|
||||
0% {
|
||||
-webkit-transform: translateX(0);
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
6.5% {
|
||||
-webkit-transform: translateX(-6px) rotateY(-9deg);
|
||||
transform: translateX(-6px) rotateY(-9deg);
|
||||
}
|
||||
|
||||
18.5% {
|
||||
-webkit-transform: translateX(5px) rotateY(7deg);
|
||||
transform: translateX(5px) rotateY(7deg);
|
||||
}
|
||||
|
||||
31.5% {
|
||||
-webkit-transform: translateX(-3px) rotateY(-5deg);
|
||||
transform: translateX(-3px) rotateY(-5deg);
|
||||
}
|
||||
|
||||
43.5% {
|
||||
-webkit-transform: translateX(2px) rotateY(3deg);
|
||||
transform: translateX(2px) rotateY(3deg);
|
||||
}
|
||||
|
||||
50% {
|
||||
-webkit-transform: translateX(0);
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
.animate__headShake {
|
||||
-webkit-animation-timing-function: ease-in-out;
|
||||
animation-timing-function: ease-in-out;
|
||||
-webkit-animation-name: headShake;
|
||||
animation-name: headShake;
|
||||
}
|
||||
|
||||
|
||||
@keyframes jello {
|
||||
from,
|
||||
11.1%,
|
||||
to {
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
22.2% {
|
||||
-webkit-transform: skewX(-12.5deg) skewY(-12.5deg);
|
||||
transform: skewX(-12.5deg) skewY(-12.5deg);
|
||||
}
|
||||
|
||||
33.3% {
|
||||
-webkit-transform: skewX(6.25deg) skewY(6.25deg);
|
||||
transform: skewX(6.25deg) skewY(6.25deg);
|
||||
}
|
||||
|
||||
44.4% {
|
||||
-webkit-transform: skewX(-3.125deg) skewY(-3.125deg);
|
||||
transform: skewX(-3.125deg) skewY(-3.125deg);
|
||||
}
|
||||
|
||||
55.5% {
|
||||
-webkit-transform: skewX(1.5625deg) skewY(1.5625deg);
|
||||
transform: skewX(1.5625deg) skewY(1.5625deg);
|
||||
}
|
||||
|
||||
66.6% {
|
||||
-webkit-transform: skewX(-0.78125deg) skewY(-0.78125deg);
|
||||
transform: skewX(-0.78125deg) skewY(-0.78125deg);
|
||||
}
|
||||
|
||||
77.7% {
|
||||
-webkit-transform: skewX(0.390625deg) skewY(0.390625deg);
|
||||
transform: skewX(0.390625deg) skewY(0.390625deg);
|
||||
}
|
||||
|
||||
88.8% {
|
||||
-webkit-transform: skewX(-0.1953125deg) skewY(-0.1953125deg);
|
||||
transform: skewX(-0.1953125deg) skewY(-0.1953125deg);
|
||||
}
|
||||
}
|
||||
.animate__jello {
|
||||
-webkit-animation-name: jello;
|
||||
animation-name: jello;
|
||||
-webkit-transform-origin: center;
|
||||
transform-origin: center;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@-webkit-keyframes bounceInRight {
|
||||
from,
|
||||
60%,
|
||||
75%,
|
||||
90%,
|
||||
to {
|
||||
-webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
}
|
||||
|
||||
from {
|
||||
opacity: 0;
|
||||
-webkit-transform: translate3d(3000px, 0, 0) scaleX(3);
|
||||
transform: translate3d(3000px, 0, 0) scaleX(3);
|
||||
}
|
||||
|
||||
60% {
|
||||
opacity: 1;
|
||||
-webkit-transform: translate3d(-25px, 0, 0) scaleX(1);
|
||||
transform: translate3d(-25px, 0, 0) scaleX(1);
|
||||
}
|
||||
|
||||
75% {
|
||||
-webkit-transform: translate3d(10px, 0, 0) scaleX(0.98);
|
||||
transform: translate3d(10px, 0, 0) scaleX(0.98);
|
||||
}
|
||||
|
||||
90% {
|
||||
-webkit-transform: translate3d(-5px, 0, 0) scaleX(0.995);
|
||||
transform: translate3d(-5px, 0, 0) scaleX(0.995);
|
||||
}
|
||||
|
||||
to {
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
@keyframes bounceInRight {
|
||||
from,
|
||||
60%,
|
||||
75%,
|
||||
90%,
|
||||
to {
|
||||
-webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
}
|
||||
|
||||
from {
|
||||
opacity: 0;
|
||||
-webkit-transform: translate3d(3000px, 0, 0) scaleX(3);
|
||||
transform: translate3d(3000px, 0, 0) scaleX(3);
|
||||
}
|
||||
|
||||
60% {
|
||||
opacity: 1;
|
||||
-webkit-transform: translate3d(-25px, 0, 0) scaleX(1);
|
||||
transform: translate3d(-25px, 0, 0) scaleX(1);
|
||||
}
|
||||
|
||||
75% {
|
||||
-webkit-transform: translate3d(10px, 0, 0) scaleX(0.98);
|
||||
transform: translate3d(10px, 0, 0) scaleX(0.98);
|
||||
}
|
||||
|
||||
90% {
|
||||
-webkit-transform: translate3d(-5px, 0, 0) scaleX(0.995);
|
||||
transform: translate3d(-5px, 0, 0) scaleX(0.995);
|
||||
}
|
||||
|
||||
to {
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
.animate__bounceInRight {
|
||||
-webkit-animation-name: bounceInRight;
|
||||
animation-name: bounceInRight;
|
||||
}
|
||||
|
||||
|
||||
/* Fading entrances */
|
||||
@-webkit-keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.animate__fadeIn {
|
||||
-webkit-animation-name: fadeIn;
|
||||
animation-name: fadeIn;
|
||||
}
|
||||
|
||||
|
||||
/* Fading exits */
|
||||
/* 删除 */
|
||||
|
||||
/* Flippers */
|
||||
/* 删除 */
|
||||
|
||||
/* Lightspeed */
|
||||
/* 删除 */
|
||||
|
||||
/* Rotating exits */
|
||||
/* 删除 */
|
||||
|
||||
/* Zooming entrances */
|
||||
/* 删除 */
|
||||
|
||||
/* Sliding entrances */
|
||||
|
||||
@-webkit-keyframes slideInLeft {
|
||||
from {
|
||||
-webkit-transform: translate3d(-100%, 0, 0);
|
||||
transform: translate3d(-100%, 0, 0);
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
to {
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
@keyframes slideInLeft {
|
||||
from {
|
||||
-webkit-transform: translate3d(-100%, 0, 0);
|
||||
transform: translate3d(-100%, 0, 0);
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
to {
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
.animate__slideInLeft {
|
||||
-webkit-animation-name: slideInLeft;
|
||||
animation-name: slideInLeft;
|
||||
}
|
||||
@-webkit-keyframes slideInRight {
|
||||
from {
|
||||
-webkit-transform: translate3d(100%, 0, 0);
|
||||
transform: translate3d(100%, 0, 0);
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
to {
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
@keyframes slideInRight {
|
||||
from {
|
||||
-webkit-transform: translate3d(100%, 0, 0);
|
||||
transform: translate3d(100%, 0, 0);
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
to {
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
.animate__slideInRight {
|
||||
-webkit-animation-name: slideInRight;
|
||||
animation-name: slideInRight;
|
||||
}
|
||||
|
||||
|
||||
@keyframes slideOutLeft {
|
||||
from {
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
to {
|
||||
visibility: hidden;
|
||||
-webkit-transform: translate3d(-100%, 0, 0);
|
||||
transform: translate3d(-100%, 0, 0);
|
||||
}
|
||||
}
|
||||
.animate__slideOutLeft {
|
||||
-webkit-animation-name: slideOutLeft;
|
||||
animation-name: slideOutLeft;
|
||||
}
|
||||
@-webkit-keyframes slideOutRight {
|
||||
from {
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
to {
|
||||
visibility: hidden;
|
||||
-webkit-transform: translate3d(100%, 0, 0);
|
||||
transform: translate3d(100%, 0, 0);
|
||||
}
|
||||
}
|
||||
@keyframes slideOutRight {
|
||||
from {
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
to {
|
||||
visibility: hidden;
|
||||
-webkit-transform: translate3d(100%, 0, 0);
|
||||
transform: translate3d(100%, 0, 0);
|
||||
}
|
||||
}
|
||||
.animate__slideOutRight {
|
||||
-webkit-animation-name: slideOutRight;
|
||||
animation-name: slideOutRight;
|
||||
}
|
||||
@@ -19,7 +19,7 @@ import NotionPage from '@/components/NotionPage'
|
||||
import Comment from '@/components/Comment'
|
||||
import ShareBar from '@/components/ShareBar'
|
||||
import SearchInput from './components/SearchInput'
|
||||
import Mark from 'mark.js'
|
||||
import replaceSearchResult from '@/components/Mark'
|
||||
import { isBrowser } from '@/lib/utils'
|
||||
import BlogListGroupByDate from './components/BlogListGroupByDate'
|
||||
import CategoryItem from './components/CategoryItem'
|
||||
@@ -175,21 +175,20 @@ const LayoutSearch = props => {
|
||||
const slotTop = <div className='pb-12'><SearchInput {...props} /></div>
|
||||
const router = useRouter()
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
if (isBrowser()) {
|
||||
// 高亮搜索到的结果
|
||||
const container = document.getElementById('posts-wrapper')
|
||||
console.log('container', container, keyword)
|
||||
if (keyword && container) {
|
||||
const re = new RegExp(keyword, 'gim')
|
||||
const instance = new Mark(container)
|
||||
instance.markRegExp(re, {
|
||||
if (isBrowser()) {
|
||||
// 高亮搜索到的结果
|
||||
const container = document.getElementById('posts-wrapper')
|
||||
if (keyword && container) {
|
||||
replaceSearchResult({
|
||||
doms: container,
|
||||
search: keyword,
|
||||
target: {
|
||||
element: 'span',
|
||||
className: 'text-red-500 border-b border-dashed'
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}, 500)
|
||||
}
|
||||
}, [router])
|
||||
|
||||
return <LayoutPostList slotTop={slotTop} {...props} />
|
||||
|
||||
@@ -20,9 +20,9 @@ import { Transition } from '@headlessui/react'
|
||||
import dynamic from 'next/dynamic'
|
||||
import { AdSlot } from '@/components/GoogleAdsense'
|
||||
import { Style } from './style'
|
||||
import replaceSearchResult from '@/components/Mark'
|
||||
|
||||
const Live2D = dynamic(() => import('@/components/Live2D'))
|
||||
const Mark = dynamic(() => import('mark.js'))
|
||||
|
||||
// 主题全局状态
|
||||
const ThemeGlobalFukasawa = createContext()
|
||||
@@ -148,17 +148,16 @@ const LayoutSearch = props => {
|
||||
const { keyword } = props
|
||||
const router = useRouter()
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
const container = isBrowser() && document.getElementById('posts-wrapper')
|
||||
if (container && container.innerHTML) {
|
||||
const re = new RegExp(keyword, 'gim')
|
||||
const instance = new Mark(container)
|
||||
instance.markRegExp(re, {
|
||||
if (isBrowser()) {
|
||||
replaceSearchResult({
|
||||
doms: document.getElementById('posts-wrapper'),
|
||||
search: keyword,
|
||||
target: {
|
||||
element: 'span',
|
||||
className: 'text-red-500 border-b border-dashed'
|
||||
})
|
||||
}
|
||||
}, 300)
|
||||
}
|
||||
})
|
||||
}
|
||||
}, [router])
|
||||
return <LayoutPostList {...props} />
|
||||
}
|
||||
|
||||
@@ -54,8 +54,8 @@ const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
{/* 搜索结果 */}
|
||||
{post.results && (
|
||||
<p className="line-clamp-2 mt-4 text-gray-700 dark:text-gray-300 text-sm font-light leading-7">
|
||||
{post.results.map(r => (
|
||||
<span key={r}>{r}</span>
|
||||
{post.results.map((r, index) => (
|
||||
<span key={index}>{r}</span>
|
||||
))}
|
||||
</p>
|
||||
)}
|
||||
|
||||
@@ -7,12 +7,10 @@ import SideRight from './components/SideRight'
|
||||
import NavBar from './components/NavBar'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import BLOG from '@/blog.config'
|
||||
import { isBrowser, loadExternalResource } from '@/lib/utils'
|
||||
import BlogPostListPage from './components/BlogPostListPage'
|
||||
import BlogPostListScroll from './components/BlogPostListScroll'
|
||||
import Hero from './components/Hero'
|
||||
import { useRouter } from 'next/router'
|
||||
import Mark from 'mark.js'
|
||||
import SearchNav from './components/SearchNav'
|
||||
import BlogPostArchive from './components/BlogPostArchive'
|
||||
import { ArticleLock } from './components/ArticleLock'
|
||||
@@ -31,6 +29,7 @@ import { NoticeBar } from './components/NoticeBar'
|
||||
import { HashTag } from '@/components/HeroIcons'
|
||||
import LatestPostsGroup from './components/LatestPostsGroup'
|
||||
import FloatTocButton from './components/FloatTocButton'
|
||||
import replaceSearchResult from '@/components/Mark'
|
||||
|
||||
/**
|
||||
* 基础布局 采用上中下布局,移动端使用顶部侧边导航栏
|
||||
@@ -42,11 +41,6 @@ const LayoutBase = props => {
|
||||
const { children, headerSlot, slotTop, slotRight, meta, siteInfo, className } = props
|
||||
const { onLoading } = useGlobal()
|
||||
|
||||
// 加载主题样式
|
||||
if (isBrowser()) {
|
||||
loadExternalResource('/css/theme-hexo.css', 'css')
|
||||
}
|
||||
|
||||
return (
|
||||
<div id='theme-heo' className='bg-[#f7f9fe] dark:bg-[#18171d] h-full min-h-screen flex flex-col'>
|
||||
{/* 网页SEO */}
|
||||
@@ -168,23 +162,20 @@ const LayoutSearch = props => {
|
||||
</header>
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
if (currentSearch) {
|
||||
const targets = document.getElementsByClassName('replace')
|
||||
for (const container of targets) {
|
||||
if (container && container.innerHTML) {
|
||||
const re = new RegExp(currentSearch, 'gim')
|
||||
const instance = new Mark(container)
|
||||
instance.markRegExp(re, {
|
||||
element: 'span',
|
||||
className: 'text-red-500 border-b border-dashed'
|
||||
})
|
||||
// 高亮搜索结果
|
||||
if (currentSearch) {
|
||||
setTimeout(() => {
|
||||
replaceSearchResult({
|
||||
doms: document.getElementsByClassName('replace'),
|
||||
search: currentSearch,
|
||||
target: {
|
||||
element: 'span',
|
||||
className: 'text-red-500 border-b border-dashed'
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 100)
|
||||
})
|
||||
|
||||
})
|
||||
}, 100)
|
||||
}
|
||||
}, [])
|
||||
return (
|
||||
<LayoutBase {...props} currentSearch={currentSearch} headerSlot={headerSlot}>
|
||||
<div id='post-outer-wrapper' className='px-5 lg:px-0'>
|
||||
|
||||
@@ -51,9 +51,9 @@ export const BlogPostCardInfo = ({ post, showPreview, showPageCover, showSummary
|
||||
{/* 搜索结果 */}
|
||||
{post.results && (
|
||||
<p className="line-clamp-2 mt-4 text-gray-700 dark:text-gray-300 text-sm font-light leading-7">
|
||||
{post.results.map(r => (
|
||||
<span key={r}>{r}</span>
|
||||
))}
|
||||
{post.results.map((r, index) => (
|
||||
<span key={index}>{r}</span>
|
||||
))}
|
||||
</p>
|
||||
)}
|
||||
{/* 预览 */}
|
||||
|
||||
@@ -12,7 +12,6 @@ import BlogPostListPage from './components/BlogPostListPage'
|
||||
import BlogPostListScroll from './components/BlogPostListScroll'
|
||||
import Hero from './components/Hero'
|
||||
import { useRouter } from 'next/router'
|
||||
import Mark from 'mark.js'
|
||||
import Card from './components/Card'
|
||||
import RightFloatArea from './components/RightFloatArea'
|
||||
import SearchNav from './components/SearchNav'
|
||||
@@ -33,6 +32,7 @@ import Link from 'next/link'
|
||||
import SlotBar from './components/SlotBar'
|
||||
import { Transition } from '@headlessui/react'
|
||||
import { Style } from './style'
|
||||
import replaceSearchResult from '@/components/Mark'
|
||||
|
||||
/**
|
||||
* 基础布局 采用左右两侧布局,移动端使用顶部导航栏
|
||||
@@ -139,21 +139,16 @@ const LayoutSearch = props => {
|
||||
const currentSearch = keyword || router?.query?.s
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
if (currentSearch) {
|
||||
const targets = document.getElementsByClassName('replace')
|
||||
for (const container of targets) {
|
||||
if (container && container.innerHTML) {
|
||||
const re = new RegExp(currentSearch, 'gim')
|
||||
const instance = new Mark(container)
|
||||
instance.markRegExp(re, {
|
||||
element: 'span',
|
||||
className: 'text-red-500 border-b border-dashed'
|
||||
})
|
||||
}
|
||||
if (currentSearch) {
|
||||
replaceSearchResult({
|
||||
doms: document.getElementsByClassName('replace'),
|
||||
search: keyword,
|
||||
target: {
|
||||
element: 'span',
|
||||
className: 'text-red-500 border-b border-dashed'
|
||||
}
|
||||
}
|
||||
}, 100)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return (
|
||||
|
||||
@@ -8,7 +8,6 @@ import Footer from './components/Footer'
|
||||
import { useEffect } from 'react'
|
||||
import RightFloatButtons from './components/RightFloatButtons'
|
||||
import { useRouter } from 'next/router'
|
||||
import Mark from 'mark.js'
|
||||
import SearchNave from './components/SearchNav'
|
||||
import BlogPostListPage from './components/BlogPostListPage'
|
||||
import BlogPostListScroll from './components/BlogPostListScroll'
|
||||
@@ -31,6 +30,7 @@ import JumpToCommentButton from './components/JumpToCommentButton'
|
||||
import BlogListBar from './components/BlogListBar'
|
||||
import { Transition } from '@headlessui/react'
|
||||
import { Style } from './style'
|
||||
import replaceSearchResult from '@/components/Mark'
|
||||
|
||||
/**
|
||||
* 基础布局
|
||||
@@ -140,21 +140,16 @@ const LayoutSearch = props => {
|
||||
const currentSearch = keyword || router?.query?.s
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
if (currentSearch) {
|
||||
const targets = document.getElementsByClassName('replace')
|
||||
for (const container of targets) {
|
||||
if (container && container.innerHTML) {
|
||||
const re = new RegExp(currentSearch, 'gim')
|
||||
const instance = new Mark(container)
|
||||
instance.markRegExp(re, {
|
||||
element: 'span',
|
||||
className: 'text-red-500 border-b border-dashed'
|
||||
})
|
||||
}
|
||||
if (currentSearch) {
|
||||
replaceSearchResult({
|
||||
doms: document.getElementsByClassName('replace'),
|
||||
search: keyword,
|
||||
target: {
|
||||
element: 'span',
|
||||
className: 'text-red-500 border-b border-dashed'
|
||||
}
|
||||
}
|
||||
}, 100)
|
||||
})
|
||||
}
|
||||
})
|
||||
return (
|
||||
<LayoutBase {...props} currentSearch={currentSearch}>
|
||||
|
||||
@@ -22,7 +22,6 @@ import { ArticleLock } from './components/ArticleLock'
|
||||
import TagGroups from './components/TagGroups'
|
||||
import CategoryGroup from './components/CategoryGroup'
|
||||
import { isBrowser } from '@/lib/utils'
|
||||
import Mark from 'mark.js'
|
||||
import BlogArchiveItem from './components/BlogArchiveItem'
|
||||
import BlogPostBar from './components/BlogPostBar'
|
||||
import NotionPage from '@/components/NotionPage'
|
||||
@@ -35,6 +34,7 @@ import ShareBar from '@/components/ShareBar'
|
||||
import Link from 'next/link'
|
||||
import { Transition } from '@headlessui/react'
|
||||
import { Style } from './style'
|
||||
import replaceSearchResult from '@/components/Mark'
|
||||
|
||||
// 主题全局状态
|
||||
const ThemeGlobalMedium = createContext()
|
||||
@@ -202,18 +202,18 @@ const LayoutSearch = (props) => {
|
||||
const currentSearch = keyword || router?.query?.s
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
const container = isBrowser() && document.getElementById('posts-wrapper')
|
||||
if (container && container.innerHTML) {
|
||||
const re = new RegExp(currentSearch, 'gim')
|
||||
const instance = new Mark(container)
|
||||
instance.markRegExp(re, {
|
||||
if (isBrowser()) {
|
||||
replaceSearchResult({
|
||||
doms: document.getElementById('posts-wrapper'),
|
||||
search: keyword,
|
||||
target: {
|
||||
element: 'span',
|
||||
className: 'text-red-500 border-b border-dashed'
|
||||
})
|
||||
}
|
||||
}, 100)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}, [])
|
||||
|
||||
return <LayoutBase {...props}>
|
||||
|
||||
{/* 搜索导航栏 */}
|
||||
|
||||
@@ -86,8 +86,8 @@ const BlogPostCard = ({ post, showSummary }) => {
|
||||
{/* 搜索结果 */}
|
||||
{post.results && (
|
||||
<p className="line-clamp-4 mt-4 text-gray-700 dark:text-gray-300 text-sm font-light leading-7">
|
||||
{post.results.map(r => (
|
||||
<span key={r}>{r}</span>
|
||||
{post.results.map((r, index) => (
|
||||
<span key={index}>{r}</span>
|
||||
))}
|
||||
</p>
|
||||
)}
|
||||
|
||||
@@ -16,7 +16,6 @@ import BlogPostListScroll from './components/BlogPostListScroll'
|
||||
import BlogPostListPage from './components/BlogPostListPage'
|
||||
import StickyBar from './components/StickyBar'
|
||||
import { isBrowser } from '@/lib/utils'
|
||||
import Mark from 'mark.js'
|
||||
import TocDrawerButton from './components/TocDrawerButton'
|
||||
import TocDrawer from './components/TocDrawer'
|
||||
import { ArticleLock } from './components/ArticleLock'
|
||||
@@ -28,6 +27,7 @@ import Link from 'next/link'
|
||||
import BlogListBar from './components/BlogListBar'
|
||||
import { Transition } from '@headlessui/react'
|
||||
import { Style } from './style'
|
||||
import replaceSearchResult from '@/components/Mark'
|
||||
|
||||
/**
|
||||
* 基础布局 采用左中右三栏布局,移动端使用顶部导航栏
|
||||
@@ -161,17 +161,20 @@ const LayoutPostList = (props) => {
|
||||
const LayoutSearch = (props) => {
|
||||
const { locale } = useGlobal()
|
||||
const { posts, keyword } = props
|
||||
setTimeout(() => {
|
||||
const container = isBrowser() && document.getElementById('posts-wrapper')
|
||||
if (container && container.innerHTML) {
|
||||
const re = new RegExp(keyword, 'gim')
|
||||
const instance = new Mark(container)
|
||||
instance.markRegExp(re, {
|
||||
element: 'span',
|
||||
className: 'text-red-500 border-b border-dashed'
|
||||
|
||||
useEffect(() => {
|
||||
if (isBrowser()) {
|
||||
replaceSearchResult({
|
||||
doms: document.getElementById('posts-wrapper'),
|
||||
search: keyword,
|
||||
target: {
|
||||
element: 'span',
|
||||
className: 'text-red-500 border-b border-dashed'
|
||||
}
|
||||
})
|
||||
}
|
||||
}, 200)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<LayoutBase {...props} >
|
||||
<StickyBar>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import BLOG from '@/blog.config'
|
||||
import CONFIG from './config'
|
||||
import CommonHead from '@/components/CommonHead'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
@@ -6,15 +7,9 @@ import { Footer } from './components/Footer'
|
||||
import JumpToTopButton from './components/JumpToTopButton'
|
||||
import Live2D from '@/components/Live2D'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
|
||||
import BLOG from '@/blog.config'
|
||||
import Announcement from './components/Announcement'
|
||||
import { BlogListPage } from './components/BlogListPage'
|
||||
import { BlogListScroll } from './components/BlogListScroll'
|
||||
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
import Mark from 'mark.js'
|
||||
import { deepClone, isBrowser } from '@/lib/utils'
|
||||
import SearchNavBar from './components/SearchNavBar'
|
||||
import BlogArchiveItem from './components/BlogArchiveItem'
|
||||
@@ -28,6 +23,7 @@ import Link from 'next/link'
|
||||
import BlogListBar from './components/BlogListBar'
|
||||
import { Transition } from '@headlessui/react'
|
||||
import { Style } from './style'
|
||||
import replaceSearchResult from '@/components/Mark'
|
||||
|
||||
/**
|
||||
* 基础布局 采用左右两侧布局,移动端使用顶部导航栏
|
||||
@@ -135,22 +131,18 @@ const LayoutPostList = props => {
|
||||
*/
|
||||
const LayoutSearch = props => {
|
||||
const { keyword } = props
|
||||
const router = useRouter()
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
const container = isBrowser() && document.getElementById('posts-wrapper')
|
||||
if (container && container.innerHTML) {
|
||||
const re = new RegExp(keyword, 'gim')
|
||||
const instance = new Mark(container)
|
||||
instance.markRegExp(re, {
|
||||
if (isBrowser()) {
|
||||
replaceSearchResult({
|
||||
doms: document.getElementById('posts-wrapper'),
|
||||
search: keyword,
|
||||
target: {
|
||||
element: 'span',
|
||||
className: 'text-red-500 border-b border-dashed'
|
||||
})
|
||||
}
|
||||
}, 100)
|
||||
}, [router.events])
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
}, [])
|
||||
return <LayoutPostList {...props} slotTop={<SearchNavBar {...props} />} />
|
||||
}
|
||||
|
||||
|
||||
@@ -7,10 +7,6 @@ import { useGlobal } from '@/lib/global'
|
||||
import BLOG from '@/blog.config'
|
||||
import { BlogListPage } from './components/BlogListPage'
|
||||
import { BlogListScroll } from './components/BlogListScroll'
|
||||
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
import Mark from 'mark.js'
|
||||
import { isBrowser } from '@/lib/utils'
|
||||
import SearchNavBar from './components/SearchNavBar'
|
||||
import BlogArchiveItem from './components/BlogArchiveItem'
|
||||
@@ -26,6 +22,7 @@ import BottomNav from './components/BottomNav'
|
||||
import { saveDarkModeToCookies } from '@/themes/theme'
|
||||
import Modal from './components/Modal'
|
||||
import { Style } from './style'
|
||||
import replaceSearchResult from '@/components/Mark'
|
||||
|
||||
// 主题全局状态
|
||||
const ThemeGlobalPlog = createContext()
|
||||
@@ -133,21 +130,19 @@ const LayoutPostList = props => {
|
||||
*/
|
||||
const LayoutSearch = props => {
|
||||
const { keyword } = props
|
||||
const router = useRouter()
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
const container = isBrowser() && document.getElementById('posts-wrapper')
|
||||
if (container && container.innerHTML) {
|
||||
const re = new RegExp(keyword, 'gim')
|
||||
const instance = new Mark(container)
|
||||
instance.markRegExp(re, {
|
||||
if (isBrowser()) {
|
||||
replaceSearchResult({
|
||||
doms: document.getElementById('posts-wrapper'),
|
||||
search: keyword,
|
||||
target: {
|
||||
element: 'span',
|
||||
className: 'text-red-500 border-b border-dashed'
|
||||
})
|
||||
}
|
||||
}, 100)
|
||||
}, [router.events])
|
||||
}
|
||||
})
|
||||
}
|
||||
}, [])
|
||||
|
||||
return <LayoutPostList {...props} topSlot={<SearchNavBar {...props} />} />
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import CONFIG from './config'
|
||||
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, loadExternalResource } from '@/lib/utils'
|
||||
import BlogArchiveItem from './components/BlogArchiveItem'
|
||||
import { ArticleLock } from './components/ArticleLock'
|
||||
@@ -26,6 +24,7 @@ import { useGlobal } from '@/lib/global'
|
||||
import SearchInput from './components/SearchInput'
|
||||
import { Transition } from '@headlessui/react'
|
||||
import { Style } from './style'
|
||||
import replaceSearchResult from '@/components/Mark'
|
||||
|
||||
/**
|
||||
* 基础布局
|
||||
@@ -120,20 +119,19 @@ const LayoutPostList = props => {
|
||||
*/
|
||||
const LayoutSearch = props => {
|
||||
const { keyword } = props
|
||||
const router = useRouter()
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
const container = isBrowser() && document.getElementById('posts-wrapper')
|
||||
if (container && container.innerHTML) {
|
||||
const re = new RegExp(keyword, 'gim')
|
||||
const instance = new Mark(container)
|
||||
instance.markRegExp(re, {
|
||||
if (isBrowser()) {
|
||||
replaceSearchResult({
|
||||
doms: document.getElementById('posts-wrapper'),
|
||||
search: keyword,
|
||||
target: {
|
||||
element: 'span',
|
||||
className: 'text-red-500 border-b border-dashed'
|
||||
})
|
||||
}
|
||||
}, 100)
|
||||
}, [router])
|
||||
}
|
||||
})
|
||||
}
|
||||
}, [])
|
||||
|
||||
return <LayoutPostList {...props} slotTop={<SearchInput {...props} />} />
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user