1
1
import type {
2
2
HighlighterCoreOptions ,
3
- LanguageInput ,
4
- LanguageRegistration ,
5
3
LoadWasmOptions ,
6
- MaybeGetter ,
7
4
ShikiInternal ,
8
- SpecialLanguage ,
9
- SpecialTheme ,
10
- ThemeInput ,
11
- ThemeRegistrationAny ,
12
- ThemeRegistrationResolved ,
13
5
} from '../types'
14
- import { Registry } from '../textmate/registry'
15
- import { Resolver } from '../textmate/resolver'
16
- import { normalizeTheme } from '../textmate/normalize-theme'
17
- import { isSpecialLang , isSpecialTheme } from '../utils'
18
- import { ShikiError } from '../error'
19
6
import { createWasmOnigEngine } from '../engines/wasm'
7
+ import { resolveLangs , resolveThemes } from '../textmate/getters-resolve'
8
+ import { createShikiInternalSync } from './internal-sync'
20
9
21
10
let _defaultWasmLoader : LoadWasmOptions | undefined
22
11
/**
@@ -27,130 +16,27 @@ export function setDefaultWasmLoader(_loader: LoadWasmOptions) {
27
16
_defaultWasmLoader = _loader
28
17
}
29
18
30
- let instancesCount = 0
31
-
32
19
/**
33
20
* Get the minimal shiki context for rendering.
34
21
*/
35
22
export async function createShikiInternal ( options : HighlighterCoreOptions = { } ) : Promise < ShikiInternal > {
36
- instancesCount += 1
37
- if ( options . warnings !== false && instancesCount >= 10 && instancesCount % 10 === 0 )
38
- console . warn ( `[Shiki] ${ instancesCount } instances have been created. Shiki is supposed to be used as a singleton, consider refactoring your code to cache your highlighter instance; Or call \`highlighter.dispose()\` to release unused instances.` )
39
-
40
- let isDisposed = false
41
-
42
- async function normalizeGetter < T > ( p : MaybeGetter < T > ) : Promise < T > {
43
- return Promise . resolve ( typeof p === 'function' ? ( p as any ) ( ) : p ) . then ( r => r . default || r )
44
- }
45
-
46
- async function resolveLangs ( langs : ( LanguageInput | SpecialLanguage ) [ ] ) {
47
- return Array . from ( new Set ( ( await Promise . all (
48
- langs
49
- . filter ( l => ! isSpecialLang ( l ) )
50
- . map ( async lang => await normalizeGetter ( lang as LanguageInput ) . then ( r => Array . isArray ( r ) ? r : [ r ] ) ) ,
51
- ) ) . flat ( ) ) )
52
- }
53
-
54
23
const [
55
24
themes ,
56
25
langs ,
26
+ engine ,
57
27
] = await Promise . all ( [
58
- Promise . all ( ( options . themes || [ ] ) . map ( normalizeGetter ) ) . then ( r => r . map ( normalizeTheme ) ) ,
28
+ resolveThemes ( options . themes || [ ] ) ,
59
29
resolveLangs ( options . langs || [ ] ) ,
30
+ ( options . engine || createWasmOnigEngine ( options . loadWasm || _defaultWasmLoader ) ) ,
60
31
] as const )
61
32
62
- const resolver = new Resolver (
63
- await ( options . engine || createWasmOnigEngine ( options . loadWasm || _defaultWasmLoader ) ) ,
33
+ return createShikiInternalSync ( {
34
+ ...options ,
35
+ loadWasm : undefined ,
36
+ themes,
64
37
langs,
65
- )
66
-
67
- const _registry = new Registry ( resolver , themes , langs , options . langAlias )
68
- await _registry . init ( )
69
-
70
- let _lastTheme : string | ThemeRegistrationAny
71
-
72
- function getLanguage ( name : string | LanguageRegistration ) {
73
- ensureNotDisposed ( )
74
- const _lang = _registry . getGrammar ( typeof name === 'string' ? name : name . name )
75
- if ( ! _lang )
76
- throw new ShikiError ( `Language \`${ name } \` not found, you may need to load it first` )
77
- return _lang
78
- }
79
-
80
- function getTheme ( name : string | ThemeRegistrationAny ) : ThemeRegistrationResolved {
81
- if ( name === 'none' )
82
- return { bg : '' , fg : '' , name : 'none' , settings : [ ] , type : 'dark' }
83
- ensureNotDisposed ( )
84
- const _theme = _registry . getTheme ( name )
85
- if ( ! _theme )
86
- throw new ShikiError ( `Theme \`${ name } \` not found, you may need to load it first` )
87
- return _theme
88
- }
89
-
90
- function setTheme ( name : string | ThemeRegistrationAny ) {
91
- ensureNotDisposed ( )
92
- const theme = getTheme ( name )
93
- if ( _lastTheme !== name ) {
94
- _registry . setTheme ( theme )
95
- _lastTheme = name
96
- }
97
- const colorMap = _registry . getColorMap ( )
98
- return {
99
- theme,
100
- colorMap,
101
- }
102
- }
103
-
104
- function getLoadedThemes ( ) {
105
- ensureNotDisposed ( )
106
- return _registry . getLoadedThemes ( )
107
- }
108
-
109
- function getLoadedLanguages ( ) {
110
- ensureNotDisposed ( )
111
- return _registry . getLoadedLanguages ( )
112
- }
113
-
114
- async function loadLanguage ( ...langs : ( LanguageInput | SpecialLanguage ) [ ] ) {
115
- ensureNotDisposed ( )
116
- await _registry . loadLanguages ( await resolveLangs ( langs ) )
117
- }
118
-
119
- async function loadTheme ( ...themes : ( ThemeInput | SpecialTheme ) [ ] ) {
120
- ensureNotDisposed ( )
121
- await Promise . all (
122
- themes . map ( async theme =>
123
- isSpecialTheme ( theme )
124
- ? null
125
- : _registry . loadTheme ( await normalizeGetter ( theme ) ) ,
126
- ) ,
127
- )
128
- }
129
-
130
- function ensureNotDisposed ( ) {
131
- if ( isDisposed )
132
- throw new ShikiError ( 'Shiki instance has been disposed' )
133
- }
134
-
135
- function dispose ( ) {
136
- if ( isDisposed )
137
- return
138
- isDisposed = true
139
- _registry . dispose ( )
140
- instancesCount -= 1
141
- }
142
-
143
- return {
144
- setTheme,
145
- getTheme,
146
- getLanguage,
147
- getLoadedThemes,
148
- getLoadedLanguages,
149
- loadLanguage,
150
- loadTheme,
151
- dispose,
152
- [ Symbol . dispose ] : dispose ,
153
- }
38
+ engine,
39
+ } )
154
40
}
155
41
156
42
/**
0 commit comments