hylite
A CLI for syntax highlighting code to HTML (...using
highlight.js under the hood).
See this blog post for an introduction about what this is:
www.peterbe.com/plog/introducing-hylite
To run
Not installed
bunx hylite --help
Or, if you don't have bun
installed, with npx
:
npx hylite --help
Installed
First install:
npm install hylite
You can either execute it directly:
./node_modules/.bin/hylite --help
Or if you have your PATH
set, like this:
export PATH="node_modules/.bin:$PATH"
...you'll be able to just type:
hylite --help
Usage
There are many way to execute the CLI. :
- By
stdin
- By giving the name of the file
- By a snippet of code
Only when you use a file name/path can it make a good guess of the language.
Otherwise, you'll have to lass the --language
(or -l
) flag.
By stdin
hylite -l py < mycode.py
🎵 This is the same as cat mycode.py | hyite -l py
By giving the name of the file
hylite myapp.jsx
By a snippet of code
hylite -l go 'var s string = Acetaminophen.String()'
The HTML it produces can be put into a web page, but you probably want
to wrap it in:
<pre>
<code class="hljs">
{SNIPPET CODE HERE}
</code>
</pre>
HTML wrap
hylite
can take care of that for you with --wrapped
(or -w
). For example:
❯ hylite -l go -w 'var s string = Acetaminophen.String()'
<pre><code class="hljs"><span class="hljs-keyword">var</span> s <span class="hljs-type">string</span> = Acetaminophen.String()</code></pre>
CSS
In its simplest form, to generate the CSS, use:
hylite -c
(or just hylite --css
)
That will use highlight.js
's default.css
stylesheet. To see what other
themes are available, run:
hylite --list-css
Now, suppose you want tokyo-night-dark
, go back and run:
hylite --css tokyo-night-dark
If you want to support both light and dark mode in your application, you
have to pick a theme that has both dark and light versions
(see hylite --list-css
). For example:
hylite --css tokyo-night-dark
hylite --css tokyo-night-light
Copy each one into this CSS template:
@media only screen and (prefers-color-scheme: dark) {
}
Preview server
If you want to see what all the different styles look like, you need to
use bun
. Example:
❯ hylite -p health.json
Now open http://localhost:3000
It will display your health.json
file but at the top of the page you
can click and select the different possible themes.
To develop
You must use Bun to test locally. The most basic form
is using bun run src/index.ts
.
First install
If you have cloned the repo, you just need to run:
bun install
...to install the dependencies.
To run:
bun run src/index.ts --help
Tests
bun test [--watch]
But note that the GitHub Actions workflows do more things with the build
artifact dist/index.js
. To generate the dist/index.js
, use:
bun run build
The Node end-to-end test suite uses this dist/index.js
execlusively.
At the moment (Sept 2023), with bun
1.0.2, it appears that generating
the dist/index.js
is potentially different depending on the platform.
To release
Run:
bun run release
This will execute bun run build
and if that dist/index.js
becomes
different, the release process is halted.
Caveats and goals
Standalone executable
I hope some day to use bun build
to compile a standalone executable
that is portable to any OS. Then this CLI can be shipped in the likes
of Debian sources or Homebrew. At the moment, the build artifact works
but only on macOS (where I'm testing this):
❯ bun build --compile --outfile hylite-executable src/index.ts
[24ms] bundle 205 modules
[222ms] compile hylite-executable
...
❯ ls -lh hylite-executable
-rwxrwxrwx 1 peterbe staff 55M Sep 24 14:47 hylite-executable
❯ ./hylite-executable /tmp/throwaway/health.json
<span class="hljs-punctuation">{</span><span class="hljs-attr">"ok"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"error"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">null</span></span><span class="hljs-punctuation">}</span>
API
At the moment, hylite
only exists as a CLI. If you want to execute it
as an install dependency API, this is currently not supported. Technically,
hylite
is a client of highlight.js
.
But let's chat if you can think this would be useful. All we need to
do is rearrange the code in src/index.ts
a bit so that its core is
plucked out into its own ESM exported function. The src/index.ts
could be just the CLI part.
Guessing the syntax
When you run hylite myfile.rb
it can deduce the Ruby language from the
file extension. But if you use cat myfile.rb | hylite
it can't know the
language so you have to use cat myfile.rb | hylite -l rb
.
But highlight.js
has a decent API for guessing called hljs.highlightAuto
which could be used. Let me know if you want to help out add this
functionality.
Benchmarking
You need Bun to hack on this project, but once the built artifact
is ready (dist/index.js
) you can use either node
or bun run
to
execute it. This is how and why you can interchange using npx
or bunx
from outside the repo. At this point, the strengths of bun
are less
advantageous because it's now mostly a matter of starting up.
Using hyperfine
to compare:
❯ hyperfine 'node dist/index.js src/index.ts' 'bun run dist/index.js src/index.ts'
Benchmark 1: node dist/index.js src/index.ts
Time (mean ± σ): 173.5 ms ± 21.1 ms [User: 152.2 ms, System: 20.6 ms]
Range (min … max): 155.8 ms … 227.3 ms 17 runs
Benchmark 2: bun run dist/index.js src/index.ts
Time (mean ± σ): 167.0 ms ± 2.9 ms [User: 180.8 ms, System: 31.8 ms]
Range (min … max): 161.8 ms … 173.5 ms 17 runs
Summary
bun run dist/index.js src/index.ts ran
1.04 ± 0.13 times faster than node dist/index.js src/index.ts
In conclusion; no speed difference.
If you run npx
or bunx
, the first time both of them would depend on
network to download the code to the global cache. But if you run them
at least once and compare, again with hyperfine
:
❯ hyperfine 'npx hylite huey_health.json' 'bunx hylite huey_health.json'
Benchmark 1: npx hylite huey_health.json
Time (mean ± σ): 1.184 s ± 0.107 s [User: 1.093 s, System: 0.272 s]
Range (min … max): 1.102 s … 1.452 s 10 runs
Benchmark 2: bunx hylite huey_health.json
Time (mean ± σ): 159.9 ms ± 3.6 ms [User: 145.7 ms, System: 30.4 ms]
Range (min … max): 154.8 ms … 168.1 ms 17 runs
Summary
bunx hylite huey_health.json ran
7.40 ± 0.69 times faster than npx hylite huey_health.json
In conclusion; **bunx
is 7 times faster than npx
.