@shikijs/core 1.2.3 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -394,6 +394,18 @@ type RuleId = {
394
394
  __brand: typeof ruleIdSymbol;
395
395
  };
396
396
 
397
+ declare class Theme {
398
+ private readonly _colorMap;
399
+ private readonly _defaults;
400
+ private readonly _root;
401
+ static createFromRawTheme(source: IRawTheme | undefined, colorMap?: string[]): Theme;
402
+ static createFromParsedTheme(source: ParsedThemeRule[], colorMap?: string[]): Theme;
403
+ private readonly _cachedMatchRoot;
404
+ constructor(_colorMap: ColorMap, _defaults: StyleAttributes, _root: ThemeTrieElement);
405
+ getColorMap(): string[];
406
+ getDefaults(): StyleAttributes;
407
+ match(scopePath: ScopeStack | null): StyleAttributes | null;
408
+ }
397
409
  /**
398
410
  * Identifiers with a binary dot operator.
399
411
  * Examples: `baz` or `foo.bar`
@@ -423,6 +435,76 @@ interface IRawThemeSetting {
423
435
  readonly background?: string;
424
436
  };
425
437
  }
438
+ declare class ScopeStack {
439
+ readonly parent: ScopeStack | null;
440
+ readonly scopeName: ScopeName;
441
+ static push(path: ScopeStack | null, scopeNames: ScopeName[]): ScopeStack | null;
442
+ static from(first: ScopeName, ...segments: ScopeName[]): ScopeStack;
443
+ static from(...segments: ScopeName[]): ScopeStack | null;
444
+ constructor(parent: ScopeStack | null, scopeName: ScopeName);
445
+ push(scopeName: ScopeName): ScopeStack;
446
+ getSegments(): ScopeName[];
447
+ toString(): string;
448
+ extends(other: ScopeStack): boolean;
449
+ getExtensionIfDefined(base: ScopeStack | null): string[] | undefined;
450
+ }
451
+ declare class StyleAttributes {
452
+ readonly fontStyle: OrMask<FontStyle$1>;
453
+ readonly foregroundId: number;
454
+ readonly backgroundId: number;
455
+ constructor(fontStyle: OrMask<FontStyle$1>, foregroundId: number, backgroundId: number);
456
+ }
457
+ declare class ParsedThemeRule {
458
+ readonly scope: ScopeName;
459
+ readonly parentScopes: ScopeName[] | null;
460
+ readonly index: number;
461
+ readonly fontStyle: OrMask<FontStyle$1>;
462
+ readonly foreground: string | null;
463
+ readonly background: string | null;
464
+ constructor(scope: ScopeName, parentScopes: ScopeName[] | null, index: number, fontStyle: OrMask<FontStyle$1>, foreground: string | null, background: string | null);
465
+ }
466
+ declare const enum FontStyle$1 {
467
+ NotSet = -1,
468
+ None = 0,
469
+ Italic = 1,
470
+ Bold = 2,
471
+ Underline = 4,
472
+ Strikethrough = 8
473
+ }
474
+ declare class ColorMap {
475
+ private readonly _isFrozen;
476
+ private _lastColorId;
477
+ private _id2color;
478
+ private _color2id;
479
+ constructor(_colorMap?: string[]);
480
+ getId(color: string | null): number;
481
+ getColorMap(): string[];
482
+ }
483
+ declare class ThemeTrieElementRule {
484
+ scopeDepth: number;
485
+ parentScopes: ScopeName[] | null;
486
+ fontStyle: number;
487
+ foreground: number;
488
+ background: number;
489
+ constructor(scopeDepth: number, parentScopes: ScopeName[] | null, fontStyle: number, foreground: number, background: number);
490
+ clone(): ThemeTrieElementRule;
491
+ static cloneArr(arr: ThemeTrieElementRule[]): ThemeTrieElementRule[];
492
+ acceptOverwrite(scopeDepth: number, fontStyle: number, foreground: number, background: number): void;
493
+ }
494
+ interface ITrieChildrenMap {
495
+ [segment: string]: ThemeTrieElement;
496
+ }
497
+ declare class ThemeTrieElement {
498
+ private readonly _mainRule;
499
+ private readonly _children;
500
+ private readonly _rulesWithParentScopes;
501
+ constructor(_mainRule: ThemeTrieElementRule, rulesWithParentScopes?: ThemeTrieElementRule[], _children?: ITrieChildrenMap);
502
+ private static _sortBySpecificity;
503
+ private static _cmpBySpecificity;
504
+ match(scope: ScopeName): ThemeTrieElementRule[];
505
+ insert(scopeDepth: number, scope: ScopeName, parentScopes: ScopeName[] | null, fontStyle: number, foreground: number, background: number): void;
506
+ private _doInsertHere;
507
+ }
426
508
 
427
509
  interface IRawGrammar extends ILocatable {
428
510
  repository: IRawRepository;
@@ -799,6 +881,7 @@ interface ShikiTransformerContext extends ShikiTransformerContextSource {
799
881
  readonly pre: Element;
800
882
  readonly code: Element;
801
883
  readonly lines: Element[];
884
+ readonly structure: CodeToHastOptions['structure'];
802
885
  /**
803
886
  * Utility to append class to a hast node
804
887
  *
@@ -1011,6 +1094,15 @@ interface CodeToHastOptionsCommon<Languages extends string = string> extends Tra
1011
1094
  * @default true
1012
1095
  */
1013
1096
  mergeWhitespaces?: boolean | 'never';
1097
+ /**
1098
+ * The structure of the generated HAST and HTML.
1099
+ *
1100
+ * - `classic`: The classic structure with `<pre>` and `<code>` elements, each line wrapped with a `<span class="line">` element.
1101
+ * - `inline`: All tokens are rendered as `<span>`, line breaks are rendered as `<br>`. No `<pre>` or `<code>` elements. Default forground and background colors are not applied.
1102
+ *
1103
+ * @default 'classic'
1104
+ */
1105
+ structure?: 'classic' | 'inline';
1014
1106
  }
1015
1107
  interface CodeOptionsMeta {
1016
1108
  /**
@@ -1228,4 +1320,4 @@ declare enum FontStyle {
1228
1320
  Underline = 4
1229
1321
  }
1230
1322
 
1231
- export { type DynamicImportThemeRegistration as $, type ShikiTransformer as A, type BundledHighlighterOptions as B, type CodeToHastOptions as C, type AnsiLanguage as D, type Element as E, FontStyle as F, type ResolveBundleKey as G, type HighlighterCoreOptions as H, INITIAL as I, type LanguageRegistration as J, type BundledLanguageInfo as K, type LanguageInput as L, type MaybeArray as M, type Nodes as N, type DynamicImportLanguageRegistration as O, type PlainTextLanguage as P, type CodeOptionsSingleTheme as Q, Registry as R, type StateStack as S, type ThemeInput as T, type CodeOptionsMultipleThemes as U, type CodeOptionsThemes as V, type CodeToHastOptionsCommon as W, type CodeOptionsMeta as X, type CodeToHastRenderOptionsCommon as Y, type ThemeRegistrationRaw as Z, type ThemeRegistration as _, type IRawTheme as a, type BundledThemeInfo as a0, type ThemedTokenScopeExplanation as a1, type ThemedTokenExplanation as a2, type TokenBase as a3, type TransformerOptions as a4, type ShikiTransformerContextMeta as a5, type ShikiTransformerContext as a6, type Awaitable as a7, type MaybeGetter as a8, type MaybeModule as a9, type StringLiteralUnion as aa, type DecorationOptions as ab, type DecorationItem as ac, type ResolvedDecorationItem as ad, type DecorationTransformType as ae, type Offset as af, type OffsetOrPosition as ag, type ResolvedPosition as ah, type IRawGrammar as b, type IGrammar as c, type IGrammarConfiguration as d, type IOnigLib as e, type RegistryOptions as f, type IRawThemeSetting as g, type Root as h, type CodeToTokensOptions as i, type TokensResult as j, type RequireKeys as k, type CodeToTokensBaseOptions as l, type ThemedToken as m, type CodeToTokensWithThemesOptions as n, type ThemedTokenWithVariants as o, type SpecialLanguage as p, type SpecialTheme as q, type TokenStyles as r, type Position as s, type ThemeRegistrationResolved as t, type TokenizeWithThemeOptions as u, type ShikiTransformerContextCommon as v, type CodeToHastRenderOptions as w, type ShikiTransformerContextSource as x, type RootContent as y, type ThemeRegistrationAny as z };
1323
+ export { type ThemeRegistration as $, type ThemeRegistrationAny as A, type BundledHighlighterOptions as B, type CodeToHastOptions as C, type ShikiTransformer as D, type Element as E, FontStyle as F, type AnsiLanguage as G, type HighlighterCoreOptions as H, INITIAL as I, type ResolveBundleKey as J, type LanguageRegistration as K, type LanguageInput as L, type MaybeArray as M, type Nodes as N, type BundledLanguageInfo as O, type PlainTextLanguage as P, type DynamicImportLanguageRegistration as Q, Registry as R, type StateStack as S, Theme as T, type CodeOptionsSingleTheme as U, type CodeOptionsMultipleThemes as V, type CodeOptionsThemes as W, type CodeToHastOptionsCommon as X, type CodeOptionsMeta as Y, type CodeToHastRenderOptionsCommon as Z, type ThemeRegistrationRaw as _, type IRawTheme as a, type DynamicImportThemeRegistration as a0, type BundledThemeInfo as a1, type ThemedTokenScopeExplanation as a2, type ThemedTokenExplanation as a3, type TokenBase as a4, type TransformerOptions as a5, type ShikiTransformerContextMeta as a6, type ShikiTransformerContext as a7, type Awaitable as a8, type MaybeGetter as a9, type MaybeModule as aa, type StringLiteralUnion as ab, type DecorationOptions as ac, type DecorationItem as ad, type ResolvedDecorationItem as ae, type DecorationTransformType as af, type Offset as ag, type OffsetOrPosition as ah, type ResolvedPosition as ai, type IRawGrammar as b, type IGrammar as c, type IGrammarConfiguration as d, type IOnigLib as e, type RegistryOptions as f, type IRawThemeSetting as g, type ThemeInput as h, type Root as i, type CodeToTokensOptions as j, type TokensResult as k, type RequireKeys as l, type CodeToTokensBaseOptions as m, type ThemedToken as n, type CodeToTokensWithThemesOptions as o, type ThemedTokenWithVariants as p, type SpecialLanguage as q, type SpecialTheme as r, type TokenStyles as s, type Position as t, type ThemeRegistrationResolved as u, type TokenizeWithThemeOptions as v, type ShikiTransformerContextCommon as w, type CodeToHastRenderOptions as x, type ShikiTransformerContextSource as y, type RootContent as z };
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { HighlighterCore, HighlighterGeneric, ShikiInternal } from './types.mjs';
2
- import { H as HighlighterCoreOptions, B as BundledHighlighterOptions, L as LanguageInput, T as ThemeInput, C as CodeToHastOptions, h as Root, i as CodeToTokensOptions, j as TokensResult, k as RequireKeys, l as CodeToTokensBaseOptions, m as ThemedToken, n as CodeToTokensWithThemesOptions, o as ThemedTokenWithVariants, M as MaybeArray, P as PlainTextLanguage, p as SpecialLanguage, q as SpecialTheme, E as Element, r as TokenStyles, s as Position, c as IGrammar, t as ThemeRegistrationResolved, u as TokenizeWithThemeOptions, v as ShikiTransformerContextCommon, w as CodeToHastRenderOptions, x as ShikiTransformerContextSource, N as Nodes$1, y as RootContent$1, z as ThemeRegistrationAny, A as ShikiTransformer } from './chunk-tokens.mjs';
3
- export { D as AnsiLanguage, a7 as Awaitable, K as BundledLanguageInfo, a0 as BundledThemeInfo, X as CodeOptionsMeta, U as CodeOptionsMultipleThemes, Q as CodeOptionsSingleTheme, V as CodeOptionsThemes, W as CodeToHastOptionsCommon, Y as CodeToHastRenderOptionsCommon, ac as DecorationItem, ab as DecorationOptions, ae as DecorationTransformType, O as DynamicImportLanguageRegistration, $ as DynamicImportThemeRegistration, F as FontStyle, J as LanguageRegistration, a8 as MaybeGetter, a9 as MaybeModule, af as Offset, ag as OffsetOrPosition, b as RawGrammar, a as RawTheme, g as RawThemeSetting, G as ResolveBundleKey, ad as ResolvedDecorationItem, ah as ResolvedPosition, a6 as ShikiTransformerContext, a5 as ShikiTransformerContextMeta, aa as StringLiteralUnion, _ as ThemeRegistration, Z as ThemeRegistrationRaw, a2 as ThemedTokenExplanation, a1 as ThemedTokenScopeExplanation, a3 as TokenBase, a4 as TransformerOptions } from './chunk-tokens.mjs';
2
+ import { H as HighlighterCoreOptions, B as BundledHighlighterOptions, L as LanguageInput, h as ThemeInput, C as CodeToHastOptions, i as Root, j as CodeToTokensOptions, k as TokensResult, l as RequireKeys, m as CodeToTokensBaseOptions, n as ThemedToken, o as CodeToTokensWithThemesOptions, p as ThemedTokenWithVariants, M as MaybeArray, P as PlainTextLanguage, q as SpecialLanguage, r as SpecialTheme, E as Element, s as TokenStyles, t as Position, c as IGrammar, u as ThemeRegistrationResolved, v as TokenizeWithThemeOptions, w as ShikiTransformerContextCommon, x as CodeToHastRenderOptions, y as ShikiTransformerContextSource, N as Nodes$1, z as RootContent$1, A as ThemeRegistrationAny, D as ShikiTransformer } from './chunk-tokens.mjs';
3
+ export { G as AnsiLanguage, a8 as Awaitable, O as BundledLanguageInfo, a1 as BundledThemeInfo, Y as CodeOptionsMeta, V as CodeOptionsMultipleThemes, U as CodeOptionsSingleTheme, W as CodeOptionsThemes, X as CodeToHastOptionsCommon, Z as CodeToHastRenderOptionsCommon, ad as DecorationItem, ac as DecorationOptions, af as DecorationTransformType, Q as DynamicImportLanguageRegistration, a0 as DynamicImportThemeRegistration, F as FontStyle, K as LanguageRegistration, a9 as MaybeGetter, aa as MaybeModule, ag as Offset, ah as OffsetOrPosition, b as RawGrammar, a as RawTheme, g as RawThemeSetting, J as ResolveBundleKey, ae as ResolvedDecorationItem, ai as ResolvedPosition, a7 as ShikiTransformerContext, a6 as ShikiTransformerContextMeta, ab as StringLiteralUnion, $ as ThemeRegistration, _ as ThemeRegistrationRaw, a3 as ThemedTokenExplanation, a2 as ThemedTokenScopeExplanation, a4 as TokenBase, a5 as TransformerOptions } from './chunk-tokens.mjs';
4
4
  import { L as LoadWasmOptions } from './chunk-index.mjs';
5
5
  export { W as WebAssemblyInstantiator, l as loadWasm } from './chunk-index.mjs';
6
6
 
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { StackElementMetadata, INITIAL, Registry as Registry$1 } from './textmate.mjs';
1
+ import { StackElementMetadata, INITIAL, Registry as Registry$1, Theme } from './textmate.mjs';
2
2
  import { FontStyle } from './types.mjs';
3
3
 
4
4
  function toArray(x) {
@@ -1032,10 +1032,11 @@ function codeToHast(internal, code, options, transformerContext = {
1032
1032
  function tokensToHast(tokens, options, transformerContext) {
1033
1033
  const transformers = getTransformers(options);
1034
1034
  const lines = [];
1035
- const tree = {
1035
+ const root = {
1036
1036
  type: 'root',
1037
1037
  children: [],
1038
1038
  };
1039
+ const { structure = 'classic', } = options;
1039
1040
  let preNode = {
1040
1041
  type: 'element',
1041
1042
  tagName: 'pre',
@@ -1057,6 +1058,7 @@ function tokensToHast(tokens, options, transformerContext) {
1057
1058
  const lineNodes = [];
1058
1059
  const context = {
1059
1060
  ...transformerContext,
1061
+ structure,
1060
1062
  addClassToHast,
1061
1063
  get source() {
1062
1064
  return transformerContext.source;
@@ -1068,7 +1070,7 @@ function tokensToHast(tokens, options, transformerContext) {
1068
1070
  return options;
1069
1071
  },
1070
1072
  get root() {
1071
- return tree;
1073
+ return root;
1072
1074
  },
1073
1075
  get pre() {
1074
1076
  return preNode;
@@ -1081,8 +1083,12 @@ function tokensToHast(tokens, options, transformerContext) {
1081
1083
  },
1082
1084
  };
1083
1085
  tokens.forEach((line, idx) => {
1084
- if (idx)
1085
- lines.push({ type: 'text', value: '\n' });
1086
+ if (idx) {
1087
+ if (structure === 'inline')
1088
+ root.children.push({ type: 'element', tagName: 'br', properties: {}, children: [] });
1089
+ else if (structure === 'classic')
1090
+ lines.push({ type: 'text', value: '\n' });
1091
+ }
1086
1092
  let lineNode = {
1087
1093
  type: 'element',
1088
1094
  tagName: 'span',
@@ -1102,21 +1108,28 @@ function tokensToHast(tokens, options, transformerContext) {
1102
1108
  tokenNode.properties.style = style;
1103
1109
  for (const transformer of transformers)
1104
1110
  tokenNode = transformer?.span?.call(context, tokenNode, idx + 1, col, lineNode) || tokenNode;
1105
- lineNode.children.push(tokenNode);
1111
+ if (structure === 'inline')
1112
+ root.children.push(tokenNode);
1113
+ else if (structure === 'classic')
1114
+ lineNode.children.push(tokenNode);
1106
1115
  col += token.content.length;
1107
1116
  }
1108
- for (const transformer of transformers)
1109
- lineNode = transformer?.line?.call(context, lineNode, idx + 1) || lineNode;
1110
- lineNodes.push(lineNode);
1111
- lines.push(lineNode);
1117
+ if (structure === 'classic') {
1118
+ for (const transformer of transformers)
1119
+ lineNode = transformer?.line?.call(context, lineNode, idx + 1) || lineNode;
1120
+ lineNodes.push(lineNode);
1121
+ lines.push(lineNode);
1122
+ }
1112
1123
  });
1113
- for (const transformer of transformers)
1114
- codeNode = transformer?.code?.call(context, codeNode) || codeNode;
1115
- preNode.children.push(codeNode);
1116
- for (const transformer of transformers)
1117
- preNode = transformer?.pre?.call(context, preNode) || preNode;
1118
- tree.children.push(preNode);
1119
- let result = tree;
1124
+ if (structure === 'classic') {
1125
+ for (const transformer of transformers)
1126
+ codeNode = transformer?.code?.call(context, codeNode) || codeNode;
1127
+ preNode.children.push(codeNode);
1128
+ for (const transformer of transformers)
1129
+ preNode = transformer?.pre?.call(context, preNode) || preNode;
1130
+ root.children.push(preNode);
1131
+ }
1132
+ let result = root;
1120
1133
  for (const transformer of transformers)
1121
1134
  result = transformer?.root?.call(context, result) || result;
1122
1135
  return result;
@@ -3259,6 +3272,12 @@ function stringifyEntities(value, options) {
3259
3272
  */
3260
3273
 
3261
3274
 
3275
+ const htmlCommentRegex = /^>|^->|<!--|-->|--!>|<!-$/g;
3276
+
3277
+ // Declare arrays as variables so it can be cached by `stringifyEntities`
3278
+ const bogusCommentEntitySubset = ['>'];
3279
+ const commentEntitySubset = ['<', '>'];
3280
+
3262
3281
  /**
3263
3282
  * Serialize a comment.
3264
3283
  *
@@ -3279,10 +3298,12 @@ function comment(node, _1, _2, state) {
3279
3298
  ? '<?' +
3280
3299
  stringifyEntities(
3281
3300
  node.value,
3282
- Object.assign({}, state.settings.characterReferences, {subset: ['>']})
3301
+ Object.assign({}, state.settings.characterReferences, {
3302
+ subset: bogusCommentEntitySubset
3303
+ })
3283
3304
  ) +
3284
3305
  '>'
3285
- : '<!--' + node.value.replace(/^>|^->|<!--|-->|--!>|<!-$/g, encode) + '-->'
3306
+ : '<!--' + node.value.replace(htmlCommentRegex, encode) + '-->'
3286
3307
 
3287
3308
  /**
3288
3309
  * @param {string} $0
@@ -3291,7 +3312,7 @@ function comment(node, _1, _2, state) {
3291
3312
  return stringifyEntities(
3292
3313
  $0,
3293
3314
  Object.assign({}, state.settings.characterReferences, {
3294
- subset: ['<', '>']
3315
+ subset: commentEntitySubset
3295
3316
  })
3296
3317
  )
3297
3318
  }
@@ -4116,7 +4137,7 @@ function element(node, index, parent, state) {
4116
4137
  state.schema = svg;
4117
4138
  }
4118
4139
 
4119
- const attrs = serializeAttributes(state, node.properties);
4140
+ const attributes = serializeAttributes(state, node.properties);
4120
4141
 
4121
4142
  const content = state.all(
4122
4143
  schema.space === 'html' && node.tagName === 'template' ? node.content : node
@@ -4132,14 +4153,14 @@ function element(node, index, parent, state) {
4132
4153
  // longer void.
4133
4154
  if (content) selfClosing = false;
4134
4155
 
4135
- if (attrs || !omit || !opening(node, index, parent)) {
4136
- parts.push('<', node.tagName, attrs ? ' ' + attrs : '');
4156
+ if (attributes || !omit || !opening(node, index, parent)) {
4157
+ parts.push('<', node.tagName, attributes ? ' ' + attributes : '');
4137
4158
 
4138
4159
  if (
4139
4160
  selfClosing &&
4140
4161
  (schema.space === 'svg' || state.settings.closeSelfClosing)
4141
4162
  ) {
4142
- last = attrs.charAt(attrs.length - 1);
4163
+ last = attributes.charAt(attributes.length - 1);
4143
4164
  if (
4144
4165
  !state.settings.tightSelfClosing ||
4145
4166
  last === '/' ||
@@ -4165,20 +4186,20 @@ function element(node, index, parent, state) {
4165
4186
 
4166
4187
  /**
4167
4188
  * @param {State} state
4168
- * @param {Properties | null | undefined} props
4189
+ * @param {Properties | null | undefined} properties
4169
4190
  * @returns {string}
4170
4191
  */
4171
- function serializeAttributes(state, props) {
4192
+ function serializeAttributes(state, properties) {
4172
4193
  /** @type {Array<string>} */
4173
4194
  const values = [];
4174
4195
  let index = -1;
4175
4196
  /** @type {string} */
4176
4197
  let key;
4177
4198
 
4178
- if (props) {
4179
- for (key in props) {
4180
- if (props[key] !== null && props[key] !== undefined) {
4181
- const value = serializeAttribute(state, key, props[key]);
4199
+ if (properties) {
4200
+ for (key in properties) {
4201
+ if (properties[key] !== null && properties[key] !== undefined) {
4202
+ const value = serializeAttribute(state, key, properties[key]);
4182
4203
  if (value) values.push(value);
4183
4204
  }
4184
4205
  }
@@ -4317,6 +4338,9 @@ function serializeAttribute(state, key, value) {
4317
4338
  */
4318
4339
 
4319
4340
 
4341
+ // Declare array as variable so it can be cached by `stringifyEntities`
4342
+ const textEntitySubset = ['<', '&'];
4343
+
4320
4344
  /**
4321
4345
  * Serialize a text node.
4322
4346
  *
@@ -4340,7 +4364,7 @@ function text(node, _, parent, state) {
4340
4364
  : stringifyEntities(
4341
4365
  node.value,
4342
4366
  Object.assign({}, state.settings.characterReferences, {
4343
- subset: ['<', '&']
4367
+ subset: textEntitySubset
4344
4368
  })
4345
4369
  )
4346
4370
  }
@@ -5111,16 +5135,20 @@ class Registry extends Registry$1 {
5111
5135
  _resolver;
5112
5136
  _themes;
5113
5137
  _langs;
5138
+ _alias;
5114
5139
  _resolvedThemes = {};
5115
5140
  _resolvedGrammars = {};
5116
5141
  _langMap = {};
5117
5142
  _langGraph = new Map();
5118
- alias = {};
5119
- constructor(_resolver, _themes, _langs) {
5143
+ _textmateThemeCache = new WeakMap();
5144
+ _loadedThemesCache = null;
5145
+ _loadedLanguagesCache = null;
5146
+ constructor(_resolver, _themes, _langs, _alias = {}) {
5120
5147
  super(_resolver);
5121
5148
  this._resolver = _resolver;
5122
5149
  this._themes = _themes;
5123
5150
  this._langs = _langs;
5151
+ this._alias = _alias;
5124
5152
  _themes.forEach(t => this.loadTheme(t));
5125
5153
  _langs.forEach(l => this.loadLanguage(l));
5126
5154
  }
@@ -5132,18 +5160,37 @@ class Registry extends Registry$1 {
5132
5160
  }
5133
5161
  loadTheme(theme) {
5134
5162
  const _theme = normalizeTheme(theme);
5135
- if (_theme.name)
5163
+ if (_theme.name) {
5136
5164
  this._resolvedThemes[_theme.name] = _theme;
5165
+ // Reset cache
5166
+ this._loadedThemesCache = null;
5167
+ }
5137
5168
  return _theme;
5138
5169
  }
5139
5170
  getLoadedThemes() {
5140
- return Object.keys(this._resolvedThemes);
5171
+ if (!this._loadedThemesCache)
5172
+ this._loadedThemesCache = Object.keys(this._resolvedThemes);
5173
+ return this._loadedThemesCache;
5174
+ }
5175
+ // Override and re-implement this method to cache the textmate themes as `TextMateTheme.createFromRawTheme`
5176
+ // is expensive. Themes can switch often especially for dual-theme support.
5177
+ //
5178
+ // The parent class also accepts `colorMap` as the second parameter, but since we don't use that,
5179
+ // we omit here so it's easier to cache the themes.
5180
+ setTheme(theme) {
5181
+ let textmateTheme = this._textmateThemeCache.get(theme);
5182
+ if (!textmateTheme) {
5183
+ textmateTheme = Theme.createFromRawTheme(theme);
5184
+ this._textmateThemeCache.set(theme, textmateTheme);
5185
+ }
5186
+ // @ts-expect-error Access private `_syncRegistry`, but should work in runtime
5187
+ this._syncRegistry.setTheme(textmateTheme);
5141
5188
  }
5142
5189
  getGrammar(name) {
5143
- if (this.alias[name]) {
5190
+ if (this._alias[name]) {
5144
5191
  const resolved = new Set([name]);
5145
- while (this.alias[name]) {
5146
- name = this.alias[name];
5192
+ while (this._alias[name]) {
5193
+ name = this._alias[name];
5147
5194
  if (resolved.has(name))
5148
5195
  throw new ShikiError(`Circular alias \`${Array.from(resolved).join(' -> ')} -> ${name}\``);
5149
5196
  resolved.add(name);
@@ -5166,13 +5213,17 @@ class Registry extends Registry$1 {
5166
5213
  this._resolvedGrammars[lang.name] = g;
5167
5214
  if (lang.aliases) {
5168
5215
  lang.aliases.forEach((alias) => {
5169
- this.alias[alias] = lang.name;
5216
+ this._alias[alias] = lang.name;
5170
5217
  });
5171
5218
  }
5219
+ // Reset cache
5220
+ this._loadedLanguagesCache = null;
5172
5221
  // If there is a language that embeds this language lazily, we need to reload it
5173
5222
  if (embeddedLazilyBy.size) {
5174
5223
  for (const e of embeddedLazilyBy) {
5175
5224
  delete this._resolvedGrammars[e.name];
5225
+ // Reset cache
5226
+ this._loadedLanguagesCache = null;
5176
5227
  // @ts-expect-error clear cache
5177
5228
  this._syncRegistry?._injectionGrammars?.delete(e.scopeName);
5178
5229
  // @ts-expect-error clear cache
@@ -5202,7 +5253,9 @@ class Registry extends Registry$1 {
5202
5253
  await this.loadLanguage(lang);
5203
5254
  }
5204
5255
  getLoadedLanguages() {
5205
- return Object.keys({ ...this._resolvedGrammars, ...this.alias });
5256
+ if (!this._loadedLanguagesCache)
5257
+ this._loadedLanguagesCache = Object.keys({ ...this._resolvedGrammars, ...this._alias });
5258
+ return this._loadedLanguagesCache;
5206
5259
  }
5207
5260
  resolveEmbeddedLanguages(lang) {
5208
5261
  this._langMap[lang.name] = lang;
@@ -5293,8 +5346,7 @@ async function getShikiInternal(options = {}) {
5293
5346
  return createOnigString(s);
5294
5347
  },
5295
5348
  }), langs);
5296
- const _registry = new Registry(resolver, themes, langs);
5297
- Object.assign(_registry.alias, options.langAlias);
5349
+ const _registry = new Registry(resolver, themes, langs, options.langAlias);
5298
5350
  await _registry.init();
5299
5351
  let _lastTheme;
5300
5352
  function getLanguage(name) {
@@ -1,5 +1,5 @@
1
1
  import { F as FontStyle } from './chunk-tokens.mjs';
2
- export { c as IGrammar, d as IGrammarConfiguration, I as INITIAL, e as IOnigLib, b as IRawGrammar, a as IRawTheme, g as IRawThemeSetting, R as Registry, f as RegistryOptions, S as StateStack } from './chunk-tokens.mjs';
2
+ export { c as IGrammar, d as IGrammarConfiguration, I as INITIAL, e as IOnigLib, b as IRawGrammar, a as IRawTheme, g as IRawThemeSetting, R as Registry, f as RegistryOptions, S as StateStack, T as Theme } from './chunk-tokens.mjs';
3
3
  import './chunk-index.mjs';
4
4
 
5
5
  declare const enum TemporaryStandardTokenType {
package/dist/textmate.mjs CHANGED
@@ -3132,4 +3132,4 @@ class StackElementMetadata {
3132
3132
  }
3133
3133
  }
3134
3134
 
3135
- export { INITIAL, Registry$1 as Registry, StackElementMetadata };
3135
+ export { INITIAL, Registry$1 as Registry, StackElementMetadata, Theme };
package/dist/types.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { T as ThemeInput, q as SpecialTheme, L as LanguageInput, p as SpecialLanguage, z as ThemeRegistrationAny, t as ThemeRegistrationResolved, J as LanguageRegistration, c as IGrammar, C as CodeToHastOptions, G as ResolveBundleKey, h as Root, i as CodeToTokensOptions, j as TokensResult, l as CodeToTokensBaseOptions, m as ThemedToken, n as CodeToTokensWithThemesOptions, o as ThemedTokenWithVariants } from './chunk-tokens.mjs';
2
- export { D as AnsiLanguage, a7 as Awaitable, B as BundledHighlighterOptions, K as BundledLanguageInfo, a0 as BundledThemeInfo, X as CodeOptionsMeta, U as CodeOptionsMultipleThemes, Q as CodeOptionsSingleTheme, V as CodeOptionsThemes, W as CodeToHastOptionsCommon, w as CodeToHastRenderOptions, Y as CodeToHastRenderOptionsCommon, ac as DecorationItem, ab as DecorationOptions, ae as DecorationTransformType, O as DynamicImportLanguageRegistration, $ as DynamicImportThemeRegistration, F as FontStyle, H as HighlighterCoreOptions, M as MaybeArray, a8 as MaybeGetter, a9 as MaybeModule, af as Offset, ag as OffsetOrPosition, P as PlainTextLanguage, s as Position, b as RawGrammar, a as RawTheme, g as RawThemeSetting, k as RequireKeys, ad as ResolvedDecorationItem, ah as ResolvedPosition, A as ShikiTransformer, a6 as ShikiTransformerContext, v as ShikiTransformerContextCommon, a5 as ShikiTransformerContextMeta, x as ShikiTransformerContextSource, aa as StringLiteralUnion, _ as ThemeRegistration, Z as ThemeRegistrationRaw, a2 as ThemedTokenExplanation, a1 as ThemedTokenScopeExplanation, a3 as TokenBase, r as TokenStyles, u as TokenizeWithThemeOptions, a4 as TransformerOptions } from './chunk-tokens.mjs';
1
+ import { h as ThemeInput, r as SpecialTheme, L as LanguageInput, q as SpecialLanguage, A as ThemeRegistrationAny, u as ThemeRegistrationResolved, K as LanguageRegistration, c as IGrammar, C as CodeToHastOptions, J as ResolveBundleKey, i as Root, j as CodeToTokensOptions, k as TokensResult, m as CodeToTokensBaseOptions, n as ThemedToken, o as CodeToTokensWithThemesOptions, p as ThemedTokenWithVariants } from './chunk-tokens.mjs';
2
+ export { G as AnsiLanguage, a8 as Awaitable, B as BundledHighlighterOptions, O as BundledLanguageInfo, a1 as BundledThemeInfo, Y as CodeOptionsMeta, V as CodeOptionsMultipleThemes, U as CodeOptionsSingleTheme, W as CodeOptionsThemes, X as CodeToHastOptionsCommon, x as CodeToHastRenderOptions, Z as CodeToHastRenderOptionsCommon, ad as DecorationItem, ac as DecorationOptions, af as DecorationTransformType, Q as DynamicImportLanguageRegistration, a0 as DynamicImportThemeRegistration, F as FontStyle, H as HighlighterCoreOptions, M as MaybeArray, a9 as MaybeGetter, aa as MaybeModule, ag as Offset, ah as OffsetOrPosition, P as PlainTextLanguage, t as Position, b as RawGrammar, a as RawTheme, g as RawThemeSetting, l as RequireKeys, ae as ResolvedDecorationItem, ai as ResolvedPosition, D as ShikiTransformer, a7 as ShikiTransformerContext, w as ShikiTransformerContextCommon, a6 as ShikiTransformerContextMeta, y as ShikiTransformerContextSource, ab as StringLiteralUnion, $ as ThemeRegistration, _ as ThemeRegistrationRaw, a3 as ThemedTokenExplanation, a2 as ThemedTokenScopeExplanation, a4 as TokenBase, s as TokenStyles, v as TokenizeWithThemeOptions, a5 as TransformerOptions } from './chunk-tokens.mjs';
3
3
  export { W as WebAssemblyInstantiator } from './chunk-index.mjs';
4
4
 
5
5
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shikijs/core",
3
3
  "type": "module",
4
- "version": "1.2.3",
4
+ "version": "1.3.0",
5
5
  "description": "Core of Shiki",
6
6
  "author": "Pine Wu <octref@gmail.com>; Anthony Fu <anthonyfu117@hotmail.com>",
7
7
  "license": "MIT",
@@ -60,7 +60,7 @@
60
60
  "dist"
61
61
  ],
62
62
  "devDependencies": {
63
- "hast-util-to-html": "^9.0.0",
63
+ "hast-util-to-html": "^9.0.1",
64
64
  "vscode-oniguruma": "^1.7.0"
65
65
  },
66
66
  "scripts": {