Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Ast Laravel Package

phug/ast

phug/ast provides the abstract syntax tree node classes that power the Phug Pug/Jade template engine for PHP. It defines the structured node types produced by the parser, enabling analysis, transformation, and compilation of templates.

View on GitHub
Deep Wiki
Context7

Getting Started

phug/ast is not a template engine you wire into a Laravel app — it's the node model underneath Phug's Pug compiler. You'll usually get it transitively (composer why phug/ast almost always shows phug/parser or phug/compiler as the parent), so the first step is confirming which version is already in your lockfile before requiring anything directly.

composer require phug/ast
# then immediately check what pulled it in and which version the ecosystem expects
composer show phug/ast
composer why phug/ast

Where to look first, in this order:

  1. src/ — the node interfaces and base classes are the real documentation. Start with the interface (NodeInterface or equivalent) and the base Node/parent-node class; every method you'll use in practice is declared there.
  2. tests/ — the test suite is the only reliable usage guide for a package with this few stars. Copy assertion patterns rather than guessing at traversal semantics.
  3. The sibling packages phug/parser and phug/compiler — they show how the AST is actually constructed and consumed, which is the context you'll be writing against.

First use case for a Laravel developer: an Artisan command that audits or rewrites Pug views. Parse resources/views/**/*.pug, walk the resulting tree, and report on (or mutate) specific nodes — for example, flagging every <img> node that lacks an alt attribute, or renaming a component attribute across all views before a refactor.

// Rough shape — confirm exact method names against src/ before relying on them.
$ast = $parser->parse($pugSource);          // from phug/parser, not phug/ast

$ast->walk(function ($node) {
    if ($node->getName() === 'img' && ! $node->hasAttribute('alt')) {
        // collect for reporting
    }
});

Do the parse-and-walk spike on one real view file before writing any abstractions. The API surface is small, but it is not self-documenting, and getting a feel for the actual node shapes (tags, text, blocks, attributes are distinct node types) will save you a lot of guesswork.

Implementation Patterns

Read-only auditing is the safest pattern. Walk the tree, collect node references into DTOs or arrays, and hand those to normal Laravel code (commands, queue jobs, validation). You never need to understand mutation semantics, and the AST stays a pure input.

class PugAuditCommand extends Command
{
    protected $signature = 'pug:audit {--path=resources/views}';

    public function handle(Parser $parser)
    {
        $findings = [];

        foreach (File::glob(base_path($this->option('path')).'/**/*.pug') as $file) {
            $parser->parse(file_get_contents($file))->walk(
                function ($node) use (&$findings, $file) {
                    // inspect $node here, push to $findings
                }
            );
        }

        // render a table, exit non-zero if $findings is non-empty (CI-friendly)
    }
}

Transform-and-emit. If you're converting Pug to something else (Blade fragments, a JSON component manifest, static HTML), structure it as visitor → intermediate DTO → writer. Don't emit strings directly from inside the walk callback; you'll regret it the moment you need to reorder or deduplicate output.

interface AstVisitor { public function visit($node): void; }

final class CollectTags implements AstVisitor { /* ... */ }
final class CollectAttributes implements AstVisitor { /* ... */ }

// One walk, many visitors
$ast->walk(function ($node) use ($visitors) {
    foreach ($visitors as $v) { $v->visit($node); }
});

Custom syntax via node subclassing. The intended extension point is subclassing the base node and registering it so the parser produces your type for a custom tag or filter. Typical Laravel use: a <x-card>-style Pug tag that maps to a Blade component. Keep the subclass thin — a name, a list of allowed attributes, and a render/compile hook — and put the Blade-specific logic in a separate service so the node stays testable in isolation.

Service container integration. Bind the parser and any visitor registry as singletons in a PugServiceProvider. Parsing is cheap per-file but not free; for anything scanning the whole views directory, cache the resulting findings keyed by file mtime rather than reparsing on every request.

Snapshot testing. For any transform, assert on a serialized dump of the tree (minus parent pointers — see gotchas) rather than on rendered strings. Tree snapshots fail loudly and legibly; rendered-string diffs don't.

Gotchas and Tips

  • It is a leaf dependency, not a framework. Two stars and zero direct dependents tells you the ecosystem uses it only through phug/parser and phug/compiler. Pin your version loosely and let the parent packages drive it; a direct require with a hard constraint is how you get a composer update deadlock later.
  • Parent pointers create cycles. Nodes almost certainly hold a reference back to their parent. json_encode($node) or var_export will recurse forever or blow the depth limit. Always detach, or write an explicit serializer that walks children only.
  • Mutating during traversal. Appending, removing, or reordering children from inside a walk() callback is the classic way to skip nodes or loop. Collect the nodes you want to change during the walk, then mutate in a second pass over the collected set.
  • Node "name" is overloaded. Tag nodes, text nodes, and attribute nodes all have a name-ish accessor, but they mean different things. Always check the node class/type before trusting getName(); a switch on class, not on a string, is the maintainable choice.
  • No Laravel-native ergonomics. No facade, no config file, no php artisan hooks. Everything is plain PHP objects. That's fine, but budget for writing your own thin wrapper rather than scattering raw node calls through controllers.
  • Documentation is essentially the source. When a method's behaviour is unclear, read the implementation and the corresponding test — don't infer from the method name. Traversal order and whether a callback fires on the root are exactly the details that bite.
  • Debugging aid. A one-liner that prints str_repeat(' ', $node->getLevel()).$node->getName() per node will tell you more about the tree shape in ten seconds than any amount of reading. Build it as a dev-only command on day one.
  • Version drift is the real risk. Phug's sub-packages move together. If you subclass a node and phug/compiler bumps a minor version, your subclass can silently stop being produced. Keep custom nodes covered by a test that parses a fixture and asserts your class is in the tree.
  • Don't reach for this if you only need output. If your goal is "render Pug in Laravel," you want phug/laravel or phug/renderer — not the AST. phug/ast is the right tool only when you need to inspect or reshape the tree itself.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource