{"id":17968549,"url":"https://github.com/kadet1090/keylighter","last_synced_at":"2025-03-25T10:32:20.561Z","repository":{"id":42909462,"uuid":"41606269","full_name":"kadet1090/KeyLighter","owner":"kadet1090","description":"Yet another syntax highlighter for PHP","archived":false,"fork":false,"pushed_at":"2024-04-08T15:33:16.000Z","size":1220,"stargazers_count":33,"open_issues_count":9,"forks_count":2,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-19T06:18:26.922Z","etag":null,"topics":["highlighter","php","php-library","syntax-highlighting"],"latest_commit_sha":null,"homepage":"https://keylighter.kadet.net","language":"PHP","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/kadet1090.png","metadata":{"files":{"readme":"README.md","changelog":"changelog.md","contributing":"CONTRIBUTING.md","funding":null,"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}},"created_at":"2015-08-29T20:22:53.000Z","updated_at":"2024-12-05T13:09:30.000Z","dependencies_parsed_at":"2024-02-03T19:29:57.551Z","dependency_job_id":"54c92ea6-fa40-4600-82fa-935d4a9c1c94","html_url":"https://github.com/kadet1090/KeyLighter","commit_stats":{"total_commits":401,"total_committers":4,"mean_commits":100.25,"dds":"0.11221945137157108","last_synced_commit":"0f9d68e69609db0321d44e9b8a5b96b0b4fd2041"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kadet1090%2FKeyLighter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kadet1090%2FKeyLighter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kadet1090%2FKeyLighter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kadet1090%2FKeyLighter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kadet1090","download_url":"https://codeload.github.com/kadet1090/KeyLighter/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245444264,"owners_count":20616347,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["highlighter","php","php-library","syntax-highlighting"],"created_at":"2024-10-29T14:40:41.370Z","updated_at":"2025-03-25T10:32:19.109Z","avatar_url":"https://github.com/kadet1090.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Logo](https://raw.githubusercontent.com/kadet1090/KeyLighter/master/Docs/assets/logo.png)\n\n[![Packagist](https://img.shields.io/packagist/v/kadet/keylighter.svg?style=flat)](https://packagist.org/packages/kadet/keylighter)\n[![GitHub Actions](https://github.com/kadet1090/keylighter/actions/workflows/tests.yml/badge.svg?event=push)](https://github.com/kadet1090/KeyLighter/actions?query=branch:master)\n[![GitHub Actions](https://github.com/kadet1090/keylighter/actions/workflows/phpstan.yml/badge.svg?event=push)](https://github.com/kadet1090/KeyLighter/actions?query=branch:master)\n[![Try it](https://img.shields.io/badge/www-try%20it-FF9700.svg?style=flat)](https://keylighter.kadet.net)\n\n[![stability: stable](https://img.shields.io/badge/Public%20API-stable-green.svg?style=flat)](Docs/2-basic-usage.md)\n[![stability: unstable](https://img.shields.io/badge/Internal%20API-unstable-yellow.svg?style=flat)](Docs/3-advanced-usage.md)\n\nYet another Syntax Highlighter in PHP meant to be as extensible and easy to use \nas it only can, but with performance in mind.\n\nYou can try it live with the most recent version on https://keylighter.kadet.net/.\n\n## Name\nName \"KeyLighter\" is inspired by Key Light concept in photography and \ncinematography.\n\n\u003e The key light is the first and usually most important light a photographer, \n\u003e cinematographer, lighting cameraman, or other scene composer will use in a \n\u003e lighting setup. The purpose of the key light is to highlight the form and \n\u003e dimension of the subject.\n\nKeyLighter is supposed to do the same thing - for code.\n\n# Installation\n```bash\n$ composer require kadet/keylighter\n```\n\nTo use **KeyLighter** you just need PHP 7.3 or later, no special extensions \nrequired.\n\n## Global installation\nIt's possible to install **KeyLighter** as a global composer library\n```bash\n$ composer global require kadet/keylighter\n```\nThen you can use builtin simple cli highlighting app:\n```bash\n$ keylighter [command = highlight] [-l|--language [LANGUAGE]] [-f|--format [FORMAT]] [-d|--debug [DEBUG]] [--]  \u003cpath\u003e...\n```\nIf you want pipe into **KeyLighter** just specify `php://stdin` as path. You can \nuse `list` command to see all available commands, and `--help` argument for \ndetailed help. You don't have to specify `highlight` command explicitly. \n\n### PowerShell\nYou're using PowerShell on Windows? Cool! **KeyLighter** comes with integrated \nPowerShell module that makes CLI usage even better. Just import module (For \nexample in profile), and you're ready to go.\n\n```powershell\nPS\u003e Import-Module \"${env:APPDATA}\\Composer\\vendor\\kadet\\keylighter\\bin\\KeyLighter.psd1\"\n```\n\nTo use autocompletion features you will need PowerShell v5 (Comes with windows \n10) or install [TabExpansion++](https://github.com/lzybkr/TabExpansionPlusPlus) \nModule.\n\n![Powershell Support](https://i.imgur.com/jH2VRA8.gif)\n\n## Why KeyLighter?\n\n### Simple to use\n```php\nuse Kadet\\Highlighter\\Language;\n\necho \\Kadet\\Highlighter\\highlight($source, new Language\\Php(), $formatter);\n// or\necho \\Kadet\\Highlighter\\KeyLighter::get()-\u003ehighlight($source, new Language\\Php(), $formatter);\n// or\n$keylighter = new \\Kadet\\Highlighter\\KeyLighter([options]);\necho $keylighter-\u003ehighlight($source, new Language\\Php(), $formatter);\n```\n\nYou can find all available languages [here](https://github.com/kadet1090/KeyLighter/tree/master/Language) \nand formatters [here](https://github.com/kadet1090/KeyLighter/tree/master/Formatter).\n\n### It works on CLI! And more!\n**KeyLighter** was originally designed as CLI highlighter for my own usage,\nbut then I decided that it should be able to generate any possible output,\ncurrently supported:\n\n#### Cli `\\Kadet\\Highlighter\\Formatter\\CliFormatter`\n![CLI](https://i.imgur.com/b2bMVrw.png)\n\nIt can even be styled, default styles are stored in `Styles\\Cli\\Default.php`, \nbut you can just pass additional argument into a constructor:\n\n```php\nnew \\Kadet\\Highlighter\\Formatter\\CliFormatter([\n    'string'      =\u003e ['color' =\u003e 'green'],\n    'keyword'     =\u003e ['color' =\u003e 'yellow'],\n    ...\n])\n```\n\n#### HTML `\\Kadet\\Highlighter\\Formatter\\HtmlFormatter`\n![HTML](https://i.imgur.com/BRThsX2.png)\n\nEvery token is placed inside it's own `span` and classes are prefixed so it can \nbe easily styled with css and should not interfere with any of your existing \nclasses\n\n```html\n\u003cspan class=\"kl-variable\"\u003e$maxOption\u003c/span\u003e\n```\n\n```css\npre \u003e span.kl-variable { color: #F7750D; }\n```\n#### Your own?\nIt's easy to write your own formatters. Documentation coming soon.\n\n### Context sensitive\nSome tokens are valid in some contexts, some are not. This library is context \nsensitive, and you can define when they are valid.\n\nIn this case, context mean just \"inside of other token\", for example lets assume \nthat `string` token is defined as everything from \" to the next \" and `keyword` \nis defined as 'sit' substring.\n\n```js\n↓ string:start     ↓ keyword:start\n\"Lorem ipsum dolor sit amtet\"\n         keyword:end ↑      ↑ string:end\n\nToken tree:\n\nToken.name           Token.pos\n------------------------------\nstring:start         0\n    keyword:start    21\n    keyword:end      23\nstring:end           30\n```\n\nSo as you can see `keyword` is inside of `string`, and therefore is not valid \nand should be deleted. You can define tokens valid only in some context, or \ninvalid in other.\n\nOh, and token names cascade, it means that `string.single` is `string`, but \n`string` is necessarily not `string.single`.\n\n### Write your own language definitions easily\nIt's possible to easily extend `KeyLighter` with new languages, more detailed \ndocumentation coming soon.\n\nFor example XML definition looks like this:\n```php\nclass Xml extends GreedyLanguage\n{\n    private const IDENTIFIER = '(?P\u003cnamespace\u003e[\\w\\.-]+:)?(?P\u003cname\u003e[\\w\\.-]+)';\n\n    /**\n     * Tokenization rules\n     */\n    public function setupRules()\n    {\n        $this-\u003erules-\u003eaddMany([\n            'tag.open'  =\u003e [\n                new OpenRule(new RegexMatcher('/(\u003c[\\w\\.-]+)[:\\/\u003e:\\s]/')),\n                new CloseRule(new SubStringMatcher('\u003e'), ['context' =\u003e ['!string', '!comment']])\n            ],\n            'tag.close' =\u003e new Rule(new RegexMatcher('/(\u003c\\/' . self::IDENTIFIER . '\u003e)/')),\n\n            'symbol.tag' =\u003e new Rule(new RegexMatcher('/\u003c\\\\/?' . self::IDENTIFIER . '/', [\n                'name'      =\u003e Token::NAME,\n                'namespace' =\u003e '$.namespace'\n            ]), ['context' =\u003e ['tag', '!string']]),\n\n            'symbol.attribute' =\u003e new Rule(new RegexMatcher('/' . self::IDENTIFIER . '=/', [\n                'name'      =\u003e Token::NAME,\n                'namespace' =\u003e '$.namespace'\n            ]), ['context' =\u003e ['tag', '!string']]),\n\n            'constant.entity' =\u003e new Rule(new RegexMatcher('/(\u0026(?:\\#\\d+|[a-z])+;)/si')),\n\n            'comment' =\u003e new Rule(new CommentMatcher(null, [['\u003c!--', '--\u003e']])),\n            'string'  =\u003e CommonFeatures::strings(['single' =\u003e '\\'', 'double' =\u003e '\"'], ['context' =\u003e ['tag']]),\n        ]);\n    }\n\n    /** {@inheritdoc} */\n    public function getIdentifier()\n    {\n        return 'xml';\n    }\n\n    public static function getMetadata()\n    {\n        return [\n            'name'      =\u003e ['xml'],\n            'mime'      =\u003e ['application/xml', 'text/xml'],\n            'extension' =\u003e ['*.xml']\n        ];\n    }\n}\n```\n\nI will try to write as many definitions as I only can, but any PRs are welcome.\n\n### Embedding languages\nMany languages can be used simultaneously, *css* or *js* inside *html*, *sql* in  \n*php* and so on. **KeyLighter** can handle and highlight embedded languages \nwithout any problem.\n\n![Embedded languages](https://i.imgur.com/gJr6shy.png)\n\n### Fast\nEven though it wasn't supposed to be fastest code highlighter in PHP it is still \nquite fast, more than 2x faster than [GeSHi](https://geshi.org/).\n\n## Testing\n**KeyLighter** uses `phpunit` for testing:\n```bash\n$ ./vendor/bin/phpunit\n```\n\n## Roadmap\nThere are still few things to do, you can find all on [trello](https://trello.com/b/9I4CO0Te/highlighter).\n\n## Contributing\nSee [CONTRIBUTING.md](./CONTRIBUTING.md) for details.\n\n## Thanks\nFor [Maciej](https://github.com/ksiazkowicz), [Maciej](https://github.com/sobak) \nand Monika for all support, moral too.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkadet1090%2Fkeylighter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkadet1090%2Fkeylighter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkadet1090%2Fkeylighter/lists"}