# AddClassesTransformer Source: https://phiki.dev/add-classes-transformer Phiki provides the `Phiki\Transformers\AddClassesTransformer` transformer out of the box, which allows you to automatically add scope-based CSS classes to HTML elements. ## Usage To use the `AddClassesTransformer`, apply it to your pending HTML content: ```php theme={null} use Phiki\Phiki; use Phiki\Transformers\AddClassesTransformer; $html = (new Phiki) ->codeToHtml("transformer(new AddClassesTransformer) ->toString(); ``` The generated HTML will include CSS classes based on the scope names for each token, for example `phiki-source.php`. You can then use these classes in your CSS to style specific elements: ```css theme={null} .token[class^="phiki-keyword"] { color: blue !important; } ``` ## Disabling `style` attributes If you want to disable the inline `style` attributes added by Phiki, you can pass the `styles: false` argument to the constructor. ```php theme={null} $html = (new Phiki) ->codeToHtml("transformer(new AddClassesTransformer(styles: false)) ->toString(); ``` This will result in HTML elements for tokens that only have the `class` attribute, allowing you to fully control the styling through CSS. # Grammars and Themes Source: https://phiki.dev/available-grammars-and-themes # Grammars The list below contains all of the grammars that are currently available in Phiki. If you would like to request a new grammar, please open an issue on the [GitHub repository](https://github.com/phikiphp/phiki). | Name | Aliases | Scope name | Enum case | | :------------------- | :-------------------------------- | :----------------------------- | :-------------------------- | | `abap` | — | `source.abap` | `Grammar::Abap` | | `actionscript-3` | — | `source.actionscript.3` | `Grammar::Actionscript_3` | | `ada` | — | `source.ada` | `Grammar::Ada` | | `angular-html` | — | `text.html.derivative.ng` | `Grammar::AngularHtml` | | `angular-ts` | — | `source.ts.ng` | `Grammar::AngularTs` | | `apache` | — | `source.apacheconf` | `Grammar::Apache` | | `apex` | — | `source.apex` | `Grammar::Apex` | | `apl` | — | `source.apl` | `Grammar::Apl` | | `applescript` | — | `source.applescript` | `Grammar::Applescript` | | `ara` | — | `source.ara` | `Grammar::Ara` | | `asciidoc` | `adoc` | `text.asciidoc` | `Grammar::Asciidoc` | | `asm` | — | `source.asm.x86_64` | `Grammar::Asm` | | `astro` | — | `source.astro` | `Grammar::Astro` | | `awk` | — | `source.awk` | `Grammar::Awk` | | `ballerina` | — | `source.ballerina` | `Grammar::Ballerina` | | `bat` | `batch` | `source.batchfile` | `Grammar::Bat` | | `beancount` | — | `text.beancount` | `Grammar::Beancount` | | `berry` | `be` | `source.berry` | `Grammar::Berry` | | `bibtex` | — | `text.bibtex` | `Grammar::Bibtex` | | `blade` | — | `text.html.php.blade` | `Grammar::Blade` | | `bsl` | `1c` | `source.bsl` | `Grammar::Bsl` | | `c` | — | `source.c` | `Grammar::C` | | `cadence` | `cdc` | `source.cadence` | `Grammar::Cadence` | | `cairo` | — | `source.cairo0` | `Grammar::Cairo` | | `clarity` | — | `source.clar` | `Grammar::Clarity` | | `clojure` | `clj` | `source.clojure` | `Grammar::Clojure` | | `cmake` | — | `source.cmake` | `Grammar::Cmake` | | `cobol` | — | `source.cobol` | `Grammar::Cobol` | | `codeowners` | — | `text.codeowners` | `Grammar::Codeowners` | | `codeql` | `ql` | `source.ql` | `Grammar::Codeql` | | `coffee` | `coffeescript` | `source.coffee` | `Grammar::Coffee` | | `common-lisp` | `lisp` | `source.commonlisp` | `Grammar::CommonLisp` | | `coq` | — | `source.coq` | `Grammar::Coq` | | `cpp` | `c++` | `source.cpp` | `Grammar::Cpp` | | `crystal` | — | `source.crystal` | `Grammar::Crystal` | | `csharp` | `c#`, `cs` | `source.cs` | `Grammar::Csharp` | | `css` | — | `source.css` | `Grammar::Css` | | `csv` | — | `text.csv` | `Grammar::Csv` | | `cue` | — | `source.cue` | `Grammar::Cue` | | `cypher` | `cql` | `source.cypher` | `Grammar::Cypher` | | `d` | — | `source.d` | `Grammar::D` | | `dart` | — | `source.dart` | `Grammar::Dart` | | `dax` | — | `source.dax` | `Grammar::Dax` | | `desktop` | — | `source.desktop` | `Grammar::Desktop` | | `diff` | — | `source.diff` | `Grammar::Diff` | | `docker` | `dockerfile` | `source.dockerfile` | `Grammar::Docker` | | `dotenv` | — | `source.dotenv` | `Grammar::Dotenv` | | `dream-maker` | — | `source.dm` | `Grammar::DreamMaker` | | `edge` | — | `text.html.edge` | `Grammar::Edge` | | `elixir` | — | `source.elixir` | `Grammar::Elixir` | | `elm` | — | `source.elm` | `Grammar::Elm` | | `emacs-lisp` | `elisp` | `source.emacs.lisp` | `Grammar::EmacsLisp` | | `erb` | — | `text.html.erb` | `Grammar::Erb` | | `erlang` | `erl` | `source.erlang` | `Grammar::Erlang` | | `fennel` | — | `source.fnl` | `Grammar::Fennel` | | `fish` | — | `source.fish` | `Grammar::Fish` | | `fluent` | `ftl` | `source.ftl` | `Grammar::Fluent` | | `fortran-fixed-form` | `f`, `for`, `f77` | `source.fortran.fixed` | `Grammar::FortranFixedForm` | | `fortran-free-form` | `f90`, `f95`, `f03`, `f08`, `f18` | `source.fortran.free` | `Grammar::FortranFreeForm` | | `fsharp` | `f#`, `fs` | `source.fsharp` | `Grammar::Fsharp` | | `gdresource` | — | `source.gdresource` | `Grammar::Gdresource` | | `gdscript` | — | `source.gdscript` | `Grammar::Gdscript` | | `gdshader` | — | `source.gdshader` | `Grammar::Gdshader` | | `genie` | — | `source.genie` | `Grammar::Genie` | | `gherkin` | — | `text.gherkin.feature` | `Grammar::Gherkin` | | `git-commit` | — | `text.git-commit` | `Grammar::GitCommit` | | `git-rebase` | — | `text.git-rebase` | `Grammar::GitRebase` | | `gleam` | — | `source.gleam` | `Grammar::Gleam` | | `glimmer-js` | `gjs` | `source.gjs` | `Grammar::GlimmerJs` | | `glimmer-ts` | `gts` | `source.gts` | `Grammar::GlimmerTs` | | `glsl` | — | `source.glsl` | `Grammar::Glsl` | | `gnuplot` | — | `source.gnuplot` | `Grammar::Gnuplot` | | `go` | — | `source.go` | `Grammar::Go` | | `graphql` | `gql` | `source.graphql` | `Grammar::Graphql` | | `groovy` | — | `source.groovy` | `Grammar::Groovy` | | `hack` | — | `source.hack` | `Grammar::Hack` | | `haml` | — | `text.haml` | `Grammar::Haml` | | `handlebars` | `hbs` | `text.html.handlebars` | `Grammar::Handlebars` | | `haskell` | `hs` | `source.haskell` | `Grammar::Haskell` | | `haxe` | — | `source.hx` | `Grammar::Haxe` | | `hcl` | — | `source.hcl` | `Grammar::Hcl` | | `hjson` | — | `source.hjson` | `Grammar::Hjson` | | `hlsl` | — | `source.hlsl` | `Grammar::Hlsl` | | `html` | — | `text.html.basic` | `Grammar::Html` | | `html-derivative` | — | `text.html.derivative` | `Grammar::HtmlDerivative` | | `http` | — | `source.http` | `Grammar::Http` | | `hxml` | — | `source.hxml` | `Grammar::Hxml` | | `hy` | — | `source.hy` | `Grammar::Hy` | | `imba` | — | `source.imba` | `Grammar::Imba` | | `ini` | `properties` | `source.ini` | `Grammar::Ini` | | `java` | — | `source.java` | `Grammar::Java` | | `javascript` | `js` | `source.js` | `Grammar::Javascript` | | `jinja` | — | `source.jinja` | `Grammar::Jinja` | | `jison` | — | `source.jison` | `Grammar::Jison` | | `json` | — | `source.json` | `Grammar::Json` | | `json5` | — | `source.json5` | `Grammar::Json5` | | `jsonc` | — | `source.json.comments` | `Grammar::Jsonc` | | `jsonl` | — | `source.json.lines` | `Grammar::Jsonl` | | `jsonnet` | — | `source.jsonnet` | `Grammar::Jsonnet` | | `jssm` | `fsl` | `source.jssm` | `Grammar::Jssm` | | `jsx` | — | `source.js.jsx` | `Grammar::Jsx` | | `julia` | `jl` | `source.julia` | `Grammar::Julia` | | `kotlin` | `kt`, `kts` | `source.kotlin` | `Grammar::Kotlin` | | `kusto` | `kql` | `source.kusto` | `Grammar::Kusto` | | `latex` | — | `text.tex.latex` | `Grammar::Latex` | | `lean` | `lean4` | `source.lean4` | `Grammar::Lean` | | `less` | — | `source.css.less` | `Grammar::Less` | | `liquid` | — | `text.html.liquid` | `Grammar::Liquid` | | `llvm` | — | `source.llvm` | `Grammar::Llvm` | | `log` | — | `text.log` | `Grammar::Log` | | `logo` | — | `source.logo` | `Grammar::Logo` | | `lua` | — | `source.lua` | `Grammar::Lua` | | `luau` | — | `source.luau` | `Grammar::Luau` | | `make` | `makefile` | `source.makefile` | `Grammar::Make` | | `markdown` | `md` | `text.html.markdown` | `Grammar::Markdown` | | `marko` | — | `text.marko` | `Grammar::Marko` | | `matlab` | — | `source.matlab` | `Grammar::Matlab` | | `mdc` | — | `text.markdown.mdc.standalone` | `Grammar::Mdc` | | `mdx` | — | `source.mdx` | `Grammar::Mdx` | | `mermaid` | `mmd` | `markdown.mermaid.codeblock` | `Grammar::Mermaid` | | `mipsasm` | `mips` | `source.mips` | `Grammar::Mipsasm` | | `mojo` | — | `source.mojo` | `Grammar::Mojo` | | `move` | — | `source.move` | `Grammar::Move` | | `narrat` | `nar` | `source.narrat` | `Grammar::Narrat` | | `nextflow` | `nf` | `source.nextflow` | `Grammar::Nextflow` | | `nginx` | — | `source.nginx` | `Grammar::Nginx` | | `nim` | — | `source.nim` | `Grammar::Nim` | | `nix` | — | `source.nix` | `Grammar::Nix` | | `nushell` | `nu` | `source.nushell` | `Grammar::Nushell` | | `objective-c` | `objc` | `source.objc` | `Grammar::ObjectiveC` | | `objective-cpp` | — | `source.objcpp` | `Grammar::ObjectiveCpp` | | `ocaml` | — | `source.ocaml` | `Grammar::Ocaml` | | `pascal` | — | `source.pascal` | `Grammar::Pascal` | | `perl` | — | `source.perl` | `Grammar::Perl` | | `php` | — | `source.php` | `Grammar::Php` | | `plsql` | — | `source.plsql.oracle` | `Grammar::Plsql` | | `polar` | — | `source.polar` | `Grammar::Polar` | | `postcss` | — | `source.css.postcss` | `Grammar::Postcss` | | `powerquery` | — | `source.powerquery` | `Grammar::Powerquery` | | `powershell` | `ps`, `ps1` | `source.powershell` | `Grammar::Powershell` | | `prisma` | — | `source.prisma` | `Grammar::Prisma` | | `prolog` | — | `source.prolog` | `Grammar::Prolog` | | `proto` | `protobuf` | `source.proto` | `Grammar::Proto` | | `pug` | `jade` | `text.pug` | `Grammar::Pug` | | `puppet` | — | `source.puppet` | `Grammar::Puppet` | | `purescript` | — | `source.purescript` | `Grammar::Purescript` | | `python` | `py` | `source.python` | `Grammar::Python` | | `qml` | — | `source.qml` | `Grammar::Qml` | | `qmldir` | — | `source.qmldir` | `Grammar::Qmldir` | | `qss` | — | `source.qss` | `Grammar::Qss` | | `r` | — | `source.r` | `Grammar::R` | | `racket` | — | `source.racket` | `Grammar::Racket` | | `raku` | `perl6` | `source.perl.6` | `Grammar::Raku` | | `razor` | — | `text.aspnetcorerazor` | `Grammar::Razor` | | `reg` | — | `source.reg` | `Grammar::Reg` | | `regexp` | `regex` | `source.regexp.python` | `Grammar::Regexp` | | `rel` | — | `source.rel` | `Grammar::Rel` | | `riscv` | — | `source.riscv` | `Grammar::Riscv` | | `rst` | — | `source.rst` | `Grammar::Rst` | | `ruby` | `rb` | `source.ruby` | `Grammar::Ruby` | | `rust` | `rs` | `source.rust` | `Grammar::Rust` | | `sas` | — | `source.sas` | `Grammar::Sas` | | `sass` | — | `source.sass` | `Grammar::Sass` | | `scala` | — | `source.scala` | `Grammar::Scala` | | `scheme` | — | `source.scheme` | `Grammar::Scheme` | | `scss` | — | `source.css.scss` | `Grammar::Scss` | | `sdbl` | `1c-query` | `source.sdbl` | `Grammar::Sdbl` | | `shaderlab` | `shader` | `source.shaderlab` | `Grammar::Shaderlab` | | `shellscript` | `bash`, `sh`, `shell`, `zsh` | `source.shell` | `Grammar::Shellscript` | | `shellsession` | `console` | `text.shell-session` | `Grammar::Shellsession` | | `smalltalk` | — | `source.smalltalk` | `Grammar::Smalltalk` | | `solidity` | — | `source.solidity` | `Grammar::Solidity` | | `soy` | `closure-templates` | `text.html.soy` | `Grammar::Soy` | | `sparql` | — | `source.sparql` | `Grammar::Sparql` | | `splunk` | `spl` | `source.splunk_search` | `Grammar::Splunk` | | `sql` | — | `source.sql` | `Grammar::Sql` | | `ssh-config` | — | `source.ssh-config` | `Grammar::SshConfig` | | `stata` | — | `source.stata` | `Grammar::Stata` | | `stylus` | `styl` | `source.stylus` | `Grammar::Stylus` | | `svelte` | — | `source.svelte` | `Grammar::Svelte` | | `swift` | — | `source.swift` | `Grammar::Swift` | | `system-verilog` | — | `source.systemverilog` | `Grammar::SystemVerilog` | | `systemd` | — | `source.systemd` | `Grammar::Systemd` | | `talonscript` | `talon` | `source.talon` | `Grammar::Talonscript` | | `tasl` | — | `source.tasl` | `Grammar::Tasl` | | `tcl` | — | `source.tcl` | `Grammar::Tcl` | | `templ` | — | `source.templ` | `Grammar::Templ` | | `terraform` | `tf`, `tfvars` | `source.hcl.terraform` | `Grammar::Terraform` | | `tex` | — | `text.tex` | `Grammar::Tex` | | `toml` | — | `source.toml` | `Grammar::Toml` | | `ts-tags` | `lit` | `source.ts.tags` | `Grammar::TsTags` | | `tsv` | — | `text.tsv` | `Grammar::Tsv` | | `tsx` | — | `source.tsx` | `Grammar::Tsx` | | `turtle` | — | `source.turtle` | `Grammar::Turtle` | | `twig` | — | `text.html.twig` | `Grammar::Twig` | | `typescript` | `ts` | `source.ts` | `Grammar::Typescript` | | `typespec` | `tsp` | `source.tsp` | `Grammar::Typespec` | | `typst` | `typ` | `source.typst` | `Grammar::Typst` | | `v` | — | `source.v` | `Grammar::V` | | `vala` | — | `source.vala` | `Grammar::Vala` | | `vb` | `cmd` | `source.asp.vb.net` | `Grammar::Vb` | | `verilog` | — | `source.verilog` | `Grammar::Verilog` | | `vhdl` | — | `source.vhdl` | `Grammar::Vhdl` | | `viml` | `vim`, `vimscript` | `source.viml` | `Grammar::Viml` | | `vue` | — | `source.vue` | `Grammar::Vue` | | `vue-html` | — | `text.html.vue-html` | `Grammar::VueHtml` | | `vue-vine` | — | `source.vue-vine` | `Grammar::VueVine` | | `vyper` | `vy` | `source.vyper` | `Grammar::Vyper` | | `wasm` | — | `source.wat` | `Grammar::Wasm` | | `wgsl` | — | `source.wgsl` | `Grammar::Wgsl` | | `wikitext` | `mediawiki`, `wiki` | `source.wikitext` | `Grammar::Wikitext` | | `wit` | — | `source.wit` | `Grammar::Wit` | | `wolfram` | `wl` | `source.wolfram` | `Grammar::Wolfram` | | `xml` | — | `text.xml` | `Grammar::Xml` | | `xsl` | — | `text.xml.xsl` | `Grammar::Xsl` | | `yaml` | `yml` | `source.yaml` | `Grammar::Yaml` | | `zenscript` | — | `source.zenscript` | `Grammar::Zenscript` | | `zig` | — | `source.zig` | `Grammar::Zig` | # Themes The list below contains all of the themes that are currently available in Phiki. If you would like to request a new theme, please open an issue on the [GitHub repository](https://github.com/phikiphp/phiki). | Name | Enum case | | :--------------------------- | :------------------------------- | | `andromeeda` | `Theme::Andromeeda` | | `aurora-x` | `Theme::AuroraX` | | `ayu-dark` | `Theme::AyuDark` | | `catppuccin-frappe` | `Theme::CatppuccinFrappe` | | `catppuccin-latte` | `Theme::CatppuccinLatte` | | `catppuccin-macchiato` | `Theme::CatppuccinMacchiato` | | `catppuccin-mocha` | `Theme::CatppuccinMocha` | | `dark-plus` | `Theme::DarkPlus` | | `dracula` | `Theme::Dracula` | | `dracula-soft` | `Theme::DraculaSoft` | | `everforest-dark` | `Theme::EverforestDark` | | `everforest-light` | `Theme::EverforestLight` | | `github-dark` | `Theme::GithubDark` | | `github-dark-default` | `Theme::GithubDarkDefault` | | `github-dark-dimmed` | `Theme::GithubDarkDimmed` | | `github-dark-high-contrast` | `Theme::GithubDarkHighContrast` | | `github-light` | `Theme::GithubLight` | | `github-light-default` | `Theme::GithubLightDefault` | | `github-light-high-contrast` | `Theme::GithubLightHighContrast` | | `gruvbox-dark-hard` | `Theme::GruvboxDarkHard` | | `gruvbox-dark-medium` | `Theme::GruvboxDarkMedium` | | `gruvbox-dark-soft` | `Theme::GruvboxDarkSoft` | | `gruvbox-light-hard` | `Theme::GruvboxLightHard` | | `gruvbox-light-medium` | `Theme::GruvboxLightMedium` | | `gruvbox-light-soft` | `Theme::GruvboxLightSoft` | | `houston` | `Theme::Houston` | | `kanagawa-dragon` | `Theme::KanagawaDragon` | | `kanagawa-lotus` | `Theme::KanagawaLotus` | | `kanagawa-wave` | `Theme::KanagawaWave` | | `laserwave` | `Theme::Laserwave` | | `light-plus` | `Theme::LightPlus` | | `material-theme` | `Theme::MaterialTheme` | | `material-theme-darker` | `Theme::MaterialThemeDarker` | | `material-theme-lighter` | `Theme::MaterialThemeLighter` | | `material-theme-ocean` | `Theme::MaterialThemeOcean` | | `material-theme-palenight` | `Theme::MaterialThemePalenight` | | `min-dark` | `Theme::MinDark` | | `min-light` | `Theme::MinLight` | | `monokai` | `Theme::Monokai` | | `night-owl` | `Theme::NightOwl` | | `nord` | `Theme::Nord` | | `one-dark-pro` | `Theme::OneDarkPro` | | `one-light` | `Theme::OneLight` | | `plastic` | `Theme::Plastic` | | `poimandres` | `Theme::Poimandres` | | `red` | `Theme::Red` | | `rose-pine` | `Theme::RosePine` | | `rose-pine-dawn` | `Theme::RosePineDawn` | | `rose-pine-moon` | `Theme::RosePineMoon` | | `slack-dark` | `Theme::SlackDark` | | `slack-ochin` | `Theme::SlackOchin` | | `snazzy-light` | `Theme::SnazzyLight` | | `solarized-dark` | `Theme::SolarizedDark` | | `solarized-light` | `Theme::SolarizedLight` | | `synthwave-84` | `Theme::Synthwave_84` | | `tokyo-night` | `Theme::TokyoNight` | | `vesper` | `Theme::Vesper` | | `vitesse-black` | `Theme::VitesseBlack` | | `vitesse-dark` | `Theme::VitesseDark` | | `vitesse-light` | `Theme::VitesseLight` | # Caching Source: https://phiki.dev/caching Syntax highlighting can be a resource-intensive operation, especially for large code snippets or when processing many snippets in a short period. To improve performance, Phiki includes a built-in caching mechanism built around the `psr/simple-cache` interface. ## Enabling caching Enabling caching is as simple as providing a cache implementation to the `Phiki::cache()` method. ```php theme={null} class SimpleCache implements \Psr\SimpleCache\CacheInterface { // ... } $phiki = (new Phiki) ->cache(new SimpleCache); ``` This will enable caching for all subsequent calls to `codeToHtml()`. The cache will store the generated HTML for each unique combination of code, grammar, theme(s), gutter setting and `Transformer` class. ## Cache invalidation Phiki does not include any built-in cache invalidation mechanism apart from a change in the cache key. If you need to invalidate the cache for any reason, you must do so using the methods provided by your chosen cache implementation. ## Caching individual snippets If you don't want to cache all syntax highlighted code, you can also cache individual `codeToHtml()` calls by passing a cache implementation to the `PendingHtmlOutput::cache()` method. ```php theme={null} $html = (new Phiki) ->codeToHtml("cache(new SimpleCache) ->toString(); ``` # CommonMark Source: https://phiki.dev/commonmark Learn how to use Phiki with The PHP League's CommonMark library. If you're using `league/commonmark` to parse and render Markdown in your PHP project, you can easily integrate Phiki using our custom extension. ## Usage ```php theme={null} use League\CommonMark\Environment\Environment; use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension; use League\CommonMark\MarkdownConverter; use Phiki\Adapters\CommonMark\PhikiExtension; use Phiki\Theme\Theme; $environment = new Environment; $environment ->addExtension(new CommonMarkCoreExtension) ->addExtension(new PhikiExtension(Theme::GithubLight)); $converter = new MarkdownConverter($environment); $output = $converter->convert("My awesome blog post with code blocks..."); ``` ### Enabling the gutter You can enable the gutter by specifying the `withGutter` argument in the `PhikiExtension` constructor. ```php theme={null} use League\CommonMark\Environment\Environment; use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension; use League\CommonMark\MarkdownConverter; use Phiki\Adapters\CommonMark\PhikiExtension; use Phiki\Theme\Theme; $environment = new Environment; $environment ->addExtension(new CommonMarkCoreExtension) ->addExtension(new PhikiExtension(Theme::GithubLight, withGutter: true)); // [!code ++] ``` ### Using multiple themes You can also pass in an array of themes to the `PhikiExtension` constructor. ```php theme={null} use League\CommonMark\Environment\Environment; use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension; use League\CommonMark\MarkdownConverter; use Phiki\Adapters\CommonMark\PhikiExtension; use Phiki\Theme\Theme; $environment = new Environment; $environment ->addExtension(new CommonMarkCoreExtension) ->addExtension(new PhikiExtension([ // [!code ++] 'light' => Theme::GithubLight, // [!code ++] 'dark' => Theme::GithubDark, // [!code ++] ])); // [!code ++] ``` ### Meta information You can add additional meta information to your Markdown code blocks to highlight and focus a specified set of lines. #### Highlighting lines You can highlight lines in your code blocks using special annotations in the code block's info string. ````md theme={null} ```php {2,4-8} ```` The braces represent the lines to highlight. In this example, line 2 will be highlighted, as well as lines 4 through 8. #### Focusing lines You can focus lines in your code blocks using special annotations in the code block's info string. ````md theme={null} ```php {}{2,4-8} ```` The first set of braces represents the lines to highlight (none in this case), while the second set of braces represents the lines to focus. In this example, line 2 will be focused, as well as lines 4 through 8. When you have focused lines inside of a code block, Phiki will add a `focus` class to the `
` element.


#### Sample CSS

Phiki does not style the highlighted or focused lines by default, so you will need to add your own CSS.

You can use the following sample CSS to get started:

```css theme={null}
pre.phiki code .line.highlight {
    background-color: hsl(197, 88%, 94%);
}

pre.phiki.focus .line:not(.focus) {
    transition: all 250ms;
    filter: blur(2px);
}

pre.phiki.focus:hover .line {
    transition: all 250ms;
    filter: blur(0);
}
```

### Inline annotations

The meta information for highlighting and focusing lines can be difficult to use when you have a large code block or if you change the code frequently since it uses line numbers.

That's why Phiki also supports inline annotations using special comments in your code.

#### Ranges

Inline annotations accept an optional range parameter to specify which lines should be highlighted or focused.

```
// [code! highlight]      → Only this line.
// [code! highlight:2]    → This line and the 2 lines after it.
// [code! highlight:-2]   → This line and the 2 lines before it.
// [code! highlight:1,3]  → From the next line, 3 lines in total.
// [code! highlight:-1,2] → From the previous line, 2 lines in total.
```

It's also possible to create an "open ended" range by using `start` and `end` to mark the beginning and end of a range.

```
// [code! highlight:start] → Start highlighting from this line.
// ...
// [code! highlight:end]   → Stop highlighting after this line.
```

#### Highlighting lines

To highlight a line, you can add a trailing comment to the line you want to highlight.

```php theme={null}
echo "Hello, world!"; // [code! highlight]
```

This comment tells Phiki to highlight this line by adding a `highlight` class to the corresponding line element.

If you don't want to write out `highlight` every time, you can use the `hl` or `~~` shorthands instead.

```php theme={null}
echo "Hello, world!"; // [code! hl]
echo "Hello, world!"; // [code! ~~]
```

#### Focusing lines

To focus a line, you can add a trailing comment to the line you want to focus.

```php theme={null}
echo "Hello, world!"; // [code! focus]
```

This comment tells Phiki to focus this line by adding a `focus` class to the corresponding line element.


  When you have focused lines inside of a code block, Phiki will add a `focus` class to the `
` element.


If you don't want to write out `focus` every time, you can use the `f` or `**` shorthands instead.

```php theme={null}
echo "Hello, world!"; // [code! f]
echo "Hello, world!"; // [code! **]
```

#### Diff annotations

Diff annotations are useful for displaying changes in a piece of code, e.g. inserting a line or removing a line.

```php theme={null}
$user = User::find(1); // [code! remove]
$user = User::findOrFail(1); // [code! insert]
```

This will add `insert` and `remove` classes to the corresponding line elements.

If you don't want to write out the full keywords, you can use these shorthands:

```php theme={null}
$user = User::find(1); // [code! --]
$user = User::findOrFail(1); // [code! ++]
```

You can also use `add`, `del`, or `delete` as alternative keywords for insert and remove respectively.

##### **Gutter diff symbols**

When the gutter is enabled, line numbers will be replaced with the following symbols based on which type of diff annotation is used:

* Inserted lines show `+` instead of the line number.
* Removed lines show `-` instead of the line number

```php theme={null}
$environment = new Environment;
$environment
    ->addExtension(new CommonMarkCoreExtension)
    ->addExtension(new PhikiExtension(Theme::GithubLight, withGutter: true));
```

#### Sample CSS

##### **Highlighted lines**

When you use an inline highlight annotation, Phiki will automatically try to find an `editor.lineHighlightBackground` or `editor.selectionHighlightBackground` color inside of your chosen theme(s) and add a CSS variable to the `
` element.

If it can't find one, it will fallback to the default background color of the theme.

Phiki automatically adds the following CSS variables:

* `--phiki-line-highlight` - Background color for highlighted lines

Those CSS variables are then applied to the line element the same as other styled elements.


  If you're using multiple themes, Phiki will also add CSS variables for each theme so you can style them differently in dark mode, for example.


```css theme={null}
@media (prefers-color-scheme: dark) {
    .phiki .line.highlight {
        background-color: var(--phiki-dark-line-highlight) !important;
    }
}
```

##### **Focused lines**

Phiki does not apply any styles to focused lines by default, so you will need to add your own CSS.

```css theme={null}
pre.phiki.focus .line:not(.focus) {
    transition: all 250ms;
    filter: blur(2px);
}

pre.phiki.focus:hover .line {
    transition: all 250ms;
    filter: blur(0);
}
```

##### **Diff annotations**

When you use diff annotations, Phiki will automatically try to find `markup.inserted` and `markup.deleted` colors inside of your chosen theme(s) and add CSS variables to the `
` element.

Phiki automatically adds the following CSS variables to the `
` element:

* `--phiki-diff-insert-bg` - Background color for inserted lines
* `--phiki-diff-insert-fg` - Text color for inserted lines
* `--phiki-diff-remove-bg` - Background color for removed lines
* `--phiki-diff-remove-fg` - Text color for removed lines

You can use these variables in your CSS:

```css theme={null}
.phiki .line.insert {
    background-color: var(--phiki-diff-insert-bg);
    color: var(--phiki-diff-insert-fg);
}

.phiki .line.remove {
    background-color: var(--phiki-diff-remove-bg);
    color: var(--phiki-diff-remove-fg);
}
```


  If you're using multiple themes, Phiki will also add CSS variables for each theme so you can style them differently in dark mode, for example.


```css theme={null}
@media (prefers-color-scheme: dark) {
    .phiki .line.insert {
        background-color: var(--phiki-dark-diff-insert-bg) !important;
        color: var(--phiki-dark-diff-insert-fg) !important;
    }

    .phiki .line.remove {
        background-color: var(--phiki-dark-diff-remove-bg) !important;
        color: var(--phiki-dark-diff-remove-fg) !important;
    }
}
```


# Custom extensions
Source: https://phiki.dev/custom-extensions

Learn how to bundle customizations into a reusable extension.

If you have a set of custom grammars and themes that you want to reuse across multiple projects or share with others, you can bundle them into a custom extension.

Custom extensions are simple PHP classes that implement the `Phiki\Contracts\ExtensionInterface` interface.

```php theme={null}
use Phiki\Contracts\ExtensionInterface;
use Phiki\Environment;

class MyExtension implements ExtensionInterface
{
    public function register(Environment $environment): void
    {
        $environment
            ->grammar('my-language', __DIR__ . '/grammars/my-language.json')
            ->theme('my-theme', __DIR__ . '/themes/my-theme.json');
    }
}
```

You can register the custom extension using the `extend()` method.

```php theme={null}
use App\Phiki\MyExtension;

$phiki = (new Phiki)
    ->extend(new MyExtension);
```

The `register()` method will be called when the extension is registered and is applied to all future usage of the `Phiki` instance.


# Custom grammars
Source: https://phiki.dev/custom-grammars

Learn how to create and use custom grammars in your projects.

Phiki comes with a set of built-in grammars for popular programming languages, but you can also create and use your own custom grammars. This is particularly useful if you're working with a language that isn't supported out of the box.

To learn more about writing custom TextMate grammars, check out the [Visual Studio Code documentation on syntax highlighting](https://code.visualstudio.com/api/language-extensions/syntax-highlight-guide).

## Local files

If your grammar is stored in a local JSON file, you can load it by passing the slug of the grammar and file path to the `grammar()` method.

```php theme={null}
use Phiki\Phiki;

$phiki = (new Phiki)
    ->grammar('my-language', '/path/to/my-language.json');
```

## Runtime grammars

You can also define grammars at runtime by providing a grammar definition as an associative array to the `Grammar::parse()` method.

```php theme={null}
use Phiki\Phiki;
use Phiki\Grammar\Grammar;

$phiki = (new Phiki)
    ->grammar('my-language', Grammar::parse([
        'name' => 'my-language',
        'scopeName' => 'source.my-language',
        'patterns' => [
            // ...
        ],
        'repository' => [
            // ...
        ]
    ]));
```

## Usage

To use your custom grammar, simply pass the slug you defined when registering the grammar instead of a `Phiki\Grammar\Grammar` enum value.

```php theme={null}
$html = (new Phiki)
    ->grammar('my-language', '/path/to/my-language.json')
    ->codeToHtml('Your code here...', 'my-language', Theme::GithubLight)
    ->toString();
```

## Aliasing

If you wish to register custom aliases for a grammar that has already been registered, you can do so by calling the `Phiki::alias()` method.

```php theme={null}
(new Phiki)
    ->alias('my-php', Grammar::Php)
    ->codeToHtml('', 'my-php', Theme::GithubLight)
    ->toString();
```

This will allow you to use `my-php` as an alias for the built-in PHP grammar.


# Custom themes
Source: https://phiki.dev/custom-themes

Learn how to create and use custom themes in your projects.

Phiki comes with a set of built-in Visual Studio Code themes, but you can also create and use your own custom theme.

To learn more about writing custom Visual Studio Code themes, check out the [Visual Studio Code documentation on theming](https://code.visualstudio.com/docs/configure/themes#_create-your-own-color-theme).

## Local files

If your theme is stored in a local JSON file, you can load it by passing the slug of the theme and file path to the `theme()` method.

```php theme={null}
use Phiki\Phiki;

$phiki = (new Phiki)
    ->theme('my-theme', '/path/to/my-theme.json');
```

## Runtime themes

You can also define themes at runtime by providing a theme definition as an associative array to the `Theme::parse()` method.

```php theme={null}
use Phiki\Phiki;
use Phiki\Theme\Theme;

$phiki = (new Phiki)
    ->theme('my-theme', Theme::parse([
        'name' => 'my-theme',
        'colors' => [
            // ...
        ],
        'tokenColors' => [
            // ...
        ]
    ]));
```

## Usage

To use your custom theme, simply pass the slug you defined when registering the theme instead of a `Phiki\Theme\Theme` enum value.

```php theme={null}
$html = (new Phiki)
    ->theme('my-theme', '/path/to/my-theme.json')
    ->codeToHtml('Your code here...', Grammar::Php, 'my-theme')
    ->toString();
```


# Decorations
Source: https://phiki.dev/decorations



Decorations allow you to apply custom classes to specific elements in the generated HTML. This is useful if you want to style certain regions of your code blocks differently, such as focusing attention on specific lines or adding custom colors.

## Pre decorations

To add additional classes to the `
` element that wraps the entire code block, you can pass a `PreDecoration` instance to the `PendingHtmlOutput::decoration()` method.

```php theme={null}
use Phiki\Transformers\Decorations\PreDecoration;

$output = (new Phiki)
    ->codeToHtml('decoration(
        PreDecoration::make()->class('pre-class'),
    );
```

This will add the `pre-class` class to the `
` element.

## Code decorations

To add additional classes to the `` element that wraps the entire code block, you can pass a `CodeDecoration` instance to the `PendingHtmlOutput::decoration()` method.

```php theme={null}
use Phiki\Transformers\Decorations\CodeDecoration;

$output = (new Phiki)
    ->codeToHtml('decoration(
        CodeDecoration::make()->class('code-class'),
    );
```

## Line decorations

To add additional classes to line elements, you can pass a `LineDecoration` instance to the `PendingHtmlOutput::decoration()` method.

```php theme={null}
use Phiki\Transformers\Decorations\LineDecoration;

$output = (new Phiki)
    ->codeToHtml('decoration(
        LineDecoration::forLine(0)->class('focus'),
    );
```

This will add the `focus` class to the first line of the code block, since lines are zero-indexed.

## Gutter decorations

To add additional classes to the gutter element that contains line numbers, you can pass a `GutterDecoration` instance to the `PendingHtmlOutput::decoration()` method.

```php theme={null}
use Phiki\Transformers\Decorations\GutterDecoration;

$output = (new Phiki)
    ->codeToHtml('withGutter()
    ->decoration(
        GutterDecoration::make()->class('gutter-class'),
    );
```

This will add the `gutter-class` class to the gutter element.

## Substring decorations

At the time of writing, you can only decorate entire lines.

There are plans to support substring decorations in a future release, which will allow you to apply classes to specific parts of a line. This is quite an involved feature so it may take some time to implement.


# Highlighting code
Source: https://phiki.dev/highlighting-code

Learn how to highlight code snippets with Phiki.

To generate syntax highlighted code snippets with Phiki, you can use the `Phiki::codeToHtml()` method.

```php lines theme={null}
use Phiki\Phiki;
use Phiki\Grammar\Grammar;
use Phiki\Theme\Theme;

$html = (new Phiki)
    ->codeToHtml("toString();
```

This method takes three parameters:

1. The code you want to highlight as a `string`.
2. The grammar (or language) of the code.
3. The theme you want to use for highlighting.

Phiki ships with several grammars and themes out of the box. You can find the full list of available grammars and themes in the [Available grammars and themes](/available-grammars-and-themes) reference page.

## Styling

Phiki applies all of its styling using inline `style` attributes, so there's no need to add any CSS to your project to get started.

However, you may want to add some basic styles to the `
` element that Phiki generates to improve the overall appearance of code blocks. Here is a sample CSS snippet you can use:

```css theme={null}
pre {
    font-family: ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace;
    font-size: 0.875rem; /* 14px */
    padding: 1rem 1.5rem; /* 16px 24px */
    border-radius: 0.375rem; /* 6px */
    overflow-x: auto;
}
```

## Gutter

By default, Phiki does not include a gutter (line numbers) in the generated HTML. However, you can enable it by calling the `withGutter()` method on the result of `codeToHtml()`.

```php theme={null}
use Phiki\Phiki;
use Phiki\Grammar\Grammar;
use Phiki\Theme\Theme;

$html = (new Phiki)
    ->codeToHtml("withGutter()
    ->toString();
```

This will add a gutter to the left side of the code block with line numbers for each line of code.

The line number elements use the `editorLineNumber.foreground` styles provided by your chosen theme, but you can override these styles using CSS.

```css theme={null}
.line-number {
    /* Your custom styles go here. */
}
```

### Changing the starting line number

If you wish to change the starting line number from the default of `1`, you can use the `startingLine()` method.

```php theme={null}
use Phiki\Phiki;
use Phiki\Grammar\Grammar;
use Phiki\Theme\Theme;

$html = (new Phiki)
    ->codeToHtml("withGutter()
    ->startingLine(5)
    ->toString();
```

The first line of code will now be numbered `5`, the second line `6`, and so on.


# Installation
Source: https://phiki.dev/installation

Learn how to install Phiki inside of your PHP project.

To install Phiki, you need to have [Composer](https://getcomposer.org/) installed on your system.

Run the following command from the root of your project:

```sh theme={null}
composer require phiki/phiki:^2.0
```

This will install the latest stable version of Phiki and add it to your `composer.json` file.


# Laravel
Source: https://phiki.dev/laravel

Learn how to use Phiki in a Laravel application.

If you have installed Phiki inside of a Laravel application, there are a couple of additional ways you can use it.

## Facade

If you're manually highlighting code with Phiki, you can replace the usage of `Phiki\Phiki` with a facade.

```php theme={null}
use Phiki\Adapters\Laravel\Facades\Phiki;

$html = Phiki::codeToHtml("toString();
```

### Registering custom extensions

If you wish to register a custom extension, you can do so in the `boot` method of a service provider.

```php theme={null}
use Phiki\Adapters\Laravel\Facades\Phiki;
use App\Phiki\MyCustomExtension;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Phiki::extend(new MyCustomExtension);
    }
}
```

### Registering custom grammars and themes

If you wish to register a custom grammar or theme in a Laravel application, you can do so in the `boot` method of a service provider.

```php theme={null}
use Phiki\Adapters\Laravel\Facades\Phiki;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Phiki::grammar('my-grammar', __DIR__ . '/path/to/grammar.json');
        Phiki::theme('my-theme', __DIR__ . '/path/to/theme.json');
    }
}
```

### Caching

Phiki automatically enables caching when used in a Laravel application. It uses your application's default cache store (`CACHE_STORE`) to cache highlighted code blocks.

If you wish to customize the cache store used by Phiki, you can do so in the `boot` method of a service provider.

```php theme={null}
use Phiki\Adapters\Laravel\Facades\Phiki;
use Illuminate\Support\Facades\Cache;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Phiki::cache(Cache::store('redis'));
    }
}
```

#### Cache invalidation

Phiki's cache key is based on the content of the code block, the grammar, the themes chosen, the gutter setting, and any transformers used.

If any of these change, Phiki will automatically generate a new cache key and re-highlight the code block.

If you need to manually clear Phiki's cache, you can do so by calling the `php artisan cache:clear` command, which will clear the entire cache for your application.

```sh theme={null}
php artisan cache:clear
```

## `Str::markdown()`

If you're using the `Str::markdown()` helper method, you can use Phiki's [CommonMark](/commonmark) extension to highlight code blocks inside of your Markdown.

```php theme={null}
use Illuminate\Support\Str;
use Phiki\Adapters\CommonMark\PhikiExtension;
use Phiki\Phiki;
use Phiki\Theme\Theme;

Str::markdown($markdown, extensions: [
    new PhikiExtension(Theme::GithubLight, resolve(Phiki::class)),
]);
```

### Enabling the gutter

As per the documentation on Phiki's [gutter](/highlighting-code), you can enable the gutter by enabling it in the `PhikiExtension` constructor.

```php theme={null}
use Illuminate\Support\Str;
use Phiki\Adapters\CommonMark\PhikiExtension;
use Phiki\Theme\Theme;
use Phiki\Phiki;

Str::markdown($markdown, extensions: [
    new PhikiExtension(Theme::GithubLight, resolve(Phiki::class), withGutter: true),
]);
```

### Using multiple themes

As per the documentation on [Multiple themes](/multiple-themes), you can also pass in an array of themes to the `PhikiExtension` constructor.

```php theme={null}
use Illuminate\Support\Str;
use Phiki\Adapters\CommonMark\PhikiExtension;
use Phiki\Phiki;
use Phiki\Theme\Theme;

Str::markdown($markdown, extensions: [
    new PhikiExtension([
        'light' => Theme::GithubLight,
        'dark' => Theme::GithubDark,
    ], resolve(Phiki::class)),
]);
```

### Using customizations

If you have registered custom extensions, grammars, or theme using the `Phiki` facade as shown above, you can use them inside of your Markdown by resolving the `Phiki\Phiki` singleton from Laravel's service container and passing it to the `PhikiExtension` constructor.

```php theme={null}
use Illuminate\Support\Str;
use Phiki\Adapters\CommonMark\PhikiExtension;
use Phiki\Theme\Theme;
use Phiki\Phiki;

Str::markdown($markdown, extensions: [
    new PhikiExtension(Theme::GithubLight, resolve(Phiki::class)),
]);
```

## Blade component

If you want to highlight code inside of a Blade view, Phiki provides a Blade component that you can use.

```blade theme={null}

echo "Hello, world!";

```

This will highlight the code block using the `Grammar::Php` grammar and the `Theme::GithubLight` theme.

### Enabling the gutter

To enable the gutter, add the `gutter` attribute to the component.

```blade theme={null}

echo "Hello, world!";

```

### Changing the starting line number

To change the starting line number, add the `starting-line` attribute to the component.

```blade theme={null}

echo "Hello, world!";

```

### Passing code as an attribute

Since Laravel trims whitespace from the slot of a Blade component, you can also pass the code to the component using the `code` attribute.

```blade theme={null}

```

This is especially useful if you want to highlight code that is stored in a variable or preserve trailing and leading whitespace.


# Multiple themes
Source: https://phiki.dev/multi-themes

Learn how to highlight code blocks with multiple themes.

The majority of modern websites support both light and dark themes. To ensure that your code blocks look great under both circumstances, Phiki allows you to specify multiple themes when highlighting code.

To do this, you can pass an array of theme names to the `Phiki::codeToHtml()` method.

```php lines theme={null}
use Phiki\Phiki;
use Phiki\Grammar\Grammar;
use Phiki\Theme\Theme;

$html = (new Phiki)
    ->codeToHtml(" Theme::GithubLight,
        'dark' => Theme::GithubDark,
    ])
    ->toString();
```

Phiki will use the first theme in the array as the default theme, and will add a set of CSS variables for each additional theme.

The CSS variables are named using the format `--phiki-{key}-{property}`, where `{key}` is the key you specified in the themes array (e.g. `dark`), and `{property}` is the name of the CSS property (e.g. `background-color`, `color`, etc.).

### Query-based dark mode

To apply the dark theme based on the user's system preferences, you can use the following CSS:

```css theme={null}
@media (prefers-color-scheme: dark) {
    .phiki,
    .phiki span {
        color: var(--phiki-dark-color) !important;
        background-color: var(--phiki-dark-background-color) !important;
        font-style: var(--phiki-dark-font-style) !important;
        font-weight: var(--phiki-dark-font-weight) !important;
        text-decoration: var(--phiki-dark-text-decoration) !important;
    }
}
```

### Class-based dark mode

If you're using a class-based approach to toggle between light and dark mode, you can use the following CSS:

```css theme={null}
html.dark .phiki,
html.dark .phiki span {
    color: var(--phiki-dark-color) !important;
    background-color: var(--phiki-dark-background-color) !important;
    font-style: var(--phiki-dark-font-style) !important;
    font-weight: var(--phiki-dark-font-weight) !important;
    text-decoration: var(--phiki-dark-text-decoration) !important;
}
```

## Beyond light and dark

The examples above are based on light and dark themes, but you're not limited to just those two.

You can use any keys you like in the themes array and Phiki will generate the appropriate CSS variables for each theme. You can then use your own CSS to apply the themes when necessary.


# Overview
Source: https://phiki.dev/overview



Phiki is a PHP package for syntax highlighting code using TextMate grammar files and Visual Studio Code themes. It is designed to be a replacement for other syntax highlighters such as [Shiki](https://shiki.style/) and [Highlight.php](https://github.com/scrivo/highlight.php).

It has zero third-party dependencies, making it easy to integrate into any PHP project.

## How it works

Phiki uses TextMate grammar files to tokenize your code and then highlights them using Visual Studio Code themes. This allows for a high degree of highlighting accuracy and makes your code look like it was highlighted in your favourite code editor.


  
    Phiki starts by tokenizing your code using a TextMate grammar file.

    This breaks your code into smaller pieces of text with detailed "scope" information.

    A **scope** is a dot-separated string that describes the type of text. For example, in PHP, a variable might have the scope `variable.other.php`.
  

  
    Once Phiki has tokenized your code it starts to highlight the tokens using the Visual Studio Code theme of your choice.

    The scopes from each token are used to match against a ruleset in the theme file. This ruleset defines the background color, foreground color, and font style for the token.

    The tokens are transformed into a special `HighlightedToken` object that contains the raw token and the "settings" / style information.
  

  
    After producing a set of highlighted tokens, Phiki then creates an AST-like structure to represent the desired HTML output.

    This intermediate structure allows for easier manipulation of the final output without requiring complex string operations.
  

  
    If required, Phiki can then transform the intermediate structure. This is typically where extensions will hook into the process to modify the AST and add additional features such as line highlighting, class names, etc.
  

  
    Finally, Phiki takes the final AST and "stringifies" it into HTML.

    This HTML can then be outputted directly to the browser, inside of a template file, or saved to disk.
  


## Why it exists

As a former user of Shiki and Highlight.php, I found both packages to be lacking in certain areas.

Highlight.php was moderately performant, but the quality of the highlighting was poor. It was a port of the popular [highlight.js](https://highlightjs.org/) library, which also suffers from the same issues.

Shiki, on the other hand, produced good looking output, but was slow to run from a PHP application as it required spawning a Node.js process to do the actual highlighting. This made it impractical to use in live-rendered applications.

Phiki aims to solve these issues by providing a pure PHP implementation of both a TextMate tokenizer and Visual Studio Code highlighter. This allows for high-quality highlighting without the need for any third-party dependencies or services.

On top of this, I'm a curious software developer who enjoys building things and pushing the limits of what is possible with PHP.


# 3-step intro
Source: https://phiki.dev/quick-start-guide

A quick guide to get you started with Phiki.


  
    ```sh theme={null}
    composer require phiki/phiki:^2.0
    ```
  

  
    ```php lines theme={null}
    use Phiki\Phiki;

    $phiki = new Phiki();
    ```
  

  
    ```php lines theme={null}
    use Phiki\Grammar\Grammar;
    use Phiki\Theme\Theme;

    $code = file_get_contents('path/to/your/code.php');
    $highlighted = $phiki->codeToHtml($code, Grammar::Php, Theme::GithubLight);

    echo $highlighted;
    ```
  



# Statamic
Source: https://phiki.dev/statamic

Learn how to use Phiki in a Statamic application.

If you have installed Phiki inside of a Statamic application, then you can use the CommonMark extension to highlight code blocks in your Markdown content.

You can enable the extension by registering it with Statamic's Markdown class inside the `boot` method of a service provider.

```php theme={null}
use Statamic\Facades\Markdown;
use Phiki\Adapters\CommonMark\PhikiExtension;
use Phiki\Theme\Theme;
use Phiki\Phiki;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Markdown::addExtension(fn () => new PhikiExtension(Theme::GithubLight, resolve(Phiki::class)));
    }
}
```

For more information on using the `PhikiExtension`, see the [CommonMark](/commonmark) documentation.

If you wish to customize Phiki further, you can also refer to the [Laravel](/laravel) documentation since Statamic is built on top of Laravel.


# TextMate Grammars
Source: https://phiki.dev/textmate-grammars




  This will be the go-to resource for writing TextMate grammars at some point in the future. Until then, please refer to the [official TextMate documentation](https://macromates.com/manual/en/language_grammars) and [Visual Studio Code syntax highlighting guide](https://code.visualstudio.com/docs/configure/themes#_create-your-own-color-theme).



# Overview
Source: https://phiki.dev/transformers



Phiki allows you to modify data at various stages in the syntax highlighting process.

We refer to these as "transformers" and they can be used to modify the input code, individual tokens, the HTML AST and the final HTML output and the return values from each "hook" are passed to the next.

All transformers must implement the `Phiki\Contracts\TransformerInterface` interface.


  If you only need to modify data at a specific stage, you can extend the `Phiki\Transformers\AbstractTransformer` class instead and override the methods you need.


## Using transformers

To use a transformer, provide an instance of one to the `PendingHtmlOutput::transformer()` method when highlighting code.

```php theme={null}
use Phiki\Phiki;
use Phiki\Theme\Theme;
use Phiki\Transformers\AbstractTransformer;

class MyTransformer extends AbstractTransformer
{
    // Implement the methods you need here...
}

$html = (new Phiki)
    ->codeToHtml("transformer(new MyTransformer)
    ->toString();
```


  Transformers are applied in the order they are added. If you add mutliple transformers, the output from one will be passed to the next.

  Be careful when modifying the HTML AST, especially if you are adding or removing elements, as this can break the structure expected by later transformers.


## Available hooks

| Method        | Description                                                                                     |
| ------------- | ----------------------------------------------------------------------------------------------- |
| `preprocess`  | Modify the input code before it is tokenized.                                                   |
| `tokens`      | Modify the array of tokens after tokenization but before highlighting.                          |
| `highlighted` | Modify the array of highlighted tokens after highlighting but before structuring.               |
| `root`        | Modify the root node of the HTML AST, usually contains a single `
` element.                |
| `pre`         | Modify the `
` element in the HTML AST, usually contains a single `` element.         |
| `code`        | Modify the `` element in the HTML AST, usually contains 1 `` element for each line. |
| `line`        | Modify each line element in the HTML AST, usually a `` element.                           |
| `gutter`      | Modify the gutter element in the HTML AST, usually a `` element.                          |
| `token`       | Modify each token element in the HTML AST, usually a `` element.                          |
| `postprocess` | Modify the final HTML output before it is returned as a string.                                 |


# Upgrading from 1.x to 2.0
Source: https://phiki.dev/upgrade-2.0



Phiki 2.0 introduces several breaking changes from the 1.x series. This guide will help you upgrade your code to be compatible with the new version.

To upgrade from Phiki 1.x to 2.0, run the following command:

```sh theme={null}
composer require phiki/phiki:^2.0
```

The likelihood of encountering issues during the upgrade process depends on how extensively you were using or relying on certain features of Phiki.

Please consult the sections below to understand the changes and how they might affect your code before opening an issue on the repository.


  For information about new features and improvements in Phiki 2.0, please refer to the rest of the documentation.


## High impact changes

### `Phiki::codeToHtml()` signature changed

This method now returns an instance of `Phiki\Output\Html\PendingHtmlOutput` instead of a raw string. This new object allows for more flexibility and lazy rendering of the final HTML output.

If you need to get the HTML string immediately, you can call the `toString()` and `__toString()` methods or cast it to a `(string)`.

To improve the usability of this method, the following parameters have been removed:

* `withGutter` – replaced with a `withGutter()` method on the returned object.
* `withWrapper` – if you were using this, see the "Medium impact changes" section below for more information.

### Terminal support removed

The terminal output feature has been removed due to low usage and maintenance overhead.

There is currently no alternative for this feature, but it may be reintroduced in a future separate package.

### Namespace changes

* The `Phiki\Environment\Environment` class is now `Phiki\Environment`.
* The `Phiki\CommonMark\PhikiExtension` class is now `Phiki\Adapters\CommonMark\PhikiExtension`.

### Custom environment support removed

The ability to pass a custom `Phiki\Environment` instance to the `Phiki` constructor has been removed.

This was a rarely used feature that added unnecessary complexity to the codebase.

### Changes to extension registration

Since the custom environment support has been removed, the method to register extensions has been moved to the `Phiki` class.

If you need to register an extension, you can use the `Phiki::extend()` method:

```php theme={null}
$phiki = (new Phiki)
    ->extend(new MyCustomExtension());
```

### Changes to custom grammar and theme registration

Since the custom environment support has been removed, the methods to register custom grammars and themes have been moved to the `Phiki` class.

If you need to register a custom grammar, you can use the `Phiki::grammar()` method:

```php theme={null}
$phiki = (new Phiki)
    ->grammar('my-custom-grammar', '/path/to/grammar.json');
```

Similarly, to register a custom theme, you can use the `Phiki::theme()` method:

```php theme={null}
$phiki = (new Phiki)
    ->theme('my-custom-theme', '/path/to/theme.json');
```

## Medium impact changes

### API for accessing repositories changed

If you were previously using the `getGrammarRepository()` or `getThemeRepository()` methods on the `Phiki\Environment\Environment` class, you can now access these repositories directly from the `Phiki::$environment` property.

```php theme={null}
$phiki = new Phiki();

$phiki->environment->grammars->...;
$phiki->environment->themes->...;
```

These properties are `readonly`, so you cannot replace them, but you can still interact with them as you did before.

### `HtmlGenerator` class removed

The `Phiki\Generators\HtmlGenerator` class has been removed. Its functionality has been integrated into the `Phiki\Output\Html\PendingHtmlOutput` class returned by `Phiki::codeToHtml()`.

### Automatic language detection removed

This feature has been removed due to its unreliability and the complexity it adds to the codebase.

Phiki only supported two languages (`php` and `js`) for automatic detection which was not enough to be useful.

It's now recommended that you always specify the language when using `Phiki::codeToHtml()` or the Phiki CommonMark extension.

### `withWrapper` option removed

If you are passing `withWrapper: true` to `Phiki::codeToHtml()` or the Phiki CommonMark extension, this feature has now been removed.

It was originally added to support a feature on my personal site but was never officially documented. Since there are alternative methods to achieve the same result, it has been removed to simplify the codebase.

## Low impact changes

### Tokenizer rewrite

The `Tokenizer` class has been completely rewritten to improve performance and accuracy.

It now uses PHP's `mbstring` extension since that uses Oniguruma under the hood, which is the same RegEx engine behind Shiki and `vscode-textmate`.

This will only affect you if you were extending the `Tokenizer` class since the underlying methods and properties have changed to accommodate the new implementation.

### Highlighter rewrite

The `Highlighter` class has also been rewritten to improve accuracy.

The previous implementation uses a very naive approach to applying styles to scoped tokens which resulted in "scope selectors" not being applied correctly.

This has now been resolved in the new implementation at the cost of some performance.

### Namespace changes

* `Phiki\Tokenizer` is now `Phiki\TextMate\Tokenizer`
* `Phiki\Highlighter` is now `Phiki\Highlighting\Highlighter`


# Websites using Phiki
Source: https://phiki.dev/websites-using-phiki



Phiki has been out there in the wild for quite some time now and there are plenty of websites already using it.

* [ryangjchandler.co.uk](https://ryangjchandler.co.uk) uses Phiki to syntax highlight code snippets in blog posts.
* [Mailviews](https://mailviews.com?ref=phiki.dev) uses Phiki for code snippets inside of their component library.
* [Prezet](https://prezet.com/features/syntax-highlighting) uses Phiki to syntax highlight their documentation and code snippets in userland applications using the package.