1
1
// api.data.ts
2
- // a file ending with data.(j|t)s will be evaluated in Node.js
3
2
import fs from 'fs'
4
3
import path from 'path'
5
4
import type { MultiSidebarConfig } from '@vue/theme/src/vitepress/config.ts'
6
5
import { sidebar } from '../../.vitepress/config'
7
6
7
+ // Interface, který definuje strukturu jednoho API nadpisu
8
8
interface APIHeader {
9
9
anchor : string
10
10
text : string
11
11
}
12
12
13
+ // Interface, kter definuje strukturu API skupiny s textem, odkazem a polem objektů
13
14
export interface APIGroup {
14
15
text : string
15
16
anchor : string
@@ -20,79 +21,108 @@ export interface APIGroup {
20
21
} [ ]
21
22
}
22
23
23
- // declare resolved data type
24
+ // Deklarace typu pro vyhodnocené API skupiny
24
25
export declare const data : APIGroup [ ]
25
26
26
- export default {
27
- // declare files that should trigger HMR
28
- watch : './*.md' ,
29
- // read from fs and generate the data
30
- load ( ) : APIGroup [ ] {
31
- return ( sidebar as MultiSidebarConfig ) [ '/api/' ] . map ( ( group ) => ( {
32
- text : group . text ,
33
- anchor : slugify ( group . text ) ,
34
- items : group . items . map ( ( item ) => ( {
35
- ...item ,
36
- headers : parsePageHeaders ( item . link )
37
- } ) )
38
- } ) )
39
- }
27
+ // Utility funkce pro vygenerování "slug" odkazu z řetězce (používaná pro odkazy (#anchors) na stránce)
28
+ function slugify ( text : string ) : string {
29
+ return (
30
+ text
31
+ // nahradit speciální znaky a mezery pomlčkami
32
+ . replace ( / [ \s ~ ` ! @ # $ % ^ & * ( ) \- _ + = [ \] { } | \\ ; : " ' < > , . ? / ] + / g, '-' )
33
+ // odstranit vícenásobné pomlčky
34
+ . replace ( / - { 2 , } / g, '-' )
35
+ // odstranit pomlčky na začátku a na konci
36
+ . replace ( / ^ - + | - + $ / g, '' )
37
+ // ujistit se, že hodnota nezačíná číslem (např. #121)
38
+ . replace ( / ^ ( \d ) / , '_$1' )
39
+ // převést na lowercase
40
+ . toLowerCase ( )
41
+ )
40
42
}
41
43
42
- const headersCache = new Map <
43
- string ,
44
- {
45
- headers : APIHeader [ ]
46
- timestamp : number
47
- }
48
- > ( )
49
-
50
- function parsePageHeaders ( link : string ) {
51
- const fullPath = path . join ( __dirname , '../' , link ) + '.md'
52
- const timestamp = fs . statSync ( fullPath ) . mtimeMs
44
+ // Utility funkce na načtení nadpisů z markdown souboru na předaném odkazu
45
+ function parsePageHeaders ( link : string ) : APIHeader [ ] {
46
+ const fullPath = path . join ( __dirname , '../' , link ) + '.md' // vyhodnotit úplnou cestu k souboru
47
+ const timestamp = fs . statSync ( fullPath ) . mtimeMs // získat čas poslední modifikace souboru
53
48
49
+ // kontrola, jestli je soubor uložen v cache a jestli čas poslední modifikace odpovídá
54
50
const cached = headersCache . get ( fullPath )
55
51
if ( cached && timestamp === cached . timestamp ) {
56
- return cached . headers
52
+ return cached . headers // vrátit uložené nadpisy, když jsou akutální
57
53
}
58
54
59
- const src = fs . readFileSync ( fullPath , 'utf-8' )
60
- const h2s = src . match ( / ^ # # [ ^ \n ] + / gm)
55
+ const src = fs . readFileSync ( fullPath , 'utf-8' ) // číst markdown soubor
56
+ const headers = extractHeadersFromMarkdown ( src ) // získat nadpisy z obsahu
57
+
58
+ // uložit získané nadpisy spolu s datem poslední modifikace do cache
59
+ headersCache . set ( fullPath , {
60
+ timestamp,
61
+ headers
62
+ } )
63
+
64
+ return headers
65
+ }
66
+
67
+ // Pomocná funkce na získání všech nadpisů (h2) z markdown obsahu
68
+ function extractHeadersFromMarkdown ( src : string ) : APIHeader [ ] {
69
+ const h2s = src . match ( / ^ # # [ ^ \n ] + / gm) // získat všechny h2 nadpisy (## nadpis)
70
+ const anchorRE = / \{ # ( [ ^ } ] + ) \} / // regulární výraz pro načtení odkazu (např.: {#some-anchor})
61
71
let headers : APIHeader [ ] = [ ]
72
+
62
73
if ( h2s ) {
63
- const anchorRE = / \{ # ( [ ^ } ] + ) \} /
74
+ // zpracovat každý h2 nadpis a získat text + odkaz
64
75
headers = h2s . map ( ( h ) => {
65
- const text = h
66
- . slice ( 2 )
67
- . replace ( / < s u p c l a s s = .* / , '' )
68
- . replace ( / \\ < / g, '<' )
69
- . replace ( / ` ( [ ^ ` ] + ) ` / g, '$1' )
70
- . replace ( anchorRE , '' ) // hidden anchor tag
71
- . trim ( )
72
- const anchor = h . match ( anchorRE ) ?. [ 1 ] ?? slugify ( text )
76
+ const text = cleanHeaderText ( h , anchorRE ) // vyčistit text nadpsisu
77
+ const anchor = extractAnchor ( h , anchorRE , text ) // extrahovat nebo vygenerovat odkaz
73
78
return { text, anchor }
74
79
} )
75
80
}
76
- headersCache . set ( fullPath , {
77
- timestamp,
78
- headers
79
- } )
81
+
80
82
return headers
81
83
}
82
84
83
- // same as vitepress' slugify logic
84
- function slugify ( text : string ) : string {
85
- return (
86
- text
87
- // Replace special characters
88
- . replace ( / [ \s ~ ` ! @ # $ % ^ & * ( ) \- _ + = [ \] { } | \\ ; : " ' < > , . ? / ] + / g, '-' )
89
- // Remove continuous separators
90
- . replace ( / - { 2 , } / g , '-' )
91
- // Remove prefixing and trailing separators
92
- . replace ( / ^ - + | - + $ / g , '' )
93
- // ensure it doesn't start with a number (#121)
94
- . replace ( / ^ ( \d ) / , '_$1' )
95
- // lowercase
96
- . toLowerCase ( )
97
- )
85
+ // Pomocná funkce pro vyčištění texu nadpisu (např. odstranit superscript či formátování kódu)
86
+ function cleanHeaderText ( h : string , anchorRE : RegExp ) : string {
87
+ return h
88
+ . slice ( 2 ) // odstranit "##" část
89
+ . replace ( / < s u p c l a s s = . * / , '' ) // odstranit superscript (např. tagy <sup>)
90
+ . replace ( / \\ < / g, '<' ) // dekódovat escape znaky jako \<
91
+ . replace ( / ` ( [ ^ ` ] + ) ` / g , '$1' ) // odstranit inline formátování (např. `code`)
92
+ . replace ( anchorRE , '' ) // odstranit tagy odkazů (např. {#anchor} )
93
+ . trim ( ) // oříznout prázdné znaky na začátku a na konci
94
+ }
95
+
96
+ // Pomocná funkce pro extrahování odkazu z nadpisu (nebo generování nového, pokud neexistuje )
97
+ function extractAnchor ( h : string , anchorRE : RegExp , text : string ) : string {
98
+ const anchorMatch = h . match ( anchorRE ) // načíst odkaz, pokud existuje
99
+ return anchorMatch ?. [ 1 ] ?? slugify ( text ) // pokud odkaz neexistuje, vygenerovat nový přes `slugify`
98
100
}
101
+
102
+ // Cache pro ukládání nadpisů a jim odpovídajících časů poslední modifikace pro omezení znovu načítání souborů
103
+ const headersCache = new Map <
104
+ string ,
105
+ {
106
+ headers : APIHeader [ ]
107
+ timestamp : number
108
+ }
109
+ > ( )
110
+
111
+ // Hlavní funkce pro načítání API dat
112
+ export default {
113
+ // deklarace souborů, které mají vyvolat HMR
114
+ watch : './*.md' ,
115
+
116
+ // načíst API data a zpracovat objekty na postranní liště
117
+ load ( ) : APIGroup [ ] {
118
+ // generovat data API skupiny zpracováním konfigurace lišty
119
+ return ( sidebar as MultiSidebarConfig ) [ '/api/' ] . map ( ( group ) => ( {
120
+ text : group . text , // text pro skupinu (např. 'API')
121
+ anchor : slugify ( group . text ) , // generovat odkaz pro název skupiny
122
+ items : group . items . map ( ( item ) => ( {
123
+ ...item , // původní vlastnosti objektu
124
+ headers : parsePageHeaders ( item . link ) , // zpracovat nadpisy z markdown odkazu
125
+ } ) )
126
+ } ) )
127
+ }
128
+ }
0 commit comments