Skip to content

Commit 4e59b65

Browse files
authoredSep 26, 2024··
feat: introduce warning system for deprecated API (#788)
1 parent 85a4ff9 commit 4e59b65

File tree

20 files changed

+171
-35
lines changed

20 files changed

+171
-35
lines changed
 

‎docs/.vitepress/config.ts

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const GUIDES: DefaultTheme.NavItemWithLink[] = [
2121
{ text: 'Synchronous Usage', link: '/guide/sync-usage' },
2222
{ text: 'Custom Themes', link: '/guide/load-theme' },
2323
{ text: 'Custom Languages', link: '/guide/load-lang' },
24+
{ text: 'Future', link: '/guide/future' },
2425
{ text: 'Migration', link: '/guide/migrate' },
2526
{ text: 'Compatibility Build', link: '/guide/compat' },
2627
]

‎docs/guide/future.md

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Future
2+
3+
We planned to remove some deprecated APIs and optimize the tree-shaking in the future major versions.
4+
5+
The plan is:
6+
7+
- 👉 `v1.x`: Deprecated APIs are still supported, marked on type level only. With optional runtime warnings to opt-in.
8+
- `v2.0`: No breaking changes, but enable runtime deprecated warnings by default.
9+
- `v3.0`: Remove deprecated APIs, breaking changes.
10+
11+
At the current version, since v1.19.0, you can opt-in to the runtime warnings by calling `enableDeprecationWarnings()` at the beginning of your application.
12+
13+
```ts
14+
import { enableDeprecationWarnings, getHighlighter } from 'shiki'
15+
16+
enableDeprecationWarnings() // [!code hl]
17+
18+
// Then calling deprecated usages like below would warn:
19+
// [SHIKI DEPRECATED]: Use `createHighlighter` instead
20+
const shiki = await getHighlighter(/* ... */)
21+
```
22+
23+
This would help you better prepare for the future changes and upgrade smoothly.
24+
25+
## Notable Deprecations
26+
27+
### `getHighlighter` -> `createHighlighter`
28+
29+
There is no functional changes, but more like correcting the naming to avoid confusion. It should be a straightforward find-and-replace.
30+
31+
### WASM Related APIs
32+
33+
Since the introduce of the [engine system](/guide/regex-engines) in v0.16, the WebAssembly related dependencies are no longer a hard requirement. To make tree-shaking easier and decoupled the engines with the core, two packages are extracted `@shikijs/engine-oniguruma` and `@shikijs/engine-javascript`. They are also re-exported from the main package's `shiki/engine/oniguruma` and `shiki/engine/javascript` respectively.
34+
35+
You might need to change your import path:
36+
37+
```ts
38+
import { loadWasm } from 'shiki' // [!code --]
39+
import { loadWasm } from 'shiki/engine/oniguruma' // [!code ++]
40+
```
41+
42+
`loadWasm` field in `getHighlighter` is replaced with `engine` field:
43+
44+
```ts
45+
import { createHighlighter } from 'shiki'
46+
import { createWasmOnigEngine } from 'shiki/engine/oniguruma' // [!code ++]
47+
48+
const shiki = await createHighlighter({
49+
// ...
50+
loadWasm: () => import('shiki/wasm'), // [!code --]
51+
engine: createWasmOnigEngine(() => import('shiki/wasm')), // [!code ++]
52+
})
53+
```

‎docs/packages/twoslash.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ Luckily, Twoslash implemented a virtual file system, which allow you to provide
174174
We make tiny wrappers around the building blocks and provide an easy-to-use API in [`twoslash-cdn`](https://twoslash.netlify.app/packages/cdn). For example:
175175

176176
```js
177-
// TODO: Replace with explicit versions in production
177+
// FIXME: Replace with explicit versions in production
178178
import { createTransformerFactory, rendererRich } from 'https://esm.sh/@shikijs/twoslash@latest/core'
179179
import { codeToHtml } from 'https://esm.sh/shiki@latest'
180180
import { createTwoslashFromCDN } from 'https://esm.sh/twoslash-cdn@latest'

‎eslint.config.js

+23
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,27 @@ export default antfu(
4242
'ts/explicit-function-return-type': 'off',
4343
},
4444
},
45+
{
46+
files: [
47+
'packages/shiki/**/*.ts',
48+
'packages/core/**/*.ts',
49+
'packages/engine-javascript/**/*.ts',
50+
'packages/engine-oniguruma/**/*.ts',
51+
],
52+
ignores: [
53+
'**/*.test.ts',
54+
],
55+
rules: {
56+
'no-restricted-imports': [
57+
'error',
58+
{
59+
paths: [
60+
{
61+
name: 'shiki',
62+
},
63+
],
64+
},
65+
],
66+
},
67+
},
4568
)

‎packages/core/src/constructors/bundle-factory.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { ShikiError } from '@shikijs/types'
2626

2727
import { createWasmOnigEngine } from '../engines/oniguruma'
2828
import { isSpecialLang, isSpecialTheme } from '../utils'
29+
import { warnDeprecated } from '../warn'
2930
import { createHighlighterCore } from './highlighter'
3031

3132
/**
@@ -74,7 +75,7 @@ export function createdBundledHighlighter<BundledLangs extends string, BundledTh
7475
let engine: () => Awaitable<RegexEngine>
7576

7677
if (arg2) {
77-
// TODO: next: console.warn('`createdBundledHighlighter` signature with `bundledLanguages` and `bundledThemes` is deprecated. Use the options object signature instead.')
78+
warnDeprecated('`createdBundledHighlighter` signature with `bundledLanguages` and `bundledThemes` is deprecated. Use the options object signature instead.')
7879
bundledLanguages = arg1 as Record<BundledLangs, LanguageInput>
7980
bundledThemes = arg2
8081
engine = () => createWasmOnigEngine(arg3)

‎packages/core/src/constructors/highlighter.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ import { codeToHtml } from '../highlight/code-to-html'
55
import { codeToTokens } from '../highlight/code-to-tokens'
66
import { codeToTokensBase, getLastGrammarState } from '../highlight/code-to-tokens-base'
77
import { codeToTokensWithThemes } from '../highlight/code-to-tokens-themes'
8-
import { createShikiInternal } from './internal'
8+
import { warnDeprecated } from '../warn'
99

10+
import { createShikiInternal } from './internal'
1011
import { createShikiInternalSync } from './internal-sync'
1112

1213
/**
@@ -89,6 +90,6 @@ export const getSingletonHighlighterCore = /* @__PURE__ */ makeSingletonHighligh
8990
*/
9091
/* v8 ignore next 5 */
9192
export function getHighlighterCore(options: HighlighterCoreOptions = {}): Promise<HighlighterCore> {
92-
// TODO: next: console.warn('`getHighlighterCore` is deprecated. Use `createHighlighterCore` or `getSingletonHighlighterCore` instead.')
93+
warnDeprecated('`getHighlighterCore` is deprecated. Use `createHighlighterCore` or `getSingletonHighlighterCore` instead.')
9394
return createHighlighterCore(options)
9495
}

‎packages/core/src/constructors/internal.ts

+7-3
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,20 @@ import type {
22
HighlighterCoreOptions,
33
ShikiInternal,
44
} from '@shikijs/types'
5-
import { createWasmOnigEngine } from '@shikijs/engine-oniguruma'
5+
import { createWasmOnigEngine, getDefaultWasmLoader } from '@shikijs/engine-oniguruma'
66

7-
import { getDefaultWasmLoader } from '../engines/oniguruma'
87
import { resolveLangs, resolveThemes } from '../textmate/getters-resolve'
8+
import { warnDeprecated } from '../warn'
99
import { createShikiInternalSync } from './internal-sync'
1010

1111
/**
1212
* Get the minimal shiki context for rendering.
1313
*/
1414
export async function createShikiInternal(options: HighlighterCoreOptions = {}): Promise<ShikiInternal> {
15+
if (options.loadWasm) {
16+
warnDeprecated('`loadWasm` option is deprecated. Use `engine: createWasmOnigEngine(loadWasm)` instead.')
17+
}
18+
1519
const [
1620
themes,
1721
langs,
@@ -35,6 +39,6 @@ export async function createShikiInternal(options: HighlighterCoreOptions = {}):
3539
* @deprecated Use `createShikiInternal` instead.
3640
*/
3741
export function getShikiInternal(options: HighlighterCoreOptions = {}): Promise<ShikiInternal> {
38-
// TODO: next: console.warn('`getShikiInternal` is deprecated. Use `createShikiInternal` instead.')
42+
warnDeprecated('`getShikiInternal` is deprecated. Use `createShikiInternal` instead.')
3943
return createShikiInternal(options)
4044
}
+11-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,11 @@
1-
export * from '@shikijs/engine-javascript'
1+
import type { JavaScriptRegexEngineOptions } from '@shikijs/engine-javascript'
2+
import type { RegexEngine } from '@shikijs/types'
3+
import { createJavaScriptRegexEngine as _createJavaScriptRegexEngine, defaultJavaScriptRegexConstructor } from '@shikijs/engine-javascript'
4+
import { warnDeprecated } from '../warn'
5+
6+
export function createJavaScriptRegexEngine(options?: JavaScriptRegexEngineOptions): RegexEngine {
7+
warnDeprecated('import `createJavaScriptRegexEngine` from `@shikijs/engine-javascript` or `shiki/engine/javascript` instead')
8+
return _createJavaScriptRegexEngine(options)
9+
}
10+
11+
export { defaultJavaScriptRegexConstructor }
+12-16
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,16 @@
1-
import type { LoadWasmOptions } from '@shikijs/types'
1+
import type { LoadWasmOptions, RegexEngine } from '@shikijs/types'
2+
import {
3+
createWasmOnigEngine as _createWasmOnigEngine,
4+
loadWasm as _loadWasm,
5+
} from '@shikijs/engine-oniguruma'
6+
import { warnDeprecated } from '../warn'
27

3-
export * from '@shikijs/engine-oniguruma'
4-
5-
let _defaultWasmLoader: LoadWasmOptions | undefined
6-
7-
/**
8-
* Set the default wasm loader for `loadWasm`.
9-
* @internal
10-
*/
11-
export function setDefaultWasmLoader(_loader: LoadWasmOptions): void {
12-
_defaultWasmLoader = _loader
8+
export function createWasmOnigEngine(options?: LoadWasmOptions | null): Promise<RegexEngine> {
9+
warnDeprecated('import `createWasmOnigEngine` from `@shikijs/engine-oniguruma` or `shiki/engine/oniguruma` instead')
10+
return _createWasmOnigEngine(options)
1311
}
1412

15-
/**
16-
* @internal
17-
*/
18-
export function getDefaultWasmLoader(): LoadWasmOptions | undefined {
19-
return _defaultWasmLoader
13+
export function loadWasm(options: LoadWasmOptions): Promise<void> {
14+
warnDeprecated('import `loadWasm` from `@shikijs/engine-oniguruma` or `shiki/engine/oniguruma` instead')
15+
return _loadWasm(options)
2016
}

‎packages/core/src/highlight/code-to-hast.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import type {
1616
import { FontStyle } from '@shikijs/vscode-textmate'
1717

1818
import { addClassToHast, getTokenStyleObject, stringifyTokenStyle } from '../utils'
19+
import { warnDeprecated } from '../warn'
1920
import { getTransformers } from './_get-transformers'
2021
import { codeToTokens } from './code-to-tokens'
2122

@@ -177,7 +178,9 @@ export function tokensToHast(
177178
children: [{ type: 'text', value: token.content }],
178179
}
179180

180-
// TODO: Shiki2: Deprecate `string` type of `htmlStyle`
181+
if (typeof token.htmlStyle === 'string')
182+
warnDeprecated('`htmlStyle` as a string is deprecated. Use an object instead.')
183+
181184
const style = stringifyTokenStyle(token.htmlStyle || getTokenStyleObject(token))
182185
if (style)
183186
tokenNode.properties.style = style

‎packages/core/src/index.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export { createShikiInternalSync } from './constructors/internal-sync'
77

88
// Engines
99
export { createJavaScriptRegexEngine, defaultJavaScriptRegexConstructor } from './engines/javascript'
10-
export { createWasmOnigEngine, loadWasm, setDefaultWasmLoader } from './engines/oniguruma'
10+
export { createWasmOnigEngine, loadWasm } from './engines/oniguruma'
1111

1212
// Low-level Highlighting
1313
export { codeToHast, tokensToHast } from './highlight/code-to-hast'
@@ -22,6 +22,7 @@ export { transformerDecorations } from './transformer-decorations'
2222

2323
// Utils and Misc
2424
export * from './utils'
25+
export { enableDeprecationWarnings, warnDeprecated } from './warn'
2526

2627
// Types
2728
export * from '@shikijs/types'

‎packages/core/src/warn.ts

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
let emitDeprecation = false
2+
3+
/**
4+
* Enable runtime warning for deprecated APIs, for the future versions of Shiki.
5+
*
6+
* Disabled by default, will be enabled in Shiki v2.
7+
*
8+
* @experimental The accuracy of the warning messages is not yet guaranteed.
9+
*/
10+
export function enableDeprecationWarnings(value = true): void {
11+
emitDeprecation = value
12+
}
13+
14+
/**
15+
* @internal
16+
*/
17+
export function warnDeprecated(message: string): void {
18+
if (emitDeprecation)
19+
// eslint-disable-next-line no-console
20+
console.trace(`[SHIKI DEPRECATE]: ${message}`)
21+
}

‎packages/core/src/wasm-inlined.ts

+4
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
1+
import { warnDeprecated } from './warn'
2+
13
export { default } from '@shikijs/engine-oniguruma/wasm-inlined'
24
export * from '@shikijs/engine-oniguruma/wasm-inlined'
5+
6+
warnDeprecated('Import from `@shikijs/engine-oniguruma/wasm-inlined` instead')

‎packages/engine-oniguruma/src/index.ts

+17
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,23 @@ import { loadWasm, OnigScanner, OnigString } from './oniguruma'
44

55
export { loadWasm }
66

7+
let _defaultWasmLoader: LoadWasmOptions | undefined
8+
9+
/**
10+
* Set the default wasm loader for `loadWasm`.
11+
* @internal
12+
*/
13+
export function setDefaultWasmLoader(_loader: LoadWasmOptions): void {
14+
_defaultWasmLoader = _loader
15+
}
16+
17+
/**
18+
* @internal
19+
*/
20+
export function getDefaultWasmLoader(): LoadWasmOptions | undefined {
21+
return _defaultWasmLoader
22+
}
23+
724
export async function createWasmOnigEngine(options?: LoadWasmOptions | null): Promise<RegexEngine> {
825
if (options)
926
await loadWasm(options)

‎packages/shiki/src/bundle-full.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type {} from 'hast'
33
import type { BundledLanguage } from './assets/langs-bundle-full'
44
import type { BundledTheme } from './themes'
55
import { bundledLanguages } from './assets/langs-bundle-full'
6-
import { createdBundledHighlighter, createSingletonShorthands, createWasmOnigEngine } from './core'
6+
import { createdBundledHighlighter, createSingletonShorthands, createWasmOnigEngine, warnDeprecated } from './core'
77
import { bundledThemes } from './themes'
88
import { getWasmInlined } from './wasm-dynamic'
99

@@ -53,6 +53,6 @@ export const {
5353
* @deprecated Use `createHighlighter` or `getSingletonHighlighter` instead.
5454
*/
5555
export const getHighlighter: CreateHighlighterFactory<BundledLanguage, BundledTheme> = /* @__PURE__ */ (options) => {
56-
// TODO: next: console.warn('`getHighlighter` is deprecated. Use `createHighlighter` or `getSingletonHighlighter` instead.')
56+
warnDeprecated('`getHighlighter` is deprecated. Use `createHighlighter` or `getSingletonHighlighter` instead.')
5757
return createHighlighter(options)
5858
}

‎packages/shiki/src/bundle-web.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import type {} from 'hast'
44
import type { BundledLanguage } from './assets/langs-bundle-web'
55
import type { BundledTheme } from './themes'
66
import { bundledLanguages } from './assets/langs-bundle-web'
7-
import { createdBundledHighlighter, createSingletonShorthands, createWasmOnigEngine } from './core'
87

8+
import { createdBundledHighlighter, createSingletonShorthands, createWasmOnigEngine, warnDeprecated } from './core'
99
import { bundledThemes } from './themes'
1010
import { getWasmInlined } from './wasm-dynamic'
1111

@@ -55,6 +55,6 @@ export const {
5555
* @deprecated Use `createHighlighter` or `getSingletonHighlighter` instead.
5656
*/
5757
export const getHighlighter: CreateHighlighterFactory<BundledLanguage, BundledTheme> = /* @__PURE__ */ (options) => {
58-
// TODO: next: console.warn('`getHighlighter` is deprecated. Use `createHighlighter` or `getSingletonHighlighter` instead.')
58+
warnDeprecated('`getHighlighter` is deprecated. Use `createHighlighter` or `getSingletonHighlighter` instead.')
5959
return createHighlighter(options)
6060
}

‎packages/shiki/src/core-unwasm.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* We add the wasm file as the dependency so users don't need to call `loadWasm` manually.
44
*/
55

6-
import { setDefaultWasmLoader } from '@shikijs/core'
6+
import { setDefaultWasmLoader } from '@shikijs/engine-oniguruma'
77

88
setDefaultWasmLoader(() => import('shiki/wasm'))
99

‎packages/shiki/src/wasm.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
export { default } from '@shikijs/core/wasm-inlined'
2-
export * from '@shikijs/core/wasm-inlined'
1+
export { default } from '@shikijs/engine-oniguruma/wasm-inlined'
2+
export * from '@shikijs/engine-oniguruma/wasm-inlined'

‎packages/shiki/test/cf.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { LanguageRegistration } from 'shiki'
1+
import type { LanguageRegistration } from '@shikijs/types'
22
import { createHighlighterCore, loadWasm } from 'shiki/core'
33

44
import js from 'shiki/langs/javascript.mjs'

‎packages/types/src/options.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,10 @@ export interface HighlighterCoreOptions<Sync extends boolean = false> {
3030
*/
3131
warnings?: boolean
3232

33-
// TODO: Deprecate this option after docs for engines are updated.
3433
/**
3534
* Load wasm file from a custom path or using a custom function.
35+
*
36+
* @deprecated Use `engine: createWasmOnigEngine(loadWasm)` instead.
3637
*/
3738
loadWasm?: Sync extends true ? never : LoadWasmOptions
3839
}

0 commit comments

Comments
 (0)
Please sign in to comment.