sugarcraft / sugar-glow
PHP port of charmbracelet/glow — Markdown CLI viewer / pager composing CandyShine + Viewport. 8 stock themes, word-wrap, OSC 8 hyperlinks.
Requires
- php: ^8.3
- sugarcraft/candy-core: dev-master
- sugarcraft/candy-shine: dev-master
- sugarcraft/sugar-bits: dev-master
- symfony/console: ^6.4 || ^7.0
Requires (Dev)
- phpunit/phpunit: ^10.5
- sugarcraft/candy-testing: dev-master
This package is auto-updated.
Last update: 2026-07-10 03:50:55 UTC
README
SugarGlow
PHP port of charmbracelet/glow — a Markdown CLI viewer that composes CandyShine (rendering) and SugarBits Viewport (scrolling).
composer require sugarcraft/sugar-glow
CLI
sugarglow README.md # render to stdout (default) sugarglow -p README.md # open in a fullscreen pager git log -1 --pretty=%B | sugarglow -p # pipe stdin sugarglow --theme dracula README.md sugarglow --width 80 --no-hyperlinks README.md sugarglow --theme-config ./my-theme.json README.md
Flags:
--theme {ansi|plain|dark|light|notty|dracula|tokyo-night|pink|solarized|monokai|github}— picks a CandyShine preset.solarized,monokai, andgithubload JSON theme files fromthemes/.--style/-s— alias for--theme(glamour-compat).--theme-config <path>— load a custom JSON theme viaTheme::fromJson. Overrides--theme.--width/-w <N>— word-wrap paragraphs / blockquotes / list bodies. 0 = no wrap.--no-hyperlinks— disable OSC 8 link envelopes; render links astext (url)instead.--pager/-p— open in a fullscreen pager.
Pager keys
Standard reader keys come from Viewport:
| Key | Action |
|---|---|
↑ / k |
line up |
↓ / j |
line down |
PgUp / b |
page up |
PgDn / space / f |
page down |
Ctrl+U / Ctrl+D |
half page |
Home / g |
top |
End / G |
bottom |
q / Esc / Ctrl+C |
exit |
Demos
Render to stdout
Fullscreen pager
Library API
Beyond the CLI, sugar-glow exposes three utility classes for integrating its behaviour into other PHP projects.
GlamourTheme
Loads and parses Glamour-style theme JSON files (block_prefix/suffix, indent_token, margin, chroma token mapping).
use SugarCraft\Glow\GlamourTheme; // From a JSON string $theme = GlamourTheme::fromJson(file_get_contents('./my-theme.json')); // From a file path $theme = GlamourTheme::fromFile('./my-theme.json'); // Resolve a chroma token to an SGR color code (e.g., "31" for red) $sgr = $theme->resolve('emphasis'); // => "31" or null
FileWatcher
File watching via mtime polling — works cross-platform with no extensions.
use SugarCraft\Glow\FileWatcher; $watcher = new FileWatcher('/path/to/file.md'); // Check if modified since a given mtime if ($watcher->hasChangedSince($lastMtime)) { // re-render } // Generator-based watch loop (e.g., in a ReactPHP stream) foreach (FileWatcher::watch('/path/to/file.md', 500) as $changed) { // $changed === true each time the file is modified }
Width helpers
CJK and emoji width handling lives in SugarCraft\Core\Util\Width. Use it
directly for visual truncation, padding, and ANSI-aware measurement:
use SugarCraft\Core\Util\Width; Width::string('hello'); // 5 Width::string('你好'); // 4 (full-width) Width::string('📦'); // 2 (emoji) Width::padRight('hi', 8); // "hi " Width::truncate('hello world', 8); // "hello wo"
Shared foundations
sugar-glow uses candy-palette for terminal capability probing. The
RenderCommand::terminalSupportsColor() wrapper calls
\SugarCraft\Palette\Probe\TerminalProbe::run() and falls back to
true (assume color) if the probe throws — ensuring graceful degradation
on Windows, over SSH, and in old terminals.
Snapshot tests
Render output is covered by golden-file snapshot tests. Fixture files live
in tests/fixtures/ with a .golden extension and are compared against
actual ANSI byte output via SugarCraft\Testing\Snapshot\Assertions::assertGoldenAnsi().
To re-record fixtures after intentional output changes:
UPDATE_GOLDENS=1 vendor/bin/phpunit
Test
cd sugar-glow && composer install && vendor/bin/phpunit

