@aparte/plugin-shiki 0.7.0 → 0.8.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/README.md CHANGED
@@ -34,6 +34,12 @@ else:
34
34
  An option listing the languages would not change that — a static import is a static import (measured:
35
35
  still 302 files). So if what you ship matters, build the highlighter yourself and hand it over:
36
36
 
37
+ Those fine-grained entry points live in **separate packages** — add them alongside `shiki`:
38
+
39
+ ```bash
40
+ npm install @shikijs/langs @shikijs/themes
41
+ ```
42
+
37
43
  ```ts
38
44
  import { createHighlighterCore } from 'shiki/core';
39
45
  import { createJavaScriptRegexEngine } from 'shiki/engine/javascript';
package/dist/core.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { type AparteConfig } from '@aparte/core';
1
2
  /**
2
3
  * The slice of a shiki highlighter this plugin actually uses — declared here rather
3
4
  * than borrowed from `HighlighterCore`, so this module needs no import from shiki at
@@ -62,5 +63,5 @@ export declare const PLAINTEXT: Set<string>;
62
63
  *
63
64
  * Framework-agnostic, and needs no `AparteClient`. Call once at startup.
64
65
  */
65
- export declare function setupShikiProviderFromHighlighter(highlighter: ShikiHighlighterLike, options?: ShikiCoreProviderOptions): void;
66
+ export declare function setupShikiProviderFromHighlighter(highlighter: ShikiHighlighterLike, options?: ShikiCoreProviderOptions, config?: AparteConfig): void;
66
67
  //# sourceMappingURL=core.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AACA;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACjC,sEAAsE;IACtE,kBAAkB,IAAI,MAAM,EAAE,CAAC;IAC/B,uEAAuE;IACvE,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAC;CAC9E;AAED,MAAM,WAAW,wBAAwB;IACrC;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,oEAAoE;AACpE,eAAO,MAAM,SAAS,aAAoD,CAAC;AAE3E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAgB,iCAAiC,CAC7C,WAAW,EAAE,oBAAoB,EACjC,OAAO,GAAE,wBAA6B,GACvC,IAAI,CAWN"}
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,YAAY,EAAC,MAAM,cAAc,CAAC;AACrE;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACjC,sEAAsE;IACtE,kBAAkB,IAAI,MAAM,EAAE,CAAC;IAC/B,uEAAuE;IACvE,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAC;CAC9E;AAED,MAAM,WAAW,wBAAwB;IACrC;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,oEAAoE;AACpE,eAAO,MAAM,SAAS,aAAoD,CAAC;AAE3E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAgB,iCAAiC,CAC7C,WAAW,EAAE,oBAAoB,EACjC,OAAO,GAAE,wBAA6B,EACtC,MAAM,GAAE,YAAiC,GAC1C,IAAI,CAWN"}
package/dist/core.js CHANGED
@@ -1,9 +1,9 @@
1
- import { AparteConfig } from "@aparte/core";
1
+ import { aparteGlobalConfig } from "@aparte/core";
2
2
  const PLAINTEXT = /* @__PURE__ */ new Set(["text", "plaintext", "txt", "ansi", ""]);
3
- function setupShikiProviderFromHighlighter(highlighter, options = {}) {
3
+ function setupShikiProviderFromHighlighter(highlighter, options = {}, config = aparteGlobalConfig) {
4
4
  const theme = options.theme ?? "github-dark";
5
5
  let loaded = null;
6
- AparteConfig.setHighlightProvider((code, lang) => {
6
+ config.setHighlightProvider((code, lang) => {
7
7
  const requested = (lang || "text").toLowerCase();
8
8
  loaded ??= new Set(highlighter.getLoadedLanguages());
9
9
  const language = PLAINTEXT.has(requested) || !loaded.has(requested) ? "text" : requested;
package/dist/core.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"core.js","sources":["../src/core.ts"],"sourcesContent":["import { AparteConfig } from '@aparte/core';\n/**\n * The slice of a shiki highlighter this plugin actually uses — declared here rather\n * than borrowed from `HighlighterCore`, so this module needs no import from shiki at\n * all, not even a type. A real `HighlighterCore` satisfies it (asserted at compile\n * time in the tests), and so does a wrapper of your own.\n */\nexport interface ShikiHighlighterLike {\n /** The grammars this highlighter carries — read once, then cached. */\n getLoadedLanguages(): string[];\n /** Render `code` as highlighted HTML with a loaded grammar + theme. */\n codeToHtml(code: string, options: { lang: string; theme: string }): string;\n}\n\nexport interface ShikiCoreProviderOptions {\n /**\n * Theme to render with — the name of a theme your highlighter was built with.\n * Default `'github-dark'`.\n */\n theme?: string;\n}\n\n/** Languages that mean \"don't highlight\", plus the empty string. */\nexport const PLAINTEXT = new Set(['text', 'plaintext', 'txt', 'ansi', '']);\n\n/**\n * Register a highlighter **you** built as aparté's highlight provider.\n *\n * Why this exists — measured, on a build whose only import was the plugin:\n *\n * | entry point | files emitted | weight |\n * | -------------------------------------------- | ------------- | ------ |\n * | `@aparte/plugin-shiki` (shiki's full bundle) | 302 | 11 MB |\n * | this one, with three grammars | 1 | 560 kB |\n *\n * The convenience entry imports `shiki`, whose bundle maps **every** known language\n * to a dynamic import, so a bundler emits one chunk per grammar —\n * `emacs-lisp` (780 kB), `wasm`, `wolfram` and 300 others — even for an app that\n * renders twenty. No runtime option can undo that: a static import is a static\n * import (verified — restricting `langs` still emits all 302). Controlling\n * distribution weight means not importing that bundle at all, which is what\n * importing THIS module instead achieves.\n *\n * ```ts\n * import { createHighlighterCore } from 'shiki/core';\n * import { createJavaScriptRegexEngine } from 'shiki/engine/javascript';\n * import ts from '@shikijs/langs/typescript';\n * import githubDark from '@shikijs/themes/github-dark';\n * import { setupShikiProviderFromHighlighter } from '@aparte/plugin-shiki/core';\n *\n * setupShikiProviderFromHighlighter(\n * await createHighlighterCore({\n * themes: [githubDark],\n * langs: [ts],\n * engine: createJavaScriptRegexEngine(),\n * }),\n * );\n * ```\n *\n * Your highlighter's grammars are fixed, so a language it does not carry renders as\n * plain text rather than throwing — same degradation as the convenience entry, minus\n * the on-demand load it cannot do.\n *\n * Framework-agnostic, and needs no `AparteClient`. Call once at startup.\n */\nexport function setupShikiProviderFromHighlighter(\n highlighter: ShikiHighlighterLike,\n options: ShikiCoreProviderOptions = {},\n): void {\n const theme = options.theme ?? 'github-dark';\n let loaded: Set<string> | null = null;\n\n AparteConfig.setHighlightProvider((code, lang) => {\n const requested = (lang || 'text').toLowerCase();\n // Cached after the first call: the grammar set of a core highlighter is fixed.\n loaded ??= new Set(highlighter.getLoadedLanguages());\n const language = PLAINTEXT.has(requested) || !loaded.has(requested) ? 'text' : requested;\n return highlighter.codeToHtml(code, { lang: language, theme });\n });\n}\n"],"names":[],"mappings":";AAuBO,MAAM,gCAAgB,IAAI,CAAC,QAAQ,aAAa,OAAO,QAAQ,EAAE,CAAC;AA0ClE,SAAS,kCACZ,aACA,UAAoC,IAChC;AACJ,QAAM,QAAQ,QAAQ,SAAS;AAC/B,MAAI,SAA6B;AAEjC,eAAa,qBAAqB,CAAC,MAAM,SAAS;AAC9C,UAAM,aAAa,QAAQ,QAAQ,YAAA;AAEnC,eAAW,IAAI,IAAI,YAAY,mBAAA,CAAoB;AACnD,UAAM,WAAW,UAAU,IAAI,SAAS,KAAK,CAAC,OAAO,IAAI,SAAS,IAAI,SAAS;AAC/E,WAAO,YAAY,WAAW,MAAM,EAAE,MAAM,UAAU,OAAO;AAAA,EACjE,CAAC;AACL;"}
1
+ {"version":3,"file":"core.js","sources":["../src/core.ts"],"sourcesContent":["import { aparteGlobalConfig , type AparteConfig} from '@aparte/core';\n/**\n * The slice of a shiki highlighter this plugin actually uses — declared here rather\n * than borrowed from `HighlighterCore`, so this module needs no import from shiki at\n * all, not even a type. A real `HighlighterCore` satisfies it (asserted at compile\n * time in the tests), and so does a wrapper of your own.\n */\nexport interface ShikiHighlighterLike {\n /** The grammars this highlighter carries — read once, then cached. */\n getLoadedLanguages(): string[];\n /** Render `code` as highlighted HTML with a loaded grammar + theme. */\n codeToHtml(code: string, options: { lang: string; theme: string }): string;\n}\n\nexport interface ShikiCoreProviderOptions {\n /**\n * Theme to render with — the name of a theme your highlighter was built with.\n * Default `'github-dark'`.\n */\n theme?: string;\n}\n\n/** Languages that mean \"don't highlight\", plus the empty string. */\nexport const PLAINTEXT = new Set(['text', 'plaintext', 'txt', 'ansi', '']);\n\n/**\n * Register a highlighter **you** built as aparté's highlight provider.\n *\n * Why this exists — measured, on a build whose only import was the plugin:\n *\n * | entry point | files emitted | weight |\n * | -------------------------------------------- | ------------- | ------ |\n * | `@aparte/plugin-shiki` (shiki's full bundle) | 302 | 11 MB |\n * | this one, with three grammars | 1 | 560 kB |\n *\n * The convenience entry imports `shiki`, whose bundle maps **every** known language\n * to a dynamic import, so a bundler emits one chunk per grammar —\n * `emacs-lisp` (780 kB), `wasm`, `wolfram` and 300 others — even for an app that\n * renders twenty. No runtime option can undo that: a static import is a static\n * import (verified — restricting `langs` still emits all 302). Controlling\n * distribution weight means not importing that bundle at all, which is what\n * importing THIS module instead achieves.\n *\n * ```ts\n * import { createHighlighterCore } from 'shiki/core';\n * import { createJavaScriptRegexEngine } from 'shiki/engine/javascript';\n * import ts from '@shikijs/langs/typescript';\n * import githubDark from '@shikijs/themes/github-dark';\n * import { setupShikiProviderFromHighlighter } from '@aparte/plugin-shiki/core';\n *\n * setupShikiProviderFromHighlighter(\n * await createHighlighterCore({\n * themes: [githubDark],\n * langs: [ts],\n * engine: createJavaScriptRegexEngine(),\n * }),\n * );\n * ```\n *\n * Your highlighter's grammars are fixed, so a language it does not carry renders as\n * plain text rather than throwing — same degradation as the convenience entry, minus\n * the on-demand load it cannot do.\n *\n * Framework-agnostic, and needs no `AparteClient`. Call once at startup.\n */\nexport function setupShikiProviderFromHighlighter(\n highlighter: ShikiHighlighterLike,\n options: ShikiCoreProviderOptions = {},\n config: AparteConfig = aparteGlobalConfig,\n): void {\n const theme = options.theme ?? 'github-dark';\n let loaded: Set<string> | null = null;\n\n config.setHighlightProvider((code, lang) => {\n const requested = (lang || 'text').toLowerCase();\n // Cached after the first call: the grammar set of a core highlighter is fixed.\n loaded ??= new Set(highlighter.getLoadedLanguages());\n const language = PLAINTEXT.has(requested) || !loaded.has(requested) ? 'text' : requested;\n return highlighter.codeToHtml(code, { lang: language, theme });\n });\n}\n"],"names":[],"mappings":";AAuBO,MAAM,gCAAgB,IAAI,CAAC,QAAQ,aAAa,OAAO,QAAQ,EAAE,CAAC;AA0ClE,SAAS,kCACZ,aACA,UAAoC,CAAA,GACpC,SAAuB,oBACnB;AACJ,QAAM,QAAQ,QAAQ,SAAS;AAC/B,MAAI,SAA6B;AAEjC,SAAO,qBAAqB,CAAC,MAAM,SAAS;AACxC,UAAM,aAAa,QAAQ,QAAQ,YAAA;AAEnC,eAAW,IAAI,IAAI,YAAY,mBAAA,CAAoB;AACnD,UAAM,WAAW,UAAU,IAAI,SAAS,KAAK,CAAC,OAAO,IAAI,SAAS,IAAI,SAAS;AAC/E,WAAO,YAAY,WAAW,MAAM,EAAE,MAAM,UAAU,OAAO;AAAA,EACjE,CAAC;AACL;"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { type AparteConfig } from '@aparte/core';
1
2
  import { type BundledTheme } from 'shiki';
2
3
  export interface ShikiProviderOptions {
3
4
  /**
@@ -32,5 +33,5 @@ export type { ShikiCoreProviderOptions, ShikiHighlighterLike } from './core.js';
32
33
  *
33
34
  * Framework-agnostic — vanilla, no framework imports. Call once at startup.
34
35
  */
35
- export declare function setupShikiProvider(options?: ShikiProviderOptions): Promise<void>;
36
+ export declare function setupShikiProvider(options?: ShikiProviderOptions, config?: AparteConfig): Promise<void>;
36
37
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAIH,KAAK,YAAY,EACpB,MAAM,OAAO,CAAC;AAEf,MAAM,WAAW,oBAAoB;IACjC;;;OAGG;IACH,KAAK,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;CACjC;AAID,OAAO,EAAE,iCAAiC,EAAE,MAAM,WAAW,CAAC;AAC9D,YAAY,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAEhF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC,CA4C1F"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,YAAY,EAAC,MAAM,cAAc,CAAC;AACrE,OAAO,EAIH,KAAK,YAAY,EACpB,MAAM,OAAO,CAAC;AAEf,MAAM,WAAW,oBAAoB;IACjC;;;OAGG;IACH,KAAK,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;CACjC;AAID,OAAO,EAAE,iCAAiC,EAAE,MAAM,WAAW,CAAC;AAC9D,YAAY,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAEhF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,GAAE,oBAAyB,EAAE,MAAM,GAAE,YAAiC,GAAG,OAAO,CAAC,IAAI,CAAC,CA4CrI"}
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
- import { AparteConfig } from "@aparte/core";
1
+ import { aparteGlobalConfig } from "@aparte/core";
2
2
  import { createHighlighter } from "shiki";
3
3
  import { PLAINTEXT } from "./core.js";
4
4
  import { setupShikiProviderFromHighlighter } from "./core.js";
5
- async function setupShikiProvider(options = {}) {
5
+ async function setupShikiProvider(options = {}, config = aparteGlobalConfig) {
6
6
  const theme = options.theme ?? "github-dark";
7
7
  let highlighter = null;
8
8
  let creating = null;
@@ -20,7 +20,7 @@ async function setupShikiProvider(options = {}) {
20
20
  }
21
21
  return creating;
22
22
  };
23
- AparteConfig.setHighlightProvider(async (code, lang) => {
23
+ config.setHighlightProvider(async (code, lang) => {
24
24
  const hl = await getHighlighter();
25
25
  let language = (lang || "text").toLowerCase();
26
26
  if (!PLAINTEXT.has(language) && !loadedLangs.has(language)) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import { AparteConfig } from '@aparte/core';\nimport {\n createHighlighter,\n type Highlighter,\n type BundledLanguage,\n type BundledTheme,\n} from 'shiki';\n\nexport interface ShikiProviderOptions {\n /**\n * Theme to render with — a bundled theme name (e.g. `'github-dark'`) or a\n * loaded custom theme name. Default `'github-dark'`.\n */\n theme?: BundledTheme | string;\n}\n\nimport { PLAINTEXT } from './core.js';\n\nexport { setupShikiProviderFromHighlighter } from './core.js';\nexport type { ShikiCoreProviderOptions, ShikiHighlighterLike } from './core.js';\n\n/**\n * Register [shiki](https://shiki.style) as aparté's syntax-highlight provider.\n *\n * Backed by a **single, lazily-created** `createHighlighter` instance: the\n * highlighter is built once on first use with only the requested theme, and each\n * language grammar is loaded on demand and cached. This is deliberately NOT the\n * `codeToHtml` shorthand, which can re-initialise a highlighter per call — the\n * cost we control here is why the plugin exists.\n *\n * **Bundle note — runtime cost and distribution cost are not the same thing.**\n * At runtime nothing is eager: a grammar is fetched the first time a language is\n * seen, so you only *execute* what you render. But this entry imports `shiki`,\n * whose bundle maps every known language to a dynamic import, so your bundler\n * **emits one chunk per grammar** — measured on a build whose only import was this\n * function: **302 files, 11 MB** (`emacs-lisp` alone is 780 kB). Restricting the\n * language list would not help; a static import is a static import.\n *\n * If the size of what you ship matters — an app delivered by `npx`, a desktop\n * bundle — use {@link setupShikiProviderFromHighlighter} from\n * `@aparte/plugin-shiki/core` and build the highlighter yourself: same plugin,\n * same behaviour, **1 file / 560 kB** for three grammars.\n *\n * Framework-agnostic — vanilla, no framework imports. Call once at startup.\n */\nexport async function setupShikiProvider(options: ShikiProviderOptions = {}): Promise<void> {\n const theme = (options.theme ?? 'github-dark') as BundledTheme;\n\n let highlighter: Highlighter | null = null;\n let creating: Promise<Highlighter> | null = null;\n const loadedLangs = new Set<string>();\n\n const getHighlighter = (): Promise<Highlighter> => {\n if (highlighter) return Promise.resolve(highlighter);\n // De-dupe concurrent first calls so we only ever create one instance.\n if (!creating) {\n creating = createHighlighter({ themes: [theme], langs: [] })\n .then((h) => {\n highlighter = h;\n return h;\n })\n .catch((err) => {\n // A transient failure (network/CSP on the dynamic theme import,\n // wasm engine hiccup) must NOT poison the singleton: clear the\n // cached promise so the next code block retries creation instead\n // of re-returning a permanently-rejected promise. Re-throw so this\n // block still degrades to plaintext via the provider's caller.\n creating = null;\n throw err;\n });\n }\n return creating;\n };\n\n AparteConfig.setHighlightProvider(async (code, lang) => {\n const hl = await getHighlighter();\n let language = (lang || 'text').toLowerCase();\n\n if (!PLAINTEXT.has(language) && !loadedLangs.has(language)) {\n try {\n await hl.loadLanguage(language as BundledLanguage);\n loadedLangs.add(language);\n } catch {\n language = 'text'; // unknown grammar → render as plain text\n }\n }\n\n return hl.codeToHtml(code, { lang: language, theme });\n });\n}\n"],"names":[],"mappings":";;;;AA6CA,eAAsB,mBAAmB,UAAgC,IAAmB;AACxF,QAAM,QAAS,QAAQ,SAAS;AAEhC,MAAI,cAAkC;AACtC,MAAI,WAAwC;AAC5C,QAAM,kCAAkB,IAAA;AAExB,QAAM,iBAAiB,MAA4B;AAC/C,QAAI,YAAa,QAAO,QAAQ,QAAQ,WAAW;AAEnD,QAAI,CAAC,UAAU;AACX,iBAAW,kBAAkB,EAAE,QAAQ,CAAC,KAAK,GAAG,OAAO,GAAC,CAAG,EACtD,KAAK,CAAC,MAAM;AACT,sBAAc;AACd,eAAO;AAAA,MACX,CAAC,EACA,MAAM,CAAC,QAAQ;AAMZ,mBAAW;AACX,cAAM;AAAA,MACV,CAAC;AAAA,IACT;AACA,WAAO;AAAA,EACX;AAEA,eAAa,qBAAqB,OAAO,MAAM,SAAS;AACpD,UAAM,KAAK,MAAM,eAAA;AACjB,QAAI,YAAY,QAAQ,QAAQ,YAAA;AAEhC,QAAI,CAAC,UAAU,IAAI,QAAQ,KAAK,CAAC,YAAY,IAAI,QAAQ,GAAG;AACxD,UAAI;AACA,cAAM,GAAG,aAAa,QAA2B;AACjD,oBAAY,IAAI,QAAQ;AAAA,MAC5B,QAAQ;AACJ,mBAAW;AAAA,MACf;AAAA,IACJ;AAEA,WAAO,GAAG,WAAW,MAAM,EAAE,MAAM,UAAU,OAAO;AAAA,EACxD,CAAC;AACL;"}
1
+ {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import { aparteGlobalConfig , type AparteConfig} from '@aparte/core';\nimport {\n createHighlighter,\n type Highlighter,\n type BundledLanguage,\n type BundledTheme,\n} from 'shiki';\n\nexport interface ShikiProviderOptions {\n /**\n * Theme to render with — a bundled theme name (e.g. `'github-dark'`) or a\n * loaded custom theme name. Default `'github-dark'`.\n */\n theme?: BundledTheme | string;\n}\n\nimport { PLAINTEXT } from './core.js';\n\nexport { setupShikiProviderFromHighlighter } from './core.js';\nexport type { ShikiCoreProviderOptions, ShikiHighlighterLike } from './core.js';\n\n/**\n * Register [shiki](https://shiki.style) as aparté's syntax-highlight provider.\n *\n * Backed by a **single, lazily-created** `createHighlighter` instance: the\n * highlighter is built once on first use with only the requested theme, and each\n * language grammar is loaded on demand and cached. This is deliberately NOT the\n * `codeToHtml` shorthand, which can re-initialise a highlighter per call — the\n * cost we control here is why the plugin exists.\n *\n * **Bundle note — runtime cost and distribution cost are not the same thing.**\n * At runtime nothing is eager: a grammar is fetched the first time a language is\n * seen, so you only *execute* what you render. But this entry imports `shiki`,\n * whose bundle maps every known language to a dynamic import, so your bundler\n * **emits one chunk per grammar** — measured on a build whose only import was this\n * function: **302 files, 11 MB** (`emacs-lisp` alone is 780 kB). Restricting the\n * language list would not help; a static import is a static import.\n *\n * If the size of what you ship matters — an app delivered by `npx`, a desktop\n * bundle — use {@link setupShikiProviderFromHighlighter} from\n * `@aparte/plugin-shiki/core` and build the highlighter yourself: same plugin,\n * same behaviour, **1 file / 560 kB** for three grammars.\n *\n * Framework-agnostic — vanilla, no framework imports. Call once at startup.\n */\nexport async function setupShikiProvider(options: ShikiProviderOptions = {}, config: AparteConfig = aparteGlobalConfig): Promise<void> {\n const theme = (options.theme ?? 'github-dark') as BundledTheme;\n\n let highlighter: Highlighter | null = null;\n let creating: Promise<Highlighter> | null = null;\n const loadedLangs = new Set<string>();\n\n const getHighlighter = (): Promise<Highlighter> => {\n if (highlighter) return Promise.resolve(highlighter);\n // De-dupe concurrent first calls so we only ever create one instance.\n if (!creating) {\n creating = createHighlighter({ themes: [theme], langs: [] })\n .then((h) => {\n highlighter = h;\n return h;\n })\n .catch((err) => {\n // A transient failure (network/CSP on the dynamic theme import,\n // wasm engine hiccup) must NOT poison the singleton: clear the\n // cached promise so the next code block retries creation instead\n // of re-returning a permanently-rejected promise. Re-throw so this\n // block still degrades to plaintext via the provider's caller.\n creating = null;\n throw err;\n });\n }\n return creating;\n };\n\n config.setHighlightProvider(async (code, lang) => {\n const hl = await getHighlighter();\n let language = (lang || 'text').toLowerCase();\n\n if (!PLAINTEXT.has(language) && !loadedLangs.has(language)) {\n try {\n await hl.loadLanguage(language as BundledLanguage);\n loadedLangs.add(language);\n } catch {\n language = 'text'; // unknown grammar → render as plain text\n }\n }\n\n return hl.codeToHtml(code, { lang: language, theme });\n });\n}\n"],"names":[],"mappings":";;;;AA6CA,eAAsB,mBAAmB,UAAgC,IAAI,SAAuB,oBAAmC;AACnI,QAAM,QAAS,QAAQ,SAAS;AAEhC,MAAI,cAAkC;AACtC,MAAI,WAAwC;AAC5C,QAAM,kCAAkB,IAAA;AAExB,QAAM,iBAAiB,MAA4B;AAC/C,QAAI,YAAa,QAAO,QAAQ,QAAQ,WAAW;AAEnD,QAAI,CAAC,UAAU;AACX,iBAAW,kBAAkB,EAAE,QAAQ,CAAC,KAAK,GAAG,OAAO,GAAC,CAAG,EACtD,KAAK,CAAC,MAAM;AACT,sBAAc;AACd,eAAO;AAAA,MACX,CAAC,EACA,MAAM,CAAC,QAAQ;AAMZ,mBAAW;AACX,cAAM;AAAA,MACV,CAAC;AAAA,IACT;AACA,WAAO;AAAA,EACX;AAEA,SAAO,qBAAqB,OAAO,MAAM,SAAS;AAC9C,UAAM,KAAK,MAAM,eAAA;AACjB,QAAI,YAAY,QAAQ,QAAQ,YAAA;AAEhC,QAAI,CAAC,UAAU,IAAI,QAAQ,KAAK,CAAC,YAAY,IAAI,QAAQ,GAAG;AACxD,UAAI;AACA,cAAM,GAAG,aAAa,QAA2B;AACjD,oBAAY,IAAI,QAAQ;AAAA,MAC5B,QAAQ;AACJ,mBAAW;AAAA,MACf;AAAA,IACJ;AAEA,WAAO,GAAG,WAAW,MAAM,EAAE,MAAM,UAAU,OAAO;AAAA,EACxD,CAAC;AACL;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aparte/plugin-shiki",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Syntax highlighting for aparté via shiki — register it as the highlight provider (single lazily-created highlighter).",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -30,15 +30,16 @@
30
30
  "node": ">=18"
31
31
  },
32
32
  "peerDependencies": {
33
- "@aparte/core": ">=0.5.0-alpha.0 <1.0.0",
34
- "shiki": ">=1.0.0"
33
+ "@aparte/core": ">=0.7.0 <1.0.0",
34
+ "shiki": "^4.0.0"
35
35
  },
36
36
  "devDependencies": {
37
+ "@shikijs/langs": "^4.0.0",
38
+ "@shikijs/themes": "^4.0.0",
37
39
  "shiki": "^4.0.0",
38
40
  "typescript": "^5.4.0",
39
41
  "vite": "^6.0.0",
40
- "vite-plugin-dts": "^4.5.4",
41
- "@aparte/core": "0.7.0"
42
+ "@aparte/core": "0.8.0"
42
43
  },
43
44
  "keywords": [
44
45
  "aparte",