1
1
import { kebabToCamelCase } from '../shared/util' ;
2
- import { forEach } from '../util/iterables' ;
2
+ import { cloneGrammar } from '../util/extend' ;
3
+ import { forEach , toArray } from '../util/iterables' ;
3
4
import { extend } from '../util/language-util' ;
4
- import type { ComponentProto , Grammar } from '../types' ;
5
+ import type { ComponentProto , Grammar , LanguageProto } from '../types' ;
5
6
import type { Prism } from './prism' ;
6
7
7
8
interface Entry {
@@ -60,6 +61,13 @@ export class Registry {
60
61
// add aliases
61
62
forEach ( proto . alias , alias => this . aliasMap . set ( alias , id ) ) ;
62
63
64
+ if ( ( proto as LanguageProto ) . base ) {
65
+ proto . require = [
66
+ ( proto as LanguageProto ) . base as ComponentProto ,
67
+ ...toArray ( proto . require ) ,
68
+ ] ;
69
+ }
70
+
63
71
// dependencies
64
72
forEach ( proto . require , register ) ;
65
73
@@ -152,11 +160,6 @@ export class Registry {
152
160
return entry . evaluatedGrammar ;
153
161
}
154
162
155
- if ( typeof grammar === 'object' ) {
156
- // the grammar is a simple object, so we don't need to evaluate it
157
- return ( entry . evaluatedGrammar = grammar ) ;
158
- }
159
-
160
163
const required = ( id : string ) : Grammar => {
161
164
const grammar = this . getLanguage ( id ) ;
162
165
if ( ! grammar ) {
@@ -165,10 +168,24 @@ export class Registry {
165
168
return grammar ;
166
169
} ;
167
170
168
- return ( entry . evaluatedGrammar = grammar ( {
169
- getLanguage : required ,
170
- getOptionalLanguage : id => this . getLanguage ( id ) ,
171
- extend : ( id , ref ) => extend ( required ( id ) , id , ref ) ,
172
- } ) ) ;
171
+ const base = ( entry ?. proto as LanguageProto ) . base ;
172
+ // We need this so that any code modifying the base grammar doesn't affect other instances
173
+ const baseGrammar = base && cloneGrammar ( required ( base . id ) , base . id ) ;
174
+
175
+ let evaluatedGrammar =
176
+ typeof grammar === 'object'
177
+ ? grammar
178
+ : grammar ( {
179
+ base : baseGrammar ,
180
+ getLanguage : required ,
181
+ getOptionalLanguage : id => this . getLanguage ( id ) ,
182
+ extend : ( id , ref ) => extend ( required ( id ) , id , ref ) ,
183
+ } ) ;
184
+
185
+ if ( base ) {
186
+ evaluatedGrammar = extend ( baseGrammar ! , base . id , evaluatedGrammar ) ;
187
+ }
188
+
189
+ return ( entry . evaluatedGrammar = evaluatedGrammar ) ;
173
190
}
174
191
}
0 commit comments