Skip to content

Commit

Permalink
feat: port @michael-makes/shiki-colorized-brackets JSR package (#831)
Browse files Browse the repository at this point in the history
* feat: port @michael-makes/shiki-colorized-brackets JSR package

* fix: colorized-brackets tests fail to find fixtures

* fix: colorized-brackets test fails to find lang on Windows

* fix: colorized-brackets test fails to find lang on Windows (again)

* feat: add explicitTrigger option for transformerColorizedBrackets

* docs: enable @shikijs/colorized-brackets in its own docs page
  • Loading branch information
MichaelMakesGames authored Nov 14, 2024
1 parent 48d6c57 commit 94cc6d8
Show file tree
Hide file tree
Showing 39 changed files with 1,384 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ logs
node_modules
temp
tmp
packages/colorized-brackets/src/themes.ts
packages/shiki/src/langs
packages/shiki/src/themes
packages/shiki/src/*.json
Expand Down
3 changes: 3 additions & 0 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { defineConfig } from 'vitepress'
import { withMermaid } from 'vitepress-plugin-mermaid'

import { version } from '../../package.json'
import { transformerColorizedBrackets } from '../../packages/colorized-brackets/src'
import { transformerMetaWordHighlight, transformerNotationWordHighlight, transformerRemoveNotationEscape } from '../../packages/transformers/src'
import { defaultHoverInfoProcessor, transformerTwoslash } from '../../packages/vitepress-twoslash/src/index'
import vite from './vite.config'
Expand Down Expand Up @@ -41,6 +42,7 @@ const INTEGRATIONS: DefaultTheme.NavItemWithLink[] = [
{ text: 'Next', link: '/packages/next' },
{ text: 'Astro', link: '/packages/astro' },
{ text: 'Common Transformers', link: '/packages/transformers' },
{ text: 'Colorized Brackets', link: '/packages/colorized-brackets' },
{ text: 'CLI', link: '/packages/cli' },
]

Expand Down Expand Up @@ -125,6 +127,7 @@ export default withMermaid(defineConfig({
},
}),
transformerRemoveNotationEscape(),
transformerColorizedBrackets({ explicitTrigger: true }),
],
},

Expand Down
2 changes: 1 addition & 1 deletion docs/guide/transformers.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const code = await codeToHtml('foo\bar', {
})
```

We also provide some common transformers for you to use, see [`@shikijs/transforms`](/packages/transformers) for more details.
We also provide some common transformers for you to use, see [`@shikijs/transforms`](/packages/transformers) and [`@shikijs/colorized-brackets](/packages/colorized-brackets) for more details.

## Transformer Hooks

Expand Down
1 change: 1 addition & 0 deletions docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
},
"devDependencies": {
"@iconify-json/svg-spinners": "catalog:",
"@shikijs/colorized-brackets": "workspace:*",
"@shikijs/transformers": "workspace:*",
"@shikijs/twoslash": "workspace:*",
"@unocss/reset": "catalog:",
Expand Down
107 changes: 107 additions & 0 deletions docs/packages/colorized-brackets.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
---
outline: deep
---

# @shikijs/colorized-brackets

<Badges name="@shikijs/colorized-brackets" />

VSCode-style colorized brackets transformer for Shiki.

## Install

```bash
npm i -D @shikijs/colorized-brackets
```

## Usage

Add to your Shiki transformers:

```ts colorize-brackets
import { transformerColorizedBrackets } from '@shikijs/colorized-brackets'
import { codeToHtml } from 'shiki'

const html = await codeToHtml('let values: number[] = [];', {
lang: 'ts',
theme: 'dark-plus',
transformers: [transformerColorizedBrackets()],
})
```

### Colors

Brackets are automatically colored according to your Shiki theme (or themes if using [dual themes](https://shiki.style/guide/dual-themes)), with support for all of Shiki's built-in themes. However, you can customize colors if you've added custom themes to Shiki, or if you want to override the colors of a built-in theme:

```ts colorize-brackets
const html = await codeToHtml('let values: number[] = [];', {
lang: 'ts',
theme: myCustomTheme,
transformers: [transformerColorizedBrackets({
themes: {
'my-custom-theme': ['goldenrod', 'blueviolet', 'dodgerblue', 'crimson'],
},
})],
})
```

The final color is the mismatched bracket color. The other colors are for each "level" of bracket pair. Any valid CSS color can be used.

If no bracket colors are found for a theme, it falls back to the default `dark-plus` theme.

### Brackets

You can customize the bracket pairs:

```ts colorize-brackets
const transformer = transformerColorizedBrackets({
bracketPairs: [{ opener: '{', closer: '}' }],
})
```

The above would only colorize `{}` curly brackets. The default config colorizes `[]` square brackets, `{}` curly brackets, `()` parentheses, and `<>` angle brackets (only in TS type annotations).

For advanced usage, you can specify which TextMate scopes a bracket pair is allowed or denied in, using `scopesAllowList` and `scopesDenyList`. For example, the default config for `<>` angle brackets is:

```ts colorize-brackets
const bracketPair = {
opener: '<',
closer: '>',
scopesAllowList: [
'punctuation.definition.typeparameters.begin.ts',
'punctuation.definition.typeparameters.end.ts',
],
}
```

### Language-specific Overrides

All settings can be overridden for specific languages using the `langs` option:

```ts colorize-brackets
const transformer = transformerColorizedBrackets({
langs: { ts: myCustomTypescriptConfig },
})
```

### Explicit Trigger

If you do not want colorized brackets for all code blocks, you can enable the `explicitTrigger` option:

```ts colorize-brackets
const transformer = transformerColorizedBrackets({
explicitTrigger: true,
})
```

Then, only code blocks with the `colorize-brackets` [meta string](/guide/transformers#meta) will have bracket colorizing enabled.

````md
```ts
// no bracket colorizing
```

```ts colorize-brackets
// brackets will be colorized
```
````
9 changes: 9 additions & 0 deletions packages/colorized-brackets/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# @shikijs/colorized-brackets

VSCode-style colorized brackets transformer for [Shiki](https://github.com/shikijs/shiki).

[Documentation](https://shiki.style/packages/colorized-brackets)

## License

MIT
19 changes: 19 additions & 0 deletions packages/colorized-brackets/build.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { defineBuildConfig } from 'unbuild'

export default defineBuildConfig({
entries: [
'src/index.ts',
],
declaration: true,
rollup: {
emitCJS: false,
dts: {
compilerOptions: {
paths: {},
},
},
},
externals: [
'hast',
],
})
42 changes: 42 additions & 0 deletions packages/colorized-brackets/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"name": "@shikijs/colorized-brackets",
"type": "module",
"version": "1.22.2",
"description": "Collective of common transformers transformers for Shiki",
"author": "Michael Moore <mscottmoore@pm.me>",
"license": "MIT",
"homepage": "https://github.com/shikijs/shiki#readme",
"repository": {
"type": "git",
"url": "git+https://github.com/shikijs/shiki.git",
"directory": "packages/colorized-brackets"
},
"bugs": "https://github.com/shikijs/shiki/issues",
"keywords": [
"shiki",
"@shikijs/colorized-brackets"
],
"sideEffects": false,
"exports": {
".": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
}
},
"main": "./dist/index.mjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.mts",
"files": [
"dist"
],
"scripts": {
"build": "unbuild",
"dev": "unbuild --stub",
"prepare": "esno scripts/prepare.ts",
"prepublishOnly": "nr build",
"test": "vitest"
},
"dependencies": {
"shiki": "workspace:*"
}
}
72 changes: 72 additions & 0 deletions packages/colorized-brackets/scripts/prepare.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import fs from 'fs-extra'
import { themes as allThemes } from 'tm-themes'

async function main() {
// if a theme doesn't define bracket colors, it falls back to these
// from vscode /src/vs/editor/common/core/editorColorRegistry.ts
const vsCodeBaseThemes: Record<string, Record<string, string>> = {
light: {
'editorBracketHighlight.foreground1': '#0431FA',
'editorBracketHighlight.foreground2': '#319331',
'editorBracketHighlight.foreground3': '#7B3814',
'editorBracketHighlight.unexpectedBracket.foreground':
'rgba(255, 18, 18, 0.8)',
},
dark: {
'editorBracketHighlight.foreground1': '#FFD700',
'editorBracketHighlight.foreground2': '#DA70D6',
'editorBracketHighlight.foreground3': '#179FFF',
'editorBracketHighlight.unexpectedBracket.foreground':
'rgba(255, 18, 18, 0.8)',
},
lightHighContrast: {
'editorBracketHighlight.foreground1': '#0431FA',
'editorBracketHighlight.foreground2': '#319331',
'editorBracketHighlight.foreground3': '#7B3814',
'editorBracketHighlight.unexpectedBracket.foreground': '#B5200D',
},
darkHighContrast: {
'editorBracketHighlight.foreground1': '#FFD700',
'editorBracketHighlight.foreground2': '#DA70D6',
'editorBracketHighlight.foreground3': '#87CEFA',
'editorBracketHighlight.unexpectedBracket.foreground':
'rgba(255, 50, 50, 1)',
},
}

const themes: Record<string, string[]> = {}
for (const t of allThemes) {
const theme = await fs.readJSON(`./node_modules/shiki/node_modules/tm-themes/themes/${t.name}.json`)
const isHighContrast = t.name.includes('high-contrast')
const themeType = theme.type ?? 'dark'
const baseTheme = isHighContrast ? `${themeType}HighContrast` : themeType
const colors: Record<string, string> = {
...vsCodeBaseThemes[baseTheme],
...theme.colors,
}
const bracketTheme = [
colors['editorBracketHighlight.foreground1'],
colors['editorBracketHighlight.foreground2'],
colors['editorBracketHighlight.foreground3'],
colors['editorBracketHighlight.foreground4'],
colors['editorBracketHighlight.foreground5'],
colors['editorBracketHighlight.foreground6'],
colors['editorBracketHighlight.unexpectedBracket.foreground'],
].filter(Boolean)
themes[t.name] = bracketTheme
}

const sorted = Object.fromEntries(
Object.entries(themes).sort((a, b) => a[0].localeCompare(b[0])),
)

await fs.writeFile(
'./src/themes.ts',
`// Generated by scripts/prepare.ts
export default ${JSON.stringify(sorted, undefined, 2)} as Record<string, string[]>
`,
{ encoding: 'utf-8' },
)
}

main()
Loading

0 comments on commit 94cc6d8

Please sign in to comment.