@shikijs/core 3.4.2 → 3.6.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.
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { CreatedBundledHighlighterOptions, CreateHighlighterFactory, CodeToHastOptions, CodeToTokensOptions, TokensResult, RequireKeys, CodeToTokensBaseOptions, ThemedToken, CodeToTokensWithThemesOptions, ThemedTokenWithVariants, BundledHighlighterOptions, HighlighterGeneric, GrammarState, Awaitable, HighlighterCoreOptions, HighlighterCore, ShikiInternal, ShikiTransformerContextCommon, CodeToHastRenderOptions, ShikiTransformerContextSource, ThemeRegistrationResolved, TokenizeWithThemeOptions, Grammar, ThemeRegistrationAny, ThemeRegistration, ShikiTransformer, MaybeArray, MaybeGetter, PlainTextLanguage, SpecialLanguage, ThemeInput, SpecialTheme, Position, TokenStyles } from '@shikijs/types';
1
+ import { CreatedBundledHighlighterOptions, CreateHighlighterFactory, CodeToHastOptions, CodeToTokensOptions, TokensResult, RequireKeys, CodeToTokensBaseOptions, ThemedToken, CodeToTokensWithThemesOptions, ThemedTokenWithVariants, BundledHighlighterOptions, HighlighterGeneric, GrammarState, Awaitable, HighlighterCoreOptions, HighlighterCore, ShikiInternal, ShikiTransformerContextCommon, CodeToHastRenderOptions, ShikiTransformerContextSource, ThemeRegistrationResolved, TokenizeWithThemeOptions, Grammar, ThemeRegistrationAny, ThemeRegistration, ShikiTransformer, MaybeArray, MaybeGetter, PlainTextLanguage, SpecialLanguage, ThemeInput, SpecialTheme, Position, CodeOptionsMultipleThemes, TokenStyles } from '@shikijs/types';
2
2
  export * from '@shikijs/types';
3
3
  import { Root, Element } from 'hast';
4
4
  import { toHtml } from 'hast-util-to-html';
@@ -254,7 +254,7 @@ declare function splitToken<T extends Pick<ThemedToken, 'content' | 'offset'>>(t
254
254
  * Split 2D tokens array by given breakpoints.
255
255
  */
256
256
  declare function splitTokens<T extends Pick<ThemedToken, 'content' | 'offset'>>(tokens: T[][], breakpoints: number[] | Set<number>): T[][];
257
- declare function flatTokenVariants(merged: ThemedTokenWithVariants, variantsOrder: string[], cssVariablePrefix: string, defaultColor: string | boolean): ThemedToken;
257
+ declare function flatTokenVariants(merged: ThemedTokenWithVariants, variantsOrder: string[], cssVariablePrefix: string, defaultColor: CodeOptionsMultipleThemes['defaultColor'], colorsRendering?: CodeOptionsMultipleThemes['colorsRendering']): ThemedToken;
258
258
  declare function getTokenStyleObject(token: TokenStyles): Record<string, string>;
259
259
  declare function stringifyTokenStyle(token: string | Record<string, string>): string;
260
260
 
package/dist/index.mjs CHANGED
@@ -117,6 +117,8 @@ function guessEmbeddedLanguages(code, _lang, highlighter) {
117
117
  return Array.from(langs).filter((l) => l && bundle[l]);
118
118
  }
119
119
 
120
+ const DEFAULT_COLOR_LIGHT_DARK = "light-dark()";
121
+
120
122
  function splitToken(token, offsets) {
121
123
  let lastOffset = 0;
122
124
  const tokens = [];
@@ -152,7 +154,7 @@ function splitTokens(tokens, breakpoints) {
152
154
  });
153
155
  });
154
156
  }
155
- function flatTokenVariants(merged, variantsOrder, cssVariablePrefix, defaultColor) {
157
+ function flatTokenVariants(merged, variantsOrder, cssVariablePrefix, defaultColor, colorsRendering = "css-vars") {
156
158
  const token = {
157
159
  content: merged.content,
158
160
  explanation: merged.explanation,
@@ -161,15 +163,30 @@ function flatTokenVariants(merged, variantsOrder, cssVariablePrefix, defaultColo
161
163
  const styles = variantsOrder.map((t) => getTokenStyleObject(merged.variants[t]));
162
164
  const styleKeys = new Set(styles.flatMap((t) => Object.keys(t)));
163
165
  const mergedStyles = {};
166
+ const varKey = (idx, key) => {
167
+ const keyName = key === "color" ? "" : key === "background-color" ? "-bg" : `-${key}`;
168
+ return cssVariablePrefix + variantsOrder[idx] + (key === "color" ? "" : keyName);
169
+ };
164
170
  styles.forEach((cur, idx) => {
165
171
  for (const key of styleKeys) {
166
172
  const value = cur[key] || "inherit";
167
173
  if (idx === 0 && defaultColor) {
168
- mergedStyles[key] = value;
174
+ if (defaultColor === DEFAULT_COLOR_LIGHT_DARK && styles.length > 1) {
175
+ const lightIndex = variantsOrder.findIndex((t) => t === "light");
176
+ const darkIndex = variantsOrder.findIndex((t) => t === "dark");
177
+ if (lightIndex === -1 || darkIndex === -1)
178
+ throw new ShikiError$1('When using `defaultColor: "light-dark()"`, you must provide both `light` and `dark` themes');
179
+ const lightValue = styles[lightIndex][key] || "inherit";
180
+ const darkValue = styles[darkIndex][key] || "inherit";
181
+ mergedStyles[key] = `light-dark(${lightValue}, ${darkValue})`;
182
+ if (colorsRendering === "css-vars")
183
+ mergedStyles[varKey(idx, key)] = value;
184
+ } else {
185
+ mergedStyles[key] = value;
186
+ }
169
187
  } else {
170
- const keyName = key === "color" ? "" : key === "background-color" ? "-bg" : `-${key}`;
171
- const varKey = cssVariablePrefix + variantsOrder[idx] + (key === "color" ? "" : keyName);
172
- mergedStyles[varKey] = value;
188
+ if (colorsRendering === "css-vars")
189
+ mergedStyles[varKey(idx, key)] = value;
173
190
  }
174
191
  }
175
192
  });
@@ -1101,7 +1118,8 @@ function codeToTokens(internal, code, options) {
1101
1118
  if ("themes" in options) {
1102
1119
  const {
1103
1120
  defaultColor = "light",
1104
- cssVariablePrefix = "--shiki-"
1121
+ cssVariablePrefix = "--shiki-",
1122
+ colorsRendering = "css-vars"
1105
1123
  } = options;
1106
1124
  const themes = Object.entries(options.themes).filter((i) => i[1]).map((i) => ({ color: i[0], theme: i[1] })).sort((a, b) => a.color === defaultColor ? -1 : b.color === defaultColor ? 1 : 0);
1107
1125
  if (themes.length === 0)
@@ -1112,16 +1130,16 @@ function codeToTokens(internal, code, options) {
1112
1130
  options
1113
1131
  );
1114
1132
  grammarState = getLastGrammarStateFromMap(themeTokens);
1115
- if (defaultColor && !themes.find((t) => t.color === defaultColor))
1133
+ if (defaultColor && DEFAULT_COLOR_LIGHT_DARK !== defaultColor && !themes.find((t) => t.color === defaultColor))
1116
1134
  throw new ShikiError$1(`\`themes\` option must contain the defaultColor key \`${defaultColor}\``);
1117
1135
  const themeRegs = themes.map((t) => internal.getTheme(t.theme));
1118
1136
  const themesOrder = themes.map((t) => t.color);
1119
- tokens = themeTokens.map((line) => line.map((token) => flatTokenVariants(token, themesOrder, cssVariablePrefix, defaultColor)));
1137
+ tokens = themeTokens.map((line) => line.map((token) => flatTokenVariants(token, themesOrder, cssVariablePrefix, defaultColor, colorsRendering)));
1120
1138
  if (grammarState)
1121
1139
  setLastGrammarStateToMap(tokens, grammarState);
1122
1140
  const themeColorReplacements = themes.map((t) => resolveColorReplacements(t.theme, options));
1123
- fg = themes.map((t, idx) => (idx === 0 && defaultColor ? "" : `${cssVariablePrefix + t.color}:`) + (applyColorReplacements(themeRegs[idx].fg, themeColorReplacements[idx]) || "inherit")).join(";");
1124
- bg = themes.map((t, idx) => (idx === 0 && defaultColor ? "" : `${cssVariablePrefix + t.color}-bg:`) + (applyColorReplacements(themeRegs[idx].bg, themeColorReplacements[idx]) || "inherit")).join(";");
1141
+ fg = mapThemeColors(themes, themeRegs, themeColorReplacements, cssVariablePrefix, defaultColor, "fg", colorsRendering);
1142
+ bg = mapThemeColors(themes, themeRegs, themeColorReplacements, cssVariablePrefix, defaultColor, "bg", colorsRendering);
1125
1143
  themeName = `shiki-themes ${themeRegs.map((t) => t.name).join(" ")}`;
1126
1144
  rootStyle = defaultColor ? void 0 : [fg, bg].join(";");
1127
1145
  } else if ("theme" in options) {
@@ -1148,6 +1166,28 @@ function codeToTokens(internal, code, options) {
1148
1166
  grammarState
1149
1167
  };
1150
1168
  }
1169
+ function mapThemeColors(themes, themeRegs, themeColorReplacements, cssVariablePrefix, defaultColor, property, colorsRendering) {
1170
+ return themes.map((t, idx) => {
1171
+ const value = applyColorReplacements(themeRegs[idx][property], themeColorReplacements[idx]) || "inherit";
1172
+ const cssVar = `${cssVariablePrefix + t.color}${property === "bg" ? "-bg" : ""}:${value}`;
1173
+ if (idx === 0 && defaultColor) {
1174
+ if (defaultColor === DEFAULT_COLOR_LIGHT_DARK && themes.length > 1) {
1175
+ const lightIndex = themes.findIndex((t2) => t2.color === "light");
1176
+ const darkIndex = themes.findIndex((t2) => t2.color === "dark");
1177
+ if (lightIndex === -1 || darkIndex === -1)
1178
+ throw new ShikiError$1('When using `defaultColor: "light-dark()"`, you must provide both `light` and `dark` themes');
1179
+ const lightValue = applyColorReplacements(themeRegs[lightIndex][property], themeColorReplacements[lightIndex]) || "inherit";
1180
+ const darkValue = applyColorReplacements(themeRegs[darkIndex][property], themeColorReplacements[darkIndex]) || "inherit";
1181
+ return `light-dark(${lightValue}, ${darkValue});${cssVar}`;
1182
+ }
1183
+ return value;
1184
+ }
1185
+ if (colorsRendering === "css-vars") {
1186
+ return cssVar;
1187
+ }
1188
+ return null;
1189
+ }).filter((i) => !!i).join(";");
1190
+ }
1151
1191
 
1152
1192
  function codeToHast(internal, code, options, transformerContext = {
1153
1193
  meta: {},
@@ -1395,8 +1435,8 @@ function mergeAdjacentStyledTokens(tokens) {
1395
1435
  continue;
1396
1436
  }
1397
1437
  const prevToken = newLine[newLine.length - 1];
1398
- const prevStyle = prevToken.htmlStyle || stringifyTokenStyle(getTokenStyleObject(prevToken));
1399
- const currentStyle = token.htmlStyle || stringifyTokenStyle(getTokenStyleObject(token));
1438
+ const prevStyle = stringifyTokenStyle(prevToken.htmlStyle || getTokenStyleObject(prevToken));
1439
+ const currentStyle = stringifyTokenStyle(token.htmlStyle || getTokenStyleObject(token));
1400
1440
  const isPrevDecorated = prevToken.fontStyle && (prevToken.fontStyle & FontStyle.Underline || prevToken.fontStyle & FontStyle.Strikethrough);
1401
1441
  const isDecorated = token.fontStyle && (token.fontStyle & FontStyle.Underline || token.fontStyle & FontStyle.Strikethrough);
1402
1442
  if (!isPrevDecorated && !isDecorated && prevStyle === currentStyle) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shikijs/core",
3
3
  "type": "module",
4
- "version": "3.4.2",
4
+ "version": "3.6.0",
5
5
  "description": "Core of Shiki",
6
6
  "author": "Pine Wu <octref@gmail.com>; Anthony Fu <anthonyfu117@hotmail.com>",
7
7
  "license": "MIT",
@@ -39,7 +39,7 @@
39
39
  "@shikijs/vscode-textmate": "^10.0.2",
40
40
  "@types/hast": "^3.0.4",
41
41
  "hast-util-to-html": "^9.0.5",
42
- "@shikijs/types": "3.4.2"
42
+ "@shikijs/types": "3.6.0"
43
43
  },
44
44
  "scripts": {
45
45
  "build": "unbuild",