Skip to content

Commit 5185091

Browse files
authored
Merge branch 'tangly1024:main' into martini
2 parents 054daa7 + 3e6cee1 commit 5185091

18 files changed

+347
-197
lines changed

components/NotionPage.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const NotionPage = ({ post, className }) => {
3131
// 页面首次打开时执行的勾子
3232
useEffect(() => {
3333
// 检测当前的url并自动滚动到对应目标
34-
autoScrollToTarget()
34+
autoScrollToHash()
3535
}, [])
3636

3737
// 页面文章发生变化时会执行的勾子
@@ -144,9 +144,9 @@ const processGalleryImg = zoom => {
144144
}
145145

146146
/**
147-
* 根据url参数自动滚动到指定区域
147+
* 根据url参数自动滚动到锚位置
148148
*/
149-
const autoScrollToTarget = () => {
149+
const autoScrollToHash = () => {
150150
setTimeout(() => {
151151
// 跳转到指定标题
152152
const needToJumpToTitle = window.location.hash

lib/config.js

+44-26
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import BLOG from '@/blog.config'
44
import { useGlobal } from './global'
5-
import { deepClone } from './utils'
5+
import { deepClone, isUrl } from './utils'
66

77
/**
88
* 读取配置顺序
@@ -32,6 +32,8 @@ export const siteConfig = (key, defaultVal = null, extendConfig = {}) => {
3232
case 'POST_LIST_STYLE':
3333
case 'POST_LIST_PREVIEW':
3434
case 'POST_URL_PREFIX_MAPPING_CATEGORY':
35+
case 'IS_TAG_COLOR_DISTINGUISHED':
36+
case 'TAG_SORT_BY_COUNT':
3537
return convertVal(extendConfig[key] || defaultVal || BLOG[key])
3638
default:
3739
}
@@ -89,46 +91,62 @@ export const siteConfig = (key, defaultVal = null, extendConfig = {}) => {
8991
return defaultVal
9092
}
9193

92-
// 从Notion_CONFIG读取的配置通常都是字符串,适当转义
9394
return convertVal(val)
9495
}
9596

9697
/**
97-
* 配置默认都是string类型;
98-
* 识别配置的值是否数字、布尔、[]数组,若是则转成对应类型
98+
* 从环境变量和NotionConfig读取的配置都是string类型;
99+
* 这里识别出配置的字符值若为否 数字、布尔、[]数组,{}对象,若是则转成对应类型
100+
* 使用JSON和eval两个函数
99101
* @param {*} val
100102
* @returns
101103
*/
102104
export const convertVal = val => {
103-
if (typeof val === 'string') {
104-
// 解析布尔
105-
if (val === 'true' || val === 'false') {
106-
return JSON.parse(val)
107-
}
105+
// 如果传入参数本身就是obj、数组、boolean 就无需处理
106+
if (typeof val !== 'string' || !val) {
107+
return val
108+
}
108109

109-
// 解析数字,parseInt将字符串转换为数字
110-
if (/^\d+$/.test(val)) {
111-
return parseInt(val)
112-
}
113-
// 转移 [] , {} 这种json串为json对象
114-
try {
115-
const parsedJson = JSON.parse(val)
116-
// 检查解析后的结果是否是对象或数组
117-
if (typeof parsedJson === 'object' && parsedJson !== null) {
118-
return parsedJson
119-
}
120-
} catch (error) {
121-
// JSON 解析失败,返回原始字符串值
122-
return val
123-
}
110+
// 解析数字,parseInt将字符串转换为数字
111+
if (/^\d+$/.test(val)) {
112+
return parseInt(val)
124113
}
125114

126-
try {
115+
// 检测是否url
116+
if (isUrl(val)) {
117+
return val
118+
}
119+
// 检测是否url
120+
if (val === 'true' || val === 'false') {
127121
return JSON.parse(val)
122+
}
123+
124+
// 配置值前可能有污染的空格
125+
if (!val.indexOf('[') > 0 || val.indexOf('{')) {
126+
return val
127+
}
128+
129+
// 转换 [] , {} , true/false 这类字符串为对象
130+
try {
131+
// 尝试解析json
132+
const parsedJson = JSON.parse(val)
133+
if (parsedJson !== null) {
134+
return parsedJson
135+
}
128136
} catch (error) {
129-
// 如果值是一个字符串但不是有效的 JSON 格式,直接返回字符串
137+
// try {
138+
// // 尝试解析对象,对象解析能力不如上一步的json
139+
// const evalObj = eval('(' + val + ')')
140+
// if (evalObj !== null) {
141+
// return evalObj
142+
// }
143+
// } catch (error) {
144+
// // Ojbject 解析失败,返回原始字符串值
145+
// return val
146+
// }
130147
return val
131148
}
149+
return val
132150
}
133151

134152
/**

lib/notion/convertInnerUrl.js

+20-14
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,15 @@ import { checkStrIsNotionId, getLastPartOfUrl, isBrowser } from '../utils'
88
*/
99
export const convertInnerUrl = allPages => {
1010
if (isBrowser) {
11+
const allAnchorTags = document
12+
?.getElementById('notion-article')
13+
?.getElementsByTagName('a')
14+
15+
if (!allAnchorTags) {
16+
return
17+
}
1118
const currentURL = window.location.origin + window.location.pathname
12-
const allAnchorTags = document.getElementsByTagName('a') // 或者使用 document.querySelectorAll('a') 获取 NodeList
19+
// url替换成slug
1320
for (const anchorTag of allAnchorTags) {
1421
// 检查url
1522
if (anchorTag?.href) {
@@ -24,20 +31,19 @@ export const convertInnerUrl = allPages => {
2431
}
2532
}
2633
}
34+
}
2735

28-
for (const anchorTag of allAnchorTags) {
29-
if (anchorTag?.target === '_blank') {
30-
const hrefWithoutQueryHash = anchorTag.href
31-
.split('?')[0]
32-
.split('#')[0]
33-
const hrefWithRelativeHash =
34-
currentURL.split('#')[0] || '' + anchorTag.href.split('#')[1] || ''
35-
if (
36-
currentURL === hrefWithoutQueryHash ||
37-
currentURL === hrefWithRelativeHash
38-
) {
39-
anchorTag.target = '_self'
40-
}
36+
// 链接在当前页面打开
37+
for (const anchorTag of allAnchorTags) {
38+
if (anchorTag?.target === '_blank') {
39+
const hrefWithoutQueryHash = anchorTag.href.split('?')[0].split('#')[0]
40+
const hrefWithRelativeHash =
41+
currentURL.split('#')[0] || '' + anchorTag.href.split('#')[1] || ''
42+
if (
43+
currentURL === hrefWithoutQueryHash ||
44+
currentURL === hrefWithRelativeHash
45+
) {
46+
anchorTag.target = '_self'
4147
}
4248
}
4349
}

lib/notion/getPageProperties.js

+16-2
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ import formatDate from '../utils/formatDate'
66
import md5 from 'js-md5'
77
import { siteConfig } from '../config'
88
import {
9-
checkContainHttp,
9+
checkStartWithHttp,
1010
convertUrlStartWithOneSlash,
11+
getLastSegmentFromUrl,
1112
sliceUrlFromHttp
1213
} from '../utils'
14+
import { extractLangPrefix } from '../utils/pageId'
1315
import { mapImgUrl } from './mapImage'
1416

1517
/**
@@ -197,7 +199,7 @@ export function adjustPageProperties(properties, NOTION_CONFIG) {
197199
}
198200

199201
// 检查处理外链
200-
properties.href = checkContainHttp(properties?.href)
202+
properties.href = checkStartWithHttp(properties?.href)
201203
? sliceUrlFromHttp(properties?.href)
202204
: convertUrlStartWithOneSlash(properties?.href)
203205

@@ -208,6 +210,18 @@ export function adjustPageProperties(properties, NOTION_CONFIG) {
208210
properties.target = '_self'
209211
}
210212

213+
// 如果跳转链接是多语言,则在新窗口打开
214+
if (BLOG.NOTION_PAGE_ID.indexOf(',') > 0) {
215+
const siteIds = BLOG.NOTION_PAGE_ID.split(',')
216+
for (let index = 0; index < siteIds.length; index++) {
217+
const siteId = siteIds[index]
218+
const prefix = extractLangPrefix(siteId)
219+
if (getLastSegmentFromUrl(properties.href) === prefix) {
220+
properties.target = '_blank'
221+
}
222+
}
223+
}
224+
211225
// 密码字段md5
212226
properties.password = properties.password
213227
? md5(properties.slug + properties.password)

lib/utils/index.js

+30-1
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,21 @@ export function convertUrlStartWithOneSlash(str) {
8181
return str
8282
}
8383

84+
/**
85+
* 是否是一个相对或绝对路径的ur类
86+
* @param {*} str
87+
* @returns
88+
*/
89+
export function isUrl(str) {
90+
if (!str) {
91+
return false
92+
}
93+
94+
return str?.indexOf('/') === 0 || checkStartWithHttp(str)
95+
}
96+
8497
// 检查是否外链
85-
export function checkContainHttp(str) {
98+
export function checkStartWithHttp(str) {
8699
// 检查字符串是否包含http
87100
if (str?.includes('http:') || str?.includes('https:')) {
88101
// 如果包含,找到http的位置
@@ -354,3 +367,19 @@ export const scanAndConvertToLinks = node => {
354367
}
355368
}
356369
}
370+
371+
/**
372+
* 获取url最后一个斜杆后面的内容
373+
* @param {*} url
374+
* @returns
375+
*/
376+
export function getLastSegmentFromUrl(url) {
377+
if (!url) {
378+
return ''
379+
}
380+
// 去掉 URL 中的查询参数部分
381+
const trimmedUrl = url.split('?')[0]
382+
// 获取最后一个斜杠后面的内容
383+
const segments = trimmedUrl.split('/')
384+
return segments[segments.length - 1]
385+
}

lib/utils/post.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* 文章相关工具
33
*/
4-
import { checkContainHttp } from '.'
4+
import { checkStartWithHttp } from '.'
55

66
/**
77
* 获取文章的关联推荐文章列表,目前根据标签关联性筛选
@@ -50,7 +50,7 @@ export function checkSlugHasNoSlash(row) {
5050
}
5151
return (
5252
(slug.match(/\//g) || []).length === 0 &&
53-
!checkContainHttp(slug) &&
53+
!checkStartWithHttp(slug) &&
5454
row.type.indexOf('Menu') < 0
5555
)
5656
}
@@ -67,7 +67,7 @@ export function checkSlugHasOneSlash(row) {
6767
}
6868
return (
6969
(slug.match(/\//g) || []).length === 1 &&
70-
!checkContainHttp(slug) &&
70+
!checkStartWithHttp(slug) &&
7171
row.type.indexOf('Menu') < 0
7272
)
7373
}
@@ -85,6 +85,6 @@ export function checkSlugHasMorThanTwoSlash(row) {
8585
return (
8686
(slug.match(/\//g) || []).length >= 2 &&
8787
row.type.indexOf('Menu') < 0 &&
88-
!checkContainHttp(slug)
88+
!checkStartWithHttp(slug)
8989
)
9090
}

themes/example/components/Header.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@ import { MenuList } from './MenuList'
44

55
/**
66
* 网站顶部
7+
* LOGO 和 菜单
78
* @returns
89
*/
910
export const Header = props => {
1011
return (
1112
<header className='w-full px-6 bg-white dark:bg-black relative z-20'>
12-
<div className='container mx-auto max-w-4xl md:flex justify-between items-center'>
13+
<div className='mx-auto max-w-4xl md:flex justify-between items-center'>
1314
<Link
1415
href='/'
1516
className='py-6 w-full text-center md:text-left md:w-auto text-gray-dark no-underline flex justify-center items-center'>

themes/example/components/MenuList.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export const MenuList = props => {
5858

5959
return (
6060
<nav className='w-full bg-white md:pt-0 px-6 relative z-20 border-t border-b border-gray-light dark:border-hexo-black-gray dark:bg-black'>
61-
<div className='container mx-auto max-w-4xl md:flex justify-between items-center text-sm md:text-md md:justify-start'>
61+
<div className='mx-auto max-w-4xl md:flex justify-between items-center text-sm md:text-md md:justify-start'>
6262
<ul className='w-full text-center md:text-left flex flex-wrap justify-center items-stretch md:justify-start md:items-start'>
6363
{links.map((link, index) => (
6464
<MenuItemDrop key={index} link={link} />

0 commit comments

Comments
 (0)