11// api.data.ts
2- // a file ending with data.(j|t)s will be evaluated in Node.js
32import fs from 'fs'
43import path from 'path'
54import type { MultiSidebarConfig } from '@vue/theme/src/vitepress/config.ts'
65import { sidebar } from '../../.vitepress/config'
76
7+ // Interface, který definuje strukturu jednoho API nadpisu
88interface APIHeader {
99 anchor : string
1010 text : string
1111}
1212
13+ // Interface, kter definuje strukturu API skupiny s textem, odkazem a polem objektů
1314export interface APIGroup {
1415 text : string
1516 anchor : string
@@ -20,79 +21,108 @@ export interface APIGroup {
2021 } [ ]
2122}
2223
23- // declare resolved data type
24+ // Deklarace typu pro vyhodnocené API skupiny
2425export declare const data : APIGroup [ ]
2526
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+ )
4042}
4143
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
5348
49+ // kontrola, jestli je soubor uložen v cache a jestli čas poslední modifikace odpovídá
5450 const cached = headersCache . get ( fullPath )
5551 if ( cached && timestamp === cached . timestamp ) {
56- return cached . headers
52+ return cached . headers // vrátit uložené nadpisy, když jsou akutální
5753 }
5854
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})
6171 let headers : APIHeader [ ] = [ ]
72+
6273 if ( h2s ) {
63- const anchorRE = / \{ # ( [ ^ } ] + ) \} /
74+ // zpracovat každý h2 nadpis a získat text + odkaz
6475 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
7378 return { text, anchor }
7479 } )
7580 }
76- headersCache . set ( fullPath , {
77- timestamp,
78- headers
79- } )
81+
8082 return headers
8183}
8284
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`
98100}
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