Skip to content

Commit

Permalink
feat(app): improve auchor architecture
Browse files Browse the repository at this point in the history
  • Loading branch information
surmon-china committed Nov 23, 2023
1 parent 6e5c0cf commit 801b61f
Show file tree
Hide file tree
Showing 20 changed files with 103 additions and 101 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "surmon.me",
"version": "4.33.0",
"version": "4.33.1",
"description": "Surmon.me blog",
"author": "Surmon",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion src/components/comment/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import { useCommentStore, CommentFetchParams } from '/@/stores/comment'
import { GAEventCategories } from '/@/constants/gtag'
import * as ANCHORS from '/@/constants/anchor'
import * as URL_HASHS from '/@/constants/url-hash'
import * as URL_HASHS from '/@/constants/anchor'
import { UNDEFINED } from '/@/constants/value'
import { SortType } from '/@/constants/state'
import { Author } from '/@/interfaces/comment'
Expand Down
2 changes: 1 addition & 1 deletion src/components/comment/list/item.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import { useCommentStore } from '/@/stores/comment'
import { useIdentityStore, UserType } from '/@/stores/identity'
import { getCommentItemElementId } from '/@/constants/anchor'
import { getCommentUrlHashById } from '/@/constants/url-hash'
import { getCommentUrlHashById } from '/@/constants/anchor'
import { LanguageKey } from '/@/language'
import { UNDEFINED } from '/@/constants/value'
import { Comment } from '/@/interfaces/comment'
Expand Down
8 changes: 6 additions & 2 deletions src/components/common/markdown.vue
Original file line number Diff line number Diff line change
Expand Up @@ -88,16 +88,20 @@
font-weight: 700;
text-indent: 0;
&:hover {
.anchor {
.anchor.static {
color: $text;
}
.anchor.link {
color: $primary;
cursor: pointer;
}
}
.anchor {
margin-right: $xs-gap;
color: $text-secondary;
text-decoration: none;
user-select: none;
cursor: pointer;
}
}
Expand Down
22 changes: 20 additions & 2 deletions src/constants/anchor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,15 @@ export const ARTICLE_SHARE_ELEMENT_ID = 'A_article_share'
export const ARTICLE_RELATED_ELEMENT_ID = 'A_article_related'

export const ARTICLE_CONTENT_HEADING_ELEMENT_ID_PREFIX = 'A_article_content_heading'
export const getArticleContentHeadingElementId = (level: number, heading: string) => {
return `${ARTICLE_CONTENT_HEADING_ELEMENT_ID_PREFIX}_${level}_${heading}`
export const getArticleContentHeadingElementId = (level: number, anchor: string) => {
return `${ARTICLE_CONTENT_HEADING_ELEMENT_ID_PREFIX}_${level}_${anchor}`
}

export const getArticleHeadingUrlHash = (heading: string) => {
return heading
.replace(/[^\p{L}\d\s\-_]/gu, '')
.toLowerCase()
.replace(/\s+/g, '-')
}

export const COMMENT_ELEMENT_ID = 'A_comment_warpper'
Expand All @@ -30,3 +37,14 @@ export const COMMENT_ITEM_ELEMENT_ID_PREFIX = 'A_comment_content_item'
export const getCommentItemElementId = (commentId: string | number) => {
return `${COMMENT_ITEM_ELEMENT_ID_PREFIX}_${commentId}`
}

export const COMMENTS_URL_HASH = 'comments'
export const COMMENT_ITEM_URL_HASH_PREFIX = 'comment-'

export const getCommentIdByUrlHash = (hash: string) => {
return hash.replace(COMMENT_ITEM_URL_HASH_PREFIX, '')
}

export const getCommentUrlHashById = (commentId: string | number) => {
return `${COMMENT_ITEM_URL_HASH_PREFIX}${commentId}`
}
16 changes: 0 additions & 16 deletions src/constants/url-hash.ts

This file was deleted.

4 changes: 2 additions & 2 deletions src/pages/article/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import { useUniversalFetch } from '/@/universal'
import { useStores } from '/@/stores'
import * as ANCHORS from '/@/constants/anchor'
import * as URL_HASHS from '/@/constants/url-hash'
import * as URL_HASHS from '/@/constants/anchor'
import { GAEventCategories } from '/@/constants/gtag'
import { LanguageKey } from '/@/language'
import { CUSTOM_ELEMENTS } from '/@/effects/elements'
Expand Down Expand Up @@ -129,7 +129,7 @@
const elementID =
urlHash === URL_HASHS.COMMENTS_URL_HASH
? ANCHORS.COMMENT_ELEMENT_ID
: articleHeadings.find(({ text }) => text === urlHash)?.id
: articleHeadings.find(({ anchor }) => anchor === urlHash)?.id
if (elementID && document.getElementById(elementID)) {
// Allow a certain amount of time to ensure that the browser is rendered.
Expand Down
2 changes: 1 addition & 1 deletion src/stores/_fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export interface FetchStoreOptions<Data> {
shallow?: boolean
}

export const useFetchStore = <Data>(options: FetchStoreOptions<Data>) => {
export const createFetchStore = <Data>(options: FetchStoreOptions<Data>) => {
// default: shallow
const isShallow = isUndefined(options.shallow) ? true : options.shallow
const refWrapper = isShallow ? shallowRef : ref
Expand Down
4 changes: 2 additions & 2 deletions src/stores/announcement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
*/

import { defineStore } from 'pinia'
import { useFetchStore } from './_fetch'
import { createFetchStore } from './_fetch'
import { Announcement } from '/@/interfaces/announcement'
import { PaginationList } from '/@/interfaces/common'
import nodepress from '/@/services/nodepress'

export const useAnnouncementStore = defineStore('announcement', () => {
return useFetchStore<Announcement[]>({
return createFetchStore<Announcement[]>({
data: [],
preclean: true,
async fetcher(params?: any) {
Expand Down
4 changes: 2 additions & 2 deletions src/stores/archive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import { computed } from 'vue'
import { defineStore } from 'pinia'
import { useFetchStore } from './_fetch'
import { createFetchStore } from './_fetch'
import { Archive } from '/@/interfaces/archive'
import { Article } from '/@/interfaces/article'
import { dateToHuman, HumanDate } from '/@/transforms/moment'
Expand All @@ -21,7 +21,7 @@ export type ArchiveTreeList = Array<{
}>

export const useArchiveStore = defineStore('archive', () => {
const fetchStore = useFetchStore<Archive | null>({
const fetchStore = createFetchStore<Archive | null>({
data: null,
once: true,
async fetcher() {
Expand Down
24 changes: 12 additions & 12 deletions src/stores/article.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@

import { ref, shallowRef, computed } from 'vue'
import { defineStore } from 'pinia'
import { useFetchStore } from './_fetch'
import { createFetchStore } from './_fetch'
import { useIdentityStore } from './identity'
import { useCDNDomain } from '/@/app/context'
import { SortType } from '/@/constants/state'
import { Article } from '/@/interfaces/article'
import { Pagination, PaginationList } from '/@/interfaces/common'
import { SortType } from '/@/constants/state'
import { getArticleContentHeadingElementId } from '/@/constants/anchor'
import { getStaticURL, getStaticPath, isOriginalStaticURL } from '/@/transforms/url'
import { getArticleContentHeadingElementId, getArticleHeadingUrlHash } from '/@/constants/anchor'
import { markdownToHTML, getMarkdownSplitIndex, MarkdownRenderOption } from '/@/transforms/markdown'
import { getStaticURL, getStaticPath, isOriginalStaticURL } from '/@/transforms/url'
import { delayPromise } from '/@/utils/delayer'
import { isClient } from '/@/app/environment'
import { RENDER_LONG_ARTICLE_THRESHOLD } from '/@/config/app.config'
Expand All @@ -23,7 +23,7 @@ import nodepress from '/@/services/nodepress'
export const ARTICLE_API_PATH = '/article'

const createSpecialArticleListStore = (_params: Record<string, any>, perPage: number = 8) => {
return useFetchStore<Article[]>({
return createFetchStore<Article[]>({
once: true,
data: [],
async fetcher() {
Expand Down Expand Up @@ -86,8 +86,9 @@ export const useArticleListStore = defineStore('articleList', () => {
})

interface ArticleHeading {
text: string
level: number
text: string
anchor: string
id: string
}

Expand All @@ -97,11 +98,11 @@ const renderArticleMarkdown = (markdown: string, imageSourceGetter: MarkdownRend
const html = markdownToHTML(markdown, {
sanitize: false,
imageSourceGetter,
headingIdGetter: (_, level, raw) => {
const escaped = raw.toLowerCase().replace(/[^a-zA-Z0-9\u4E00-\u9FA5]+/g, '-')
const id = getArticleContentHeadingElementId(level, escaped)
headings.push({ level, id, text: raw })
return id
headingIdentifierGetter: (_, level, raw) => {
const anchor = getArticleHeadingUrlHash(raw)
const id = getArticleContentHeadingElementId(level, anchor)
headings.push({ level, text: raw, id, anchor })
return { id, anchor }
}
})

Expand Down Expand Up @@ -143,7 +144,6 @@ export const useArticleDetailStore = defineStore('articleDetail', () => {
if (!isOriginalStaticURL(src)) {
return src
}

const cdnDomain = useCDNDomain()
const path = getStaticPath(src)
return getStaticURL(cdnDomain, path)
Expand Down
6 changes: 3 additions & 3 deletions src/stores/basic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@

import { computed } from 'vue'
import { defineStore } from 'pinia'
import { useFetchStore } from './_fetch'
import { createFetchStore } from './_fetch'
import { CommentPostId } from '/@/constants/state'
import { UNDEFINED } from '/@/constants/value'
import { AdminInfo, AppOption, AppAdConfig } from '/@/interfaces/option'
import { useIdentityStore, UserType } from './identity'
import nodepress from '/@/services/nodepress'

export const useAdminInfoStore = defineStore('adminInfo', () => {
return useFetchStore<AdminInfo | null>({
return createFetchStore<AdminInfo | null>({
data: null,
async fetcher() {
const response = await nodepress.get<AdminInfo>('/auth/admin')
Expand All @@ -24,7 +24,7 @@ export const useAdminInfoStore = defineStore('adminInfo', () => {
})

export const useAppOptionStore = defineStore('appOption', () => {
const fetchStore = useFetchStore<AppOption | null>({
const fetchStore = createFetchStore<AppOption | null>({
shallow: false,
data: null,
async fetcher() {
Expand Down
8 changes: 4 additions & 4 deletions src/stores/calendar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@

import { computed } from 'vue'
import { defineStore } from 'pinia'
import { useFetchStore } from './_fetch'
import { createFetchStore } from './_fetch'
import { TunnelModule } from '/@/constants/tunnel'
import nodepress from '/@/services/nodepress'
import tunnel from '/@/services/tunnel'

type CalendarDay = { date: string; count: number }

export const useArticleCalendarStore = defineStore('articleCalendar', () => {
return useFetchStore<CalendarDay[]>({
return createFetchStore<CalendarDay[]>({
once: true,
data: [],
async fetcher() {
Expand All @@ -27,7 +27,7 @@ export const useArticleCalendarStore = defineStore('articleCalendar', () => {
})

export const useInstagramCalendarStore = defineStore('instagramCalendar', () => {
return useFetchStore<CalendarDay[]>({
return createFetchStore<CalendarDay[]>({
once: true,
data: [],
fetcher: () => {
Expand All @@ -37,7 +37,7 @@ export const useInstagramCalendarStore = defineStore('instagramCalendar', () =>
})

export const useGitHubCalendarStore = defineStore('githubContributionsCalendar', () => {
const fetchStore = useFetchStore({
const fetchStore = createFetchStore({
once: true,
data: null,
fetcher: () => tunnel.dispatch(TunnelModule.GitHubContributions)
Expand Down
4 changes: 2 additions & 2 deletions src/stores/category.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
*/

import { defineStore } from 'pinia'
import { useFetchStore } from './_fetch'
import { createFetchStore } from './_fetch'
import { Category } from '/@/interfaces/category'
import { PaginationList } from '/@/interfaces/common'
import nodepress from '/@/services/nodepress'

export const useCategoryStore = defineStore('category', () => {
return useFetchStore<Category[]>({
return createFetchStore<Category[]>({
data: [],
once: true,
fetcher() {
Expand Down
14 changes: 7 additions & 7 deletions src/stores/media.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

import { defineStore } from 'pinia'
import { useFetchStore } from './_fetch'
import { createFetchStore } from './_fetch'
import { TunnelModule } from '/@/constants/tunnel'
import { isClient } from '/@/app/environment'
import { delayPromise } from '/@/utils/delayer'
Expand All @@ -15,7 +15,7 @@ import tunnel from '/@/services/tunnel'

// Douban movies
export const useDoubanMoviesStore = defineStore('doubanMovies', () => {
return useFetchStore({
return createFetchStore({
once: true,
data: null,
fetcher: () => tunnel.dispatch(TunnelModule.DoubanMovies)
Expand All @@ -24,7 +24,7 @@ export const useDoubanMoviesStore = defineStore('doubanMovies', () => {

// Instagram timeline
export const useInstagramTimelineStore = defineStore('instagramTimeline', () => {
return useFetchStore<InstagramMediaListResponse | null>({
return createFetchStore<InstagramMediaListResponse | null>({
data: null,
fetcher: () => {
const request = tunnel.dispatch<InstagramMediaListResponse>(TunnelModule.InstagramMedias)
Expand All @@ -35,15 +35,15 @@ export const useInstagramTimelineStore = defineStore('instagramTimeline', () =>

// Instagram profile
export const useInstagramProfileStore = defineStore('instagramProfile', () => {
return useFetchStore<InstagramProfile | null>({
return createFetchStore<InstagramProfile | null>({
data: null,
fetcher: () => tunnel.dispatch<InstagramProfile>(TunnelModule.InstagramProfile)
})
})

// YouTube playlist
export const useYouTubePlayListStore = defineStore('youtubePlaylist', () => {
return useFetchStore<Array<any>>({
return createFetchStore<Array<any>>({
data: [],
async fetcher() {
const response = await tunnel.dispatch<Array<any>>(TunnelModule.YouTubePlaylist)
Expand All @@ -55,7 +55,7 @@ export const useYouTubePlayListStore = defineStore('youtubePlaylist', () => {

// Twitter userinfo
export const useTwitterStore = defineStore('twitterAggregate', () => {
return useFetchStore<TwitterAggregate | null>({
return createFetchStore<TwitterAggregate | null>({
data: null,
fetcher: () => {
return tunnel.dispatch<TwitterAggregate>(TunnelModule.TwitterAggregate)
Expand All @@ -65,7 +65,7 @@ export const useTwitterStore = defineStore('twitterAggregate', () => {

// My Google map
export const useMyGoogleMapStore = defineStore('myGoogleMap', () => {
return useFetchStore({
return createFetchStore({
once: true,
data: null,
fetcher: () => tunnel.dispatch(TunnelModule.MyGoogleMap)
Expand Down
4 changes: 2 additions & 2 deletions src/stores/sponsor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@

import { computed } from 'vue'
import { defineStore } from 'pinia'
import { useFetchStore } from './_fetch'
import { createFetchStore } from './_fetch'
import type { GitHubSponsorsResponse, GitHubSponsorUser } from '/@/server/getters/github'
import { TunnelModule } from '/@/constants/tunnel'
import tunnel from '/@/services/tunnel'

export const useSponsorStore = defineStore('githubSponsor', () => {
const fetchStore = useFetchStore<GitHubSponsorsResponse | null>({
const fetchStore = createFetchStore<GitHubSponsorsResponse | null>({
fetcher: () => tunnel.dispatch<GitHubSponsorsResponse>(TunnelModule.GitHubSponsors),
once: true,
data: null
Expand Down
Loading

0 comments on commit 801b61f

Please sign in to comment.