1
1
import MagicString from 'magic-string' ;
2
- import { createHash } from 'node:crypto' ;
2
+ import { createHash , Hash } from 'node:crypto' ;
3
3
import fs from 'node:fs' ;
4
4
import path from 'node:path' ;
5
5
import ts from 'typescript' ;
@@ -34,6 +34,81 @@ const theme = createCssVariablesTheme({
34
34
fontStyle : true
35
35
} ) ;
36
36
37
+ const hash = createHash ( 'sha256' ) ;
38
+ hash . update ( fs . readFileSync ( '../../pnpm-lock.yaml' , 'utf-8' ) ) ;
39
+ hash_graph ( hash , fileURLToPath ( import . meta. url ) ) ;
40
+ const digest = hash . digest ( ) . toString ( 'base64' ) . replace ( / \/ / g, '-' ) ;
41
+
42
+ /**
43
+ * Utility function to work with code snippet caching.
44
+ *
45
+ * @example
46
+ *
47
+ * ```js
48
+ * const SNIPPETS_CACHE = create_snippet_cache(true);
49
+ *
50
+ * const { uid, code } = SNIPPETS_CACHE.get(source);
51
+ *
52
+ * // Later to save the code to the cache
53
+ * SNIPPETS_CACHE.save(uid, processed_code);
54
+ * ```
55
+ */
56
+ async function create_snippet_cache ( ) {
57
+ const cache = new Map ( ) ;
58
+ const directory = find_nearest_node_modules ( import . meta. url ) + '/.snippets' ;
59
+ const current = `${ directory } /${ digest } ` ;
60
+
61
+ if ( fs . existsSync ( directory ) ) {
62
+ for ( const dir of fs . readdirSync ( directory ) ) {
63
+ if ( dir !== digest ) {
64
+ fs . rmSync ( `${ directory } /${ dir } ` , { force : true , recursive : true } ) ;
65
+ }
66
+ }
67
+ } else {
68
+ fs . mkdirSync ( directory ) ;
69
+ }
70
+
71
+ try {
72
+ fs . mkdirSync ( `${ directory } /${ digest } ` ) ;
73
+ } catch { }
74
+
75
+ function get_file ( source : string ) {
76
+ const hash = createHash ( 'sha256' ) ;
77
+ hash . update ( source ) ;
78
+ const digest = hash . digest ( ) . toString ( 'base64' ) . replace ( / \/ / g, '-' ) ;
79
+
80
+ return `${ current } /${ digest } .html` ;
81
+ }
82
+
83
+ return {
84
+ get ( source : string ) {
85
+ let snippet = cache . get ( source ) ;
86
+
87
+ if ( snippet === undefined ) {
88
+ const file = get_file ( source ) ;
89
+
90
+ if ( fs . existsSync ( file ) ) {
91
+ snippet = fs . readFileSync ( file , 'utf-8' ) ;
92
+ cache . set ( source , snippet ) ;
93
+ }
94
+ }
95
+
96
+ return snippet ;
97
+ } ,
98
+ save ( source : string , html : string ) {
99
+ cache . set ( source , html ) ;
100
+
101
+ try {
102
+ fs . mkdirSync ( directory ) ;
103
+ } catch { }
104
+
105
+ fs . writeFileSync ( get_file ( source ) , html ) ;
106
+ }
107
+ } ;
108
+ }
109
+
110
+ const snippets = await create_snippet_cache ( ) ;
111
+
37
112
/**
38
113
* A super markdown renderer function. Renders svelte and kit docs specific specific markdown code to html.
39
114
*
@@ -119,8 +194,6 @@ export async function render_content_markdown(
119
194
body : string ,
120
195
{ twoslashBanner } : { twoslashBanner ?: TwoslashBanner } = { }
121
196
) {
122
- const snippets = await create_snippet_cache ( true ) ;
123
-
124
197
const headings : string [ ] = [ ] ;
125
198
126
199
return await transform ( body , {
@@ -453,14 +526,13 @@ function find_nearest_node_modules(file: string): string | null {
453
526
}
454
527
455
528
/**
456
- * Get the `mtime` of the most recently modified file in a dependency graph,
529
+ * Get the hash of a dependency graph,
457
530
* excluding imports from `node_modules`
458
531
*/
459
- function get_mtime ( file : string , seen = new Set < string > ( ) ) {
460
- if ( seen . has ( file ) ) return - 1 ;
532
+ function hash_graph ( hash : Hash , file : string , seen = new Set < string > ( ) ) {
533
+ if ( seen . has ( file ) ) return ;
461
534
seen . add ( file ) ;
462
535
463
- let mtime = fs . statSync ( file ) . mtimeMs ;
464
536
const content = fs . readFileSync ( file , 'utf-8' ) ;
465
537
466
538
for ( const [ _ , source ] of content . matchAll ( / ^ i m p o r t (?: .+ ?\s + f r o m \s + ) ? [ ' " ] ( .+ ) [ ' " ] ; ? $ / gm) ) {
@@ -471,118 +543,10 @@ function get_mtime(file: string, seen = new Set<string>()) {
471
543
if ( ! fs . existsSync ( resolved ) )
472
544
throw new Error ( `Could not resolve ${ source } relative to ${ file } ` ) ;
473
545
474
- mtime = Math . max ( mtime , get_mtime ( resolved , seen ) ) ;
475
- }
476
-
477
- return mtime ;
478
- }
479
-
480
- const mtime = Math . max (
481
- get_mtime ( fileURLToPath ( import . meta. url ) ) ,
482
- fs . statSync ( 'node_modules' ) . mtimeMs ,
483
- fs . statSync ( '../../pnpm-lock.yaml' ) . mtimeMs
484
- ) ;
485
-
486
- /**
487
- * Utility function to work with code snippet caching.
488
- *
489
- * @example
490
- *
491
- * ```js
492
- * const SNIPPETS_CACHE = create_snippet_cache(true);
493
- *
494
- * const { uid, code } = SNIPPETS_CACHE.get(source);
495
- *
496
- * // Later to save the code to the cache
497
- * SNIPPETS_CACHE.save(uid, processed_code);
498
- * ```
499
- */
500
- async function create_snippet_cache ( should : boolean ) {
501
- const cache = new Map ( ) ;
502
- const directory = find_nearest_node_modules ( import . meta. url ) + '/.snippets' ;
503
-
504
- if ( fs . existsSync ( directory ) ) {
505
- for ( const dir of fs . readdirSync ( directory ) ) {
506
- if ( ! fs . statSync ( `${ directory } /${ dir } ` ) . isDirectory ( ) || + dir < mtime ) {
507
- fs . rmSync ( `${ directory } /${ dir } ` , { force : true , recursive : true } ) ;
508
- }
509
- }
510
- } else {
511
- fs . mkdirSync ( directory ) ;
512
- }
513
-
514
- try {
515
- fs . mkdirSync ( `${ directory } /${ mtime } ` ) ;
516
- } catch { }
517
-
518
- function get_file ( source : string ) {
519
- const hash = createHash ( 'sha256' ) ;
520
- hash . update ( source ) ;
521
- const digest = hash . digest ( ) . toString ( 'base64' ) . replace ( / \/ / g, '-' ) ;
522
-
523
- return `${ directory } /${ mtime } /${ digest } .html` ;
524
- }
525
-
526
- return {
527
- get ( source : string ) {
528
- if ( ! should ) return ;
529
-
530
- let snippet = cache . get ( source ) ;
531
-
532
- if ( snippet === undefined ) {
533
- const file = get_file ( source ) ;
534
-
535
- if ( fs . existsSync ( file ) ) {
536
- snippet = fs . readFileSync ( file , 'utf-8' ) ;
537
- cache . set ( source , snippet ) ;
538
- }
539
- }
540
-
541
- return snippet ;
542
- } ,
543
- save ( source : string , html : string ) {
544
- cache . set ( source , html ) ;
545
-
546
- try {
547
- fs . mkdirSync ( directory ) ;
548
- } catch { }
549
-
550
- fs . writeFileSync ( get_file ( source ) , html ) ;
551
- }
552
- } ;
553
- }
554
-
555
- function create_type_links (
556
- modules : Modules | undefined ,
557
- resolve_link ?: ( module_name : string , type_name : string ) => { slug : string ; page : string }
558
- ) : {
559
- type_regex : RegExp | null ;
560
- type_links : Map < string , { slug : string ; page : string ; relativeURL : string } > | null ;
561
- } {
562
- if ( ! modules || modules . length === 0 || ! resolve_link )
563
- return { type_regex : null , type_links : null } ;
564
-
565
- const type_regex = new RegExp (
566
- `(import\\('(?:svelte|@sveltejs\\/kit)'\\)\\.)?\\b(${ modules
567
- . flatMap ( ( module ) => module . types )
568
- . map ( ( type ) => type ?. name )
569
- . join ( '|' ) } )\\b`,
570
- 'g'
571
- ) ;
572
-
573
- /** @type {Map<string, { slug: string; page: string; relativeURL: string; }> } */
574
- const type_links = new Map ( ) ;
575
-
576
- for ( const module of modules ) {
577
- if ( ! module || ! module . name ) continue ;
578
-
579
- for ( const type of module . types ?? [ ] ) {
580
- const link = resolve_link ( module . name , type . name ) ;
581
- type_links . set ( type . name , { ...link , relativeURL : link . page + '#' + link . slug } ) ;
582
- }
546
+ hash_graph ( hash , resolved , seen ) ;
583
547
}
584
548
585
- return { type_regex , type_links } ;
549
+ hash . update ( content ) ;
586
550
}
587
551
588
552
function parse_options ( source : string , language : string ) {
0 commit comments