@@ -8,6 +8,7 @@ import { codeToHtml, createCssVariablesTheme } from 'shiki';
8
8
import { transformerTwoslash } from '@shikijs/twoslash' ;
9
9
import { SHIKI_LANGUAGE_MAP , escape , normalizeSlugify , smart_quotes , transform } from './utils' ;
10
10
import type { Modules } from './index' ;
11
+ import { fileURLToPath } from 'node:url' ;
11
12
12
13
interface SnippetOptions {
13
14
file : string | null ;
@@ -508,6 +509,37 @@ function find_nearest_node_modules(file: string): string | null {
508
509
return null ;
509
510
}
510
511
512
+ /**
513
+ * Get the `mtime` of the most recently modified file in a dependency graph,
514
+ * excluding imports from `node_modules`
515
+ */
516
+ function get_mtime ( file : string , seen = new Set < string > ( ) ) {
517
+ if ( seen . has ( file ) ) return - 1 ;
518
+ seen . add ( file ) ;
519
+
520
+ let mtime = fs . statSync ( file ) . mtimeMs ;
521
+ const content = fs . readFileSync ( file , 'utf-8' ) ;
522
+
523
+ for ( const [ _ , source ] of content . matchAll ( / ^ i m p o r t (?: .+ ?\s + f r o m \s + ) ? [ ' " ] ( .+ ) [ ' " ] ; ? $ / gm) ) {
524
+ if ( source [ 0 ] !== '.' ) continue ;
525
+
526
+ let resolved = path . resolve ( file , '..' , source ) ;
527
+ if ( ! fs . existsSync ( resolved ) ) resolved += '.ts' ;
528
+ if ( ! fs . existsSync ( resolved ) )
529
+ throw new Error ( `Could not resolve ${ source } relative to ${ file } ` ) ;
530
+
531
+ mtime = Math . max ( mtime , get_mtime ( resolved , seen ) ) ;
532
+ }
533
+
534
+ return mtime ;
535
+ }
536
+
537
+ const mtime = Math . max (
538
+ get_mtime ( fileURLToPath ( import . meta. url ) ) ,
539
+ fs . statSync ( 'node_modules' ) . mtimeMs ,
540
+ fs . statSync ( '../../pnpm-lock.yaml' ) . mtimeMs
541
+ ) ;
542
+
511
543
/**
512
544
* Utility function to work with code snippet caching.
513
545
*
@@ -526,12 +558,26 @@ async function create_snippet_cache(should: boolean) {
526
558
const cache = new Map ( ) ;
527
559
const directory = find_nearest_node_modules ( import . meta. url ) + '/.snippets' ;
528
560
561
+ if ( fs . existsSync ( directory ) ) {
562
+ for ( const dir of fs . readdirSync ( directory ) ) {
563
+ if ( ! fs . statSync ( `${ directory } /${ dir } ` ) . isDirectory ( ) || + dir < mtime ) {
564
+ fs . rmSync ( `${ directory } /${ dir } ` , { force : true , recursive : true } ) ;
565
+ }
566
+ }
567
+ } else {
568
+ fs . mkdirSync ( directory ) ;
569
+ }
570
+
571
+ try {
572
+ fs . mkdirSync ( `${ directory } /${ mtime } ` ) ;
573
+ } catch { }
574
+
529
575
function get_file ( source : string ) {
530
576
const hash = createHash ( 'sha256' ) ;
531
577
hash . update ( source ) ;
532
578
const digest = hash . digest ( ) . toString ( 'base64' ) . replace ( / \/ / g, '-' ) ;
533
579
534
- return `${ directory } /${ digest } .html` ;
580
+ return `${ directory } /${ mtime } / ${ digest } .html` ;
535
581
}
536
582
537
583
return {
@@ -681,7 +727,15 @@ async function syntax_highlight({
681
727
html = await codeToHtml ( source , {
682
728
lang : 'ts' ,
683
729
theme,
684
- transformers : [ transformerTwoslash ( { } ) ]
730
+ transformers : [
731
+ transformerTwoslash ( {
732
+ twoslashOptions : {
733
+ compilerOptions : {
734
+ types : [ 'svelte' , '@sveltejs/kit' ]
735
+ }
736
+ }
737
+ } )
738
+ ]
685
739
} ) ;
686
740
} catch ( e ) {
687
741
console . error ( `Error compiling snippet in ${ filename } ` ) ;
0 commit comments