{"id":47944930,"url":"https://github.com/tamdaz/tempest-twig","last_synced_at":"2026-04-04T08:23:15.000Z","repository":{"id":347654957,"uuid":"1194776506","full_name":"tamdaz/tempest-twig","owner":"tamdaz","description":"A third-party package that provides Twig for Tempest.","archived":false,"fork":false,"pushed_at":"2026-03-28T21:06:20.000Z","size":47,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-28T22:26:21.644Z","etag":null,"topics":["tempest","third-party","twig"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tamdaz.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-28T19:53:11.000Z","updated_at":"2026-03-28T21:06:20.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/tamdaz/tempest-twig","commit_stats":null,"previous_names":["tamdaz/tempest-twig"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/tamdaz/tempest-twig","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tamdaz%2Ftempest-twig","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tamdaz%2Ftempest-twig/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tamdaz%2Ftempest-twig/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tamdaz%2Ftempest-twig/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tamdaz","download_url":"https://codeload.github.com/tamdaz/tempest-twig/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tamdaz%2Ftempest-twig/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31392900,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T04:26:24.776Z","status":"ssl_error","status_checked_at":"2026-04-04T04:23:34.147Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["tempest","third-party","twig"],"created_at":"2026-04-04T08:23:14.458Z","updated_at":"2026-04-04T08:23:14.994Z","avatar_url":"https://github.com/tamdaz.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# tempest-twig\n\nTempest Twig is a third-party package that integrates the Twig templating engine with the [Tempest framework](https://tempestphp.com). It provides full Twig `3.x` support, custom extensions for routing and debugging, and an innovative component system using HTML-like syntax.\n\nThe package includes flexible configuration for template paths, built-in Twig extensions that work with Tempest's routing and Vite pipeline, and a sophisticated component transformation system. Everything is fully tested with PHPUnit and includes GitHub Actions CI.\n\n## Installation\n\nFirst, install the Composer package:\n\n```bash\ncomposer require tamdaz/tempest-twig\n```\n\n## Configuration\n\nTo use Tempest Twig, create a configuration file in your `config` directory. Tempest will automatically discover and load this configuration.\n\n```php\n// config/twig.config.php\nuse Tamdaz\\TempestTwig\\TwigConfig;\nuse function Tempest\\root_path;\n\nreturn new TwigConfig(\n    viewPaths: [\n        root_path('templates'),\n    ],\n    debug: env('APP_DEBUG', false),\n    strictVariables: true,\n);\n```\n\nThe `TwigConfig` class wraps Twig's standard options. The `viewPaths` parameter specifies which directories to search for templates. You can add multiple directories for different template locations. Other options like `debug`, `charset`, `strictVariables`, and `autoescape` follow Twig's standard behavior.\n\n## Twig Functions\n\nTempest Twig automatically registers custom Twig functions that integrate with the Tempest framework. These functions are available in all templates without any additional setup.\n\n### Routing Functions\n\nThe `route()` function generates URLs for named routes or controller methods. You can pass route parameters directly:\n\n```twig\n{{ route('route.name') }}\n{{ route([ControllerClass::class, 'method']) }}\n{{ route([ControllerClass::class, 'method'], param1, param2) }}\n```\n\nUse `signed_route()` to generate URLs with cryptographic signatures. Use `temporary_signed_route()` for links that expire after a duration (in seconds):\n\n```twig\n{{ signed_route('route.name') }}\n{{ temporary_signed_route('route.name', 3600) }}\n```\n\nCheck the current route with `is_current_route()` to highlight active navigation items:\n\n```twig\n{% if is_current_route('route.name') %}\n  \u003cspan class=\"active\"\u003eActive\u003c/span\u003e\n{% endif %}\n```\n\nThe `current_path` variable provides the current request path as a string.\n\n### Vite Functions\n\nIf your Tempest application uses Vite for asset bundling, the package provides integration functions. Use `vite_tags()` to generate script and link tags for Vite entry points:\n\n```twig\n{{ vite_tags('resources/js/app.ts', 'resources/css/app.css') }}\n```\n\nUse `vite_asset()` to get the public URL of an asset from Vite's manifest:\n\n```twig\n\u003cimg src=\"{{ vite_asset('resources/images/logo.png') }}\" /\u003e\n```\n\n### Debug Functions\n\nTempest Twig includes debugging and utility functions. The `dump()` function inspects variables during development. The `class()` function returns an object's class name, and `is_empty()` checks if a variable is empty:\n\n```twig\n{{ dump(user, post) }}\n{{ class(user) }}\n{% if is_empty(posts) %}No posts{% endif %}\n```\n\nAdditional utilities include `get_type()` for variable types, `env()` for environment variables with fallback, and `to_json()` for converting PHP values to JSON:\n\n```twig\n{{ get_type(value) }}\n{{ env('APP_NAME', 'MyApp') }}\n\u003cscript\u003e\n  const data = {{ to_json(users) }};\n\u003c/script\u003e\n```\n\nThe `count()` function counts array elements, `current_url` gives the full URL, and `now` provides the current timestamp.\n\n## Component System\n\nTempest Twig includes a component system using HTML-like syntax. Instead of writing Twig `include` and `embed` directives, you write component tags that look like HTML custom elements. The package transforms these tags into native Twig directives automatically.\n\n### Self-Closing Components\n\nSelf-closing components are ideal for simple UI elements like buttons and badges. Write them as XML-style tags with attributes:\n\n```twig\n\u003ctwig:Button label=\"Click me\" variant=\"primary\" /\u003e\n```\n\nThis transforms into a Twig `include` directive that passes attributes as variables:\n\n```twig\n{% include 'components/Button.html.twig' with { label: 'Click me', variant: 'primary' } only %}\n```\n\nYour component template at `templates/components/Button.html.twig`:\n\n```twig\n\u003cbutton class=\"btn btn-{{ variant ?? 'primary' }}\"\u003e\n  {{ label }}\n\u003c/button\u003e\n```\n\n### Components with Content\n\nComponents can wrap content, similar to Vue or React components. When you add content between tags, it transforms into an `embed` directive:\n\n```twig\n\u003ctwig:Alert type=\"warning\"\u003e\n  This is a warning message\n\u003c/twig:Alert\u003e\n```\n\nThis becomes:\n\n```twig\n{% embed 'components/Alert.html.twig' with { type: 'warning' } %}\n  {% block content %}This is a warning message{% endblock %}\n{% endembed %}\n```\n\nYour component template accesses the content through Twig's block system:\n\n```twig\n\u003cdiv class=\"alert alert-{{ type ?? 'info' }}\"\u003e\n  {% block content %}{% endblock %}\n\u003c/div\u003e\n```\n\n### Components with Named Slots\n\nFor complex components, define named content areas using `\u003ctwig:block\u003e` tags. This allows different parts to accept different content:\n\n```twig\n\u003ctwig:Card title=\"Welcome\"\u003e\n  \u003ctwig:block name=\"header\"\u003e\n    \u003ch2\u003e{{ title }}\u003c/h2\u003e\n  \u003c/twig:block\u003e\n  \n  \u003cp\u003eCard content goes here\u003c/p\u003e\n\u003c/twig:Card\u003e\n```\n\nYour component template can define multiple named blocks:\n\n```twig\n\u003cdiv class=\"card\"\u003e\n  {% if block('header') is not empty %}\n    \u003cdiv class=\"card-header\"\u003e\n      {% block header %}{% endblock %}\n    \u003c/div\u003e\n  {% endif %}\n  \n  \u003cdiv class=\"card-body\"\u003e\n    {% block content %}{% endblock %}\n  \u003c/div\u003e\n\u003c/div\u003e\n```\n\nDefault content (anything not in `\u003ctwig:block\u003e`) goes into the `content` block. Named blocks are optional, so check if they have content before rendering them.\n\n### Attribute Binding\n\nComponents accept both static attributes and dynamic Twig expressions. Static attributes are quoted strings, while dynamic attributes use a colon prefix:\n\n```twig\n\u003ctwig:Button label=\"Click\" variant=\"primary\" disabled=\"true\" /\u003e\n\n\u003ctwig:Button\n  label=\"{{ buttonLabel }}\"\n  :variant=\"isSecondary ? 'secondary' : 'primary'\" \n  :disabled=\"isLoading\" /\u003e\n```\n\nAll attributes are available as variables in your component. The preprocessor handles nested components and escapes attribute values properly.\n\n### Component Organization\n\nOrganize components in a dedicated `components` directory within your template's folder. This separates them from page templates and layouts:\n\n```\ntemplates/\n├── components/\n│   ├── Button.html.twig\n│   ├── Card.html.twig\n│   ├── Alert.html.twig\n│   └── UserProfile.html.twig\n├── layouts/\n│   └── base.html.twig\n└── pages/\n    ├── home.html.twig\n    └── about.html.twig\n```\n\nAlways provide a default `content` block for the main content area. For optional slots, check if the block is empty before rendering to avoid extra HTML. Use PascalCase for component names to distinguish them from standard HTML tags.\n\n## How It Works\n\nTempest Twig integrates several components. The `TwigInitializer` is the entry point discovered by Tempest's service container. It registers the Twig environment, sets up the `ComponentLoader` for transformation, and registers custom extensions. The `TwigViewRendererInitializer` then selects the `TwigViewRenderer` as the default renderer.\n\nThe `ComponentPreprocessor` transforms your component syntax into standard Twig directives before Twig processes the template. Component tags become `include` or `embed` directives with proper variable passing. The transformation is transparent, so you never think about the underlying Twig code.\n\nThree extensions are automatically registered. The `DebugExtension` provides debugging utilities. The `RoutingExtension` integrates with Tempest's routing system. The `ViteExtension` handles Vite asset manifest integration.\n\n## Testing and Development\n\nThe package includes a test suite covering component attribute parsing, template transformation, and loader functionality. Run tests with:\n\n```bash\ncomposer test\n```\n\nAll tests use PHPUnit and follow the standard test directory structure. The package includes GitHub Actions workflows for continuous integration and compatibility checks.\n\n## License\n\nThis package is licensed under the MIT license. See `LICENSE` for details.\n\n## Support and Contributing\n\nIf you encounter any issues or have suggestions for improvements, you can open an issue or a PR on GitHub. Contributions are welcome!","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftamdaz%2Ftempest-twig","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftamdaz%2Ftempest-twig","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftamdaz%2Ftempest-twig/lists"}