Skip to main content
Wik/Lex offers two configuration approaches. The config-file approach is recommended for most projects because Lexer::fromConfig() locates the file automatically without you hardcoding any paths. The fluent API is useful when you prefer to configure everything in code or when embedding Lex inside a framework.

Factory method

Lexer::fromConfig(string $startDir = ''): static
Searches upward from $startDir (defaults to the current working directory) for a lex.config.json file — the same strategy used by tools like ESLint and Prettier. When it finds the file it instantiates a Lexer pre-configured with the values it contains and places the .lexer/ cache directory next to the config file. Throw LexException if no lex.config.json is found anywhere in the directory tree.
// Called from anywhere inside the project — no explicit path needed
$lexer = Lexer::fromConfig();

// Restrict the search to a specific subdirectory
$lexer = Lexer::fromConfig('/var/www/myapp/src');

Fluent API reference

Every method returns static, so you can chain calls in any order. Calling a configuration method after the engine has been used resets the internal engine instance so the new settings take effect.

View paths

paths(array $paths): static

Replace the entire list of view directories. Pass absolute paths.
$lexer->paths([__DIR__ . '/views', __DIR__ . '/resources/views']);

addPath(string $path): static

Append a single directory to the existing view path list without replacing it.
$lexer->addPath(__DIR__ . '/views/vendor');

cache(string $dir): static

Override the default .lexer/ cache directory location. The directory is created automatically if it does not exist.
$lexer->cache(__DIR__ . '/storage/lex-cache');

Production and sandbox

setProduction(bool $production = true): static

Enable or disable production mode. In production mode the engine skips source-file mtime checks and serves templates from the precompiled index. LexDebugger is disabled automatically. Pass false to revert to dev mode.
$lexer->setProduction();        // enable
$lexer->setProduction(false);   // revert to dev mode

enableSandbox(?SandboxConfig $config = null): static

Enable sandbox mode. Defaults to SandboxConfig::secure() when no config is provided, which forbids raw echo and applies a strict function whitelist.
use Wik\Lexer\Security\SandboxConfig;

$lexer->enableSandbox();  // uses SandboxConfig::secure()

$lexer->enableSandbox(
    SandboxConfig::secure()
        ->withAllowedFunctions(['date', 'number_format', 'strtolower'])
        ->withRawEcho(false)
);

setSandboxConfig(SandboxConfig $config): static

Replace the active SandboxConfig without switching the security preset. Use this to update sandbox rules after calling enableSandbox().
$lexer->setSandboxConfig(
    SandboxConfig::permissive()
);

Escaping

setEscaper(EscaperInterface $escaper): static

Replace the default HTML escaper used for {{ $expr }} output. The default uses htmlspecialchars(ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8').
use Wik\Lexer\Contracts\EscaperInterface;

class MyEscaper implements EscaperInterface
{
    public function escape(mixed $value): string
    {
        return htmlspecialchars((string) $value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
    }
}

$lexer->setEscaper(new MyEscaper());

Custom directives

directive(string $name, callable $handler): static

Register a custom template directive. The handler receives the expression string (everything inside the parentheses) and must return a PHP code snippet to embed in the compiled output. Directives are resolved at parse time — the callable runs once during compilation, not on every render.
$lexer->directive('datetime', function (string $expression): string {
    return "<?php echo date('d/m/Y H:i', strtotime({$expression})); ?>";
});
In templates:
#datetime($post->created_at)

Components

component(string $name, string $viewPath): static

Register a named component mapped to a specific .lex file. Use this when the file is outside the standard components/ subdirectory or when you want an explicit mapping.
$lexer->component('Alert', __DIR__ . '/views/components/alert.lex');

registerComponentClass(string $name, string $class): static

Bind a component name to a PHP class that implements a mount() method. Props are injected into mount() via reflection, and all public properties of the class are available in the component template.
$lexer->registerComponentClass('Alert', App\View\Components\AlertComponent::class);

componentClassNamespace(string $namespace): static

Set the PHP namespace used for auto-discovering component classes. Given namespace App\View\Components, a <Card> tag auto-resolves to App\View\Components\CardComponent.
$lexer->componentClassNamespace('App\\View\\Components');

componentPath(string $path): static

Add an extra directory for component file discovery. Explicitly registered paths take priority because they are added before the automatic components/ subdirectory scanning.
$lexer->componentPath(__DIR__ . '/vendor/acme/components');

Build docs developers (and LLMs) love