{"id":24983722,"url":"https://github.com/posthtml/posthtml-shiki","last_synced_at":"2026-02-16T08:32:13.719Z","repository":{"id":225886997,"uuid":"767133207","full_name":"posthtml/posthtml-shiki","owner":"posthtml","description":"Highlight code blocks with PostHTML and Shiki","archived":false,"fork":false,"pushed_at":"2025-10-13T19:11:39.000Z","size":1078,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-10-19T18:50:52.522Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/posthtml.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":null,"patreon":"posthtml","open_collective":"posthtml","ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":["https://mailviews.com"]}},"created_at":"2024-03-04T19:02:52.000Z","updated_at":"2025-10-06T22:54:10.000Z","dependencies_parsed_at":"2024-03-04T20:36:23.954Z","dependency_job_id":"76dbf883-0fa5-4d8d-ac77-72a8d9a9748f","html_url":"https://github.com/posthtml/posthtml-shiki","commit_stats":{"total_commits":89,"total_committers":2,"mean_commits":44.5,"dds":0.3595505617977528,"last_synced_commit":"e2cadba4f290a151b3f10e4f5665fe23c239dc58"},"previous_names":["posthtml/posthtml-shiki"],"tags_count":21,"template":false,"template_full_name":null,"purl":"pkg:github/posthtml/posthtml-shiki","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/posthtml%2Fposthtml-shiki","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/posthtml%2Fposthtml-shiki/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/posthtml%2Fposthtml-shiki/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/posthtml%2Fposthtml-shiki/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/posthtml","download_url":"https://codeload.github.com/posthtml/posthtml-shiki/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/posthtml%2Fposthtml-shiki/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29503809,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-16T08:14:25.707Z","status":"ssl_error","status_checked_at":"2026-02-16T08:14:25.334Z","response_time":115,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-02-04T09:20:46.207Z","updated_at":"2026-02-16T08:32:13.692Z","avatar_url":"https://github.com/posthtml.png","language":"HTML","readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg width=\"150\" height=\"150\" alt=\"PostHTML\" src=\"https://posthtml.github.io/posthtml/logo.svg\"\u003e\n  \u003ch1\u003eShiki Plugin\u003c/h1\u003e\n  \u003cp\u003eHighlight code with PostHTML and Shiki\u003c/p\u003e\n\n  [![Version][npm-version-shield]][npm]\n  [![Build][github-ci-shield]][github-ci]\n  [![License][license-shield]][license]\n  [![Downloads][npm-stats-shield]][npm-stats]\n\u003c/div\u003e\n\n## Introduction\n\n- [Installation](#installation)\n- [Usage](#usage)\n- [Attributes](#attributes)\n- [Options](#options)\n\nThis is a PostHTML plugin that uses [Shiki](https://shiki.style) to highlight code blocks.\n\nFeatures:\n\n- [x] Configure [`langs`](#langs)\n- [x] Configure [`themes`](#themes)\n- [x] [`lang`](#lang) attribute\n- [x] [`theme`](#theme) attribute\n- [x] [Dual Themes](#theme-1)\n- [x] [Wrap in custom tag](#wrap)\n- [x] [Default color theme](#default-color)\n- [x] [Decorations](#decorations)\n- [x] [Transformers](#transformers)\n- [x] [Custom themes](#custom-themes)\n- [x] [Custom languages](#custom-languages)\n\nInput:\n\n```xml\n\u003cshiki\u003e\n  \u003ch1 class=\"text-xl\"\u003eHello\u003c/h1\u003e\n\u003c/shiki\u003e\n```\n\nOutput:\n\n```html\n\u003cpre class=\"shiki nord\" style=\"background-color:#2e3440ff;color:#d8dee9ff\" tabindex=\"0\"\u003e\u003ccode\u003e\u003cspan class=\"line\"\u003e\u003c/span\u003e\n\u003cspan class=\"line\"\u003e\u003cspan style=\"color:#81A1C1\"\u003e  \u0026#x3C;h1\u003c/span\u003e\u003cspan style=\"color:#8FBCBB\"\u003e class\u003c/span\u003e\u003cspan style=\"color:#ECEFF4\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ECEFF4\"\u003e\"\u003c/span\u003e\u003cspan style=\"color:#A3BE8C\"\u003etext-xl\u003c/span\u003e\u003cspan style=\"color:#ECEFF4\"\u003e\"\u003c/span\u003e\u003cspan style=\"color:#81A1C1\"\u003e\u003e\u003c/span\u003e\u003cspan style=\"color:#D8DEE9FF\"\u003eHello\u003c/span\u003e\u003cspan style=\"color:#81A1C1\"\u003e\u0026#x3C;/h1\u003e\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"line\"\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n```\n\n## Installation\n\n```\nnpm i posthtml posthtml-shiki\n```\n\n## Usage\n\nUse the `\u003cshiki\u003e` tag to highlight all code inside it:\n\n```js\nimport posthtml from 'posthtml'\nimport shiki from 'posthtml-shiki'\n\nposthtml([\n  shiki()\n])\n  .process('\u003cshiki\u003e\u003ch1 class=\"text-xl\"\u003eHello\u003c/h1\u003e\u003c/shiki\u003e')\n  .then(result =\u003e result.html)\n```\n\n## Attributes\n\nYou may use certain attributes to configure which themes or language to use.\n\n### `lang`\n\nAlias: `language`\n\nUse the `lang` attribute to specify the language of the code block.\n\n```xml\n\u003cshiki lang=\"javascript\"\u003e\n  import { codeToHtml } from 'shiki'\n\u003c/shiki\u003e\n```\n\n### `theme`\n\nUse the `theme` attribute to specify the theme to use.\n\n```xml\n\u003cshiki theme=\"github-light\"\u003e\n  \u003ch1 class=\"text-xl\"\u003eHello\u003c/h1\u003e\n\u003c/shiki\u003e\n```\n\n### `theme-*`\n\nShiki's [Dual Themes](https://shiki.style/guide/dual-themes) is supported through `theme-*` attributes:\n\n```xml\n\u003cshiki theme-light=\"github-light\" theme-dark=\"github-dark\"\u003e\n  \u003ch1 class=\"text-xl\"\u003eHello\u003c/h1\u003e\n\u003c/shiki\u003e\n```\n\n\u003e [!NOTE]\n\u003e If a `theme` attribute is present, it will override the `theme-*` attributes.\n\nThis uses CSS variables to switch between themes, so you'll need to define the CSS variables in your stylesheet.\n\nWith media queries:\n\n```css\n@media (prefers-color-scheme: dark) {\n  .shiki,\n  .shiki span {\n    color: var(--shiki-dark) !important;\n    background-color: var(--shiki-dark-bg) !important;\n    /* Optional, if you also want font styles */\n    font-style: var(--shiki-dark-font-style) !important;\n    font-weight: var(--shiki-dark-font-weight) !important;\n    text-decoration: var(--shiki-dark-text-decoration) !important;\n  }\n}\n```\n\nClass-based:\n\n```css\nhtml.dark .shiki,\nhtml.dark .shiki span {\n  color: var(--shiki-dark) !important;\n  background-color: var(--shiki-dark-bg) !important;\n  /* Optional, if you also want font styles */\n  font-style: var(--shiki-dark-font-style) !important;\n  font-weight: var(--shiki-dark-font-weight) !important;\n  text-decoration: var(--shiki-dark-text-decoration) !important;\n}\n```\n\n### `default-color`\n\nWhen using multiple themes, you may specify the default color theme for Shiki to use.\n\nThe value of the attribute must be the name of one of the `theme-*` attributes, so for example if you have `theme-light` and `theme-dark` attributes, the attribute value must be either `light` or `dark`.\n\n```xml\n\u003cshiki \n  theme-light=\"github-light\" \n  theme-dark=\"github-dark\" \n  default-color=\"dark\"\n\u003e\n  \u003ch1 class=\"text-xl\"\u003eHello\u003c/h1\u003e\n\u003c/shiki\u003e\n```\n\nShiki relies on CSS specificity and changes the order of the classes on the wrapping `\u003cpre\u003e` tag.\n\nBy default, the plugin does not set `default-color`.\n\n### `wrap`\n\nBy default, the `\u003cshiki\u003e` tag will be removed and the code block will be wrapped in a `\u003cpre\u003e` tag. Use the `wrap` attribute to define a custom tag to wrap the code block in.\n\n```xml\n\u003cshiki lang=\"js\" wrap=\"div\"\u003e\n  import { codeToHtml } from 'shiki'\n\u003c/shiki\u003e\n```\n\nResult:\n\n```html\n\u003cdiv\u003e\u003cpre class=\"shiki nord\" style=\"background-color:#2e3440ff;color:#d8dee9ff\" tabindex=\"0\"\u003e\u003ccode\u003e\u003cspan class=\"line\"\u003e\u003cspan style=\"color:#81A1C1\"\u003eimport\u003c/span\u003e\u003cspan style=\"color:#ECEFF4\"\u003e {\u003c/span\u003e\u003cspan style=\"color:#8FBCBB\"\u003e codeToHtml\u003c/span\u003e\u003cspan style=\"color:#ECEFF4\"\u003e }\u003c/span\u003e\u003cspan style=\"color:#81A1C1\"\u003e from\u003c/span\u003e\u003cspan style=\"color:#ECEFF4\"\u003e '\u003c/span\u003e\u003cspan style=\"color:#A3BE8C\"\u003eshiki\u003c/span\u003e\u003cspan style=\"color:#ECEFF4\"\u003e'\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n```\n\n\u003e [!IMPORTANT]  \n\u003e The value of the `wrap` attribute must be a valid tag name, CSS selectors are not supported.\n\n## Options\n\nThe plugin accepts an options object as the first argument, which can be used to configure things like the tag name or the options to pass to Shiki.\n\n### `tag`\n\nType: `string`\\\nDefault: `shiki`\n\nUse the `tag` option to specify the tag name to use.\n\n```js\nimport posthtml from 'posthtml'\nimport shiki from 'posthtml-shiki'\n\nposthtml([\n  shiki({\n    tag: 'highlight'\n  })\n])\n  .process('\u003chighlight\u003e... your code\u003c/highlight\u003e')\n  .then(result =\u003e result.html)\n```\n\n### `langs`\n\nType: `string[]`\\\nDefault: `['html']`\n\nUse the `langs` option to specify the languages for Shiki to load. \n\nIt's recommended to load only the languages that you need.\n\n```js\nimport posthtml from 'posthtml'\nimport shiki from 'posthtml-shiki'\n\nposthtml([\n  shiki({\n    langs: ['html', 'javascript']\n  })\n])\n  .process(`\n    \u003cshiki lang=\"html\"\u003e... some html\u003c/shiki\u003e\n    \u003cshiki lang=\"javascript\"\u003e... some js\u003c/shiki\u003e\n  `)\n    .then(result =\u003e result.html)\n```\n\nSee the list of [supported languages](https://shiki.style/languages) in Shiki.\n\n#### Custom Languages\n\nYou may also load custom languages by passing a TextMate grammar object to the `langs` option.\n\n```js\nconst customDiffLang = JSON.parse(readFileSync('./custom-diff.json', 'utf8'))\n\nposthtml([\n  shiki({\n    langs: [customDiffLang]\n  })\n])\n  .process(`\n    \u003cshiki lang=\"custom-diff\"\u003e\n      - FOO\n      + BAR\n    \u003c/shiki\u003e\n  `)\n    .then(result =\u003e result.html)\n```\n\nYou must specify the `lang` attribute with the name of the language, and the value must match the `name` property of the TextMate grammar object.\n\nSee [tm-grammars](https://github.com/shikijs/textmate-grammars-themes/tree/main/packages/tm-grammars) for examples.\n\n### `themes`\n\nType: `Array\u003cstring\u003e | Array\u003cobject\u003e`\\\nDefault: `['nord']`\n\nUse the `themes` option to specify the themes for Shiki to load.\n\nIt's recommended to load only the themes that you need.\n\n```js\nimport posthtml from 'posthtml'\nimport shiki from 'posthtml-shiki'\n\nposthtml([\n  shiki({\n    themes: ['github-light', 'github-dark']\n  })\n])\n  .process(`\n    \u003cshiki theme=\"github-light\"\u003e[code]\u003c/shiki\u003e\n    \u003cshiki theme=\"github-dark\"\u003e[code]\u003c/shiki\u003e\n  `)\n    .then(result =\u003e result.html)\n```\n\nSee the list of [available themes](https://shiki.style/themes) in Shiki.\n\n\u003e [!NOTE]\n\u003e If you don't specify a `theme=\"\"` attribute, the first theme in the `themes` option will be used.\n\n#### Custom Themes\n\nYou may also load [custom themes](https://shiki.style/guide/load-theme) by passing a TextMate theme object to the `themes` option:\n\n```js\n// Define textmate theme\nconst myTheme = {\n  name: 'my-theme',\n  settings: [\n    {\n      scope: ['string'],\n      settings: {\n        foreground: '#888'\n      }\n    },\n  ]\n}\n\nposthtml([\n  shiki({\n    themes: [myTheme],\n  })\n])\n  .process(`\u003cshiki theme=\"my-theme\"\u003e[code]\u003c/shiki\u003e`)\n  .then(result =\u003e result.html)\n```\n\nIf you're loading multiple themes, you will need to specify which theme to use with the `theme=\"\"` attribute. For custom themes, the attribute value must match the name of the theme - in the example above, that would be `my-theme`.\n\n### `wrapTag`\n\nType: `string|boolean`\\\nDefault: `false`\n\nUse the `wrapTag` option to specify a custom tag to wrap the highlighted code block in.\n\nBy default, the plugin does not wrap the code block in any tag.\n\n```js\nimport posthtml from 'posthtml'\nimport shiki from 'posthtml-shiki'\n\nposthtml([\n  shiki({\n    wrapTag: 'div'\n  })\n])\n  .process('\u003cshiki\u003e... your code\u003c/shiki\u003e')\n  .then(result =\u003e result.html)\n```\n\nResult:\n\n```html\n\u003cdiv\u003e\n  [highlighted code]\n\u003c/div\u003e\n```\n\n### `defaultColor`\n\nType: `string`\\\nDefault: `undefined`\n\nUse the `defaultColor` option to specify the default color theme for Shiki to use.\n\nThe value must be the key name of one of the themes in the `themes` option.\n\n```js\nimport posthtml from 'posthtml'\nimport shiki from 'posthtml-shiki'\n\nposthtml([\n  shiki({\n    themes: {\n      light: 'github-light',\n      dark: 'github-dark',\n    },\n    defaultColor: 'dark'\n  })\n])\n  .process(`\n    \u003cshiki\u003e\n      [code]\n    \u003c/shiki\u003e\n  `)\n  .then(result =\u003e result.html)\n```\n\n### `decorations`\n\nType: `array`\\\nDefault: `[]`\n\nShiki's [Decorations](https://shiki.style/guide/decorations) are supported through the `decorations` option.\n\nYou can use this to wrap custom classes and attributes around character ranges in your code.\n\n```js\nimport posthtml from 'posthtml'\nimport shiki from 'posthtml-shiki'\n\nposthtml([\n  shiki({\n    decorations: [\n      {\n        // line and character are 0-indexed\n        start: { line: 0, character: 0 },\n        end: { line: 0, character: 5 },\n        properties: { class: 'highlighted-word' }\n      }\n    ]\n  })\n])\n  .process(`\n    \u003cshiki\u003e\n      const foo = 'bar'\n    \u003c/shiki\u003e\n  `)\n  .then(result =\u003e result.html)\n```\n\nThe word `const` will be wrapped in a `\u003cspan class=\"highlighted-word\"\u003e` tag.\n\n### `transformers`\n\nType: `array`\\\nDefault: `[]`\n\nUse this option to transform the highlighted code block with Shiki's [Transformers](https://shiki.style/guide/transformers).\n\n```js\nimport posthtml from 'posthtml'\nimport shiki from 'posthtml-shiki'\nimport { transformerNotationHighlight } from '@shikijs/transformers'\n\nposthtml([\n  shiki({\n    transformers: [\n      transformerNotationHighlight(),\n      {\n        code(node) {\n          this.addClassToHast(node, 'custom-class')\n        },\n      },\n    ]\n  })\n])\n  .process(`\n    \u003cshiki\u003e\n      const foo = 'bar'\n      let baz = 'biz' // [!code highlight]\n    \u003c/shiki\u003e\n  `)\n  .then(result =\u003e result.html)\n```\n\nSee the docs for [Shiki Transformers](https://shiki.style/guide/transformers) and a list of [common Shiki Transformers](https://shiki.style/packages/transformers).\n\n[npm]: https://www.npmjs.com/package/posthtml-shiki\n[npm-version-shield]: https://img.shields.io/npm/v/posthtml-shiki.svg\n[npm-stats]: http://npm-stat.com/charts.html?package=posthtml-shiki\n[npm-stats-shield]: https://img.shields.io/npm/dt/posthtml-shiki.svg\n[github-ci]: https://github.com/posthtml/posthtml-shiki/actions/workflows/nodejs.yml\n[github-ci-shield]: https://github.com/posthtml/posthtml-shiki/actions/workflows/nodejs.yml/badge.svg\n[license]: ./LICENSE\n[license-shield]: https://img.shields.io/npm/l/posthtml-shiki.svg\n","funding_links":["https://patreon.com/posthtml","https://opencollective.com/posthtml","https://mailviews.com"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fposthtml%2Fposthtml-shiki","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fposthtml%2Fposthtml-shiki","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fposthtml%2Fposthtml-shiki/lists"}