Syntax Highlighters

1
Phiki stands out as the strongest modern candidate for replacing WackoWiki's outdated syntax highlighters. It delivers high-quality, server-side rendering using TextMate grammars and VS Code themes, with zero third-party dependencies.

Current WackoWiki Situation

WackoWiki relies on:
  • Pear Text_Highlighter — outdated and unmaintained.
  • Handcrafted highlighters and the built-in PHP highlighter (limited scope and maintenance).
  • GeSHi plugin — also outdated/unmaintained.
  • Highlight.js as an optional plugin — excellent language coverage but client-side JavaScript rendering (re-renders on each load, adds JS dependency, and less ideal for static/server-rendered output).

This setup creates maintenance burden, inconsistent quality, and suboptimal performance (especially with client-side JS).

Recommended Primary Replacement: Phiki

Phiki (by Ryan Chandler) is a pure-PHP syntax highlighter inspired by Shiki. It uses TextMate grammar files for accurate tokenization and VS Code themes for styling.
Key strengths:
  • High-quality highlighting — Matches VS Code/editor accuracy for many languages.
  • Server-side only — Generates static HTML once (no repeated client-side work).
  • Fast and lightweight — Pure PHP, no Node.js or heavy deps.
  • Themes — Supports popular VS Code themes (e.g., GitHub Light/Dark).
  • Extensible — Transformers for custom features (line numbers, highlighting, etc.).
  • Actively maintained — Recent releases (v2.x as of 2026), good documentation at phiki.dev.

Basic usage (Composer install: composer require phiki/phiki:^2.0):
PHP
use Phiki\Phiki;
use Phiki\Grammar\Grammar;
use Phiki\Theme\Theme;

$phiki = new Phiki();
$code = 'your code here...';

$highlighted = $phiki->codeToHtml($code, Grammar::Php, Theme::GithubLight);
echo $highlighted;  // Ready-to-use HTML

It also supports terminal output and various grammars/themes.
Integration into WackoWiki:
  • Create a new formatter (e.g., phiki.php in the formatters directory).
  • Hook it into the %%(language) code %% syntax (Wacko already supports language specifiers).
  • Map common language names to Phiki's Grammar::* constants.
  • Add configuration for default theme, line numbers, etc.
  • Cache highlighted output (Wacko already does some caching; enhance for code blocks).
  • Provide a fallback for unsupported languages.

Pros for Wacko:
  • Replaces multiple outdated systems with one modern library.
  • Consistent, beautiful output that matches modern editors.
  • Better performance than JS-based solutions for page loads.
  • Easy to extend with Wacko-specific features (e.g., copy button, line highlighting).

Potential cons:
  • Language support depends on included TextMate grammars (strong for popular languages; may need additions for obscure ones).
  • Initial integration effort (but far less than maintaining old highlighters).

Strong Alternative: Tempest Highlight

Another excellent modern PHP option is Tempest Highlight (tempest/highlight).
  • Very fast, extensible, server-side.
  • Good for common languages (PHP, HTML, CSS, Blade, etc.).
  • Easy API and custom language support.
  • Actively developed and used in real projects.

It could serve as a lighter alternative or complement if Phiki's grammar approach feels heavy for some use cases.

Other Options

  • Keep/enhance Highlight.js — As a progressive enhancement or for rare languages. Load it lazily or only when Phiki doesn't support a language. This gives the best of both (server for most, client for edge cases).
  • Pygments — Excellent Python library with massive language support, but requires a bridge (e.g., exec or microservice), adding complexity and a Python dependency. Not ideal for pure-PHP Wacko.
  • Shiki (via shiki-php) — Similar quality to Phiki but spawns Node.js (slower for live rendering).
  • Prism.js or updated highlight.php — Client- or older server-side; generally inferior to Phiki/Tempest now.

Implementation Roadmap Suggestion

  1. Evaluate — Test Phiki + Tempest on Wacko sample pages with various languages.
  2. Core Integration — Build a PhikiFormatter (or make it configurable between Phiki/Tempest).
  3. Backward Compatibility — Alias old formatters or migrate gradually.
  4. Configuration — Admin settings for default theme, enabled languages, line numbers.
  5. Enhancements — Add common features: copy-to-clipboard, line numbers, diff highlighting, language auto-detect (fallback).
  6. Performance — Benchmark render times and implement caching for code blocks.
  7. Plugins — Optional full Highlight.js fallback or additional themes.
  8. Documentation & Testing — Update Wacko docs and test with real user content.

Phiki is the clear frontrunner: modern, high-quality, pure PHP, and designed exactly for this use case. It would significantly modernize WackoWiki's code presentation and reduce long-term maintenance.
If you share more details (e.g., target Wacko version, priority languages, or specific requirements like line numbers), I can help refine the integration approach or suggest code snippets.

Comments

  1. Phiki Implementation

    PHP
    <?php
    /**
     * Phiki Syntax Highlighter Formatter for WackoWiki
     */
    
    use Phiki\Phiki;
    use Phiki\Grammar\Grammar;
    use Phiki\Theme\Theme;
    
    $lang_input = strtolower(trim($options['_default'] ?? 'text'));
    
    // 1. Static common aliases (fast lookup)
    $grammar = match($lang_input) {
    	'apache', 'htaccess'    => Grammar::Apache,
    	'c++', 'cpp'            => Grammar::Cpp,
    	'csharp', 'cs', 'c#'    => Grammar::Csharp,
    	'cmake'                 => Grammar::CMake,
    	'css'                   => Grammar::Css,
    	'dart'                  => Grammar::Dart,
    	'diff'                  => Grammar::Diff,
    	'docker', 'dockerfile'  => Grammar::Docker,
    	'go', 'golang'          => Grammar::Go,
    	'html'                  => Grammar::Html,
    	'http'                  => Grammar::Http,
    	'ini'                   => Grammar::Ini,
    	'java'                  => Grammar::Java,
    	'javascript', 'js'      => Grammar::Javascript,
    	'json'                  => Grammar::Json,
    	'kotlin', 'kt'          => Grammar::Kotlin,
    	'latex', 'tex'          => Grammar::Latex,
    	'lua'                   => Grammar::Lua,
    	'makefile'              => Grammar::Makefile,
    	'markdown', 'md'        => Grammar::Markdown,
    	'nginx'                 => Grammar::Nginx,
    	'perl'                  => Grammar::Perl,
    	'php'                   => Grammar::Php,
    	'powershell', 'ps'      => Grammar::Powershell,
    	'python'                => Grammar::Python,
    	'r'                     => Grammar::R,
    	'regex', 'regexp'       => Grammar::Regex,
    	'ruby', 'rb'            => Grammar::Ruby,
    	'rust', 'rs'            => Grammar::Rust,
    	'scala'                 => Grammar::Scala,
    	'bash', 'sh', 'shell'   => Grammar::Shellscript,
    	'sql'                   => Grammar::Sql,
    	'swift'                 => Grammar::Swift,
    	'text', 'txt'           => Grammar::Txt,
    	'toml'                  => Grammar::Toml,
    	'typescript', 'ts'      => Grammar::Typescript,
    	'xml'                   => Grammar::Xml,
    	'yaml', 'yml'           => Grammar::Yaml,
    	default                 => null,
    };
    
    $line_numbers	= isset($options['numbers']);
    $start_line		= max(1, (int)($options['start'] ?? 1));
    
    try {
    	$phiki = new Phiki();
    
    	// 2. Try dynamic alias registration if not in static map
    	if ($grammar === null) {
    		try {
    			// Test if grammar exists by attempting a small highlight (cheap test)
    			$phiki->codeToHtml('// test', $lang_input, Theme::GithubDark);
    			#$phiki->alias($lang_input, $lang_input);
    			$grammar = $lang_input;
    		} catch (\Throwable $e) {
    			$grammar = Grammar::Txt;
    		}
    	}
    
    	$result = $phiki->codeToHtml(
    		code: $text,
    		grammar: $grammar,
    		theme: [
    			'light' => Theme::GithubLight,
    			'dark'  => Theme::GithubDark,
    		]
    	);
    
    	if ($line_numbers)
    	{
    		$result = $result
    			->withGutter()
    			->startingLine($start_line);
    	}
    
    	$highlighted	= $result->toString();
    	$token			= 'cb-' . Ut::random_token(7);
    
    	$tpl->token		= $token;
    
    	$highlighted = preg_replace(
    		'/<pre([^>]*)>/i',
    		'<pre id="' . $token . '"$1>',
    		$highlighted,
    		1
    	);
    
    	$tpl->language	= !empty($lang_input) && $lang_input !== 'text' ? strtoupper($lang_input) : '';
    	$tpl->text		= $highlighted;
    
    } catch (\Throwable $e) {
    	$tpl->text = '<pre class="code-error">' . Ut::html($text) . '</pre>';
    	error_log('Phiki Formatter Error: ' . $e->getMessage());
    }
    


    HTML
    [ === main === ]
    <ignore>
    <!--notypo-->
    <div class="hl-code">
    	<div class="hl-header">
    		<span class="hl-language">[ ' language ' ]</span>
    		<button type="button" class="clipb hl-copy-btn" 
    				title="[ ' _t: SourceCopyToClipboard ' ]" 
    				data-clipboard-target="#[ ' token ' ]">
    			<img src="[ ' db: theme_url ' ]icon/spacer.png" 
    				 class="ico-copy ico-sm" 
    				 alt="Copy">
    		</button>
    	</div>
    	<div class="hl-body">
    		[ ' text | pre ' ]
    	</div>
    </div>
    <!--/notypo-->
    </ignore>
    
    • WikiAdmin
    • 05/28/2026 08:20 edited