diff --git a/.gitignore b/.gitignore index 0727ae9..e531948 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,8 @@ desktop.ini npm-debug.log yarn-error.log ###< symfony/webpack-encore-bundle ### + +###> symfony/asset-mapper ### +/public/assets/ +/assets/vendor/ +###< symfony/asset-mapper ### diff --git a/assets/app.ts b/assets/app.js similarity index 92% rename from assets/app.ts rename to assets/app.js index 7e55b54..31f5d0a 100644 --- a/assets/app.ts +++ b/assets/app.js @@ -5,7 +5,7 @@ * (and its CSS file) in your base layout (base.html.twig). */ -// require('bootstrap'); +require('bootstrap'); // any CSS you import will output into a single css file (app.scss in this case) import './styles/app.scss'; diff --git a/assets/fonts/agave-regular.woff2 b/assets/fonts/agave-regular.woff2 new file mode 100644 index 0000000..847b2cc Binary files /dev/null and b/assets/fonts/agave-regular.woff2 differ diff --git a/assets/fonts/fantasque-sans-mono-regular.woff2 b/assets/fonts/fantasque-sans-mono-regular.woff2 new file mode 100644 index 0000000..07172c7 Binary files /dev/null and b/assets/fonts/fantasque-sans-mono-regular.woff2 differ diff --git a/assets/fonts/jetbrains-mono-regular.woff2 b/assets/fonts/jetbrains-mono-regular.woff2 new file mode 100644 index 0000000..40da427 Binary files /dev/null and b/assets/fonts/jetbrains-mono-regular.woff2 differ diff --git a/assets/fonts/material-symbols-outlined.woff2 b/assets/fonts/material-symbols-outlined.woff2 new file mode 100644 index 0000000..c2c9610 Binary files /dev/null and b/assets/fonts/material-symbols-outlined.woff2 differ diff --git a/assets/images/logo.png b/assets/images/logo.png new file mode 100755 index 0000000..82fa3c3 Binary files /dev/null and b/assets/images/logo.png differ diff --git a/assets/styles/app.scss b/assets/styles/app.scss index 4e66aa8..c6c4498 100644 --- a/assets/styles/app.scss +++ b/assets/styles/app.scss @@ -1,3 +1,37 @@ +@use 'app/nav'; +@use 'app/footer'; + +// ============================================================================= +// Fonts +// ============================================================================= + +@font-face { + font-family: 'Agave'; + src: url('../fonts/agave-regular.woff2') format('woff2'); + font-weight: 600; + font-style: normal; +} + +@font-face { + font-family: 'Fantasque Sans Mono'; + src: url('../fonts/fantasque-sans-mono-regular.woff2') format('woff2'); + font-weight: 400; + font-style: normal; +} + +@font-face { + font-family: 'JetBrains Mono'; + src: url('../fonts/jetbrains-mono-regular.woff2') format('woff2'); + font-weight: 400; + font-style: normal; +} + +@font-face { + font-family: 'Material Symbols Outlined'; + font-style: normal; + src: url('../fonts/material-symbols-outlined.woff2') format('woff'); +} + // ============================================================================= // Design Tokens — Light Palette // ============================================================================= @@ -90,8 +124,8 @@ $dk-on-background: #dae2fd; // Shared Tokens — Typography & Radius // ============================================================================= -$font-display: 'Space Grotesk', system-ui, sans-serif; -$font-body: 'Geist', system-ui, -apple-system, sans-serif; +$font-display: 'Agave', system-ui, sans-serif; +$font-body: 'Fantasque Sans Mono', system-ui, -apple-system, sans-serif; $font-mono: 'JetBrains Mono', 'Courier New', monospace; $radius-sm: 0.25rem; @@ -545,3 +579,17 @@ pre { box-shadow: var(--glow-primary); } } + +.material-symbols-outlined { + font-family: 'Material Symbols Outlined'; + font-weight: normal; + font-style: normal; + font-size: 20px; + display: inline-block; + line-height: 1; + text-transform: none; + letter-spacing: normal; + word-wrap: normal; + white-space: nowrap; + direction: ltr; +} diff --git a/assets/styles/app/footer.css b/assets/styles/app/footer.css new file mode 100644 index 0000000..a8f1ce5 --- /dev/null +++ b/assets/styles/app/footer.css @@ -0,0 +1,20 @@ +.footer-link { + color: rgba(255, 255, 255, .6); + transition: color .15s ease; +} + +.footer-link:hover { + color: var(--color-primary-container); +} + +#footer { + z-index: 50; + background: rgba(0,0,0,.3); + backdrop-filter: blur(8px); + -webkit-backdrop-filter: blur(8px); + border-color: rgba(192, 199, 211, .1) !important; +} + +#footer-copyright { + color: rgba(255,255,255,.4); +} diff --git a/assets/styles/app/nav.css b/assets/styles/app/nav.css new file mode 100644 index 0000000..11fdc00 --- /dev/null +++ b/assets/styles/app/nav.css @@ -0,0 +1,31 @@ +nav div { + height: 64px; +} + +/* Glassmorphism nav — uses RGB channel var for rgba() composition */ +.nav-glass { + background-color: rgba(var(--color-surface-container-lowest-rgb), .85); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); +} + +/* Nav link colours — needs :hover, can't do inline */ +.nav-link-ds { + color: var(--color-on-surface-variant); + transition: color .15s ease; +} + +.nav-link-ds:hover { + color: #50a7fa; +} + +#top-nav { + z-index: 50; + border-color: rgba(192, 199, 211, .3) !important; +} + +#nav-site-name { + font-family: var(--font-display); + letter-spacing: -.02em; + font-size: 1rem; +} diff --git a/composer.json b/composer.json index 32528f6..95e3d4d 100644 --- a/composer.json +++ b/composer.json @@ -10,14 +10,20 @@ "ext-ctype": "*", "ext-iconv": "*", "ext-redis": "*", + "symfony/asset": "8.1.*", + "symfony/asset-mapper": "8.1.*", "symfony/cache": "8.1.*", "symfony/console": "8.1.*", "symfony/dotenv": "8.1.*", "symfony/flex": "^2", "symfony/framework-bundle": "8.1.*", "symfony/runtime": "8.1.*", + "symfony/twig-bundle": "8.1.*", + "symfony/web-link": "8.1.*", "symfony/webpack-encore-bundle": "^2.4", - "symfony/yaml": "8.1.*" + "symfony/yaml": "8.1.*", + "twig/extra-bundle": "^2.12|^3.0", + "twig/twig": "^2.12|^3.0" }, "require-dev": { "symfony/debug-bundle": "8.1.*", @@ -47,7 +53,8 @@ "scripts": { "auto-scripts": { "cache:clear": "symfony-cmd", - "assets:install %PUBLIC_DIR%": "symfony-cmd" + "assets:install %PUBLIC_DIR%": "symfony-cmd", + "importmap:install": "symfony-cmd" }, "post-install-cmd": [ "@auto-scripts" diff --git a/composer.lock b/composer.lock index ff5439a..090929d 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,85 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ac587198ca8dd206caeaf9c45a3e1934", + "content-hash": "96e1f33a9305b01c5a60a23677f28c09", "packages": [ + { + "name": "composer/semver", + "version": "3.4.4", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/198166618906cb2de69b95d7d47e5fa8aa1b2b95", + "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.11", + "symfony/phpunit-bridge": "^3 || ^7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.4.4" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + } + ], + "time": "2025-08-20T19:15:30+00:00" + }, { "name": "psr/cache", "version": "3.0.0", @@ -158,6 +235,62 @@ }, "time": "2019-01-08T18:20:26+00:00" }, + { + "name": "psr/link", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/link.git", + "reference": "84b159194ecfd7eaa472280213976e96415433f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/link/zipball/84b159194ecfd7eaa472280213976e96415433f7", + "reference": "84b159194ecfd7eaa472280213976e96415433f7", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "suggest": { + "fig/link-util": "Provides some useful PSR-13 utilities" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Link\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for HTTP links", + "homepage": "https://github.com/php-fig/link", + "keywords": [ + "http", + "http-link", + "link", + "psr", + "psr-13", + "rest" + ], + "support": { + "source": "https://github.com/php-fig/link/tree/2.0.1" + }, + "time": "2021-03-11T23:00:27+00:00" + }, { "name": "psr/log", "version": "3.0.2", @@ -278,6 +411,87 @@ ], "time": "2026-05-29T05:06:50+00:00" }, + { + "name": "symfony/asset-mapper", + "version": "v8.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/asset-mapper.git", + "reference": "74b1b7b7019c728cb1f8672b502260e683b6374e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/asset-mapper/zipball/74b1b7b7019c728cb1f8672b502260e683b6374e", + "reference": "74b1b7b7019c728cb1f8672b502260e683b6374e", + "shasum": "" + }, + "require": { + "composer/semver": "^3.0", + "php": ">=8.4.1", + "symfony/filesystem": "^7.4|^8.0", + "symfony/http-client": "^7.4|^8.0" + }, + "require-dev": { + "symfony/asset": "^7.4|^8.0", + "symfony/browser-kit": "^7.4|^8.0", + "symfony/console": "^7.4|^8.0", + "symfony/event-dispatcher-contracts": "^3.0", + "symfony/finder": "^7.4|^8.0", + "symfony/framework-bundle": "^7.4|^8.0", + "symfony/http-foundation": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/process": "^7.4|^8.0", + "symfony/runtime": "^7.4|^8.0", + "symfony/web-link": "^7.4|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\AssetMapper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Maps directories of assets & makes them available in a public directory with versioned filenames.", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/asset-mapper/tree/v8.1.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-05-29T05:06:50+00:00" + }, { "name": "symfony/cache", "version": "v8.1.0", @@ -1463,6 +1677,185 @@ ], "time": "2026-05-29T05:06:50+00:00" }, + { + "name": "symfony/http-client", + "version": "v8.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-client.git", + "reference": "68a48e4c31f63fcd1bdff997a85a09e55efe8cdb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-client/zipball/68a48e4c31f63fcd1bdff997a85a09e55efe8cdb", + "reference": "68a48e4c31f63fcd1bdff997a85a09e55efe8cdb", + "shasum": "" + }, + "require": { + "php": ">=8.4.1", + "psr/log": "^1|^2|^3", + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/http-client-contracts": "^3.7", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "amphp/amp": "<3", + "php-http/discovery": "<1.15" + }, + "provide": { + "php-http/async-client-implementation": "*", + "php-http/client-implementation": "*", + "psr/http-client-implementation": "1.0", + "symfony/http-client-implementation": "3.0" + }, + "require-dev": { + "amphp/http-client": "^5.3.2", + "amphp/http-tunnel": "^2.0", + "guzzlehttp/guzzle": "^7.10", + "nyholm/psr7": "^1.0", + "php-http/httplug": "^1.0|^2.0", + "psr/http-client": "^1.0", + "symfony/cache": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/messenger": "^7.4|^8.0", + "symfony/process": "^7.4|^8.0", + "symfony/rate-limiter": "^7.4|^8.0", + "symfony/stopwatch": "^7.4|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", + "homepage": "https://symfony.com", + "keywords": [ + "http" + ], + "support": { + "source": "https://github.com/symfony/http-client/tree/v8.1.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-05-29T05:06:50+00:00" + }, + { + "name": "symfony/http-client-contracts", + "version": "v3.7.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-client-contracts.git", + "reference": "4a2d00c37651c0bdc2b9e1c773487a8bf4edb12d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/4a2d00c37651c0bdc2b9e1c773487a8bf4edb12d", + "reference": "4a2d00c37651c0bdc2b9e1c773487a8bf4edb12d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to HTTP clients", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/http-client-contracts/tree/v3.7.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-03-06T13:17:50+00:00" + }, { "name": "symfony/http-foundation", "version": "v8.1.0", @@ -2496,6 +2889,280 @@ ], "time": "2026-05-29T05:06:50+00:00" }, + { + "name": "symfony/translation-contracts", + "version": "v3.7.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation-contracts.git", + "reference": "0ab302977a952b42fd51475c4ebac81f8da0a95d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/0ab302977a952b42fd51475c4ebac81f8da0a95d", + "reference": "0ab302977a952b42fd51475c4ebac81f8da0a95d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to translation", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/translation-contracts/tree/v3.7.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-01-05T13:30:16+00:00" + }, + { + "name": "symfony/twig-bridge", + "version": "v8.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/twig-bridge.git", + "reference": "25bb8c01edaab85e13142f6010df09b990388343" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/25bb8c01edaab85e13142f6010df09b990388343", + "reference": "25bb8c01edaab85e13142f6010df09b990388343", + "shasum": "" + }, + "require": { + "php": ">=8.4.1", + "symfony/translation-contracts": "^2.5|^3", + "twig/twig": "^3.25" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "<5.2|>=7", + "phpdocumentor/type-resolver": "<1.5.1", + "symfony/form": "<7.4.4|>8.0,<8.0.4", + "symfony/mime": "<7.4.9|>8.0,<8.0.9" + }, + "require-dev": { + "egulias/email-validator": "^2.1.10|^3|^4", + "league/html-to-markdown": "^5.0", + "phpdocumentor/reflection-docblock": "^5.2|^6.0", + "symfony/asset": "^7.4|^8.0", + "symfony/asset-mapper": "^7.4|^8.0", + "symfony/console": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/emoji": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", + "symfony/finder": "^7.4|^8.0", + "symfony/form": "^7.4.4|^8.0.4", + "symfony/html-sanitizer": "^7.4|^8.0", + "symfony/http-foundation": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/intl": "^7.4|^8.0", + "symfony/mime": "^7.4.9|^8.0.9", + "symfony/polyfill-intl-icu": "^1.0", + "symfony/property-info": "^7.4|^8.0", + "symfony/routing": "^7.4|^8.0", + "symfony/security-acl": "^2.8|^3.0", + "symfony/security-core": "^7.4|^8.0", + "symfony/security-csrf": "^7.4|^8.0", + "symfony/security-http": "^7.4|^8.0", + "symfony/serializer": "^7.4|^8.0", + "symfony/stopwatch": "^7.4|^8.0", + "symfony/translation": "^7.4|^8.0", + "symfony/validator": "^7.4|^8.0", + "symfony/web-link": "^7.4|^8.0", + "symfony/workflow": "^7.4|^8.0", + "symfony/yaml": "^7.4|^8.0", + "twig/cssinliner-extra": "^3", + "twig/inky-extra": "^3", + "twig/markdown-extra": "^3" + }, + "type": "symfony-bridge", + "autoload": { + "psr-4": { + "Symfony\\Bridge\\Twig\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides integration for Twig with various Symfony components", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/twig-bridge/tree/v8.1.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-05-29T05:06:50+00:00" + }, + { + "name": "symfony/twig-bundle", + "version": "v8.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/twig-bundle.git", + "reference": "b7f4a471a07b8b52174d153e4db12f46954192ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/b7f4a471a07b8b52174d153e4db12f46954192ed", + "reference": "b7f4a471a07b8b52174d153e4db12f46954192ed", + "shasum": "" + }, + "require": { + "composer-runtime-api": ">=2.1", + "php": ">=8.4.1", + "symfony/config": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/http-foundation": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/twig-bridge": "^7.4|^8.0" + }, + "require-dev": { + "symfony/asset": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", + "symfony/finder": "^7.4|^8.0", + "symfony/form": "^7.4|^8.0", + "symfony/framework-bundle": "^7.4|^8.0", + "symfony/routing": "^7.4|^8.0", + "symfony/runtime": "^7.4|^8.0", + "symfony/stopwatch": "^7.4|^8.0", + "symfony/translation": "^7.4|^8.0", + "symfony/web-link": "^7.4|^8.0", + "symfony/yaml": "^7.4|^8.0" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Symfony\\Bundle\\TwigBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a tight integration of Twig into the Symfony full-stack framework", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/twig-bundle/tree/v8.1.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-05-29T05:06:50+00:00" + }, { "name": "symfony/var-dumper", "version": "v8.1.0", @@ -2666,6 +3333,90 @@ ], "time": "2026-05-29T05:06:50+00:00" }, + { + "name": "symfony/web-link", + "version": "v8.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/web-link.git", + "reference": "87ca04297acf837a1de25d3f6c31b9551235dcbd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/web-link/zipball/87ca04297acf837a1de25d3f6c31b9551235dcbd", + "reference": "87ca04297acf837a1de25d3f6c31b9551235dcbd", + "shasum": "" + }, + "require": { + "php": ">=8.4.1", + "psr/link": "^1.1|^2.0" + }, + "provide": { + "psr/link-implementation": "1.0|2.0" + }, + "require-dev": { + "symfony/http-kernel": "^7.4|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\WebLink\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kévin Dunglas", + "email": "dunglas@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Manages links between resources", + "homepage": "https://symfony.com", + "keywords": [ + "dns-prefetch", + "http", + "http2", + "link", + "performance", + "prefetch", + "preload", + "prerender", + "psr13", + "push" + ], + "support": { + "source": "https://github.com/symfony/web-link/tree/v8.1.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-05-29T05:06:50+00:00" + }, { "name": "symfony/webpack-encore-bundle", "version": "v2.4.0", @@ -2817,6 +3568,160 @@ } ], "time": "2026-05-29T05:06:50+00:00" + }, + { + "name": "twig/extra-bundle", + "version": "v3.24.0", + "source": { + "type": "git", + "url": "https://github.com/twigphp/twig-extra-bundle.git", + "reference": "6a621fcb1f28aa9ea7b34a99047ae0cdf5b834c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twigphp/twig-extra-bundle/zipball/6a621fcb1f28aa9ea7b34a99047ae0cdf5b834c9", + "reference": "6a621fcb1f28aa9ea7b34a99047ae0cdf5b834c9", + "shasum": "" + }, + "require": { + "php": ">=8.1.0", + "symfony/framework-bundle": "^5.4|^6.4|^7.0|^8.0", + "symfony/twig-bundle": "^5.4|^6.4|^7.0|^8.0", + "twig/twig": "^3.2|^4.0" + }, + "require-dev": { + "league/commonmark": "^2.7", + "symfony/phpunit-bridge": "^6.4|^7.0", + "twig/cache-extra": "^3.0", + "twig/cssinliner-extra": "^3.0", + "twig/html-extra": "^3.0", + "twig/inky-extra": "^3.0", + "twig/intl-extra": "^3.0", + "twig/markdown-extra": "^3.0", + "twig/string-extra": "^3.0" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Twig\\Extra\\TwigExtraBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + } + ], + "description": "A Symfony bundle for extra Twig extensions", + "homepage": "https://twig.symfony.com", + "keywords": [ + "bundle", + "extra", + "twig" + ], + "support": { + "source": "https://github.com/twigphp/twig-extra-bundle/tree/v3.24.0" + }, + "funding": [ + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/twig/twig", + "type": "tidelift" + } + ], + "time": "2026-02-07T08:07:38+00:00" + }, + { + "name": "twig/twig", + "version": "v3.27.1", + "source": { + "type": "git", + "url": "https://github.com/twigphp/Twig.git", + "reference": "ae2071bffb38f04847fc0864d730c94b9cb8ab74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/ae2071bffb38f04847fc0864d730c94b9cb8ab74", + "reference": "ae2071bffb38f04847fc0864d730c94b9cb8ab74", + "shasum": "" + }, + "require": { + "php": ">=8.1.0", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-mbstring": "^1.3" + }, + "require-dev": { + "php-cs-fixer/shim": "^3.0@stable", + "phpstan/phpstan": "^2.0@stable", + "psr/container": "^1.0|^2.0", + "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "src/Resources/core.php", + "src/Resources/debug.php", + "src/Resources/escaper.php", + "src/Resources/string_loader.php" + ], + "psr-4": { + "Twig\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + }, + { + "name": "Twig Team", + "role": "Contributors" + }, + { + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "role": "Project Founder" + } + ], + "description": "Twig, the flexible, fast, and secure template language for PHP", + "homepage": "https://twig.symfony.com", + "keywords": [ + "templating" + ], + "support": { + "issues": "https://github.com/twigphp/Twig/issues", + "source": "https://github.com/twigphp/Twig/tree/v3.27.1" + }, + "funding": [ + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/twig/twig", + "type": "tidelift" + } + ], + "time": "2026-05-30T17:09:26+00:00" } ], "packages-dev": [ @@ -3273,280 +4178,6 @@ ], "time": "2026-05-29T05:06:50+00:00" }, - { - "name": "symfony/translation-contracts", - "version": "v3.7.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/translation-contracts.git", - "reference": "0ab302977a952b42fd51475c4ebac81f8da0a95d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/0ab302977a952b42fd51475c4ebac81f8da0a95d", - "reference": "0ab302977a952b42fd51475c4ebac81f8da0a95d", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/contracts", - "name": "symfony/contracts" - }, - "branch-alias": { - "dev-main": "3.7-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Translation\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to translation", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.7.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2026-01-05T13:30:16+00:00" - }, - { - "name": "symfony/twig-bridge", - "version": "v8.1.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/twig-bridge.git", - "reference": "25bb8c01edaab85e13142f6010df09b990388343" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/25bb8c01edaab85e13142f6010df09b990388343", - "reference": "25bb8c01edaab85e13142f6010df09b990388343", - "shasum": "" - }, - "require": { - "php": ">=8.4.1", - "symfony/translation-contracts": "^2.5|^3", - "twig/twig": "^3.25" - }, - "conflict": { - "phpdocumentor/reflection-docblock": "<5.2|>=7", - "phpdocumentor/type-resolver": "<1.5.1", - "symfony/form": "<7.4.4|>8.0,<8.0.4", - "symfony/mime": "<7.4.9|>8.0,<8.0.9" - }, - "require-dev": { - "egulias/email-validator": "^2.1.10|^3|^4", - "league/html-to-markdown": "^5.0", - "phpdocumentor/reflection-docblock": "^5.2|^6.0", - "symfony/asset": "^7.4|^8.0", - "symfony/asset-mapper": "^7.4|^8.0", - "symfony/console": "^7.4|^8.0", - "symfony/dependency-injection": "^7.4|^8.0", - "symfony/emoji": "^7.4|^8.0", - "symfony/expression-language": "^7.4|^8.0", - "symfony/finder": "^7.4|^8.0", - "symfony/form": "^7.4.4|^8.0.4", - "symfony/html-sanitizer": "^7.4|^8.0", - "symfony/http-foundation": "^7.4|^8.0", - "symfony/http-kernel": "^7.4|^8.0", - "symfony/intl": "^7.4|^8.0", - "symfony/mime": "^7.4.9|^8.0.9", - "symfony/polyfill-intl-icu": "^1.0", - "symfony/property-info": "^7.4|^8.0", - "symfony/routing": "^7.4|^8.0", - "symfony/security-acl": "^2.8|^3.0", - "symfony/security-core": "^7.4|^8.0", - "symfony/security-csrf": "^7.4|^8.0", - "symfony/security-http": "^7.4|^8.0", - "symfony/serializer": "^7.4|^8.0", - "symfony/stopwatch": "^7.4|^8.0", - "symfony/translation": "^7.4|^8.0", - "symfony/validator": "^7.4|^8.0", - "symfony/web-link": "^7.4|^8.0", - "symfony/workflow": "^7.4|^8.0", - "symfony/yaml": "^7.4|^8.0", - "twig/cssinliner-extra": "^3", - "twig/inky-extra": "^3", - "twig/markdown-extra": "^3" - }, - "type": "symfony-bridge", - "autoload": { - "psr-4": { - "Symfony\\Bridge\\Twig\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides integration for Twig with various Symfony components", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/twig-bridge/tree/v8.1.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2026-05-29T05:06:50+00:00" - }, - { - "name": "symfony/twig-bundle", - "version": "v8.1.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/twig-bundle.git", - "reference": "b7f4a471a07b8b52174d153e4db12f46954192ed" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/b7f4a471a07b8b52174d153e4db12f46954192ed", - "reference": "b7f4a471a07b8b52174d153e4db12f46954192ed", - "shasum": "" - }, - "require": { - "composer-runtime-api": ">=2.1", - "php": ">=8.4.1", - "symfony/config": "^7.4|^8.0", - "symfony/dependency-injection": "^7.4|^8.0", - "symfony/http-foundation": "^7.4|^8.0", - "symfony/http-kernel": "^7.4|^8.0", - "symfony/twig-bridge": "^7.4|^8.0" - }, - "require-dev": { - "symfony/asset": "^7.4|^8.0", - "symfony/expression-language": "^7.4|^8.0", - "symfony/finder": "^7.4|^8.0", - "symfony/form": "^7.4|^8.0", - "symfony/framework-bundle": "^7.4|^8.0", - "symfony/routing": "^7.4|^8.0", - "symfony/runtime": "^7.4|^8.0", - "symfony/stopwatch": "^7.4|^8.0", - "symfony/translation": "^7.4|^8.0", - "symfony/web-link": "^7.4|^8.0", - "symfony/yaml": "^7.4|^8.0" - }, - "type": "symfony-bundle", - "autoload": { - "psr-4": { - "Symfony\\Bundle\\TwigBundle\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides a tight integration of Twig into the Symfony full-stack framework", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/twig-bundle/tree/v8.1.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2026-05-29T05:06:50+00:00" - }, { "name": "symfony/web-profiler-bundle", "version": "v8.1.0", @@ -3631,86 +4262,6 @@ } ], "time": "2026-05-29T05:06:50+00:00" - }, - { - "name": "twig/twig", - "version": "v3.27.1", - "source": { - "type": "git", - "url": "https://github.com/twigphp/Twig.git", - "reference": "ae2071bffb38f04847fc0864d730c94b9cb8ab74" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/ae2071bffb38f04847fc0864d730c94b9cb8ab74", - "reference": "ae2071bffb38f04847fc0864d730c94b9cb8ab74", - "shasum": "" - }, - "require": { - "php": ">=8.1.0", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-ctype": "^1.8", - "symfony/polyfill-mbstring": "^1.3" - }, - "require-dev": { - "php-cs-fixer/shim": "^3.0@stable", - "phpstan/phpstan": "^2.0@stable", - "psr/container": "^1.0|^2.0", - "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0" - }, - "type": "library", - "autoload": { - "files": [ - "src/Resources/core.php", - "src/Resources/debug.php", - "src/Resources/escaper.php", - "src/Resources/string_loader.php" - ], - "psr-4": { - "Twig\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - }, - { - "name": "Twig Team", - "role": "Contributors" - }, - { - "name": "Armin Ronacher", - "email": "armin.ronacher@active-4.com", - "role": "Project Founder" - } - ], - "description": "Twig, the flexible, fast, and secure template language for PHP", - "homepage": "https://twig.symfony.com", - "keywords": [ - "templating" - ], - "support": { - "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.27.1" - }, - "funding": [ - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/twig/twig", - "type": "tidelift" - } - ], - "time": "2026-05-30T17:09:26+00:00" } ], "aliases": [], diff --git a/config/bundles.php b/config/bundles.php index 5e40030..ec7e4e1 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -7,4 +7,5 @@ return [ Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true], + Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true], ]; diff --git a/config/packages/asset_mapper.yaml b/config/packages/asset_mapper.yaml new file mode 100644 index 0000000..f7653e9 --- /dev/null +++ b/config/packages/asset_mapper.yaml @@ -0,0 +1,11 @@ +framework: + asset_mapper: + # The paths to make available to the asset mapper. + paths: + - assets/ + missing_import_mode: strict + +when@prod: + framework: + asset_mapper: + missing_import_mode: warn diff --git a/config/packages/framework.yaml b/config/packages/framework.yaml index 53d4368..258148d 100644 --- a/config/packages/framework.yaml +++ b/config/packages/framework.yaml @@ -17,3 +17,7 @@ when@test: test: true session: storage_factory_id: session.storage.factory.mock_file + +when@prod: + framework: + http_cache: true diff --git a/config/reference.php b/config/reference.php index 228805e..41634a3 100644 --- a/config/reference.php +++ b/config/reference.php @@ -286,7 +286,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param; * }>, * }, * asset_mapper?: bool|array{ // Asset Mapper configuration - * enabled?: bool|Param, // Default: false + * enabled?: bool|Param, // Default: true * paths?: string|array, * excluded_patterns?: list, * exclude_dotfiles?: bool|Param, // If true, any files starting with "." will be excluded from the asset mapper. // Default: true @@ -416,7 +416,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param; * log_channel?: scalar|Param|null, // The channel of log message. Null to let Symfony decide. // Default: null * }>, * web_link?: bool|array{ // Web links configuration - * enabled?: bool|Param, // Default: false + * enabled?: bool|Param, // Default: true * }, * lock?: bool|string|array{ // Lock configuration * enabled?: bool|Param, // Default: false @@ -471,7 +471,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param; * }, * disallow_search_engine_index?: bool|Param, // Enabled by default when debug is enabled. // Default: true * http_client?: bool|array{ // HTTP Client configuration - * enabled?: bool|Param, // Default: false + * enabled?: bool|Param, // Default: true * max_host_connections?: int|Param, // The maximum number of connections to a single host. * default_options?: array{ * headers?: array, @@ -763,6 +763,53 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param; * script_attributes?: array, * link_attributes?: array, * } + * @psalm-type TwigExtraConfig = array{ + * cache?: bool|array{ + * enabled?: bool|Param, // Default: false + * }, + * html?: bool|array{ + * enabled?: bool|Param, // Default: false + * }, + * markdown?: bool|array{ + * enabled?: bool|Param, // Default: false + * }, + * intl?: bool|array{ + * enabled?: bool|Param, // Default: false + * }, + * cssinliner?: bool|array{ + * enabled?: bool|Param, // Default: false + * }, + * inky?: bool|array{ + * enabled?: bool|Param, // Default: false + * }, + * string?: bool|array{ + * enabled?: bool|Param, // Default: false + * }, + * commonmark?: array{ + * renderer?: array{ // Array of options for rendering HTML. + * block_separator?: scalar|Param|null, + * inner_separator?: scalar|Param|null, + * soft_break?: scalar|Param|null, + * }, + * html_input?: "strip"|"allow"|"escape"|Param, // How to handle HTML input. + * allow_unsafe_links?: bool|Param, // Remove risky link and image URLs by setting this to false. // Default: true + * max_nesting_level?: int|Param, // The maximum nesting level for blocks. // Default: 9223372036854775807 + * max_delimiters_per_line?: int|Param, // The maximum number of strong/emphasis delimiters per line. // Default: 9223372036854775807 + * slug_normalizer?: array{ // Array of options for configuring how URL-safe slugs are created. + * instance?: mixed, + * max_length?: int|Param, // Default: 255 + * unique?: mixed, + * }, + * commonmark?: array{ // Array of options for configuring the CommonMark core extension. + * enable_em?: bool|Param, // Default: true + * enable_strong?: bool|Param, // Default: true + * use_asterisk?: bool|Param, // Default: true + * use_underscore?: bool|Param, // Default: true + * unordered_list_markers?: list, + * }, + * ... + * }, + * } * @psalm-type ConfigType = array{ * imports?: ImportsConfig, * parameters?: ParametersConfig, @@ -770,6 +817,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param; * framework?: FrameworkConfig, * twig?: TwigConfig, * webpack_encore?: WebpackEncoreConfig, + * twig_extra?: TwigExtraConfig, * "when@dev"?: array{ * imports?: ImportsConfig, * parameters?: ParametersConfig, @@ -780,6 +828,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param; * twig?: TwigConfig, * maker?: MakerConfig, * webpack_encore?: WebpackEncoreConfig, + * twig_extra?: TwigExtraConfig, * }, * "when@prod"?: array{ * imports?: ImportsConfig, @@ -788,6 +837,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param; * framework?: FrameworkConfig, * twig?: TwigConfig, * webpack_encore?: WebpackEncoreConfig, + * twig_extra?: TwigExtraConfig, * }, * "when@test"?: array{ * imports?: ImportsConfig, @@ -798,6 +848,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param; * debug?: DebugConfig, * twig?: TwigConfig, * webpack_encore?: WebpackEncoreConfig, + * twig_extra?: TwigExtraConfig, * }, * ... [ + 'path' => './assets/app.js', + 'entrypoint' => true, + ], +]; diff --git a/symfony.lock b/symfony.lock index 86a122c..01deee7 100644 --- a/symfony.lock +++ b/symfony.lock @@ -1,4 +1,19 @@ { + "symfony/asset-mapper": { + "version": "8.1", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "6.4", + "ref": "c01c47af2ec66a74ec046eccb919cfe27d3464ec" + }, + "files": [ + "assets/app.js", + "assets/styles/app.css", + "config/packages/asset_mapper.yaml", + "importmap.php" + ] + }, "symfony/console": { "version": "8.1", "recipe": { @@ -113,11 +128,14 @@ "ref": "b346dae458e64a1921ded2125993d94bd719a8dd" }, "files": [ - "assets/app.ts", + "assets/app.js", "assets/styles/app.css", "config/packages/webpack_encore.yaml", "package.json", "webpack.config.js" ] + }, + "twig/extra-bundle": { + "version": "v3.24.0" } } diff --git a/templates/base.html.twig b/templates/base.html.twig index 5855c9f..ff27531 100644 --- a/templates/base.html.twig +++ b/templates/base.html.twig @@ -1,29 +1,37 @@ - + - {% block title %}Welcome!{% endblock %} - + + {% block title %}creative-dragonslayer.de{% endblock %} + + + {% block stylesheets %} {{ encore_entry_link_tags('app') }} {% endblock %} + {% block head %}{% endblock %} + {% set frankenphpHotReload = app.request.server.get('FRANKENPHP_HOT_RELOAD') %} {% if frankenphpHotReload %} - - - + + + {% endif %} + {% include 'widgets/nav_bar.html.twig' %} +
- {% block body %}{% endblock %} + {% block body %}{% endblock %}
-
- {% block javascripts %} - {{ encore_entry_script_tags('app') }} - {% endblock %} -
+ {% include 'widgets/footer.html.twig' %} + + {% block javascripts %} + {% block importmap %}{{ importmap('app') }}{% endblock %} + {{ encore_entry_script_tags('app') }} + {% endblock %} diff --git a/templates/widgets/footer.html.twig b/templates/widgets/footer.html.twig new file mode 100644 index 0000000..ba7fb91 --- /dev/null +++ b/templates/widgets/footer.html.twig @@ -0,0 +1,14 @@ + diff --git a/templates/widgets/nav_bar.html.twig b/templates/widgets/nav_bar.html.twig new file mode 100644 index 0000000..26a6c45 --- /dev/null +++ b/templates/widgets/nav_bar.html.twig @@ -0,0 +1,17 @@ + diff --git a/tsconfig.json b/tsconfig.json index 49b50d7..5b7dcff 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,7 +8,12 @@ "isolatedModules": true, "esModuleInterop": true, "skipLibCheck": true, - "noEmit": true + "noEmit": true, + "plugins":[ + { + "name": "typescript-plugin-css" + } + ] }, "include": ["assets/**/*"] } diff --git a/webpack.config.js b/webpack.config.js index 1faa902..0debbbf 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -20,7 +20,9 @@ Encore * Each entry will result in one JavaScript file (e.g. app.js) * and one CSS file (e.g. app.css) if your JavaScript imports CSS. */ - .addEntry('app', './assets/app.ts') + .addEntry('app', './assets/app.js') + + .addEntry('root', './assets/ts/root/root.ts') // When enabled, Webpack "splits" your files into smaller pieces for greater optimization. .splitEntryChunks() @@ -61,6 +63,9 @@ Encore // uncomment if you use TypeScript .enableTypeScriptLoader() + // optionally enable forked type script for faster builds + // https://www.npmjs.com/package/fork-ts-checker-webpack-plugin + // requires that you have a tsconfig.json file that is setup correctly. .enableForkedTypeScriptTypesChecking() // uncomment if you use React