diff --git a/.editorconfig b/.editorconfig index 6699076..4ec97ea 100644 --- a/.editorconfig +++ b/.editorconfig @@ -5,7 +5,7 @@ root = true [*] charset = utf-8 end_of_line = lf -indent_size = 4 +indent_size = 2 indent_style = space insert_final_newline = true trim_trailing_whitespace = true diff --git a/.env b/.env deleted file mode 100644 index 5450e90..0000000 --- a/.env +++ /dev/null @@ -1,48 +0,0 @@ -# In all environments, the following files are loaded if they exist, -# the latter taking precedence over the former: -# -# * .env contains default values for the environment variables needed by the app -# * .env.local uncommitted file with local overrides -# * .env.$APP_ENV committed environment-specific defaults -# * .env.$APP_ENV.local uncommitted environment-specific overrides -# -# Real environment variables win over .env files. -# -# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES. -# https://symfony.com/doc/current/configuration/secrets.html -# -# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2). -# https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration - -###> symfony/framework-bundle ### -APP_ENV=dev -APP_SECRET= -APP_SHARE_DIR=var/share -###< symfony/framework-bundle ### - -###> symfony/routing ### -# Configure how to generate URLs in non-HTTP contexts, such as CLI commands. -# See https://symfony.com/doc/current/routing.html#generating-urls-in-commands -DEFAULT_URI=http://localhost -###< symfony/routing ### - -###> doctrine/doctrine-bundle ### -# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url -# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml -# -# DATABASE_URL="sqlite:///%kernel.project_dir%/var/data_%kernel.environment%.db" -# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8.0.32&charset=utf8mb4" -# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=10.11.2-MariaDB&charset=utf8mb4" -DATABASE_URL="postgresql://app:!ChangeMe!@127.0.0.1:5432/app?serverVersion=16&charset=utf8" -###< doctrine/doctrine-bundle ### - -###> symfony/messenger ### -# Choose one of the transports below -# MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages -# MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages -MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=0 -###< symfony/messenger ### - -###> symfony/mailer ### -MAILER_DSN=null://null -###< symfony/mailer ### diff --git a/.env.dev b/.env.dev deleted file mode 100644 index 57d9344..0000000 --- a/.env.dev +++ /dev/null @@ -1,4 +0,0 @@ - -###> symfony/framework-bundle ### -APP_SECRET=add2825264a0dd588b79e4681ba37d1a -###< symfony/framework-bundle ### diff --git a/.env.test b/.env.test deleted file mode 100644 index 64bd111..0000000 --- a/.env.test +++ /dev/null @@ -1,3 +0,0 @@ -# define your env variables for the test env here -KERNEL_CLASS='App\Kernel' -APP_SECRET='$ecretf0rt3st' diff --git a/.gitignore b/.gitignore index 40af00d..4752b1a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ - +.env +.env.dev +.env.test ###> symfony/framework-bundle ### /.env.local /.env.local.php @@ -18,3 +20,9 @@ /public/assets/ /assets/vendor/ ###< symfony/asset-mapper ### + +node_modules +/assets/styles/*.css.map +###> dont upload files to repo +/public/photos + diff --git a/assets/app.js b/assets/app.js deleted file mode 100644 index e56396c..0000000 --- a/assets/app.js +++ /dev/null @@ -1,10 +0,0 @@ -import './stimulus_bootstrap.js'; -/* - * Welcome to your app's main JavaScript file! - * - * This file will be included onto the page via the importmap() Twig function, - * which should already be in your base.html.twig. - */ -import './styles/app.css'; - -console.log('This log comes from assets/app.js - welcome to AssetMapper! 🎉'); diff --git a/assets/brain.js b/assets/brain.js new file mode 100644 index 0000000..4cabf21 --- /dev/null +++ b/assets/brain.js @@ -0,0 +1,100 @@ +import './styles/brain.css'; +import './stimulus_bootstrap.js'; + +const init = () => { + menu(); + editorInit(); + photosUploadInit(); +}; + +const menu = () => { + const subMenus = document.querySelectorAll('.sub-menu--link'); + + subMenus.forEach((menu) => { + + menu.addEventListener('mouseover', (event) => { + const targetedMenu = event.target.nextElementSibling; + + const openMenu = document.querySelector('.level-2.open'); + if (openMenu) { + openMenu.classList.remove('open'); + } + + if (targetedMenu.classList.contains('open')) { + targetedMenu.classList.remove('open'); + } else { + targetedMenu.classList.add('open'); + } + + }); + }); +} + +const editorInit = () => { + if (document.querySelector('#post_text')) { + const editor = Jodit.make('#post_text', { + "enter": "P", + "theme": 'dark', + "disablePlugins": "ai-assistant,about", + "width": 800, + "height": 500 + }); + } + + if (document.querySelector('#page_text')) { + const editor = Jodit.make('#page_text', { + "enter": "P", + "theme": 'dark', + "disablePlugins": "ai-assistant,about", + "width": 800, + "height": 500 + }); + } + + if (document.querySelector('#photos_text')) { + const editor = Jodit.make('#photos_text', { + "enter": "P", + "theme": 'dark', + "disablePlugins": "ai-assistant,about", + "width": 800, + "height": 500 + }); + } +} + +const photosUploadInit = () => { + document + .querySelectorAll('.add_item_link') + .forEach(btn => { + btn.addEventListener("click", addFormToCollection) + }); + + function addFormToCollection(e) { + const collectionHolder = document.querySelector('#' + e.target.dataset.collectionHolderId); + const item = document.createElement('li'); + + let index; + + if (!collectionHolder.dataset.index) { + collectionHolder.dataset.index = 0; + } + + index = collectionHolder.dataset.index; + + item.innerHTML = collectionHolder + .dataset + .prototype + .replace( + /__name__/g, + index + ); + + collectionHolder.appendChild(item); + + collectionHolder.dataset.index++; + }; +} + +init(); + + diff --git a/assets/controllers.json b/assets/controllers.json index 29ea244..c59f1ab 100644 --- a/assets/controllers.json +++ b/assets/controllers.json @@ -1,5 +1,16 @@ { "controllers": { + "@symfony/ux-autocomplete": { + "autocomplete": { + "enabled": true, + "fetch": "eager", + "autoimport": { + "tom-select/dist/css/tom-select.default.css": true, + "tom-select/dist/css/tom-select.bootstrap4.css": false, + "tom-select/dist/css/tom-select.bootstrap5.css": false + } + } + }, "@symfony/ux-turbo": { "turbo-core": { "enabled": true, diff --git a/assets/landing.js b/assets/landing.js new file mode 100644 index 0000000..349ac7f --- /dev/null +++ b/assets/landing.js @@ -0,0 +1,57 @@ +import './styles/landing.css'; +import './stimulus_bootstrap.js'; + +const mobileMenu = () => { + const icon = document.querySelector('.icon-menu'); + const menu = document.querySelector('.front-menu'); + + icon.addEventListener('click', (event) => { + icon.classList.toggle('open'); + menu.classList.toggle('open'); + }); +} + +const jobInfoToggle = () => { + const jobs = document.querySelectorAll('#work .jobs .job'); + + jobs.forEach((job) => { + job.addEventListener('click', (event) => { + const jobId = job.dataset.jobId; + const jobInfo = document.querySelector(`#${jobId}`); + const activeJobLabel = document.querySelector('#work .jobs .job.active'); + + if (jobInfo.classList.contains('hide')) { + const openJob = document.querySelector('#work .jobs .job-highlight.show'); + + if (jobInfo.classList.contains('hide')) { + + jobInfo.classList.remove('hide'); + jobInfo.classList.add('show'); + openJob.classList.remove('show'); + openJob.classList.add('hide'); + } + } + + if (!job.classList.contains('active')) { + job.classList.add('active'); + activeJobLabel.classList.remove('active'); + } + }); + }); +} + +const scrollTo = () => { + const links = document.querySelectorAll('#outro .menu a'); + + links.forEach((link) => { + link.addEventListener('click', (event) => { + const anchor = link.dataset.scrollTo; + const element = document.querySelector(`#${anchor}`).scrollIntoView(); + window.history.pushState({}, '', `#${anchor}`); + }) + }); +} + +mobileMenu(); +jobInfoToggle(); +scrollTo(); \ No newline at end of file diff --git a/assets/main.js b/assets/main.js new file mode 100644 index 0000000..9f437fd --- /dev/null +++ b/assets/main.js @@ -0,0 +1,52 @@ +import './stimulus_bootstrap.js'; +import './styles/main.css'; + +const mobileMenu = () => { + const icon = document.querySelector('.icon-menu'); + const menu = document.querySelector('.menu'); + const header = document.querySelector('header'); + const body = document.querySelector('body'); + + icon.addEventListener('click', (event) => { + icon.classList.toggle('open'); + menu.classList.toggle('open'); + header.classList.toggle('open'); + body.classList.toggle('menu-open'); + }); +} + +const album = () => { + const album = document.querySelector('#album'); + + if (album) { + const photos = album.querySelectorAll('.photo'); + const openImageContainer = document.querySelector('#open-image'); + const close = openImageContainer.querySelector('.close'); + + photos.forEach((photo) => { + photo.addEventListener('click', (event) => { + const dataset = photo.dataset; + openImageContainer.querySelector('#image').setAttribute('src', dataset.url); + openImageContainer.querySelector('#image').setAttribute('alt', dataset.alt); + openImageContainer.querySelector('#caption').innerHTML = dataset.caption; + openImageContainer.querySelector('#date').innerHTML = `Date Taken: ${dataset.date}`; + openImageContainer.querySelector('#location').innerHTML = `Location: ${dataset.location}`; + openImageContainer.querySelector('#equipment').innerHTML = `Camera Used: ${dataset.equipment}`; + openImageContainer.classList.toggle('open'); + document.querySelector('body').classList.toggle('photo-open'); + }); + }); + + close.addEventListener('click', (event) => { + if (openImageContainer.classList.contains('open')) { + openImageContainer.classList.remove('open'); + document.querySelector('body').classList.remove('photo-open'); + } + }) + } + + +} + +mobileMenu(); +album(); \ No newline at end of file diff --git a/assets/package-lock.json b/assets/package-lock.json new file mode 100644 index 0000000..01159a9 --- /dev/null +++ b/assets/package-lock.json @@ -0,0 +1,446 @@ +{ + "name": "brain", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "brain", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "sass": "^1.100.0" + } + }, + "node_modules/@parcel/watcher": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz", + "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.3", + "is-glob": "^4.0.3", + "node-addon-api": "^7.0.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.6", + "@parcel/watcher-darwin-arm64": "2.5.6", + "@parcel/watcher-darwin-x64": "2.5.6", + "@parcel/watcher-freebsd-x64": "2.5.6", + "@parcel/watcher-linux-arm-glibc": "2.5.6", + "@parcel/watcher-linux-arm-musl": "2.5.6", + "@parcel/watcher-linux-arm64-glibc": "2.5.6", + "@parcel/watcher-linux-arm64-musl": "2.5.6", + "@parcel/watcher-linux-x64-glibc": "2.5.6", + "@parcel/watcher-linux-x64-musl": "2.5.6", + "@parcel/watcher-win32-arm64": "2.5.6", + "@parcel/watcher-win32-ia32": "2.5.6", + "@parcel/watcher-win32-x64": "2.5.6" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz", + "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz", + "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz", + "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz", + "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz", + "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz", + "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==", + "cpu": [ + "arm" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz", + "integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz", + "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz", + "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz", + "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz", + "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz", + "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz", + "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "license": "MIT", + "dependencies": { + "readdirp": "^5.0.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/immutable": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.5.tgz", + "integrity": "sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==", + "license": "MIT" + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "optional": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT", + "optional": true + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/readdirp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", + "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/sass": { + "version": "1.100.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.100.0.tgz", + "integrity": "sha512-B5j0rYMlinhhOo9tjQebMVVn0TfyXAF+wB3b2ggZUuJ/is/Y+7+JGjirAMxHZ9Z3hIP98NPfamlAkBHa1lAaXQ==", + "license": "MIT", + "dependencies": { + "chokidar": "^5.0.0", + "immutable": "^5.1.5", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=20.19.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + } + } +} diff --git a/assets/package.json b/assets/package.json new file mode 100644 index 0000000..d713a52 --- /dev/null +++ b/assets/package.json @@ -0,0 +1,26 @@ +{ + "name": "brain", + "version": "1.0.0", + "description": "", + "license": "ISC", + "author": "", + "type": "commonjs", + "main": "index.js", + "directories": { + "test": "tests" + }, + "scripts": { + "fe-watch": "sass styles/scss/main.scss styles/main.css -w", + "be-watch": "sass styles/scss/brain.scss styles/brain.css -w", + "landing-watch": "sass styles/scss/landing.scss styles/landing.css -W", + "fe-build": "sass styles/scss/main.scss styles/main.css --style compressed --no-source-map", + "be-build": "sass styles/scss/brain.scss styles/brain.css --style compressed --no-source-map", + "landing-build": "sass styles/scss/brain.scss styles/brain.css --style compressed --no-source-map", + "all-build": "npm run fe-build && npm run be-build && npm run landing-build" + + + }, + "dependencies": { + "sass": "^1.100.0" + } +} diff --git a/assets/styles/app.css b/assets/styles/app.css deleted file mode 100644 index dd6181a..0000000 --- a/assets/styles/app.css +++ /dev/null @@ -1,3 +0,0 @@ -body { - background-color: skyblue; -} diff --git a/assets/styles/brain.css b/assets/styles/brain.css new file mode 100644 index 0000000..7368933 --- /dev/null +++ b/assets/styles/brain.css @@ -0,0 +1 @@ +.page{max-width:800px;width:100%;margin:0 auto}.page h2{margin:0}.page .row{display:block;padding:1rem 0}.page .row label{display:block}.page .row input{height:30px;width:300px}.page .row #post_published{width:30px;height:30px}.page .row #post_save{width:100px;height:30px;background-color:green;border:none;color:#fff}#brain-wrapper header .level-1{display:flex;justify-content:center;align-items:flex-start;position:relative;list-style-type:none}#brain-wrapper header .level-1--item{padding:1rem 2rem}#brain-wrapper header .level-1 .level-2{display:none;margin:0;padding:0}#brain-wrapper header .level-1 .level-2.open{display:block;position:absolute}#brain-wrapper header .level-1 .level-2--item{padding:1rem 0}body{background-color:#d3d3d3} diff --git a/assets/styles/landing.css b/assets/styles/landing.css new file mode 100644 index 0000000..0a5fc14 --- /dev/null +++ b/assets/styles/landing.css @@ -0,0 +1,644 @@ +.home { + display: flex; + align-items: center; + flex-direction: column; + background-color: #696969; + margin: 0; +} +.home header { + width: 100%; +} +.home header h1 { + margin: 0; +} +.home header h1 a { + display: block; + font-size: 1.5rem; + text-decoration: none; + color: #1d1f20; + background-color: #d7b94c; + border: 2px solid #d7b94c; + padding: 2px 2px; +} +.home header h1 a:hover { + color: #d7b94c; + background-color: unset; +} +.home header nav { + display: flex; + justify-content: space-between; + align-items: center; + padding: 1rem 2rem; + overflow: hidden; + position: relative; +} +.home header nav .icon.icon-menu { + position: absolute; + z-index: 999; + display: block; + right: 2rem; + width: 30px; + height: 30px; + transition: right 100ms ease; +} +@media screen and (min-width: 600px) { + .home header nav .icon.icon-menu { + display: none; + } +} +.home header nav .icon.icon-menu:before { + content: ""; + display: block; + background-image: url("/icons/menu-grid.svg"); + background-size: 100%; + position: absolute; + width: 30px; + height: 30px; +} +.home header nav .icon.icon-menu:hover { + cursor: pointer; +} +.home header nav .icon.icon-menu.open { + right: calc(33.3333333333% + 1rem); +} +.home header nav .front-menu { + display: flex; + flex-direction: column; + gap: 1rem; + overflow: hidden; + position: fixed; + right: -100%; + top: 1rem; + margin: 0; + padding: 0; + transition: right 200ms ease; +} +.home header nav .front-menu.open { + right: 1rem; +} +@media screen and (min-width: 600px) { + .home header nav .front-menu { + flex-direction: row; + position: relative; + top: unset; + right: unset; + } +} +.home header nav .front-menu { + list-style: none; +} +.home header nav .front-menu li a { + display: block; + font-family: AtomicAge-Regular; + color: #d7b94c; + font-size: 1.5rem; + text-decoration: none; + padding-bottom: 2px; +} +.home header nav .front-menu li a:hover { + border-bottom: 2px solid #d7b94c; + padding-bottom: 0; +} +.home #root.v1 { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + height: auto; + width: 100%; + margin: 0 auto; +} +.home #root.v1 section { + margin: 0; + padding: 1rem 0; +} +.home #root.v1 section .title { + margin: 0; +} +.home #root.v1 .top { + display: flex; + min-height: 100vh; + justify-content: center; + align-items: center; + width: 100%; +} +.home #root.v1 .top .computer { + display: block; + max-width: 1024px; + max-height: 1024px; + width: 100%; + background-color: #1d1f20; + border: 2rem solid #a6a695; + padding: 1rem 1rem; + box-shadow: 0 0 5px 10px rgba(29, 31, 32, 0.45); +} +.home #root.v1 .top .computer .heading { + margin: 0; + font-size: 1rem; + font-family: Montserrat-Light; + color: #d7b94c; + position: relative; + padding-left: 1rem; +} +@media screen and (min-width: 600px) { + .home #root.v1 .top .computer .heading { + font-size: 2rem; + } +} +.home #root.v1 .top .computer .heading:before { + content: ">"; + position: absolute; + left: 0; + width: 100%; +} +.home #root.v1 .top .computer .heading:after { + content: "|"; + position: absolute; + right: 0; + width: 100%; + background: #1d1f20; + animation: typing 0.5s steps(16) forwards, cursor 1s infinite; +} +@media screen and (min-width: 600px) { + .home #root.v1 .top .computer .heading:after { + animation: typing 0.5s steps(16) forwards, cursor 1s infinite; + } +} +.home #root.v1 .top .computer #intro { + width: fit-content; +} +.home #root.v1 .top .computer #intro .heading { + width: 240px; +} +.home #root.v1 .top .computer #body { + width: fit-content; +} +.home #root.v1 .top .computer #body .about { + opacity: 0; + animation: showText 0.1s forwards; + animation-delay: 1s; + font-size: 1rem; + color: #d7b94c; +} +@media screen and (min-width: 600px) { + .home #root.v1 .top .computer #body .about { + font-size: 2rem; + animation: showText 0.1s forwards; + animation-delay: 1s; + } +} +.home #root.v1 .top .computer #outro { + width: fit-content; +} +.home #root.v1 .top .computer #outro .heading { + width: 160px; +} +.home #root.v1 .top .computer #outro .heading:after { + color: #1d1f20; + animation: typing 0.5s steps(16) forwards, cursor 1s infinite; + animation-delay: 2.5s; +} +@media screen and (min-width: 600px) { + .home #root.v1 .top .computer #outro .heading:after { + animation: typing 0.5s steps(16) forwards, cursor 1s infinite; + animation-delay: 2.5s; + } +} +.home #root.v1 .top .computer #outro .menu { + opacity: 0; + animation: showText 0.1s forwards; + animation-delay: 3s; + display: flex; + flex-wrap: wrap; + gap: 1rem; + padding-top: 2rem; + padding-bottom: 2rem; +} +@media screen and (min-width: 600px) { + .home #root.v1 .top .computer #outro .menu { + animation-delay: 3.5s; + } +} +.home #root.v1 .top .computer #outro .menu a { + font-size: 1rem; + color: #d7b94c; + cursor: pointer; +} +@media screen and (min-width: 600px) { + .home #root.v1 .top .computer #outro .menu a { + font-size: 2rem; + } +} +.home #root.v1 .bottom { + width: 100%; + height: 100%; +} +.home #root.v1 .bottom section { + box-shadow: 0 0 5px 4px rgba(29, 31, 32, 0.45); + margin: 4rem 0; +} +.home #root.v1 .bottom #cool-stuff { + display: flex; + flex-direction: column; + align-items: center; + width: 100%; + height: auto; + background-color: #d7b94c; + padding: 2rem 0; +} +.home #root.v1 .bottom #cool-stuff .title:after { + content: ""; + display: block; + width: 150px; + margin: 0 auto; + border-bottom: 5px solid #04392f; +} +.home #root.v1 .bottom #cool-stuff .highlights { + display: flex; + justify-content: center; + align-items: center; + flex-wrap: wrap; + gap: 2rem; + position: relative; + height: 100%; + width: 100%; + padding-top: 1rem; +} +.home #root.v1 .bottom #cool-stuff .highlights .highlight { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + align-self: stretch; + padding: 1rem 1rem; + position: relative; + width: 100%; + height: auto; + max-width: 400px; + box-shadow: 0 0 5px 0 rgba(29, 31, 32, 0.45); +} +.home #root.v1 .bottom #cool-stuff .highlights .highlight img { + width: 75%; +} +.home #root.v1 .bottom #cool-stuff .highlights .highlight p { + font-size: 1.25rem; + text-align: center; +} +.home #root.v1 .bottom #cool-stuff .highlights .highlight a { + display: block; + font-family: Orbitron-Regular; + color: #49111C; + font-size: 1.5rem; + font-weight: bold; + text-decoration: none; + padding-bottom: 5px; +} +.home #root.v1 .bottom #cool-stuff .highlights .highlight a:hover { + border-bottom: 5px solid #49111C; + padding-bottom: 0; +} +.home #root.v1 .bottom #cool-stuff .highlights .highlight .icon.icon-paperclip { + position: absolute; + top: 0; + left: 0; +} +.home #root.v1 .bottom #cool-stuff .highlights .highlight .icon.icon-paperclip:before { + content: ""; + display: block; + background-image: url("/icons/paperclip.svg"); + background-size: 100%; + position: absolute; + width: 50px; + height: 50px; + top: -10px; + left: -10px; +} +.home #root.v1 .bottom #cool-stuff .highlights .highlight:hover { + box-shadow: 0 0 5px 5px rgba(29, 31, 32, 0.45); +} +.home #root.v1 .bottom #work { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + background-color: #a6a695; + padding: 1rem 2rem; +} +.home #root.v1 .bottom #work > .title { + color: #49111C; + font-weight: bold; +} +.home #root.v1 .bottom #work > .title:after { + content: ""; + display: block; + width: 50px; + margin: 0 auto; + border-bottom: 5px solid #d7b94c; +} +.home #root.v1 .bottom #work .jobs { + display: flex; + justify-content: center; + flex-wrap: wrap; + gap: 2rem; + width: 100%; + height: 100%; +} +@media screen and (min-width: 800px) { + .home #root.v1 .bottom #work .jobs { + flex-wrap: nowrap; + } +} +.home #root.v1 .bottom #work .jobs .left, .home #root.v1 .bottom #work .jobs .right { + width: 100%; + height: 100%; +} +@media screen and (min-width: 800px) { + .home #root.v1 .bottom #work .jobs .left, .home #root.v1 .bottom #work .jobs .right { + width: 50%; + } +} +.home #root.v1 .bottom #work .jobs .left .title, .home #root.v1 .bottom #work .jobs .right .title { + text-align: center; + color: #49111C; +} +.home #root.v1 .bottom #work .jobs .left .wrapper { + display: flex; + flex-direction: column; + justify-content: space-between; +} +.home #root.v1 .bottom #work .jobs .left .job { + padding: 1rem 2rem; + margin-top: 1rem; + padding: 5px; + position: relative; + box-shadow: 0 0 5px 0px rgba(29, 31, 32, 0.45); +} +.home #root.v1 .bottom #work .jobs .left .job .title { + text-align: left; + color: #49111C; +} +.home #root.v1 .bottom #work .jobs .left .job:hover { + cursor: pointer; +} +.home #root.v1 .bottom #work .jobs .left .job.active { + border-left: 1rem solid #d7b94c; + box-shadow: 0 0 5px 5px rgba(29, 31, 32, 0.45); +} +.home #root.v1 .bottom #work .jobs .right .highlights { + display: block; + height: 100%; + width: 100%; + margin-top: 1rem; +} +.home #root.v1 .bottom #work .jobs .right .job-highlight { + padding: 1rem 2rem; +} +.home #root.v1 .bottom #work .jobs .right .job-highlight ul { + padding: 0; +} +.home #root.v1 .bottom #work .jobs .right .job-highlight.show { + display: block; + border-left: 1rem solid #d7b94c; + box-shadow: 0 0 5px 5px rgba(29, 31, 32, 0.45); +} +@media screen and (min-width: 800px) { + .home #root.v1 .bottom #work .jobs .right .job-highlight.show { + border-right: 1rem solid #d7b94c; + border-left: unset; + } +} +.home #root.v1 .bottom #work .jobs .right .job-highlight.hide { + display: none; +} +.home #root.v1 .bottom #contact { + display: block; + background-color: #1F2421; +} +.home #root.v1 .bottom #contact .title { + color: #FBFCFF; + text-align: center; +} +.home #root.v1 .bottom #contact .title:after { + content: ""; + display: block; + width: 75px; + margin: 0 auto; + border-bottom: 5px solid #696969; +} +.home #root.v1 .bottom #contact .info { + display: flex; + justify-content: center; + padding: 1rem 0; +} +.home #root.v1 .bottom #contact .info .icon.icon-email { + position: relative; +} +.home #root.v1 .bottom #contact .info .icon.icon-email:before { + content: ""; + display: block; + background-image: url("/icons/email.svg"); + background-size: 100%; + width: 30px; + height: 30px; +} +.home #root.v1 #continue { + display: block; + position: absolute; + bottom: 5rem; + left: 50%; + transform: translateX(-50%); + text-align: center; + width: 100%; + opacity: 0; + color: #FBFCFF; + animation: showText 0.1s forwards, continue 0.5s steps(50) forwards; + animation-delay: 4s; +} +@media screen and (min-width: 600px) { + .home #root.v1 #continue { + animation-delay: 6s; + } +} +.home #root.v1 #continue .icon.icon-arrow-down:after { + content: ""; + display: block; + position: absolute; + top: 0; + left: 50%; + transform: translateX(-50%); + background-image: url("/icons/arrow-down-top-line.svg"); + background-size: 100%; + width: 50px; + height: 50px; +} + +@keyframes typing { + 0% { + color: #d7b94c; + } + 100% { + width: 0; + color: #1d1f20; + } +} +@keyframes typing2 { + 0% { + color: #d7b94c; + } + 99.9% { + color: #d7b94c; + } + 100% { + width: 0; + color: #1d1f20; + } +} +@keyframes cursor { + 50% { + color: transparent; + } +} +@keyframes showText { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } +} +@keyframes continue { + 0% { + bottom: 5rem; + } + 100% { + bottom: 4rem; + } +} +@font-face { + font-family: RobotoSlab-Regular; + src: url("/fonts/RobotoSlab-Regular.ttf") format("opentype"); +} +@font-face { + font-family: RobotoSlab-Medium; + src: url("/fonts/RobotoSlab-Regular.ttf") format("opentype"); +} +@font-face { + font-family: RobotoSlab-Bold; + src: url("/fonts/RobotoSlab-Bold.ttf") format("opentype"); +} +@font-face { + font-family: RobotoSlab-Black; + src: url("/fonts/RobotoSlab-Black.ttf") format("opentype"); +} +@font-face { + font-family: AtomicAge-Regular; + src: url("/fonts/AtomicAge-Regular.ttf") format("opentype"); +} +@font-face { + font-family: Montserrat-Regular; + src: url("/fonts/Montserrat-Regular.ttf") format("opentype"); +} +@font-face { + font-family: Montserrat-Light; + src: url("/fonts/Montserrat-Light.ttf") format("opentype"); +} +@font-face { + font-family: Montserrat-Italic; + src: url("/fonts/Montserrat-Italic.ttf") format("opentype"); +} +@font-face { + font-family: Montserrat-Bold; + src: url("/fonts/Montserrat-Bold.ttf") format("opentype"); +} +@font-face { + font-family: Montserrat-SemiBold; + src: url("/fonts/Montserrat-SemiBold.ttf") format("opentype"); +} +@font-face { + font-family: Orbitron-Regular; + src: url("/fonts/Orbitron-Regular.ttf") format(); +} +h1, h2, h3, h4, h5, h6 { + font-family: AtomicAge-Regular; + letter-spacing: 2px; +} + +h1 { + font-size: 2rem; +} +@media screen and (min-width: 600px) { + h1 { + font-size: 3rem; + } +} + +h2 { + font-size: 1.75rem; +} +@media screen and (min-width: 600px) { + h2 { + font-size: 2.5rem; + } +} + +h3 { + font-size: 1.5rem; +} +@media screen and (min-width: 600px) { + h3 { + font-size: 2rem; + } +} + +h4 { + font-size: 1.25rem; +} +@media screen and (min-width: 600px) { + h4 { + font-size: 1.5rem; + } +} + +h5 { + font-size: 1rem; +} +@media screen and (min-width: 600px) { + h5 { + font-size: 1.25rem; + } +} + +h6 { + font-size: 1rem; +} +@media screen and (min-width: 600px) { + h6 { + font-size: 1em; + } +} + +p, a, li, span { + font-family: RobotoSlab-Regular; +} + +strong { + font-family: Montserrat-Bold; +} + +em { + font-family: Montserrat-Italic; +} + +u { + font-family: Montserrat-SemiBold; +} + +cite, q, small { + font-family: Orbitron-Regular; +} + +s { + font-family: Montserrat-SemiBold; +} + +/*# sourceMappingURL=landing.css.map */ diff --git a/assets/styles/main.css b/assets/styles/main.css new file mode 100644 index 0000000..3b358bd --- /dev/null +++ b/assets/styles/main.css @@ -0,0 +1,839 @@ +/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ +/* Document + ========================================================================== */ +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in iOS. + */ +html { + line-height: 1.15; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/* Sections + ========================================================================== */ +/** + * Remove the margin in all browsers. + */ +body { + margin: 0; +} + +/** + * Render the `main` element consistently in IE. + */ +main { + display: block; +} + +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/* Grouping content + ========================================================================== */ +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ +hr { + box-sizing: content-box; /* 1 */ + height: 0; /* 1 */ + overflow: visible; /* 2 */ +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ +pre { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/* Text-level semantics + ========================================================================== */ +/** + * Remove the gray background on active links in IE 10. + */ +a { + background-color: transparent; +} + +/** + * 1. Remove the bottom border in Chrome 57- + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ +abbr[title] { + border-bottom: none; /* 1 */ + text-decoration: underline; /* 2 */ + text-decoration: underline dotted; /* 2 */ +} + +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ +b, +strong { + font-weight: bolder; +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ +code, +kbd, +samp { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/** + * Add the correct font size in all browsers. + */ +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* Embedded content + ========================================================================== */ +/** + * Remove the border on images inside links in IE 10. + */ +img { + border-style: none; +} + +/* Forms + ========================================================================== */ +/** + * 1. Change the font styles in all browsers. + * 2. Remove the margin in Firefox and Safari. + */ +button, +input, +optgroup, +select, +textarea { + font-family: inherit; /* 1 */ + font-size: 100%; /* 1 */ + line-height: 1.15; /* 1 */ + margin: 0; /* 2 */ +} + +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ +button, +input { /* 1 */ + overflow: visible; +} + +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ +button, +select { /* 1 */ + text-transform: none; +} + +/** + * Correct the inability to style clickable types in iOS and Safari. + */ +button, +[type=button], +[type=reset], +[type=submit] { + -webkit-appearance: button; +} + +/** + * Remove the inner border and padding in Firefox. + */ +button::-moz-focus-inner, +[type=button]::-moz-focus-inner, +[type=reset]::-moz-focus-inner, +[type=submit]::-moz-focus-inner { + border-style: none; + padding: 0; +} + +/** + * Restore the focus styles unset by the previous rule. + */ +button:-moz-focusring, +[type=button]:-moz-focusring, +[type=reset]:-moz-focusring, +[type=submit]:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/** + * Correct the padding in Firefox. + */ +fieldset { + padding: 0.35em 0.75em 0.625em; +} + +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ +legend { + box-sizing: border-box; /* 1 */ + color: inherit; /* 2 */ + display: table; /* 1 */ + max-width: 100%; /* 1 */ + padding: 0; /* 3 */ + white-space: normal; /* 1 */ +} + +/** + * Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ +progress { + vertical-align: baseline; +} + +/** + * Remove the default vertical scrollbar in IE 10+. + */ +textarea { + overflow: auto; +} + +/** + * 1. Add the correct box sizing in IE 10. + * 2. Remove the padding in IE 10. + */ +[type=checkbox], +[type=radio] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ +[type=number]::-webkit-inner-spin-button, +[type=number]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ +[type=search] { + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ +} + +/** + * Remove the inner padding in Chrome and Safari on macOS. + */ +[type=search]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ +::-webkit-file-upload-button { + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ +} + +/* Interactive + ========================================================================== */ +/* + * Add the correct display in Edge, IE 10+, and Firefox. + */ +details { + display: block; +} + +/* + * Add the correct display in all browsers. + */ +summary { + display: list-item; +} + +/* Misc + ========================================================================== */ +/** + * Add the correct display in IE 10+. + */ +template { + display: none; +} + +/** + * Add the correct display in IE 10. + */ +[hidden] { + display: none; +} + +@font-face { + font-family: RobotoSlab-Regular; + src: url("/fonts/RobotoSlab-Regular.ttf") format("opentype"); +} +@font-face { + font-family: RobotoSlab-Medium; + src: url("/fonts/RobotoSlab-Regular.ttf") format("opentype"); +} +@font-face { + font-family: RobotoSlab-Bold; + src: url("/fonts/RobotoSlab-Bold.ttf") format("opentype"); +} +@font-face { + font-family: RobotoSlab-Black; + src: url("/fonts/RobotoSlab-Black.ttf") format("opentype"); +} +@font-face { + font-family: AtomicAge-Regular; + src: url("/fonts/AtomicAge-Regular.ttf") format("opentype"); +} +@font-face { + font-family: Montserrat-Regular; + src: url("/fonts/Montserrat-Regular.ttf") format("opentype"); +} +@font-face { + font-family: Montserrat-Light; + src: url("/fonts/Montserrat-Light.ttf") format("opentype"); +} +@font-face { + font-family: Montserrat-Italic; + src: url("/fonts/Montserrat-Italic.ttf") format("opentype"); +} +@font-face { + font-family: Montserrat-Bold; + src: url("/fonts/Montserrat-Bold.ttf") format("opentype"); +} +@font-face { + font-family: Montserrat-SemiBold; + src: url("/fonts/Montserrat-SemiBold.ttf") format("opentype"); +} +@font-face { + font-family: Orbitron-Regular; + src: url("/fonts/Orbitron-Regular.ttf") format(); +} +h1, h2, h3, h4, h5, h6 { + font-family: AtomicAge-Regular; + letter-spacing: 2px; +} + +h1 { + font-size: 2rem; +} +@media screen and (min-width: 600px) { + h1 { + font-size: 3rem; + } +} + +h2 { + font-size: 1.75rem; +} +@media screen and (min-width: 600px) { + h2 { + font-size: 2.5rem; + } +} + +h3 { + font-size: 1.5rem; +} +@media screen and (min-width: 600px) { + h3 { + font-size: 2rem; + } +} + +h4 { + font-size: 1.25rem; +} +@media screen and (min-width: 600px) { + h4 { + font-size: 1.5rem; + } +} + +h5 { + font-size: 1rem; +} +@media screen and (min-width: 600px) { + h5 { + font-size: 1.25rem; + } +} + +h6 { + font-size: 1rem; +} +@media screen and (min-width: 600px) { + h6 { + font-size: 1em; + } +} + +p, a, li, span { + font-family: RobotoSlab-Regular; + letter-spacing: 1px; +} + +strong { + font-family: Montserrat-Bold; +} + +em { + font-family: Montserrat-Italic; +} + +u { + font-family: Montserrat-SemiBold; +} + +cite, q, small { + font-family: Orbitron-Regular; +} + +s { + font-family: Montserrat-SemiBold; +} + +h1, +h2, +h3, +h4, +h5, +h6, +p, +a, +span, +time { + color: #FBFCFF; +} + +.secondary.layout--v1 { + display: block; + position: relative; + padding: 0.5rem 0.5rem; + background-color: #d7b94c; +} +.secondary.layout--v1 #root { + display: flex; + flex-direction: column; +} +@media (min-width: 800px) { + .secondary.layout--v1 #root { + display: grid; + grid-template-columns: 25% 75%; + grid-template-rows: 1fr; + margin: 0 auto; + padding: 1rem 1rem; + } +} +.secondary.layout--v1 #root { + gap: 1rem; + position: relative; + width: 100%; + height: 100%; + min-height: 100vh; + max-width: 1200px; + background-color: #1F2421; + box-shadow: 0 0 5px 10px rgba(29, 31, 32, 0.45); +} +.secondary.layout--v1 #root main { + padding: 1rem 1rem; +} +.secondary.layout--v1.menu-open, .secondary.layout--v1.photo-open { + overflow: hidden; +} +.secondary.layout--v1.photo-open .overlay { + display: block; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: #171A21; + opacity: 0.9; +} + +header { + display: block; + position: sticky; + overflow: auto; + width: 100%; + height: 50px; + top: 0; + padding-bottom: 1rem; + background-color: #1F2421; +} +@media (min-width: 600px) { + header { + height: 500px; + } +} +header.open { + overflow: visible; +} +header.open .top h1 { + display: none; +} +header nav.main { + display: block; + position: relative; +} +@media (min-width: 600px) { + header nav.main { + display: flex; + flex-direction: column; + gap: 2rem; + } +} +header nav.main .top { + display: flex; +} +header nav.main .top h1 { + margin: 0; +} +header nav.main .top h1 a { + display: block; + position: relative; + top: 1rem; + left: 1rem; + font-size: 1.5rem; + text-decoration: none; + color: #1d1f20; + background-color: #d7b94c; + border: 2px solid #d7b94c; + padding: 2px 2px; +} +header nav.main .top h1 a:hover { + color: #d7b94c; + background-color: unset; +} +header nav.main .top .icon.icon-menu { + display: block; + position: absolute; + top: 1rem; + right: 1rem; + width: 35px; + height: 35px; + z-index: 999; + transition: right 100ms ease; +} +@media screen and (min-width: 600px) { + header nav.main .top .icon.icon-menu { + display: none; + } +} +header nav.main .top .icon.icon-menu:before { + content: ""; + display: block; + background-image: url("/icons/menu-grid.svg"); + background-size: 100%; + position: absolute; + width: 35px; + height: 35px; +} +header nav.main .top .icon.icon-menu:hover { + cursor: pointer; +} +header nav.main .top .icon.icon-menu.open { + right: 325px; +} +header nav.main .top .icon.icon-menu.open:before { + background-image: url("/icons/menu-close.svg"); +} +header nav.main menu { + position: absolute; + right: 0; + top: 0; + width: 0; + background-color: #d7b94c; + overflow: hidden; + padding: 0; + margin: 0; + transition: width 100ms ease; +} +@media (min-width: 600px) { + header nav.main menu { + position: relative; + top: unset; + right: unset; + width: 100%; + transition: unset; + background-color: unset; + } +} +header nav.main menu.open { + width: 300px; + box-shadow: 0 0 5px 10px rgba(29, 31, 32, 0.45); +} +header nav.main menu li { + padding: 1rem 2rem; +} +header nav.main menu li a { + display: block; + color: #FBFCFF; + text-decoration: none; +} +header nav.main menu li a:hover { + text-decoration: underline; +} + +.posts .list ul { + list-style: none; + padding: 0; +} +.posts .list ul li { + padding: 1rem 0; +} +.posts .list ul li a { + color: #FBFCFF; + text-decoration: none; + display: block; +} +.posts .list ul li a .post-title { + margin: 0; +} + +.photos { + display: block; +} +.photos .albums { + display: flex; + flex-direction: column; + width: 100%; +} +@media (min-width: 800px) { + .photos .albums { + display: grid; + grid-template-columns: 1fr 1fr; + grid-template-rows: auto; + } +} +.photos .albums { + gap: 1rem; + list-style: none; + padding: 0; +} +.photos .albums .album { + display: block; + width: 100%; +} +.photos .albums .album a { + display: block; + position: relative; + color: white; + text-decoration: none; + overflow: hidden; +} +.photos .albums .album a img { + display: block; + width: 100%; + height: auto; +} +.photos .albums .album a .title, .photos .albums .album a .date, .photos .albums .album a .overlay { + position: absolute; + visibility: visible; + margin: 0; +} +.photos .albums .album a .title, .photos .albums .album a .date, .photos .albums .album a .category { + z-index: 2; +} +.photos .albums .album a .title { + top: 1rem; + left: 1rem; +} +.photos .albums .album a .date { + bottom: 1rem; + left: 1rem; + font-weight: bold; +} +.photos .albums .album a .overlay { + width: 100%; + height: auto; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.333); + z-index: 1; +} +.photos .albums .album a:hover .title, .photos .albums .album a:hover .date, .photos .albums .album a:hover .category, .photos .albums .album a:hover .overlay { + visibility: hidden; +} +.photos .albums .album a:hover img { + transform: scale(1.01); + transition: transform 100ms ease-in-out; +} +.photos img { + width: 100%; +} + +#album .title { + margin: 0; +} +#album .meta { + border-bottom: 5px solid #a6a695; +} +#album .photos { + display: flex; + flex-direction: column; + width: 100%; +} +@media (min-width: 800px) { + #album .photos { + display: grid; + grid-template-columns: 1fr 1fr; + grid-template-rows: auto; + } +} +#album .photos { + gap: 1rem; + list-style: none; + padding: 0; +} +#album .photos .photo { + width: 100%; + overflow: hidden; +} +#album .photos .photo img { + transition: transform 100ms ease-in-out; +} +#album .photos .photo:hover { + cursor: pointer; +} +#album .photos .photo:hover img { + transform: scale(1.01); + transition: transform 100ms ease-in-out; +} + +#open-image { + display: none; + position: absolute; + top: 50%; + left: 0; + transform: translateY(-50%); + z-index: 999; +} +#open-image .close { + cursor: pointer; + font-size: 2rem; + position: absolute; + right: 0; + top: 0; +} +#open-image img { + width: 100%; + height: auto; +} +#open-image #details { + display: block; + height: auto; + padding: 1rem 1rem; + background-color: #a6a695; +} +#open-image #details p { + margin: 0; +} +#open-image #details #caption { + font-size: 1.5rem; + padding-bottom: 1rem; +} +#open-image #details #location, #open-image #details #date, #open-image #details #equipment { + font-size: 1.25rem; +} +#open-image.open { + display: block; +} + +.posts { + display: block; +} +.posts h2, .posts h3 { + position: relative; + margin: 0; + width: fit-content; +} +.posts h2:after, .posts h3:after { + content: ""; + display: block; + width: 75px; + height: 5px; + background-color: #a6a695; +} +.posts .list { + padding-top: 1rem; + border-top: 5px solid #d7b94c; +} +.posts .list .post a .title { + padding: 0.5rem 0; +} +.posts .list .post a:hover { + text-decoration: underline; + text-decoration-color: #a6a695; +} + +.post { + display: block; +} +.post .title { + margin: 0.5rem 0; +} +.post .meta { + padding-bottom: 1rem; + border-bottom: 5px solid #a6a695; +} +.post .meta .admin-actions { + padding-bottom: 1rem; +} +.post .meta .published { + font-size: 1.125rem; +} +.post .meta .category { + font-size: 1.125rem; +} +.post .text p { + font-size: 1.25rem; + line-height: 1.5; +} + +/*# sourceMappingURL=main.css.map */ diff --git a/assets/styles/scss/brain.scss b/assets/styles/scss/brain.scss new file mode 100644 index 0000000..685f968 --- /dev/null +++ b/assets/styles/scss/brain.scss @@ -0,0 +1,6 @@ +@use './brain/form'; +@use './brain/layout'; + +body { + background-color: lightgrey; +} \ No newline at end of file diff --git a/assets/styles/scss/brain/_form.scss b/assets/styles/scss/brain/_form.scss new file mode 100644 index 0000000..54500ca --- /dev/null +++ b/assets/styles/scss/brain/_form.scss @@ -0,0 +1,36 @@ +.page { + max-width: 800px; + width: 100%; + margin: 0 auto; + + h2 { + margin: 0; + } + + .row { + display: block; + padding: 1rem 0; + + label { + display: block; + } + + input { + height: 30px; + width: 300px; + } + + #post_published { + width: 30px; + height: 30px; + } + + #post_save { + width: 100px; + height: 30px; + background-color: green; + border: none; + color: white; + } + } +} \ No newline at end of file diff --git a/assets/styles/scss/brain/_layout.scss b/assets/styles/scss/brain/_layout.scss new file mode 100644 index 0000000..73539d0 --- /dev/null +++ b/assets/styles/scss/brain/_layout.scss @@ -0,0 +1,33 @@ +#brain-wrapper { + header { + .level-1 { + display: flex; + justify-content: center; + align-items: flex-start; + + position: relative; + + list-style-type: none; + + &--item { + padding: 1rem 2rem; + } + + .level-2 { + display: none; + margin: 0; + padding: 0; + + &.open { + display: block; + position: absolute; + + } + + &--item { + padding: 1rem 0; + } + } + } + } +} \ No newline at end of file diff --git a/assets/styles/scss/front/_layout.scss b/assets/styles/scss/front/_layout.scss new file mode 100644 index 0000000..0b6cd90 --- /dev/null +++ b/assets/styles/scss/front/_layout.scss @@ -0,0 +1,57 @@ +@use '../shared/colors' as colors; + +.secondary.layout--v1 { + display: block; + position: relative; + padding: 0.5rem 0.5rem; + background-color: colors.$primaryYellow; + + #root { + display: flex; + flex-direction: column; + + @media (min-width: 800px) { + display: grid; + grid-template-columns: 25% 75%; + grid-template-rows: 1fr; + + margin: 0 auto; + padding: 1rem 1rem; + } + + gap: 1rem; + position: relative; + + width: 100%; + height: 100%; + min-height: 100vh; + max-width: 1200px; + + + + background-color: colors.$carbonBlack; + box-shadow: 0 0 5px 10px rgba(29, 31, 32, 0.45); + + main { + padding: 1rem 1rem; + } + } + + &.menu-open, + &.photo-open { + overflow: hidden; + } + + &.photo-open { + .overlay { + display: block; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: colors.$inkBlack; + opacity: .9; + } + } +} diff --git a/assets/styles/scss/front/_lists.scss b/assets/styles/scss/front/_lists.scss new file mode 100644 index 0000000..406aba9 --- /dev/null +++ b/assets/styles/scss/front/_lists.scss @@ -0,0 +1,24 @@ +@use '../shared/colors'; + +.posts { + .list { + ul { + list-style: none; + padding: 0; + + li { + padding: 1rem 0; + + a { + color: colors.$primaryWhite; + text-decoration: none; + display: block; + + .post-title { + margin: 0; + } + } + } + } + } +} \ No newline at end of file diff --git a/assets/styles/scss/front/_menu.scss b/assets/styles/scss/front/_menu.scss new file mode 100644 index 0000000..e175a5b --- /dev/null +++ b/assets/styles/scss/front/_menu.scss @@ -0,0 +1,147 @@ +@use '../shared/colors' as colors; + +header { + display: block; + position: sticky; + overflow: auto; + width: 100%; + height: 50px; + top: 0; + padding-bottom: 1rem; + background-color: colors.$carbonBlack; + + @media (min-width: 600px) { + height: 500px; + + } + + &.open { + overflow: visible; + } + + &.open { + .top { + h1 { + display: none; + } + } + } + + + nav.main { + display: block; + position: relative; + + @media (min-width: 600px) { + display: flex; + flex-direction: column; + gap: 2rem; + } + + .top { + display: flex; + + h1 { + margin: 0; + + a { + display: block; + position: relative; + top: 1rem; + left: 1rem; + + font-size: 1.5rem; + text-decoration: none; + color: colors.$primaryBlack; + background-color: colors.$primaryYellow; + border: 2px solid colors.$primaryYellow; + padding: 2px 2px; + + &:hover { + color: colors.$primaryYellow; + background-color: unset; + } + } + } + + .icon { + &.icon-menu { + display: block; + position: absolute; + top: 1rem; + right: 1rem; + width: 35px; + height: 35px; + z-index: 999; + transition: right 100ms ease; + + @media screen and (min-width: 600px) { + display: none; + } + + &:before { + content: ''; + display: block; + background-image: url('/icons/menu-grid.svg'); + background-size: 100%; + position: absolute; + width: 35px; + height: 35px; + } + + &:hover { + cursor: pointer; + } + + &.open { + right: 325px; + &:before { + background-image: url('/icons/menu-close.svg'); + } + + } + } + } + } + + menu { + position: absolute; + right: 0; + top: 0; + width: 0; + background-color: colors.$primaryYellow; + overflow: hidden; + padding: 0; + margin: 0; + transition: width 100ms ease; + + @media (min-width: 600px) { + position: relative; + top: unset; + right: unset; + width: 100%; + transition: unset; + background-color: unset; + } + + &.open { + width: 300px; + box-shadow: 0 0 5px 10px rgba(29, 31, 32, 0.45); + } + + li { + padding: 1rem 2rem; + + a { + display: block; + color: colors.$primaryWhite; + text-decoration: none; + + &:hover { + text-decoration: underline; + } + } + } + } + } +} \ No newline at end of file diff --git a/assets/styles/scss/front/_photos.scss b/assets/styles/scss/front/_photos.scss new file mode 100644 index 0000000..d33ca2b --- /dev/null +++ b/assets/styles/scss/front/_photos.scss @@ -0,0 +1,179 @@ +@use '../shared/colors' as colors; +.photos { + display: block; + + .albums { + + display: flex; + flex-direction: column; + width: 100%; + + @media (min-width: 800px) { + display: grid; + grid-template-columns: 1fr 1fr; + grid-template-rows: auto; + } + + gap: 1rem; + list-style: none; + padding: 0; + + .album { + display: block; + width: 100%; + + a { + display: block; + position: relative; + + color: white; + text-decoration: none; + overflow: hidden; + + img { + display: block; + width: 100%; + height: auto; + } + + .title, .date, .overlay { + position: absolute; + visibility: visible; + margin: 0; + } + + .title, .date, .category { + z-index: 2; + } + + .title { + top: 1rem; + left: 1rem; + } + + .date { + bottom: 1rem; + left: 1rem; + font-weight: bold; + } + + .overlay { + width: 100%; + height: auto; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.333); + z-index: 1; + } + + &:hover { + .title, .date, .category, .overlay { + visibility: hidden; + } + + img { + transform: scale(1.01); + transition: transform 100ms ease-in-out; + } + } + } + } + } + + img { + width: 100%; + } +} + +#album { + .title { + margin: 0; + } + .meta { + border-bottom: 5px solid colors.$computerBorder; + } + + .photos { + display: flex; + flex-direction: column; + width: 100%; + + @media (min-width: 800px) { + display: grid; + grid-template-columns: 1fr 1fr; + grid-template-rows: auto; + } + + gap: 1rem; + list-style: none; + padding: 0; + + .photo { + width: 100%; + overflow: hidden; + + img { + //width: 100%; + transition: transform 100ms ease-in-out; + } + + &:hover { + cursor: pointer; + + img { + transform: scale(1.01); + transition: transform 100ms ease-in-out; + } + } + } + } +} + +#open-image { + display: none; + position: absolute; + top: 50%; + left: 0; + transform: translateY(-50%); + z-index: 999; + + .close { + cursor: pointer; + font-size: 2rem; + position: absolute; + right: 0; + top: 0; + } + + img { + width: 100%; + height: auto; + } + + #details { + display: block; + height: auto; + padding: 1rem 1rem; + + background-color: colors.$computerBorder; + + p { + margin: 0; + } + + #caption { + font-size: 1.5rem; + padding-bottom: 1rem; + } + + #location, #date, #equipment { + font-size: 1.25rem; + } + } + + &.open { + display: block; + } +} \ No newline at end of file diff --git a/assets/styles/scss/front/_posts.scss b/assets/styles/scss/front/_posts.scss new file mode 100644 index 0000000..a4a214f --- /dev/null +++ b/assets/styles/scss/front/_posts.scss @@ -0,0 +1,73 @@ +@use '../shared/colors' as colors; + +.posts { + display: block; + h2, h3 { + position: relative; + margin: 0; + width: fit-content; + + &:after { + content: ''; + display: block; + + width: 75px; + height: 5px; + + background-color: colors.$computerBorder; + } + } + .intro { + //color: colors.$primaryWhite; + } + + .list { + padding-top: 1rem; + border-top: 5px solid colors.$primaryYellow; + + .post { + + a { + .title { + padding: 0.5rem 0; + } + + &:hover { + text-decoration: underline; + text-decoration-color: colors.$computerBorder; + } + } + } + } +} + +.post { + display: block; + + .title { + margin: 0.5rem 0; + } + + .meta { + padding-bottom: 1rem; + + border-bottom: 5px solid colors.$computerBorder; + + .admin-actions { + padding-bottom: 1rem; + } + + .published { + font-size: 1.125rem; + } + + .category { + font-size: 1.125rem; + } + } + + .text p { + font-size: 1.25rem; + line-height: 1.5; + } +} \ No newline at end of file diff --git a/assets/styles/scss/front/_typography.scss b/assets/styles/scss/front/_typography.scss new file mode 100644 index 0000000..680255f --- /dev/null +++ b/assets/styles/scss/front/_typography.scss @@ -0,0 +1,15 @@ +@use '../shared/colors' as colors; + +h1, +h2, +h3, +h4, +h5, +h6, +p, +a, +span, +time { + color: colors.$primaryWhite; +} + diff --git a/assets/styles/scss/landing.scss b/assets/styles/scss/landing.scss new file mode 100644 index 0000000..bbf7dfe --- /dev/null +++ b/assets/styles/scss/landing.scss @@ -0,0 +1,2 @@ +@use './landing/computer'; +@use './shared/fonts'; \ No newline at end of file diff --git a/assets/styles/scss/landing/_computer.scss b/assets/styles/scss/landing/_computer.scss new file mode 100644 index 0000000..546b138 --- /dev/null +++ b/assets/styles/scss/landing/_computer.scss @@ -0,0 +1,619 @@ +@use '../shared/colors' as colors; + +.home { + display: flex; + align-items: center; + flex-direction: column; + background-color: colors.$primaryGrey; + margin: 0; + + header { + width: 100%; + + h1 { + margin: 0; + + a { + display: block; + font-size: 1.5rem; + text-decoration: none; + color: colors.$primaryBlack; + background-color: colors.$primaryYellow; + border: 2px solid colors.$primaryYellow; + padding: 2px 2px; + + &:hover { + color: colors.$primaryYellow; + background-color: unset; + } + } + } + + nav { + display: flex; + justify-content: space-between; + align-items: center; + padding: 1rem 2rem; + overflow: hidden; + position: relative; + + .icon { + &.icon-menu { + position: absolute; + z-index: 999; + display: block; + right: 2rem; + width: 30px; + height: 30px; + transition: right 100ms ease; + + @media screen and (min-width: 600px) { + display: none; + } + + &:before { + content: ''; + display: block; + background-image: url('/icons/menu-grid.svg'); + background-size: 100%; + position: absolute; + width: 30px; + height: 30px; + } + + &:hover { + cursor: pointer; + } + + &.open { + right: calc(1/3 * 100% + 1rem); + } + } + } + + .front-menu { + display: flex; + flex-direction: column; + gap: 1rem; + overflow: hidden; + + position: fixed; + right: -100%; + top: 1rem; + margin: 0; + padding: 0; + + transition: right 200ms ease; + + &.open { + right: 1rem; + } + + @media screen and (min-width: 600px) { + flex-direction: row; + position: relative; + top: unset; + right: unset; + } + + list-style: none; + + li { + a { + display: block; + font-family: AtomicAge-Regular; + color: colors.$primaryYellow; + font-size: 1.5rem; + text-decoration: none; + padding-bottom: 2px; + + &:hover { + border-bottom: 2px solid colors.$primaryYellow; + padding-bottom: 0; + } + } + } + } + } + } + + #root { + &.v1 { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + height: auto; + width: 100%; + margin: 0 auto; + + section { + margin: 0; + padding: 1rem 0; + + .title { + margin: 0; + } + } + + .top { + display: flex; + min-height: 100vh; + justify-content: center; + align-items: center; + width: 100%; + + .computer { + display: block; + max-width: 1024px; + max-height: 1024px; + width: 100%; + background-color: colors.$primaryBlack; + border: 2rem solid colors.$computerBorder; + padding: 1rem 1rem; + + box-shadow: 0 0 5px 10px rgba(29, 31, 32, 0.45); + + .heading { + margin: 0; + font-size: 1rem; + font-family: Montserrat-Light; + color: colors.$primaryYellow; + position: relative; + padding-left: 1rem; + + @media screen and (min-width: 600px) { + font-size: 2rem; + } + + &:before { + content: '>'; + position: absolute; + left: 0; + width: 100%; + //background: #1d1f20; + } + + &:after { + content: "|"; + position: absolute; + right: 0; + width: 100%; + background: colors.$primaryBlack; + animation: typing 0.5s steps(16) forwards, + cursor 1s infinite; + + @media screen and (min-width: 600px) { + animation: typing 0.5s steps(16) forwards, + cursor 1s infinite; + } + } + } + + #intro { + width: fit-content; + + .heading { + width: 240px; + } + } + + #body { + width: fit-content; + + .about { + opacity: 0; + animation: showText 0.1s forwards; + animation-delay: 1s; + font-size: 1rem; + color: colors.$primaryYellow; + + @media screen and (min-width: 600px) { + font-size: 2rem; + animation: showText 0.1s forwards; + animation-delay: 1s; + } + } + } + + #outro { + width: fit-content; + + .heading { + width: 160px; + + &:after{ + color: colors.$primaryBlack; + animation: typing 0.5s steps(16) forwards, + cursor 1s infinite; + animation-delay: 2.5s; + + @media screen and (min-width: 600px) { + animation: typing 0.5s steps(16) forwards, + cursor 1s infinite; + animation-delay: 2.5s; + } + } + } + + .menu { + opacity: 0; + animation: showText 0.1s forwards; + animation-delay: 3s; + display: flex; + flex-wrap: wrap; + gap: 1rem; + padding-top: 2rem; + padding-bottom: 2rem; + + @media screen and (min-width: 600px) { + animation-delay: 3.5s; + } + + a { + font-size: 1rem; + color: colors.$primaryYellow; + cursor: pointer; + + @media screen and (min-width: 600px) { + font-size: 2rem; + } + } + } + } + } + } + + .bottom { + width: 100%; + height: 100%; + + section { + box-shadow: 0 0 5px 4px rgba(29, 31, 32, 0.45); + margin: 4rem 0; + } + + #cool-stuff{ + display: flex; + flex-direction: column; + align-items: center; + width: 100%; + height: auto; + background-color: colors.$primaryYellow; + padding: 2rem 0; + + .title { + &:after { + content: ''; + display: block; + width: 150px; + margin: 0 auto; + border-bottom: 5px solid colors.$primaryGreen; + } + } + + .highlights { + display: flex; + justify-content: center; + align-items: center; + flex-wrap: wrap; + gap: 2rem; + position: relative; + + height: 100%; + width: 100%; + padding-top: 1rem; + + .highlight { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + align-self: stretch; + padding: 1rem 1rem; + position: relative; + + width: 100%; + height: auto; + max-width: 400px; + + box-shadow: 0 0 5px 0 rgba(29, 31, 32, 0.45); + + img { + width: 75%; + } + + p { + font-size: 1.25rem; + text-align: center; + } + + a { + display: block; + font-family: Orbitron-Regular; + color: colors.$primaryRed; + font-size: 1.5rem; + font-weight: bold; + text-decoration: none; + padding-bottom: 5px; + + &:hover { + border-bottom: 5px solid colors.$primaryRed; + padding-bottom: 0; + } + } + + .icon { + &.icon-paperclip { + position: absolute; + top: 0; + left: 0; + + &:before { + content: ''; + display: block; + background-image: url('/icons/paperclip.svg'); + background-size: 100%; + position: absolute; + width: 50px; + height: 50px; + top: -10px; + left: -10px; + } + } + } + + &:hover { + box-shadow: 0 0 5px 5px rgba(29, 31, 32, 0.45); + } + } + + } + } + + #work { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + background-color: colors.$computerBorder; + padding: 1rem 2rem; + + > .title { + color: colors.$primaryRed; + font-weight: bold; + + &:after { + content: ''; + display: block; + width: 50px; + margin: 0 auto; + border-bottom: 5px solid colors.$primaryYellow; + + } + } + + .jobs { + display: flex; + justify-content: center; + flex-wrap: wrap; + gap: 2rem; + width: 100%; + height: 100%; + + @media screen and (min-width: 800px) { + flex-wrap: nowrap; + } + + .left, .right { + width: 100%; + height: 100%; + + @media screen and (min-width: 800px) { + width: 50%; + } + + .title { + text-align: center; + color: colors.$primaryRed; + } + } + + .left { + .wrapper { + display: flex; + flex-direction: column; + justify-content: space-between; + } + + .job { + padding: 1rem 2rem; + margin-top: 1rem; + padding: 5px; + position: relative; + box-shadow: 0 0 5px 0px rgba(29, 31, 32, 0.45); + + .title { + text-align: left; + color: colors.$primaryRed; + } + + &:hover { + cursor: pointer; + } + + &.active { + border-left: 1rem solid colors.$primaryYellow; + box-shadow: 0 0 5px 5px rgba(29, 31, 32, 0.45); + } + } + } + + .right { + .highlights { + display: block; + height: 100%; + width: 100%; + margin-top: 1rem; + } + + .job-highlight { + //width: 100%; + //height: 100%; + padding: 1rem 2rem; + + ul { + padding: 0; + //margin: 0; + } + + &.show { + display: block; + border-left: 1rem solid colors.$primaryYellow; + box-shadow: 0 0 5px 5px rgba(29, 31, 32, 0.45); + + @media screen and (min-width: 800px) { + border-right: 1rem solid colors.$primaryYellow; + border-left: unset; + } + } + + &.hide { + display: none; + } + } + } + + + } + } + + #contact { + display: block; + background-color: colors.$carbonBlack; + + .title { + color: colors.$primaryWhite; + text-align: center; + + &:after { + content: ''; + display: block; + width: 75px; + margin: 0 auto; + border-bottom: 5px solid colors.$primaryGrey; + + } + } + + .info { + display: flex; + justify-content: center; + padding: 1rem 0; + + .icon { + &.icon-email { + position: relative; + + &:before { + content: ''; + display: block; + background-image: url('/icons/email.svg'); + background-size: 100%; + + width: 30px; + height: 30px; + } + } + } + } + + } + } + + #continue { + display: block; + position: absolute; + bottom: 5rem; + left: 50%; + transform: translateX(-50%); + text-align: center; + width: 100%; + opacity: 0; + color: colors.$primaryWhite; + animation: showText 0.1s forwards, + continue 0.5s steps(50) forwards; + + animation-delay: 4s; + + @media screen and (min-width: 600px) { + animation-delay: 6s; + } + + .icon { + &.icon-arrow-down { + &:after { + content: ''; + display: block; + position: absolute; + top: 0; + left: 50%; + transform: translateX(-50%); + + background-image: url('/icons/arrow-down-top-line.svg'); + background-size: 100%; + width: 50px; + height: 50px; + } + } + } + } + } + } +} + +@keyframes typing { + 0% { + color: colors.$primaryYellow; + } + 100% { + width: 0; + color: colors.$primaryBlack; + } +} + +@keyframes typing2 { + 0% { + color: colors.$primaryYellow; + } + 99.9% { + color: colors.$primaryYellow; + } + 100% { + width: 0; + color: colors.$primaryBlack; + } +} + +@keyframes cursor { + 50% { color: transparent } +} + +@keyframes showText { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +@keyframes continue { + 0% { + bottom: 5rem; + } + 100% { + bottom: 4rem; + } +} \ No newline at end of file diff --git a/assets/styles/scss/main.scss b/assets/styles/scss/main.scss new file mode 100644 index 0000000..3a3f7dc --- /dev/null +++ b/assets/styles/scss/main.scss @@ -0,0 +1,9 @@ +@use './shared/normalize'; +@use './shared/fonts'; +@use './front/typography'; +@use './front/layout'; +@use './front/menu'; + +@use './front/lists'; +@use './front/photos'; +@use './front/posts'; \ No newline at end of file diff --git a/assets/styles/scss/shared/_colors.scss b/assets/styles/scss/shared/_colors.scss new file mode 100644 index 0000000..265c3e1 --- /dev/null +++ b/assets/styles/scss/shared/_colors.scss @@ -0,0 +1,18 @@ +$primaryRed: #49111C; +$crimson: #9B1D20; +$primaryYellow: #d7b94c; +$primaryGreen: #04392f; +$primaryBlack: #1d1f20; +$primaryWhite: #FBFCFF; +$primaryGrey: #696969; +$primaryLightGrey: #a8a8a8; + +$green: #0E6E0C; + +//Landing +$computerBorder: #a6a695; + +$evergreen: $primaryGreen; +$inkBlack: #171A21; +$fern: #3F784C; +$carbonBlack: #1F2421; \ No newline at end of file diff --git a/assets/styles/scss/shared/_fonts.scss b/assets/styles/scss/shared/_fonts.scss new file mode 100644 index 0000000..114d521 --- /dev/null +++ b/assets/styles/scss/shared/_fonts.scss @@ -0,0 +1,135 @@ +//headings +@font-face { + font-family: RobotoSlab-Regular; + src: url('/fonts/RobotoSlab-Regular.ttf') format('opentype'); +} + +@font-face { + font-family: RobotoSlab-Medium; + src: url('/fonts/RobotoSlab-Regular.ttf') format('opentype'); +} + +@font-face { + font-family: RobotoSlab-Bold; + src: url('/fonts/RobotoSlab-Bold.ttf') format('opentype'); +} + +@font-face { + font-family: RobotoSlab-Black; + src: url('/fonts/RobotoSlab-Black.ttf') format('opentype'); +} + +@font-face { + font-family: AtomicAge-Regular; + src: url('/fonts/AtomicAge-Regular.ttf') format('opentype'); +} + +//non-headings +@font-face { + font-family: Montserrat-Regular; + src: url('/fonts/Montserrat-Regular.ttf') format('opentype'); +} + +@font-face { + font-family: Montserrat-Light; + src: url('/fonts/Montserrat-Light.ttf') format('opentype'); +} + +@font-face { + font-family: Montserrat-Italic; + src: url('/fonts/Montserrat-Italic.ttf') format('opentype'); +} + +@font-face { + font-family: Montserrat-Bold; + src: url('/fonts/Montserrat-Bold.ttf') format('opentype'); +} + +@font-face { + font-family: Montserrat-SemiBold; + src: url('/fonts/Montserrat-SemiBold.ttf') format('opentype'); +} + +@font-face { + font-family: Orbitron-Regular; + src: url('/fonts/Orbitron-Regular.ttf') format(); +} + +h1, h2, h3, h4, h5, h6 { + font-family: AtomicAge-Regular; + letter-spacing: 2px; +} + +h1 { + + font-size: 2rem; + + @media screen and (min-width: 600px) { + font-size: 3rem; + } +} + +h2 { + font-size: 1.75rem; + + @media screen and (min-width: 600px) { + font-size: 2.5rem; + } +} + +h3 { + font-size: 1.5rem; + + @media screen and (min-width: 600px) { + font-size: 2rem; + } +} + +h4 { + font-size: 1.25rem; + + @media screen and (min-width: 600px) { + font-size: 1.5rem; + } +} + +h5 { + font-size: 1rem; + + @media screen and (min-width: 600px) { + font-size: 1.25rem; + } +} + +h6 { + font-size: 1rem; + + @media screen and (min-width: 600px) { + font-size: 1em; + } +} + +p, a, li, span { + font-family: RobotoSlab-Regular; + letter-spacing: 1px; +} + +strong { + font-family: Montserrat-Bold; +} + +em { + font-family: Montserrat-Italic; +} + +u { + font-family: Montserrat-SemiBold; +} + +cite, q, small { + font-family: Orbitron-Regular; +} + +s { + font-family: Montserrat-SemiBold; +} \ No newline at end of file diff --git a/assets/styles/scss/shared/_normalize.scss b/assets/styles/scss/shared/_normalize.scss new file mode 100644 index 0000000..192eb9c --- /dev/null +++ b/assets/styles/scss/shared/_normalize.scss @@ -0,0 +1,349 @@ +/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ + +/* Document + ========================================================================== */ + +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in iOS. + */ + +html { + line-height: 1.15; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/* Sections + ========================================================================== */ + +/** + * Remove the margin in all browsers. + */ + +body { + margin: 0; +} + +/** + * Render the `main` element consistently in IE. + */ + +main { + display: block; +} + +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/* Grouping content + ========================================================================== */ + +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ + +hr { + box-sizing: content-box; /* 1 */ + height: 0; /* 1 */ + overflow: visible; /* 2 */ +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +pre { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Remove the gray background on active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * 1. Remove the bottom border in Chrome 57- + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ + +abbr[title] { + border-bottom: none; /* 1 */ + text-decoration: underline; /* 2 */ + text-decoration: underline dotted; /* 2 */ +} + +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ + +b, +strong { + font-weight: bolder; +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +code, +kbd, +samp { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/** + * Add the correct font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Remove the border on images inside links in IE 10. + */ + +img { + border-style: none; +} + +/* Forms + ========================================================================== */ + +/** + * 1. Change the font styles in all browsers. + * 2. Remove the margin in Firefox and Safari. + */ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; /* 1 */ + font-size: 100%; /* 1 */ + line-height: 1.15; /* 1 */ + margin: 0; /* 2 */ +} + +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ + +button, +input { /* 1 */ + overflow: visible; +} + +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ + +button, +select { /* 1 */ + text-transform: none; +} + +/** + * Correct the inability to style clickable types in iOS and Safari. + */ + +button, +[type="button"], +[type="reset"], +[type="submit"] { + -webkit-appearance: button; +} + +/** + * Remove the inner border and padding in Firefox. + */ + +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; +} + +/** + * Restore the focus styles unset by the previous rule. + */ + +button:-moz-focusring, +[type="button"]:-moz-focusring, +[type="reset"]:-moz-focusring, +[type="submit"]:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/** + * Correct the padding in Firefox. + */ + +fieldset { + padding: 0.35em 0.75em 0.625em; +} + +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ + +legend { + box-sizing: border-box; /* 1 */ + color: inherit; /* 2 */ + display: table; /* 1 */ + max-width: 100%; /* 1 */ + padding: 0; /* 3 */ + white-space: normal; /* 1 */ +} + +/** + * Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ + +progress { + vertical-align: baseline; +} + +/** + * Remove the default vertical scrollbar in IE 10+. + */ + +textarea { + overflow: auto; +} + +/** + * 1. Add the correct box sizing in IE 10. + * 2. Remove the padding in IE 10. + */ + +[type="checkbox"], +[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ + +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ + +[type="search"] { + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ +} + +/** + * Remove the inner padding in Chrome and Safari on macOS. + */ + +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ + +::-webkit-file-upload-button { + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ +} + +/* Interactive + ========================================================================== */ + +/* + * Add the correct display in Edge, IE 10+, and Firefox. + */ + +details { + display: block; +} + +/* + * Add the correct display in all browsers. + */ + +summary { + display: list-item; +} + +/* Misc + ========================================================================== */ + +/** + * Add the correct display in IE 10+. + */ + +template { + display: none; +} + +/** + * Add the correct display in IE 10. + */ + +[hidden] { + display: none; +} diff --git a/composer.json b/composer.json index f7073f7..e08b00d 100644 --- a/composer.json +++ b/composer.json @@ -37,6 +37,7 @@ "symfony/string": "8.0.*", "symfony/translation": "8.0.*", "symfony/twig-bundle": "8.0.*", + "symfony/ux-autocomplete": "^3.0", "symfony/ux-turbo": "^3.0", "symfony/validator": "8.0.*", "symfony/web-link": "8.0.*", diff --git a/composer.lock b/composer.lock index a57ee64..4e5e227 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "65abca745ae3808e65e51e93fab26cb2", + "content-hash": "26a3636c56c6fcac9b420294751a8bd7", "packages": [ { "name": "composer/semver", @@ -1367,242 +1367,6 @@ ], "time": "2026-01-02T08:56:05+00:00" }, - { - "name": "myclabs/deep-copy", - "version": "1.13.4", - "source": { - "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", - "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "conflict": { - "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3 <3.2.2" - }, - "require-dev": { - "doctrine/collections": "^1.6.8", - "doctrine/common": "^2.13.3 || ^3.2.2", - "phpspec/prophecy": "^1.10", - "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" - }, - "type": "library", - "autoload": { - "files": [ - "src/DeepCopy/deep_copy.php" - ], - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Create deep copies (clones) of your objects", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" - ], - "support": { - "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" - }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" - } - ], - "time": "2025-08-01T08:46:24+00:00" - }, - { - "name": "nikic/php-parser", - "version": "v5.7.0", - "source": { - "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82", - "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "ext-json": "*", - "ext-tokenizer": "*", - "php": ">=7.4" - }, - "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^9.0" - }, - "bin": [ - "bin/php-parse" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov" - } - ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], - "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0" - }, - "time": "2025-12-06T11:56:16+00:00" - }, - { - "name": "phar-io/manifest", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "54750ef60c58e43759730615a392c31c80e23176" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", - "reference": "54750ef60c58e43759730615a392c31c80e23176", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-phar": "*", - "ext-xmlwriter": "*", - "phar-io/version": "^3.0.1", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "support": { - "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2024-03-03T12:33:53+00:00" - }, - { - "name": "phar-io/version", - "version": "3.2.1", - "source": { - "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Library for handling version information and constraints", - "support": { - "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.2.1" - }, - "time": "2022-02-21T01:04:05+00:00" - }, { "name": "phpdocumentor/reflection-common", "version": "2.2.0", @@ -1826,480 +1590,6 @@ }, "time": "2026-01-25T14:56:51+00:00" }, - { - "name": "phpunit/php-code-coverage", - "version": "14.1.9", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "655533a65696bbc4231cd8027af150dadc40ec88" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/655533a65696bbc4231cd8027af150dadc40ec88", - "reference": "655533a65696bbc4231cd8027af150dadc40ec88", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xmlwriter": "*", - "nikic/php-parser": "^5.7.0", - "php": ">=8.4", - "phpunit/php-text-template": "^6.0", - "sebastian/complexity": "^6.0", - "sebastian/environment": "^9.2", - "sebastian/git-state": "^1.0", - "sebastian/lines-of-code": "^5.0", - "sebastian/version": "^7.0", - "theseer/tokenizer": "^2.0.1" - }, - "require-dev": { - "phpunit/phpunit": "^13.1" - }, - "suggest": { - "ext-pcov": "PHP extension that provides line coverage", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "14.1.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/14.1.9" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/php-code-coverage", - "type": "tidelift" - } - ], - "time": "2026-05-16T05:16:14+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "7.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "6e5aa1fb0a95b1703d83e721299ee18bb4e2de50" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6e5aa1fb0a95b1703d83e721299ee18bb4e2de50", - "reference": "6e5aa1fb0a95b1703d83e721299ee18bb4e2de50", - "shasum": "" - }, - "require": { - "php": ">=8.4" - }, - "require-dev": { - "phpunit/phpunit": "^13.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "7.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/7.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/php-file-iterator", - "type": "tidelift" - } - ], - "time": "2026-02-06T04:33:26+00:00" - }, - { - "name": "phpunit/php-invoker", - "version": "7.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "42e5c5cae0c65df12d1b1a3ab52bf3f50f244d88" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/42e5c5cae0c65df12d1b1a3ab52bf3f50f244d88", - "reference": "42e5c5cae0c65df12d1b1a3ab52bf3f50f244d88", - "shasum": "" - }, - "require": { - "php": ">=8.4" - }, - "require-dev": { - "ext-pcntl": "*", - "phpunit/phpunit": "^13.0" - }, - "suggest": { - "ext-pcntl": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "7.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Invoke callables with a timeout", - "homepage": "https://github.com/sebastianbergmann/php-invoker/", - "keywords": [ - "process" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/7.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/php-invoker", - "type": "tidelift" - } - ], - "time": "2026-02-06T04:34:47+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "6.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "a47af19f93f76aa3368303d752aa5272ca3299f4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/a47af19f93f76aa3368303d752aa5272ca3299f4", - "reference": "a47af19f93f76aa3368303d752aa5272ca3299f4", - "shasum": "" - }, - "require": { - "php": ">=8.4" - }, - "require-dev": { - "phpunit/phpunit": "^13.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/6.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/php-text-template", - "type": "tidelift" - } - ], - "time": "2026-02-06T04:36:37+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "9.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "a0e12065831f6ab0d83120dc61513eb8d9a966f6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/a0e12065831f6ab0d83120dc61513eb8d9a966f6", - "reference": "a0e12065831f6ab0d83120dc61513eb8d9a966f6", - "shasum": "" - }, - "require": { - "php": ">=8.4" - }, - "require-dev": { - "phpunit/phpunit": "^13.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "9.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "security": "https://github.com/sebastianbergmann/php-timer/security/policy", - "source": "https://github.com/sebastianbergmann/php-timer/tree/9.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/php-timer", - "type": "tidelift" - } - ], - "time": "2026-02-06T04:37:53+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "13.1.11", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "0f540976373361d1b4549adcb87913ce2116e904" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0f540976373361d1b4549adcb87913ce2116e904", - "reference": "0f540976373361d1b4549adcb87913ce2116e904", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.13.4", - "phar-io/manifest": "^2.0.4", - "phar-io/version": "^3.2.1", - "php": ">=8.4.1", - "phpunit/php-code-coverage": "^14.1.9", - "phpunit/php-file-iterator": "^7.0.0", - "phpunit/php-invoker": "^7.0.0", - "phpunit/php-text-template": "^6.0.0", - "phpunit/php-timer": "^9.0.0", - "sebastian/cli-parser": "^5.0.0", - "sebastian/comparator": "^8.2.1", - "sebastian/diff": "^8.3.0", - "sebastian/environment": "^9.3.1", - "sebastian/exporter": "^8.1.0", - "sebastian/git-state": "^1.0", - "sebastian/global-state": "^9.0.0", - "sebastian/object-enumerator": "^8.0.0", - "sebastian/recursion-context": "^8.0.0", - "sebastian/type": "^7.0.1", - "sebastian/version": "^7.0.0", - "staabm/side-effects-detector": "^1.0.5" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "13.1-dev" - } - }, - "autoload": { - "files": [ - "src/Framework/Assert/Functions.php" - ], - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/13.1.11" - }, - "funding": [ - { - "url": "https://phpunit.de/sponsoring.html", - "type": "other" - } - ], - "time": "2026-05-21T12:38:47+00:00" - }, { "name": "psr/cache", "version": "3.0.0", @@ -2606,1096 +1896,6 @@ }, "time": "2024-09-11T13:17:53+00:00" }, - { - "name": "sebastian/cli-parser", - "version": "5.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "48a4654fa5e48c1c81214e9930048a572d4b23ca" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/48a4654fa5e48c1c81214e9930048a572d4b23ca", - "reference": "48a4654fa5e48c1c81214e9930048a572d4b23ca", - "shasum": "" - }, - "require": { - "php": ">=8.4" - }, - "require-dev": { - "phpunit/phpunit": "^13.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for parsing CLI options", - "homepage": "https://github.com/sebastianbergmann/cli-parser", - "support": { - "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/5.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/cli-parser", - "type": "tidelift" - } - ], - "time": "2026-02-06T04:39:44+00:00" - }, - { - "name": "sebastian/comparator", - "version": "8.2.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "ce999bf08b2c387a5423fe56961c32eed3f88089" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/ce999bf08b2c387a5423fe56961c32eed3f88089", - "reference": "ce999bf08b2c387a5423fe56961c32eed3f88089", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-mbstring": "*", - "php": ">=8.4", - "sebastian/diff": "^8.3", - "sebastian/exporter": "^8.0.3" - }, - "require-dev": { - "phpunit/phpunit": "^13.1.10" - }, - "suggest": { - "ext-bcmath": "For comparing BcMath\\Number objects" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "8.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/comparator/issues", - "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/8.2.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", - "type": "tidelift" - } - ], - "time": "2026-05-21T04:46:40+00:00" - }, - { - "name": "sebastian/complexity", - "version": "6.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "c5651c795c98093480df79350cb050813fc7a2f3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/c5651c795c98093480df79350cb050813fc7a2f3", - "reference": "c5651c795c98093480df79350cb050813fc7a2f3", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^5.0", - "php": ">=8.4" - }, - "require-dev": { - "phpunit/phpunit": "^13.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for calculating the complexity of PHP code units", - "homepage": "https://github.com/sebastianbergmann/complexity", - "support": { - "issues": "https://github.com/sebastianbergmann/complexity/issues", - "security": "https://github.com/sebastianbergmann/complexity/security/policy", - "source": "https://github.com/sebastianbergmann/complexity/tree/6.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/complexity", - "type": "tidelift" - } - ], - "time": "2026-02-06T04:41:32+00:00" - }, - { - "name": "sebastian/diff", - "version": "8.3.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "b36d33b6e796513de7cb7df053afb3f55eefcd47" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b36d33b6e796513de7cb7df053afb3f55eefcd47", - "reference": "b36d33b6e796513de7cb7df053afb3f55eefcd47", - "shasum": "" - }, - "require": { - "php": ">=8.4" - }, - "require-dev": { - "phpunit/phpunit": "^13.0", - "symfony/process": "^7.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "8.3-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "security": "https://github.com/sebastianbergmann/diff/security/policy", - "source": "https://github.com/sebastianbergmann/diff/tree/8.3.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/diff", - "type": "tidelift" - } - ], - "time": "2026-05-15T04:58:09+00:00" - }, - { - "name": "sebastian/environment", - "version": "9.3.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "a15fa79a5f5cfd0e9f6817dbcdb0048e99efa146" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/a15fa79a5f5cfd0e9f6817dbcdb0048e99efa146", - "reference": "a15fa79a5f5cfd0e9f6817dbcdb0048e99efa146", - "shasum": "" - }, - "require": { - "php": ">=8.4" - }, - "require-dev": { - "phpunit/phpunit": "^13.1.10" - }, - "suggest": { - "ext-posix": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "9.3-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "https://github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/environment/issues", - "security": "https://github.com/sebastianbergmann/environment/security/policy", - "source": "https://github.com/sebastianbergmann/environment/tree/9.3.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/environment", - "type": "tidelift" - } - ], - "time": "2026-05-21T08:47:00+00:00" - }, - { - "name": "sebastian/exporter", - "version": "8.1.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "c0d29a945f8cf82f300a05e69874508e307ca4c6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/c0d29a945f8cf82f300a05e69874508e307ca4c6", - "reference": "c0d29a945f8cf82f300a05e69874508e307ca4c6", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "php": ">=8.4", - "sebastian/recursion-context": "^8.0" - }, - "require-dev": { - "phpunit/phpunit": "^13.1.10" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "8.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "https://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/exporter/issues", - "security": "https://github.com/sebastianbergmann/exporter/security/policy", - "source": "https://github.com/sebastianbergmann/exporter/tree/8.1.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", - "type": "tidelift" - } - ], - "time": "2026-05-21T11:50:56+00:00" - }, - { - "name": "sebastian/git-state", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/git-state.git", - "reference": "792a952e0eba55b6960a48aeceb9f371aad1f76b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/git-state/zipball/792a952e0eba55b6960a48aeceb9f371aad1f76b", - "reference": "792a952e0eba55b6960a48aeceb9f371aad1f76b", - "shasum": "" - }, - "require": { - "php": ">=8.4" - }, - "require-dev": { - "phpunit/phpunit": "^13.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for describing the state of a Git checkout", - "homepage": "https://github.com/sebastianbergmann/git-state", - "support": { - "issues": "https://github.com/sebastianbergmann/git-state/issues", - "security": "https://github.com/sebastianbergmann/git-state/security/policy", - "source": "https://github.com/sebastianbergmann/git-state/tree/1.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/git-state", - "type": "tidelift" - } - ], - "time": "2026-03-21T12:54:28+00:00" - }, - { - "name": "sebastian/global-state", - "version": "9.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "e52e3dc22441e6218c710afe72c3042f8fc41ea7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e52e3dc22441e6218c710afe72c3042f8fc41ea7", - "reference": "e52e3dc22441e6218c710afe72c3042f8fc41ea7", - "shasum": "" - }, - "require": { - "php": ">=8.4", - "sebastian/object-reflector": "^6.0", - "sebastian/recursion-context": "^8.0" - }, - "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^13.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "9.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "https://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/global-state/issues", - "security": "https://github.com/sebastianbergmann/global-state/security/policy", - "source": "https://github.com/sebastianbergmann/global-state/tree/9.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/global-state", - "type": "tidelift" - } - ], - "time": "2026-02-06T04:45:13+00:00" - }, - { - "name": "sebastian/lines-of-code", - "version": "5.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "d2cff273a90c79b0eb590baa682d4b5c318bdbb7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d2cff273a90c79b0eb590baa682d4b5c318bdbb7", - "reference": "d2cff273a90c79b0eb590baa682d4b5c318bdbb7", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^5.7.0", - "php": ">=8.4" - }, - "require-dev": { - "phpunit/phpunit": "^13.1.10" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for counting the lines of code in PHP source code", - "homepage": "https://github.com/sebastianbergmann/lines-of-code", - "support": { - "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/5.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/lines-of-code", - "type": "tidelift" - } - ], - "time": "2026-05-19T16:23:37+00:00" - }, - { - "name": "sebastian/object-enumerator", - "version": "8.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "b39ab125fd9a7434b0ecbc4202eebce11a98cfc5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/b39ab125fd9a7434b0ecbc4202eebce11a98cfc5", - "reference": "b39ab125fd9a7434b0ecbc4202eebce11a98cfc5", - "shasum": "" - }, - "require": { - "php": ">=8.4", - "sebastian/object-reflector": "^6.0", - "sebastian/recursion-context": "^8.0" - }, - "require-dev": { - "phpunit/phpunit": "^13.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "8.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/8.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/object-enumerator", - "type": "tidelift" - } - ], - "time": "2026-02-06T04:46:36+00:00" - }, - { - "name": "sebastian/object-reflector", - "version": "6.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "3ca042c2c60b0eab094f8a1b6a7093f4d4c72200" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/3ca042c2c60b0eab094f8a1b6a7093f4d4c72200", - "reference": "3ca042c2c60b0eab094f8a1b6a7093f4d4c72200", - "shasum": "" - }, - "require": { - "php": ">=8.4" - }, - "require-dev": { - "phpunit/phpunit": "^13.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/6.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/object-reflector", - "type": "tidelift" - } - ], - "time": "2026-02-06T04:47:13+00:00" - }, - { - "name": "sebastian/recursion-context", - "version": "8.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "74c5af21f6a5833e91767ca068c4d3dfec15317e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/74c5af21f6a5833e91767ca068c4d3dfec15317e", - "reference": "74c5af21f6a5833e91767ca068c4d3dfec15317e", - "shasum": "" - }, - "require": { - "php": ">=8.4" - }, - "require-dev": { - "phpunit/phpunit": "^13.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "8.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "https://github.com/sebastianbergmann/recursion-context", - "support": { - "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/8.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", - "type": "tidelift" - } - ], - "time": "2026-02-06T04:51:28+00:00" - }, - { - "name": "sebastian/type", - "version": "7.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "fee0309275847fefd7636167085e379c1dbf6990" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fee0309275847fefd7636167085e379c1dbf6990", - "reference": "fee0309275847fefd7636167085e379c1dbf6990", - "shasum": "" - }, - "require": { - "php": ">=8.4" - }, - "require-dev": { - "phpunit/phpunit": "^13.1.10" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "7.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", - "support": { - "issues": "https://github.com/sebastianbergmann/type/issues", - "security": "https://github.com/sebastianbergmann/type/security/policy", - "source": "https://github.com/sebastianbergmann/type/tree/7.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/type", - "type": "tidelift" - } - ], - "time": "2026-05-20T06:49:11+00:00" - }, - { - "name": "sebastian/version", - "version": "7.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "ad37a5552c8e2b88572249fdc19b6da7792e021b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/ad37a5552c8e2b88572249fdc19b6da7792e021b", - "reference": "ad37a5552c8e2b88572249fdc19b6da7792e021b", - "shasum": "" - }, - "require": { - "php": ">=8.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "7.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "support": { - "issues": "https://github.com/sebastianbergmann/version/issues", - "security": "https://github.com/sebastianbergmann/version/security/policy", - "source": "https://github.com/sebastianbergmann/version/tree/7.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/version", - "type": "tidelift" - } - ], - "time": "2026-02-06T04:52:52+00:00" - }, - { - "name": "staabm/side-effects-detector", - "version": "1.0.5", - "source": { - "type": "git", - "url": "https://github.com/staabm/side-effects-detector.git", - "reference": "d8334211a140ce329c13726d4a715adbddd0a163" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", - "reference": "d8334211a140ce329c13726d4a715adbddd0a163", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": "^7.4 || ^8.0" - }, - "require-dev": { - "phpstan/extension-installer": "^1.4.3", - "phpstan/phpstan": "^1.12.6", - "phpunit/phpunit": "^9.6.21", - "symfony/var-dumper": "^5.4.43", - "tomasvotruba/type-coverage": "1.0.0", - "tomasvotruba/unused-public": "1.0.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "lib/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "A static analysis tool to detect side effects in PHP code", - "keywords": [ - "static analysis" - ], - "support": { - "issues": "https://github.com/staabm/side-effects-detector/issues", - "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" - }, - "funding": [ - { - "url": "https://github.com/staabm", - "type": "github" - } - ], - "time": "2024-10-20T05:08:20+00:00" - }, { "name": "symfony/asset", "version": "v8.0.8", @@ -3847,78 +2047,6 @@ ], "time": "2026-05-13T12:07:53+00:00" }, - { - "name": "symfony/browser-kit", - "version": "v8.0.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/browser-kit.git", - "reference": "f5a28fca785416cf489dd579011e74c831100cc3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/f5a28fca785416cf489dd579011e74c831100cc3", - "reference": "f5a28fca785416cf489dd579011e74c831100cc3", - "shasum": "" - }, - "require": { - "php": ">=8.4", - "symfony/dom-crawler": "^7.4|^8.0" - }, - "require-dev": { - "symfony/css-selector": "^7.4|^8.0", - "symfony/http-client": "^7.4|^8.0", - "symfony/mime": "^7.4|^8.0", - "symfony/process": "^7.4|^8.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\BrowserKit\\": "" - }, - "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": "Simulates the behavior of a web browser, allowing you to make requests, click on links and submit forms programmatically", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/browser-kit/tree/v8.0.8" - }, - "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-30T15:14:47+00:00" - }, { "name": "symfony/cache", "version": "v8.0.12", @@ -4343,150 +2471,6 @@ ], "time": "2026-05-13T12:07:53+00:00" }, - { - "name": "symfony/css-selector", - "version": "v8.0.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/css-selector.git", - "reference": "3665cfade90565430909b906394c73c8739e57d0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/3665cfade90565430909b906394c73c8739e57d0", - "reference": "3665cfade90565430909b906394c73c8739e57d0", - "shasum": "" - }, - "require": { - "php": ">=8.4" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\CssSelector\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Jean-François Simon", - "email": "jeanfrancois.simon@sensiolabs.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Converts CSS selectors to XPath expressions", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/css-selector/tree/v8.0.9" - }, - "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-04-18T13:51:42+00:00" - }, - { - "name": "symfony/debug-bundle", - "version": "v8.0.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/debug-bundle.git", - "reference": "d9d127d61fb2aa7f7f324a8b1928767e2211d1bc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/debug-bundle/zipball/d9d127d61fb2aa7f7f324a8b1928767e2211d1bc", - "reference": "d9d127d61fb2aa7f7f324a8b1928767e2211d1bc", - "shasum": "" - }, - "require": { - "composer-runtime-api": ">=2.1", - "ext-xml": "*", - "php": ">=8.4", - "symfony/config": "^7.4|^8.0", - "symfony/dependency-injection": "^7.4|^8.0", - "symfony/http-kernel": "^7.4|^8.0", - "symfony/twig-bridge": "^7.4|^8.0", - "symfony/var-dumper": "^7.4|^8.0" - }, - "require-dev": { - "symfony/web-profiler-bundle": "^7.4|^8.0" - }, - "type": "symfony-bundle", - "autoload": { - "psr-4": { - "Symfony\\Bundle\\DebugBundle\\": "" - }, - "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 the Symfony VarDumper component and the ServerLogCommand from MonologBridge into the Symfony full-stack framework", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/debug-bundle/tree/v8.0.8" - }, - "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-30T15:14:47+00:00" - }, { "name": "symfony/dependency-injection", "version": "v8.0.10", @@ -4817,76 +2801,6 @@ ], "time": "2026-02-20T07:51:53+00:00" }, - { - "name": "symfony/dom-crawler", - "version": "v8.0.12", - "source": { - "type": "git", - "url": "https://github.com/symfony/dom-crawler.git", - "reference": "011b0ce60417f6d40052434d8ae6295b876ecbdd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/011b0ce60417f6d40052434d8ae6295b876ecbdd", - "reference": "011b0ce60417f6d40052434d8ae6295b876ecbdd", - "shasum": "" - }, - "require": { - "php": ">=8.4", - "symfony/polyfill-ctype": "^1.8", - "symfony/polyfill-mbstring": "^1.0" - }, - "require-dev": { - "symfony/css-selector": "^7.4|^8.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\DomCrawler\\": "" - }, - "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": "Eases DOM navigation for HTML and XML documents", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/dom-crawler/tree/v8.0.12" - }, - "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-20T07:22:03+00:00" - }, { "name": "symfony/dotenv", "version": "v8.0.11", @@ -6252,105 +4166,6 @@ ], "time": "2026-05-20T07:22:03+00:00" }, - { - "name": "symfony/maker-bundle", - "version": "v1.67.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/maker-bundle.git", - "reference": "6ce8b313845f16bcf385ee3cb31d8b24e30d5516" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/maker-bundle/zipball/6ce8b313845f16bcf385ee3cb31d8b24e30d5516", - "reference": "6ce8b313845f16bcf385ee3cb31d8b24e30d5516", - "shasum": "" - }, - "require": { - "composer-runtime-api": "^2.1", - "doctrine/inflector": "^2.0", - "nikic/php-parser": "^5.0", - "php": ">=8.1", - "symfony/config": "^6.4|^7.0|^8.0", - "symfony/console": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/deprecation-contracts": "^2.2|^3", - "symfony/filesystem": "^6.4|^7.0|^8.0", - "symfony/finder": "^6.4|^7.0|^8.0", - "symfony/framework-bundle": "^6.4|^7.0|^8.0", - "symfony/http-kernel": "^6.4|^7.0|^8.0", - "symfony/process": "^6.4|^7.0|^8.0" - }, - "conflict": { - "doctrine/doctrine-bundle": "<2.10", - "doctrine/orm": "<2.15" - }, - "require-dev": { - "composer/semver": "^3.0", - "doctrine/doctrine-bundle": "^2.10|^3.0", - "doctrine/orm": "^2.15|^3", - "doctrine/persistence": "^3.1|^4.0", - "symfony/http-client": "^6.4|^7.0|^8.0", - "symfony/phpunit-bridge": "^6.4.1|^7.0|^8.0", - "symfony/security-core": "^6.4|^7.0|^8.0", - "symfony/security-http": "^6.4|^7.0|^8.0", - "symfony/yaml": "^6.4|^7.0|^8.0", - "twig/twig": "^3.0|^4.x-dev" - }, - "type": "symfony-bundle", - "extra": { - "branch-alias": { - "dev-main": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Bundle\\MakerBundle\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Maker helps you create empty commands, controllers, form classes, tests and more so you can forget about writing boilerplate code.", - "homepage": "https://symfony.com/doc/current/bundles/SymfonyMakerBundle/index.html", - "keywords": [ - "code generator", - "dev", - "generator", - "scaffold", - "scaffolding" - ], - "support": { - "issues": "https://github.com/symfony/maker-bundle/issues", - "source": "https://github.com/symfony/maker-bundle/tree/v1.67.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-18T13:39:06+00:00" - }, { "name": "symfony/messenger", "version": "v8.0.12", @@ -9018,6 +6833,100 @@ ], "time": "2026-04-29T15:02:55+00:00" }, + { + "name": "symfony/ux-autocomplete", + "version": "v3.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/ux-autocomplete.git", + "reference": "58981eba6118fa7ae6e3c0d69481431bb4a0fcd4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/ux-autocomplete/zipball/58981eba6118fa7ae6e3c0d69481431bb4a0fcd4", + "reference": "58981eba6118fa7ae6e3c0d69481431bb4a0fcd4", + "shasum": "" + }, + "require": { + "php": ">=8.4", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-foundation": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/property-access": "^7.4|^8.0" + }, + "conflict": { + "doctrine/orm": "2.9.0 || 2.9.1" + }, + "require-dev": { + "doctrine/collections": "^1.6.8|^2.0", + "doctrine/doctrine-bundle": "^2.14|^3.0|^4.0", + "doctrine/orm": "^2.9.4|^3.0", + "fakerphp/faker": "^1.22", + "mtdowling/jmespath.php": "^2.6", + "phpunit/phpunit": "^11.1|^12.0", + "symfony/form": "^7.2|^8.0", + "symfony/framework-bundle": "^7.4|^8.0", + "symfony/maker-bundle": "^1.40", + "symfony/options-resolver": "^7.4|^8.0", + "symfony/process": "^7.4|^8.0", + "symfony/security-bundle": "^7.4|^8.0", + "symfony/twig-bundle": "^7.4|^8.0", + "symfony/uid": "^7.4|^8.0", + "twig/twig": "^2.14.7|^3.0.4", + "zenstruck/browser": "^1.9", + "zenstruck/foundry": "^2.7" + }, + "type": "symfony-bundle", + "extra": { + "thanks": { + "url": "https://github.com/symfony/ux", + "name": "symfony/ux" + } + }, + "autoload": { + "psr-4": { + "Symfony\\UX\\Autocomplete\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "JavaScript Autocomplete functionality for Symfony", + "homepage": "https://symfony.com", + "keywords": [ + "symfony-ux" + ], + "support": { + "source": "https://github.com/symfony/ux-autocomplete/tree/v3.0.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-04-09T22:56:44+00:00" + }, { "name": "symfony/ux-turbo", "version": "v3.0.0", @@ -9467,91 +7376,6 @@ ], "time": "2026-03-30T15:14:47+00:00" }, - { - "name": "symfony/web-profiler-bundle", - "version": "v8.0.12", - "source": { - "type": "git", - "url": "https://github.com/symfony/web-profiler-bundle.git", - "reference": "1d92c5e8b4939c93717cde24c6a5bfd909409dbf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/1d92c5e8b4939c93717cde24c6a5bfd909409dbf", - "reference": "1d92c5e8b4939c93717cde24c6a5bfd909409dbf", - "shasum": "" - }, - "require": { - "composer-runtime-api": ">=2.1", - "php": ">=8.4", - "symfony/config": "^7.4|^8.0", - "symfony/framework-bundle": "^7.4|^8.0", - "symfony/http-kernel": "^7.4|^8.0", - "symfony/routing": "^7.4|^8.0", - "symfony/twig-bundle": "^7.4|^8.0" - }, - "conflict": { - "symfony/serializer": "<7.4", - "symfony/workflow": "<7.4" - }, - "require-dev": { - "symfony/browser-kit": "^7.4|^8.0", - "symfony/console": "^7.4|^8.0", - "symfony/css-selector": "^7.4|^8.0", - "symfony/runtime": "^7.4|^8.0", - "symfony/stopwatch": "^7.4|^8.0" - }, - "type": "symfony-bundle", - "autoload": { - "psr-4": { - "Symfony\\Bundle\\WebProfilerBundle\\": "" - }, - "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 development tool that gives detailed information about the execution of any request", - "homepage": "https://symfony.com", - "keywords": [ - "dev" - ], - "support": { - "source": "https://github.com/symfony/web-profiler-bundle/tree/v8.0.12" - }, - "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-20T07:22:03+00:00" - }, { "name": "symfony/yaml", "version": "v8.0.12", @@ -9627,56 +7451,6 @@ ], "time": "2026-05-20T07:22:03+00:00" }, - { - "name": "theseer/tokenizer", - "version": "2.0.1", - "source": { - "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "7989e43bf381af0eac72e4f0ca5bcbfa81658be4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/7989e43bf381af0eac72e4f0ca5bcbfa81658be4", - "reference": "7989e43bf381af0eac72e4f0ca5bcbfa81658be4", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": "^8.1" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - } - ], - "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "support": { - "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/2.0.1" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2025-12-08T11:19:18+00:00" - }, { "name": "twig/extra-bundle", "version": "v3.24.0", @@ -9898,10 +7672,2331 @@ "time": "2026-05-20T13:07:01+00:00" } ], - "packages-dev": [], + "packages-dev": [ + { + "name": "myclabs/deep-copy", + "version": "1.13.4", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2025-08-01T08:46:24+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v5.7.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82", + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0" + }, + "time": "2025-12-06T11:56:16+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "14.1.9", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "655533a65696bbc4231cd8027af150dadc40ec88" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/655533a65696bbc4231cd8027af150dadc40ec88", + "reference": "655533a65696bbc4231cd8027af150dadc40ec88", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^5.7.0", + "php": ">=8.4", + "phpunit/php-text-template": "^6.0", + "sebastian/complexity": "^6.0", + "sebastian/environment": "^9.2", + "sebastian/git-state": "^1.0", + "sebastian/lines-of-code": "^5.0", + "sebastian/version": "^7.0", + "theseer/tokenizer": "^2.0.1" + }, + "require-dev": { + "phpunit/phpunit": "^13.1" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "14.1.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/14.1.9" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-code-coverage", + "type": "tidelift" + } + ], + "time": "2026-05-16T05:16:14+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "7.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "6e5aa1fb0a95b1703d83e721299ee18bb4e2de50" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6e5aa1fb0a95b1703d83e721299ee18bb4e2de50", + "reference": "6e5aa1fb0a95b1703d83e721299ee18bb4e2de50", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "require-dev": { + "phpunit/phpunit": "^13.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/7.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-file-iterator", + "type": "tidelift" + } + ], + "time": "2026-02-06T04:33:26+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "7.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "42e5c5cae0c65df12d1b1a3ab52bf3f50f244d88" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/42e5c5cae0c65df12d1b1a3ab52bf3f50f244d88", + "reference": "42e5c5cae0c65df12d1b1a3ab52bf3f50f244d88", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^13.0" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/7.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-invoker", + "type": "tidelift" + } + ], + "time": "2026-02-06T04:34:47+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "a47af19f93f76aa3368303d752aa5272ca3299f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/a47af19f93f76aa3368303d752aa5272ca3299f4", + "reference": "a47af19f93f76aa3368303d752aa5272ca3299f4", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "require-dev": { + "phpunit/phpunit": "^13.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/6.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-text-template", + "type": "tidelift" + } + ], + "time": "2026-02-06T04:36:37+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "9.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "a0e12065831f6ab0d83120dc61513eb8d9a966f6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/a0e12065831f6ab0d83120dc61513eb8d9a966f6", + "reference": "a0e12065831f6ab0d83120dc61513eb8d9a966f6", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "require-dev": { + "phpunit/phpunit": "^13.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "9.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "security": "https://github.com/sebastianbergmann/php-timer/security/policy", + "source": "https://github.com/sebastianbergmann/php-timer/tree/9.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-timer", + "type": "tidelift" + } + ], + "time": "2026-02-06T04:37:53+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "13.1.11", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "0f540976373361d1b4549adcb87913ce2116e904" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0f540976373361d1b4549adcb87913ce2116e904", + "reference": "0f540976373361d1b4549adcb87913ce2116e904", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.13.4", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=8.4.1", + "phpunit/php-code-coverage": "^14.1.9", + "phpunit/php-file-iterator": "^7.0.0", + "phpunit/php-invoker": "^7.0.0", + "phpunit/php-text-template": "^6.0.0", + "phpunit/php-timer": "^9.0.0", + "sebastian/cli-parser": "^5.0.0", + "sebastian/comparator": "^8.2.1", + "sebastian/diff": "^8.3.0", + "sebastian/environment": "^9.3.1", + "sebastian/exporter": "^8.1.0", + "sebastian/git-state": "^1.0", + "sebastian/global-state": "^9.0.0", + "sebastian/object-enumerator": "^8.0.0", + "sebastian/recursion-context": "^8.0.0", + "sebastian/type": "^7.0.1", + "sebastian/version": "^7.0.0", + "staabm/side-effects-detector": "^1.0.5" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "13.1-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/13.1.11" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsoring.html", + "type": "other" + } + ], + "time": "2026-05-21T12:38:47+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "48a4654fa5e48c1c81214e9930048a572d4b23ca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/48a4654fa5e48c1c81214e9930048a572d4b23ca", + "reference": "48a4654fa5e48c1c81214e9930048a572d4b23ca", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "require-dev": { + "phpunit/phpunit": "^13.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/cli-parser", + "type": "tidelift" + } + ], + "time": "2026-02-06T04:39:44+00:00" + }, + { + "name": "sebastian/comparator", + "version": "8.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "ce999bf08b2c387a5423fe56961c32eed3f88089" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/ce999bf08b2c387a5423fe56961c32eed3f88089", + "reference": "ce999bf08b2c387a5423fe56961c32eed3f88089", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.4", + "sebastian/diff": "^8.3", + "sebastian/exporter": "^8.0.3" + }, + "require-dev": { + "phpunit/phpunit": "^13.1.10" + }, + "suggest": { + "ext-bcmath": "For comparing BcMath\\Number objects" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "8.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/8.2.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", + "type": "tidelift" + } + ], + "time": "2026-05-21T04:46:40+00:00" + }, + { + "name": "sebastian/complexity", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "c5651c795c98093480df79350cb050813fc7a2f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/c5651c795c98093480df79350cb050813fc7a2f3", + "reference": "c5651c795c98093480df79350cb050813fc7a2f3", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.4" + }, + "require-dev": { + "phpunit/phpunit": "^13.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/6.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/complexity", + "type": "tidelift" + } + ], + "time": "2026-02-06T04:41:32+00:00" + }, + { + "name": "sebastian/diff", + "version": "8.3.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "b36d33b6e796513de7cb7df053afb3f55eefcd47" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b36d33b6e796513de7cb7df053afb3f55eefcd47", + "reference": "b36d33b6e796513de7cb7df053afb3f55eefcd47", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "require-dev": { + "phpunit/phpunit": "^13.0", + "symfony/process": "^7.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "8.3-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/8.3.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/diff", + "type": "tidelift" + } + ], + "time": "2026-05-15T04:58:09+00:00" + }, + { + "name": "sebastian/environment", + "version": "9.3.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "a15fa79a5f5cfd0e9f6817dbcdb0048e99efa146" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/a15fa79a5f5cfd0e9f6817dbcdb0048e99efa146", + "reference": "a15fa79a5f5cfd0e9f6817dbcdb0048e99efa146", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "require-dev": { + "phpunit/phpunit": "^13.1.10" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "9.3-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "https://github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/9.3.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/environment", + "type": "tidelift" + } + ], + "time": "2026-05-21T08:47:00+00:00" + }, + { + "name": "sebastian/exporter", + "version": "8.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "c0d29a945f8cf82f300a05e69874508e307ca4c6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/c0d29a945f8cf82f300a05e69874508e307ca4c6", + "reference": "c0d29a945f8cf82f300a05e69874508e307ca4c6", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=8.4", + "sebastian/recursion-context": "^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^13.1.10" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "8.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/8.1.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", + "type": "tidelift" + } + ], + "time": "2026-05-21T11:50:56+00:00" + }, + { + "name": "sebastian/git-state", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/git-state.git", + "reference": "792a952e0eba55b6960a48aeceb9f371aad1f76b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/git-state/zipball/792a952e0eba55b6960a48aeceb9f371aad1f76b", + "reference": "792a952e0eba55b6960a48aeceb9f371aad1f76b", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "require-dev": { + "phpunit/phpunit": "^13.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for describing the state of a Git checkout", + "homepage": "https://github.com/sebastianbergmann/git-state", + "support": { + "issues": "https://github.com/sebastianbergmann/git-state/issues", + "security": "https://github.com/sebastianbergmann/git-state/security/policy", + "source": "https://github.com/sebastianbergmann/git-state/tree/1.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/git-state", + "type": "tidelift" + } + ], + "time": "2026-03-21T12:54:28+00:00" + }, + { + "name": "sebastian/global-state", + "version": "9.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "e52e3dc22441e6218c710afe72c3042f8fc41ea7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e52e3dc22441e6218c710afe72c3042f8fc41ea7", + "reference": "e52e3dc22441e6218c710afe72c3042f8fc41ea7", + "shasum": "" + }, + "require": { + "php": ">=8.4", + "sebastian/object-reflector": "^6.0", + "sebastian/recursion-context": "^8.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^13.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "9.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/9.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/global-state", + "type": "tidelift" + } + ], + "time": "2026-02-06T04:45:13+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "5.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "d2cff273a90c79b0eb590baa682d4b5c318bdbb7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d2cff273a90c79b0eb590baa682d4b5c318bdbb7", + "reference": "d2cff273a90c79b0eb590baa682d4b5c318bdbb7", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.7.0", + "php": ">=8.4" + }, + "require-dev": { + "phpunit/phpunit": "^13.1.10" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/5.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/lines-of-code", + "type": "tidelift" + } + ], + "time": "2026-05-19T16:23:37+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "8.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "b39ab125fd9a7434b0ecbc4202eebce11a98cfc5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/b39ab125fd9a7434b0ecbc4202eebce11a98cfc5", + "reference": "b39ab125fd9a7434b0ecbc4202eebce11a98cfc5", + "shasum": "" + }, + "require": { + "php": ">=8.4", + "sebastian/object-reflector": "^6.0", + "sebastian/recursion-context": "^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^13.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "8.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/8.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/object-enumerator", + "type": "tidelift" + } + ], + "time": "2026-02-06T04:46:36+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "3ca042c2c60b0eab094f8a1b6a7093f4d4c72200" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/3ca042c2c60b0eab094f8a1b6a7093f4d4c72200", + "reference": "3ca042c2c60b0eab094f8a1b6a7093f4d4c72200", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "require-dev": { + "phpunit/phpunit": "^13.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/6.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/object-reflector", + "type": "tidelift" + } + ], + "time": "2026-02-06T04:47:13+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "8.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "74c5af21f6a5833e91767ca068c4d3dfec15317e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/74c5af21f6a5833e91767ca068c4d3dfec15317e", + "reference": "74c5af21f6a5833e91767ca068c4d3dfec15317e", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "require-dev": { + "phpunit/phpunit": "^13.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "8.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/8.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", + "type": "tidelift" + } + ], + "time": "2026-02-06T04:51:28+00:00" + }, + { + "name": "sebastian/type", + "version": "7.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "fee0309275847fefd7636167085e379c1dbf6990" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fee0309275847fefd7636167085e379c1dbf6990", + "reference": "fee0309275847fefd7636167085e379c1dbf6990", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "require-dev": { + "phpunit/phpunit": "^13.1.10" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "security": "https://github.com/sebastianbergmann/type/security/policy", + "source": "https://github.com/sebastianbergmann/type/tree/7.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/type", + "type": "tidelift" + } + ], + "time": "2026-05-20T06:49:11+00:00" + }, + { + "name": "sebastian/version", + "version": "7.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "ad37a5552c8e2b88572249fdc19b6da7792e021b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/ad37a5552c8e2b88572249fdc19b6da7792e021b", + "reference": "ad37a5552c8e2b88572249fdc19b6da7792e021b", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "security": "https://github.com/sebastianbergmann/version/security/policy", + "source": "https://github.com/sebastianbergmann/version/tree/7.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/version", + "type": "tidelift" + } + ], + "time": "2026-02-06T04:52:52+00:00" + }, + { + "name": "staabm/side-effects-detector", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/staabm/side-effects-detector.git", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.6", + "phpunit/phpunit": "^9.6.21", + "symfony/var-dumper": "^5.4.43", + "tomasvotruba/type-coverage": "1.0.0", + "tomasvotruba/unused-public": "1.0.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A static analysis tool to detect side effects in PHP code", + "keywords": [ + "static analysis" + ], + "support": { + "issues": "https://github.com/staabm/side-effects-detector/issues", + "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" + }, + "funding": [ + { + "url": "https://github.com/staabm", + "type": "github" + } + ], + "time": "2024-10-20T05:08:20+00:00" + }, + { + "name": "symfony/browser-kit", + "version": "v8.0.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/browser-kit.git", + "reference": "f5a28fca785416cf489dd579011e74c831100cc3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/f5a28fca785416cf489dd579011e74c831100cc3", + "reference": "f5a28fca785416cf489dd579011e74c831100cc3", + "shasum": "" + }, + "require": { + "php": ">=8.4", + "symfony/dom-crawler": "^7.4|^8.0" + }, + "require-dev": { + "symfony/css-selector": "^7.4|^8.0", + "symfony/http-client": "^7.4|^8.0", + "symfony/mime": "^7.4|^8.0", + "symfony/process": "^7.4|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\BrowserKit\\": "" + }, + "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": "Simulates the behavior of a web browser, allowing you to make requests, click on links and submit forms programmatically", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/browser-kit/tree/v8.0.8" + }, + "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-30T15:14:47+00:00" + }, + { + "name": "symfony/css-selector", + "version": "v8.0.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/css-selector.git", + "reference": "3665cfade90565430909b906394c73c8739e57d0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/3665cfade90565430909b906394c73c8739e57d0", + "reference": "3665cfade90565430909b906394c73c8739e57d0", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\CssSelector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Converts CSS selectors to XPath expressions", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/css-selector/tree/v8.0.9" + }, + "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-04-18T13:51:42+00:00" + }, + { + "name": "symfony/debug-bundle", + "version": "v8.0.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/debug-bundle.git", + "reference": "d9d127d61fb2aa7f7f324a8b1928767e2211d1bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/debug-bundle/zipball/d9d127d61fb2aa7f7f324a8b1928767e2211d1bc", + "reference": "d9d127d61fb2aa7f7f324a8b1928767e2211d1bc", + "shasum": "" + }, + "require": { + "composer-runtime-api": ">=2.1", + "ext-xml": "*", + "php": ">=8.4", + "symfony/config": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/twig-bridge": "^7.4|^8.0", + "symfony/var-dumper": "^7.4|^8.0" + }, + "require-dev": { + "symfony/web-profiler-bundle": "^7.4|^8.0" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Symfony\\Bundle\\DebugBundle\\": "" + }, + "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 the Symfony VarDumper component and the ServerLogCommand from MonologBridge into the Symfony full-stack framework", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/debug-bundle/tree/v8.0.8" + }, + "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-30T15:14:47+00:00" + }, + { + "name": "symfony/dom-crawler", + "version": "v8.0.12", + "source": { + "type": "git", + "url": "https://github.com/symfony/dom-crawler.git", + "reference": "011b0ce60417f6d40052434d8ae6295b876ecbdd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/011b0ce60417f6d40052434d8ae6295b876ecbdd", + "reference": "011b0ce60417f6d40052434d8ae6295b876ecbdd", + "shasum": "" + }, + "require": { + "php": ">=8.4", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-mbstring": "^1.0" + }, + "require-dev": { + "symfony/css-selector": "^7.4|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\DomCrawler\\": "" + }, + "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": "Eases DOM navigation for HTML and XML documents", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/dom-crawler/tree/v8.0.12" + }, + "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-20T07:22:03+00:00" + }, + { + "name": "symfony/maker-bundle", + "version": "v1.67.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/maker-bundle.git", + "reference": "6ce8b313845f16bcf385ee3cb31d8b24e30d5516" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/maker-bundle/zipball/6ce8b313845f16bcf385ee3cb31d8b24e30d5516", + "reference": "6ce8b313845f16bcf385ee3cb31d8b24e30d5516", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.1", + "doctrine/inflector": "^2.0", + "nikic/php-parser": "^5.0", + "php": ">=8.1", + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/deprecation-contracts": "^2.2|^3", + "symfony/filesystem": "^6.4|^7.0|^8.0", + "symfony/finder": "^6.4|^7.0|^8.0", + "symfony/framework-bundle": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0|^8.0" + }, + "conflict": { + "doctrine/doctrine-bundle": "<2.10", + "doctrine/orm": "<2.15" + }, + "require-dev": { + "composer/semver": "^3.0", + "doctrine/doctrine-bundle": "^2.10|^3.0", + "doctrine/orm": "^2.15|^3", + "doctrine/persistence": "^3.1|^4.0", + "symfony/http-client": "^6.4|^7.0|^8.0", + "symfony/phpunit-bridge": "^6.4.1|^7.0|^8.0", + "symfony/security-core": "^6.4|^7.0|^8.0", + "symfony/security-http": "^6.4|^7.0|^8.0", + "symfony/yaml": "^6.4|^7.0|^8.0", + "twig/twig": "^3.0|^4.x-dev" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Bundle\\MakerBundle\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Maker helps you create empty commands, controllers, form classes, tests and more so you can forget about writing boilerplate code.", + "homepage": "https://symfony.com/doc/current/bundles/SymfonyMakerBundle/index.html", + "keywords": [ + "code generator", + "dev", + "generator", + "scaffold", + "scaffolding" + ], + "support": { + "issues": "https://github.com/symfony/maker-bundle/issues", + "source": "https://github.com/symfony/maker-bundle/tree/v1.67.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-18T13:39:06+00:00" + }, + { + "name": "symfony/web-profiler-bundle", + "version": "v8.0.12", + "source": { + "type": "git", + "url": "https://github.com/symfony/web-profiler-bundle.git", + "reference": "1d92c5e8b4939c93717cde24c6a5bfd909409dbf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/1d92c5e8b4939c93717cde24c6a5bfd909409dbf", + "reference": "1d92c5e8b4939c93717cde24c6a5bfd909409dbf", + "shasum": "" + }, + "require": { + "composer-runtime-api": ">=2.1", + "php": ">=8.4", + "symfony/config": "^7.4|^8.0", + "symfony/framework-bundle": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/routing": "^7.4|^8.0", + "symfony/twig-bundle": "^7.4|^8.0" + }, + "conflict": { + "symfony/serializer": "<7.4", + "symfony/workflow": "<7.4" + }, + "require-dev": { + "symfony/browser-kit": "^7.4|^8.0", + "symfony/console": "^7.4|^8.0", + "symfony/css-selector": "^7.4|^8.0", + "symfony/runtime": "^7.4|^8.0", + "symfony/stopwatch": "^7.4|^8.0" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Symfony\\Bundle\\WebProfilerBundle\\": "" + }, + "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 development tool that gives detailed information about the execution of any request", + "homepage": "https://symfony.com", + "keywords": [ + "dev" + ], + "support": { + "source": "https://github.com/symfony/web-profiler-bundle/tree/v8.0.12" + }, + "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-20T07:22:03+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "7989e43bf381af0eac72e4f0ca5bcbfa81658be4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/7989e43bf381af0eac72e4f0ca5bcbfa81658be4", + "reference": "7989e43bf381af0eac72e4f0ca5bcbfa81658be4", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^8.1" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/2.0.1" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2025-12-08T11:19:18+00:00" + } + ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": true, "prefer-lowest": false, "platform": { @@ -9909,6 +10004,6 @@ "ext-ctype": "*", "ext-iconv": "*" }, - "platform-dev": [], + "platform-dev": {}, "plugin-api-version": "2.9.0" } diff --git a/config/bundles.php b/config/bundles.php index 4e3a560..cd05b90 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -13,4 +13,5 @@ return [ Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true], Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], + Symfony\UX\Autocomplete\AutocompleteBundle::class => ['all' => true], ]; diff --git a/config/packages/security.yaml b/config/packages/security.yaml index 8964044..4ee4332 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -5,7 +5,11 @@ security: # https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider providers: - users_in_memory: { memory: null } + # used to reload user from session & other features (e.g. switch_user) + app_user_provider: + entity: + class: App\Entity\User + property: username firewalls: dev: @@ -14,7 +18,15 @@ security: security: false main: lazy: true - provider: users_in_memory + provider: app_user_provider + form_login: + login_path: brain_login + check_path: brain_login + enable_csrf: true + logout: + path: brain_logout + # where to redirect after logout + # target: app_any_route # Activate different ways to authenticate: # https://symfony.com/doc/current/security.html#the-firewall @@ -24,7 +36,7 @@ security: # Note: Only the *first* matching rule is applied access_control: - # - { path: ^/admin, roles: ROLE_ADMIN } + - { path: ^/brain, roles: ROLE_ADMIN } # - { path: ^/profile, roles: ROLE_USER } when@test: diff --git a/config/routes/ux_autocomplete.yaml b/config/routes/ux_autocomplete.yaml new file mode 100644 index 0000000..da6b261 --- /dev/null +++ b/config/routes/ux_autocomplete.yaml @@ -0,0 +1,3 @@ +ux_autocomplete: + resource: '@AutocompleteBundle/config/routes.php' + prefix: '/autocomplete' diff --git a/config/services.yaml b/config/services.yaml index 79b8ce2..69b3562 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -21,3 +21,6 @@ services: # add more service definitions when explicit configuration is needed # please note that last definitions always *replace* previous ones + App\Service\PhotoUploader: + arguments: + $targetDirectory: '%' diff --git a/importmap.php b/importmap.php index 9b2baf8..f3d7d96 100644 --- a/importmap.php +++ b/importmap.php @@ -12,8 +12,16 @@ * The "importmap:require" command can be used to add new entries to this file. */ return [ - 'app' => [ - 'path' => './assets/app.js', + 'main' => [ + 'path' => './assets/main.js', + 'entrypoint' => true, + ], + 'brain' => [ + 'path' => './assets/brain.js', + 'entrypoint' => true, + ], + 'landing' => [ + 'path' => './assets/landing.js', 'entrypoint' => true, ], '@hotwired/stimulus' => [ @@ -25,4 +33,29 @@ return [ '@hotwired/turbo' => [ 'version' => '8.0.23', ], + 'tom-select' => [ + 'version' => '2.6.1', + ], + '@orchidjs/sifter' => [ + 'version' => '1.1.0', + ], + '@orchidjs/unicode-variants' => [ + 'version' => '1.1.2', + ], + 'tom-select/dist/css/tom-select.default.min.css' => [ + 'version' => '2.6.1', + 'type' => 'css', + ], + 'tom-select/dist/css/tom-select.default.css' => [ + 'version' => '2.6.1', + 'type' => 'css', + ], + 'tom-select/dist/css/tom-select.bootstrap4.css' => [ + 'version' => '2.6.1', + 'type' => 'css', + ], + 'tom-select/dist/css/tom-select.bootstrap5.css' => [ + 'version' => '2.6.1', + 'type' => 'css', + ], ]; diff --git a/migrations/Version20260522200819.php b/migrations/Version20260522200819.php new file mode 100644 index 0000000..8971a57 --- /dev/null +++ b/migrations/Version20260522200819.php @@ -0,0 +1,33 @@ +addSql('CREATE TABLE page (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, title VARCHAR(255) NOT NULL, text TEXT NOT NULL, url VARCHAR(255) NOT NULL, PRIMARY KEY (id))'); + $this->addSql('CREATE TABLE post (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, title VARCHAR(255) NOT NULL, date TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, text TEXT NOT NULL, url VARCHAR(255) NOT NULL, PRIMARY KEY (id))'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('DROP TABLE page'); + $this->addSql('DROP TABLE post'); + } +} diff --git a/migrations/Version20260522202515.php b/migrations/Version20260522202515.php new file mode 100644 index 0000000..7c4b7f1 --- /dev/null +++ b/migrations/Version20260522202515.php @@ -0,0 +1,33 @@ +addSql('ALTER TABLE page ADD published BOOLEAN NOT NULL'); + $this->addSql('ALTER TABLE post ADD published BOOLEAN NOT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE page DROP published'); + $this->addSql('ALTER TABLE post DROP published'); + } +} diff --git a/migrations/Version20260522205620.php b/migrations/Version20260522205620.php new file mode 100644 index 0000000..966ea62 --- /dev/null +++ b/migrations/Version20260522205620.php @@ -0,0 +1,47 @@ +addSql('CREATE TABLE category (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, title VARCHAR(255) NOT NULL, PRIMARY KEY (id))'); + $this->addSql('CREATE TABLE post_tag (post_id INT NOT NULL, tag_id INT NOT NULL, PRIMARY KEY (post_id, tag_id))'); + $this->addSql('CREATE INDEX IDX_5ACE3AF04B89032C ON post_tag (post_id)'); + $this->addSql('CREATE INDEX IDX_5ACE3AF0BAD26311 ON post_tag (tag_id)'); + $this->addSql('CREATE TABLE tag (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, title VARCHAR(255) NOT NULL, PRIMARY KEY (id))'); + $this->addSql('ALTER TABLE post_tag ADD CONSTRAINT FK_5ACE3AF04B89032C FOREIGN KEY (post_id) REFERENCES post (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE post_tag ADD CONSTRAINT FK_5ACE3AF0BAD26311 FOREIGN KEY (tag_id) REFERENCES tag (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE post ADD category_id INT DEFAULT NULL'); + $this->addSql('ALTER TABLE post ADD CONSTRAINT FK_5A8A6C8D12469DE2 FOREIGN KEY (category_id) REFERENCES category (id)'); + $this->addSql('CREATE INDEX IDX_5A8A6C8D12469DE2 ON post (category_id)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE post_tag DROP CONSTRAINT FK_5ACE3AF04B89032C'); + $this->addSql('ALTER TABLE post_tag DROP CONSTRAINT FK_5ACE3AF0BAD26311'); + $this->addSql('DROP TABLE category'); + $this->addSql('DROP TABLE post_tag'); + $this->addSql('DROP TABLE tag'); + $this->addSql('ALTER TABLE post DROP CONSTRAINT FK_5A8A6C8D12469DE2'); + $this->addSql('DROP INDEX IDX_5A8A6C8D12469DE2'); + $this->addSql('ALTER TABLE post DROP category_id'); + } +} diff --git a/migrations/Version20260601003707.php b/migrations/Version20260601003707.php new file mode 100644 index 0000000..3754a1e --- /dev/null +++ b/migrations/Version20260601003707.php @@ -0,0 +1,39 @@ +addSql('CREATE TABLE photo (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, file VARCHAR(255) NOT NULL, equipment VARCHAR(255) NOT NULL, location VARCHAR(255) NOT NULL, caption VARCHAR(255) NOT NULL, date DATE NOT NULL, photos_id INT DEFAULT NULL, PRIMARY KEY (id))'); + $this->addSql('CREATE INDEX IDX_14B78418301EC62 ON photo (photos_id)'); + $this->addSql('CREATE TABLE photos (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, title VARCHAR(255) NOT NULL, date TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, category_id INT DEFAULT NULL, PRIMARY KEY (id))'); + $this->addSql('CREATE INDEX IDX_876E0D912469DE2 ON photos (category_id)'); + $this->addSql('ALTER TABLE photo ADD CONSTRAINT FK_14B78418301EC62 FOREIGN KEY (photos_id) REFERENCES photos (id)'); + $this->addSql('ALTER TABLE photos ADD CONSTRAINT FK_876E0D912469DE2 FOREIGN KEY (category_id) REFERENCES category (id)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE photo DROP CONSTRAINT FK_14B78418301EC62'); + $this->addSql('ALTER TABLE photos DROP CONSTRAINT FK_876E0D912469DE2'); + $this->addSql('DROP TABLE photo'); + $this->addSql('DROP TABLE photos'); + } +} diff --git a/migrations/Version20260601011643.php b/migrations/Version20260601011643.php new file mode 100644 index 0000000..87a6b71 --- /dev/null +++ b/migrations/Version20260601011643.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE photo ADD alt_text VARCHAR(255) NOT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE photo DROP alt_text'); + } +} diff --git a/migrations/Version20260601013417.php b/migrations/Version20260601013417.php new file mode 100644 index 0000000..b15b0cc --- /dev/null +++ b/migrations/Version20260601013417.php @@ -0,0 +1,33 @@ +addSql('ALTER TABLE photos ADD text TEXT NOT NULL'); + $this->addSql('ALTER TABLE photos ADD url VARCHAR(255) NOT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE photos DROP text'); + $this->addSql('ALTER TABLE photos DROP url'); + } +} diff --git a/migrations/Version20260601201050.php b/migrations/Version20260601201050.php new file mode 100644 index 0000000..13da816 --- /dev/null +++ b/migrations/Version20260601201050.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE photos ADD thumbnail VARCHAR(255) NOT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE photos DROP thumbnail'); + } +} diff --git a/public/fonts/AtomicAge-Regular.ttf b/public/fonts/AtomicAge-Regular.ttf new file mode 100644 index 0000000..fb8f824 Binary files /dev/null and b/public/fonts/AtomicAge-Regular.ttf differ diff --git a/public/fonts/Montserrat-Black.ttf b/public/fonts/Montserrat-Black.ttf new file mode 100644 index 0000000..2fab7ab Binary files /dev/null and b/public/fonts/Montserrat-Black.ttf differ diff --git a/public/fonts/Montserrat-BlackItalic.ttf b/public/fonts/Montserrat-BlackItalic.ttf new file mode 100644 index 0000000..04d3b47 Binary files /dev/null and b/public/fonts/Montserrat-BlackItalic.ttf differ diff --git a/public/fonts/Montserrat-Bold.ttf b/public/fonts/Montserrat-Bold.ttf new file mode 100644 index 0000000..4033587 Binary files /dev/null and b/public/fonts/Montserrat-Bold.ttf differ diff --git a/public/fonts/Montserrat-BoldItalic.ttf b/public/fonts/Montserrat-BoldItalic.ttf new file mode 100644 index 0000000..0cc5c2c Binary files /dev/null and b/public/fonts/Montserrat-BoldItalic.ttf differ diff --git a/public/fonts/Montserrat-ExtraBold.ttf b/public/fonts/Montserrat-ExtraBold.ttf new file mode 100644 index 0000000..476ec30 Binary files /dev/null and b/public/fonts/Montserrat-ExtraBold.ttf differ diff --git a/public/fonts/Montserrat-ExtraBoldItalic.ttf b/public/fonts/Montserrat-ExtraBoldItalic.ttf new file mode 100644 index 0000000..a1ac9a9 Binary files /dev/null and b/public/fonts/Montserrat-ExtraBoldItalic.ttf differ diff --git a/public/fonts/Montserrat-ExtraLight.ttf b/public/fonts/Montserrat-ExtraLight.ttf new file mode 100644 index 0000000..efaeab0 Binary files /dev/null and b/public/fonts/Montserrat-ExtraLight.ttf differ diff --git a/public/fonts/Montserrat-ExtraLightItalic.ttf b/public/fonts/Montserrat-ExtraLightItalic.ttf new file mode 100644 index 0000000..a8d18de Binary files /dev/null and b/public/fonts/Montserrat-ExtraLightItalic.ttf differ diff --git a/public/fonts/Montserrat-Italic.ttf b/public/fonts/Montserrat-Italic.ttf new file mode 100644 index 0000000..5f08df0 Binary files /dev/null and b/public/fonts/Montserrat-Italic.ttf differ diff --git a/public/fonts/Montserrat-Light.ttf b/public/fonts/Montserrat-Light.ttf new file mode 100644 index 0000000..881f12d Binary files /dev/null and b/public/fonts/Montserrat-Light.ttf differ diff --git a/public/fonts/Montserrat-LightItalic.ttf b/public/fonts/Montserrat-LightItalic.ttf new file mode 100644 index 0000000..b2991d0 Binary files /dev/null and b/public/fonts/Montserrat-LightItalic.ttf differ diff --git a/public/fonts/Montserrat-Medium.ttf b/public/fonts/Montserrat-Medium.ttf new file mode 100644 index 0000000..c9a39ea Binary files /dev/null and b/public/fonts/Montserrat-Medium.ttf differ diff --git a/public/fonts/Montserrat-MediumItalic.ttf b/public/fonts/Montserrat-MediumItalic.ttf new file mode 100644 index 0000000..086dd6e Binary files /dev/null and b/public/fonts/Montserrat-MediumItalic.ttf differ diff --git a/public/fonts/Montserrat-Regular.ttf b/public/fonts/Montserrat-Regular.ttf new file mode 100644 index 0000000..895e220 Binary files /dev/null and b/public/fonts/Montserrat-Regular.ttf differ diff --git a/public/fonts/Montserrat-SemiBold.ttf b/public/fonts/Montserrat-SemiBold.ttf new file mode 100644 index 0000000..161477a Binary files /dev/null and b/public/fonts/Montserrat-SemiBold.ttf differ diff --git a/public/fonts/Montserrat-SemiBoldItalic.ttf b/public/fonts/Montserrat-SemiBoldItalic.ttf new file mode 100644 index 0000000..73dc6c6 Binary files /dev/null and b/public/fonts/Montserrat-SemiBoldItalic.ttf differ diff --git a/public/fonts/Montserrat-Thin.ttf b/public/fonts/Montserrat-Thin.ttf new file mode 100644 index 0000000..c9cf195 Binary files /dev/null and b/public/fonts/Montserrat-Thin.ttf differ diff --git a/public/fonts/Montserrat-ThinItalic.ttf b/public/fonts/Montserrat-ThinItalic.ttf new file mode 100644 index 0000000..e6dfc05 Binary files /dev/null and b/public/fonts/Montserrat-ThinItalic.ttf differ diff --git a/public/fonts/Orbitron-Regular.ttf b/public/fonts/Orbitron-Regular.ttf new file mode 100644 index 0000000..34c9c88 Binary files /dev/null and b/public/fonts/Orbitron-Regular.ttf differ diff --git a/public/fonts/RobotoSlab-Black.ttf b/public/fonts/RobotoSlab-Black.ttf new file mode 100644 index 0000000..9de300f Binary files /dev/null and b/public/fonts/RobotoSlab-Black.ttf differ diff --git a/public/fonts/RobotoSlab-Bold.ttf b/public/fonts/RobotoSlab-Bold.ttf new file mode 100644 index 0000000..9eb3ca7 Binary files /dev/null and b/public/fonts/RobotoSlab-Bold.ttf differ diff --git a/public/fonts/RobotoSlab-ExtraBold.ttf b/public/fonts/RobotoSlab-ExtraBold.ttf new file mode 100644 index 0000000..4679815 Binary files /dev/null and b/public/fonts/RobotoSlab-ExtraBold.ttf differ diff --git a/public/fonts/RobotoSlab-ExtraLight.ttf b/public/fonts/RobotoSlab-ExtraLight.ttf new file mode 100644 index 0000000..0eece47 Binary files /dev/null and b/public/fonts/RobotoSlab-ExtraLight.ttf differ diff --git a/public/fonts/RobotoSlab-Light.ttf b/public/fonts/RobotoSlab-Light.ttf new file mode 100644 index 0000000..ee82cf7 Binary files /dev/null and b/public/fonts/RobotoSlab-Light.ttf differ diff --git a/public/fonts/RobotoSlab-Medium.ttf b/public/fonts/RobotoSlab-Medium.ttf new file mode 100644 index 0000000..cc04919 Binary files /dev/null and b/public/fonts/RobotoSlab-Medium.ttf differ diff --git a/public/fonts/RobotoSlab-Regular.ttf b/public/fonts/RobotoSlab-Regular.ttf new file mode 100644 index 0000000..f163cfd Binary files /dev/null and b/public/fonts/RobotoSlab-Regular.ttf differ diff --git a/public/fonts/RobotoSlab-SemiBold.ttf b/public/fonts/RobotoSlab-SemiBold.ttf new file mode 100644 index 0000000..9d45846 Binary files /dev/null and b/public/fonts/RobotoSlab-SemiBold.ttf differ diff --git a/public/fonts/RobotoSlab-Thin.ttf b/public/fonts/RobotoSlab-Thin.ttf new file mode 100644 index 0000000..b8d3d08 Binary files /dev/null and b/public/fonts/RobotoSlab-Thin.ttf differ diff --git a/public/icons/arrow-down-top-line.svg b/public/icons/arrow-down-top-line.svg new file mode 100644 index 0000000..6ece5e7 --- /dev/null +++ b/public/icons/arrow-down-top-line.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/public/icons/arrow-right.svg b/public/icons/arrow-right.svg new file mode 100644 index 0000000..f39cd77 --- /dev/null +++ b/public/icons/arrow-right.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/public/icons/email.svg b/public/icons/email.svg new file mode 100644 index 0000000..474b928 --- /dev/null +++ b/public/icons/email.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/public/icons/menu-close.svg b/public/icons/menu-close.svg new file mode 100644 index 0000000..bfdab97 --- /dev/null +++ b/public/icons/menu-close.svg @@ -0,0 +1 @@ + close_mini [#d7b94c] Created with Sketch. \ No newline at end of file diff --git a/public/icons/menu-grid.svg b/public/icons/menu-grid.svg new file mode 100644 index 0000000..037c7de --- /dev/null +++ b/public/icons/menu-grid.svg @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/public/icons/paperclip.svg b/public/icons/paperclip.svg new file mode 100644 index 0000000..9318673 --- /dev/null +++ b/public/icons/paperclip.svg @@ -0,0 +1,18 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/Controller/Brain/BrainController.php b/src/Controller/Brain/BrainController.php new file mode 100644 index 0000000..03d1ae3 --- /dev/null +++ b/src/Controller/Brain/BrainController.php @@ -0,0 +1,18 @@ +render('brain/home/index.html.twig', [ + + ]); + } +} diff --git a/src/Controller/Brain/BrainPageController.php b/src/Controller/Brain/BrainPageController.php new file mode 100644 index 0000000..3f2aafc --- /dev/null +++ b/src/Controller/Brain/BrainPageController.php @@ -0,0 +1,95 @@ +getRepository(Page::class)->findAll(); + + return $this->render('brain/page/index.html.twig', [ + 'pages' => $pages + ]); + } + + #[Route('/brain/page/new', name: 'brain_page_new')] + public function new(EntityManagerInterface $entityManager, Request $request): Response + { + + $form = $this->createForm(PageType::class); + + $form->handleRequest($request); + + if ($form->isSubmitted()) { + $data = $form->getData(); + $page = new Page(); + + $page->setTitle($data->getTitle()); + $page->setText($data->getText()); + $page->setUrl($data->getUrl()); + + if ($data->isPublished()) { + $page->setPublished(true); + } else { + $page->setPublished(false); + } + + $entityManager->persist($page); + + $entityManager->flush(); + + return $this->redirectToRoute('brain_page_list'); + } + + return $this->render('brain/page/create.html.twig', [ + 'action' => 'New', + 'form' => $form + ]); + } + + #[Route('/brain/page/edit/{id}', name: 'brain_page_edit')] + public function edit(EntityManagerInterface $entityManager, string $id, Request $request): Response + { + + $page = $entityManager->getRepository(Page::class)->findOneBy(['id' => $id]); + + $form = $this->createForm(PageType::class, $page); + + $form->handleRequest($request); + + if ($form->isSubmitted()) { + $data = $form->getData(); + + $page->setTitle($data->getTitle()); + $page->setText($data->getText()); + $page->setUrl($data->getUrl()); + + if ($data->isPublished()) { + $page->setPublished(true); + } else { + $page->setPublished(false); + } + + $entityManager->flush(); + + return $this->redirectToRoute('brain_page_list'); + } + + return $this->render('brain/page/create.html.twig', [ + 'action' => 'Edit', + 'form' => $form + ]); + } +} diff --git a/src/Controller/Brain/BrainPhotosController.php b/src/Controller/Brain/BrainPhotosController.php new file mode 100644 index 0000000..e9dd3db --- /dev/null +++ b/src/Controller/Brain/BrainPhotosController.php @@ -0,0 +1,140 @@ +getRepository(Photos::class)->findAllOrderByLatest(); + + return $this->render('brain/photos/index.html.twig', [ + 'photos' => $photos + ]); + } + + #[Route('/brain/photos/new', name: 'brain_photos_new')] + public function new(EntityManagerInterface $entityManager, Request $request, PhotoUploader $photoUploader): Response + { + $form = $this->createForm(PhotosType::class); + + $form->handleRequest($request); + + if ($form->isSubmitted()) { + $data = $form->getData(); + $photos = new Photos(); + $fileNames = []; + + $photos->setTitle($data->getTitle()); + $photos->setDate($data->getDate()); + $photos->setText($data->getText()); + $photos->setUrl($data->getUrl()); + + $tax = $request->request->all('photos'); + + if ($data->getCategory() == null) { + $cat = $tax['category']; + + if ($cat !== null) { + $categoryToAdd = new Category()->setTitle($cat); + $photos->setCategory($categoryToAdd); + + $entityManager->persist($categoryToAdd); + } + } else { + $photos->setCategory($data->getCategory()); + } + + $thumbnail = $request->files->get('photos')['thumbnail']; + + $fileName = $photoUploader->upload($thumbnail, $photos->getTitle()); + $photos->setThumbnail($fileName); + + $uploadedPhotos = $request->files->get('photos')['uploads']; + + foreach ($uploadedPhotos as $upload) { + $filenames[] = $photoUploader->upload($upload['file'], $photos->getTitle()); + } + + foreach ($data->getUploads() as $index => $photo) { + $photo->setFile($filenames[$index]); + $photos->addUpload($photo); + } + + $entityManager->persist($photos); + + $entityManager->flush(); + + return $this->redirectToRoute('brain_photos_list'); + } + + return $this->render('brain/photos/create.html.twig', [ + 'action' => 'New', + 'form' => $form + ]); + } + + #[Route('/brain/photos/edit/{id}', name: 'brain_photos_edit')] + public function edit(EntityManagerInterface $entityManager, string $id, Request $request, PhotoUploader $photoUploader): Response + { + + $photos = $entityManager->getRepository(Photos::class)->findOneBy(['id' => $id]); + + $form = $this->createForm(PhotosType::class, $photos); + + $form->handleRequest($request); + /* TODO handle editing! */ + /*if (!$form->isSubmitted() && $photos->getUploads()) { + $dirName = 'uploads/' . strtolower(str_replace(' ', '_', $photos->getTitle())); + $form->setData(['uploads' => $dirName . '/' . $photos->getUploads()[0]->getFile()]); + } */ + + if ($form->isSubmitted()) { + $data = $form->getData(); + $photos = new Photos(); + $fileNames = []; + + $photos->setTitle($data->getTitle()); + + $uploadedPhotos = $request->files->get('photos')['uploads']; + + foreach ($uploadedPhotos as $upload) { + $filenames[] = $photoUploader->upload($upload['file'], $photos->getTitle()); + } + + foreach ($data->getUploads() as $index => $photo) { + $photo->setFile($filenames[$index]); + } + + //$entityManager->persist($data); + + $entityManager->flush(); + + return $this->redirectToRoute('brain_photos_list'); + } + + return $this->render('brain/photos/create.html.twig', [ + 'action' => 'Edit', + 'form' => $form + ]); + } + + private function handleFilenameToFileConversion(string $directory, array $uploads) + { + + } + +} diff --git a/src/Controller/Brain/BrainPostController.php b/src/Controller/Brain/BrainPostController.php new file mode 100644 index 0000000..718316a --- /dev/null +++ b/src/Controller/Brain/BrainPostController.php @@ -0,0 +1,138 @@ +getRepository(Post::class)->findAllOrderByLatest(); + + return $this->render('brain/post/index.html.twig', [ + 'posts' => $posts + ]); + } + + #[Route('/brain/post/new', name: 'brain_post_new')] + public function new(EntityManagerInterface $entityManager, Request $request): Response + { + $form = $this->createForm(PostType::class); + + $form->handleRequest($request); + + if ($form->isSubmitted()) { + $data = $form->getData(); + $post = new Post(); + + $post->setTitle($data->getTitle()); + $post->setDate($data->getDate()); + $post->setText($data->getText()); + $post->setUrl($data->getUrl()); + + foreach ($data->getTags() as $tag) { + $post->addTag($tag); + } + + if ($data->isPublished()) { + $post->setPublished(true); + } else { + $post->SetPublished(false); + } + + $tax = $request->request->all('post'); + + if ($data->getCategory() == null) { + $cat = $tax['category']; + + if ($cat !== null) { + $categoryToAdd = new Category()->setTitle($cat); + $post->setCategory($categoryToAdd); + + $entityManager->persist($categoryToAdd); + } + } else { + $post->setCategory($data->getCategory()); + } + + $entityManager->persist($post); + + $entityManager->flush(); + + return $this->redirectToRoute('brain_post_list'); + } + + return $this->render('brain/post/create.html.twig', [ + 'action' => 'new', + 'form' => $form, + ]); + } + + #[Route('/brain/post/edit/{id}', name: 'brain_post_edit')] + public function edit(EntityManagerInterface $entityManager, string $id, Request $request): Response + { + $post = $entityManager->getRepository(Post::class)->findOneBy(['id' => $id]); + + $form = $this->createForm(PostType::class, $post); + + $form->handleRequest($request); + + if ($form->isSubmitted()) { + $data = $form->getData(); + //$post = new Post(); + + + $post->setTitle($data->getTitle()); + $post->setDate($data->getDate()); + $post->setText($data->getText()); + $post->setUrl($data->getUrl()); + + foreach ($data->getTags() as $tag) { + $post->addTag($tag); + } + + if ($data->isPublished()) { + $post->setPublished(true); + } else { + $post->SetPublished(false); + } + + $tax = $request->request->all('post'); + + if ($data->getCategory() == null) { + $cat = $tax['category']; + + if ($cat !== null) { + $categoryToAdd = new Category()->setTitle($cat); + $post->setCategory($categoryToAdd); + + $entityManager->persist($categoryToAdd); + } + } else { + $post->setCategory($data->getCategory()); + } + + $entityManager->flush(); + + return $this->redirectToRoute('brain_post_list'); + } + return $this->render('brain/post/create.html.twig', [ + 'action' => 'edit', + 'form' => $form + ]); + } +} diff --git a/src/Controller/FrontEnd/CategoryController.php b/src/Controller/FrontEnd/CategoryController.php new file mode 100644 index 0000000..8d7bc23 --- /dev/null +++ b/src/Controller/FrontEnd/CategoryController.php @@ -0,0 +1,47 @@ +getRepository(Category::class)->findAll(); + + $categoriesDisplay = []; + + foreach ($categories as $index => $category) { + $categoriesDisplay[] = [ + 'title' => $category->getTitle(), + 'urlSafeTitle' => strtolower(str_replace(' ', '-', $category->getTitle())), + 'count' => $category->getCount(), + ]; + } + + return $this->render('front/category/index.html.twig', [ + 'categories' => $categoriesDisplay + ]); + } + + #[Route('/categories/{categoryTitle}', name: 'front_end_category_detail')] + public function detail(EntityManagerInterface $entityManager, string $categoryTitle): Response + { + $formattedTitle = ucwords(str_replace('-', ' ', $categoryTitle)); + $category = $entityManager->getRepository(Category::class)->findOneBy(['title' => $formattedTitle]); + return $this->render('front/category/detail.html.twig', [ + 'title' => $category->getTitle(), + 'posts' => $category->getPosts(), + 'photos' => $category->getPhotos(), + 'count' => $category->getCount() + ]); + } +} diff --git a/src/Controller/FrontEnd/FrontController.php b/src/Controller/FrontEnd/FrontController.php new file mode 100644 index 0000000..0a6ba53 --- /dev/null +++ b/src/Controller/FrontEnd/FrontController.php @@ -0,0 +1,25 @@ +render('front/home/index.html.twig', [ + + ]); + } + + #[Route('/secret/styleguide', name: 'front_end_styleguide')] + public function styleGuide(): Response + { + return $this->render('front/styleguide/styleguide.html.twig',[]); + } +} diff --git a/src/Controller/FrontEnd/PageController.php b/src/Controller/FrontEnd/PageController.php new file mode 100644 index 0000000..338e0bc --- /dev/null +++ b/src/Controller/FrontEnd/PageController.php @@ -0,0 +1,24 @@ +isPublished()) { + return $this->render('front/page/index.html.twig', [ + 'page' => $page + ]); + } + + return new Response('

Page not found

'); + } +} diff --git a/src/Controller/FrontEnd/PhotosController.php b/src/Controller/FrontEnd/PhotosController.php new file mode 100644 index 0000000..75e0231 --- /dev/null +++ b/src/Controller/FrontEnd/PhotosController.php @@ -0,0 +1,69 @@ +getRepository(Photos::class)->findAllOrderByLatest(); + + $albums = []; + + foreach ($photos as $index => $photo) { + $albums[] = [ + 'title' => $photo->getTitle(), + 'date' => $photo->getDate(), + 'category' => $photo->getCategory()->getTitle(), + 'thumbnail' => 'photos/' . strtolower(str_replace(' ', '_', $photo->getTitle())) . '/' . $photo->getThumbnail(), + 'url' => $photo->getUrl(), + ]; + } + + return $this->render('front/photos/index.html.twig', [ + 'photos' => $albums + ]); + } + + #[Route('/photos/{url:photos}', name: 'front_end_photos_detail')] + public function detail(Photos $photos): Response + { + $album = []; + $uploads = $photos->getUploads(); + + $album = [ + 'title' => $photos->getTitle(), + 'category' => $photos->getCategory()->getTitle(), + 'urlSafeCategory' => $photos->getCategory()->getUrlSafeTitle(), + 'text' => $photos->getText(), + 'date' => $photos->getDate() + ]; + + foreach ($uploads as $index => $upload) { + $filePath = 'photos/' . strtolower(str_replace(' ', '_', $album['title'])) . '/' . $upload->getFile(); + + $album['uploads'][] = [ + 'file' => $filePath, + 'alt' => $upload->getAltText(), + 'equipment' => $upload->getEquipment(), + 'caption' => $upload->getCaption(), + 'location' => $upload->getLocation(), + 'date' => $upload->getDate() + ]; + } + + return $this->render('front/photos/detail.html.twig', [ + 'photos' => $album + ]); + } +} + diff --git a/src/Controller/FrontEnd/PostController.php b/src/Controller/FrontEnd/PostController.php new file mode 100644 index 0000000..1cf2419 --- /dev/null +++ b/src/Controller/FrontEnd/PostController.php @@ -0,0 +1,50 @@ +getRepository(Post::class)->findAllOrderByLatest(); + + $formattedPosts = []; + + foreach ($posts as $index => $post) { + $formattedPosts [] = [ + 'title' => $post->getTitle(), + 'category' => $post->getCategory()->getTitle(), + 'urlSafeCategory' => $post->getCategory()->getUrlSafeTitle(), + 'date' => $post->getDate(), + 'url' => $post->getUrl() + ]; + } + + return $this->render('front/post/index.html.twig', [ + 'posts' => $formattedPosts + ]); + } + + #[Route('/words/{url:post}', name: 'front_end_post_detail')] + public function post(Post $post): Response + { + if ($post->isPublished()) { + return $this->render('front/post/detail.html.twig', [ + 'post' => $post, + 'urlSafeCategory' => $post->getCategory()->getUrlSafeTitle() + ]); + } + + return new Response('

Page not found

'); + } +} diff --git a/src/Controller/RegistrationController.php b/src/Controller/RegistrationController.php new file mode 100644 index 0000000..019d6a7 --- /dev/null +++ b/src/Controller/RegistrationController.php @@ -0,0 +1,42 @@ +createForm(RegistrationFormType::class, $user); + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + /** @var string $plainPassword */ + $plainPassword = $form->get('plainPassword')->getData(); + + // encode the plain password + $user->setPassword($userPasswordHasher->hashPassword($user, $plainPassword)); + + $entityManager->persist($user); + $entityManager->flush(); + + // do anything else you need here, like send an email + + return $this->redirectToRoute('brain_home'); + } + + return $this->render('registration/register.html.twig', [ + 'registrationForm' => $form, + ]); + } +} diff --git a/src/Controller/SecurityController.php b/src/Controller/SecurityController.php new file mode 100644 index 0000000..e0661fd --- /dev/null +++ b/src/Controller/SecurityController.php @@ -0,0 +1,32 @@ +getLastAuthenticationError(); + + // last username entered by the user + $lastUsername = $authenticationUtils->getLastUsername(); + + return $this->render('security/login.html.twig', [ + 'last_username' => $lastUsername, + 'error' => $error, + ]); + } + + #[Route(path: '/letmeout', name: 'brain_logout', priority: 1)] + public function logout(): void + { + throw new \LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.'); + } +} diff --git a/src/Entity/Category.php b/src/Entity/Category.php new file mode 100644 index 0000000..b4862cf --- /dev/null +++ b/src/Entity/Category.php @@ -0,0 +1,130 @@ + + */ + #[ORM\OneToMany(targetEntity: Post::class, mappedBy: 'category')] + private Collection $posts; + + /** + * @var Collection + */ + #[ORM\OneToMany(targetEntity: Photos::class, mappedBy: 'category')] + private Collection $photos; + + public function __construct() + { + $this->posts = new ArrayCollection(); + $this->photos = new ArrayCollection(); + } + + public function getId(): ?int + { + return $this->id; + } + + public function getTitle(): ?string + { + return $this->title; + } + + public function setTitle(string $title): static + { + $this->title = $title; + + return $this; + } + + /** + * @return Collection + */ + public function getPosts(): Collection + { + return $this->posts; + } + + public function addPost(Post $post): static + { + if (!$this->posts->contains($post)) { + $this->posts->add($post); + $post->setCategory($this); + } + + return $this; + } + + public function removePost(Post $post): static + { + if ($this->posts->removeElement($post)) { + // set the owning side to null (unless already changed) + if ($post->getCategory() === $this) { + $post->setCategory(null); + } + } + + return $this; + } + + /** + * @return Collection + */ + public function getPhotos(): Collection + { + return $this->photos; + } + + public function addPhoto(Photos $photo): static + { + if (!$this->photos->contains($photo)) { + $this->photos->add($photo); + $photo->setCategory($this); + } + + return $this; + } + + public function removePhoto(Photos $photo): static + { + if ($this->photos->removeElement($photo)) { + // set the owning side to null (unless already changed) + if ($photo->getCategory() === $this) { + $photo->setCategory(null); + } + } + + return $this; + } + + public function getCount() : int + { + return $this->posts->count() + $this->photos->count(); + } + + public function getUrlSafeTitle() : string + { + return strtolower(str_replace(' ', '-', $this->title)); + } + + public function getDisplaySafeTitle(string $urlSafeTitle) : string + { + return ucwords(str_replace('-', ' ', $urlSafeTitle)); + } +} diff --git a/src/Entity/Page.php b/src/Entity/Page.php new file mode 100644 index 0000000..42ff2c1 --- /dev/null +++ b/src/Entity/Page.php @@ -0,0 +1,81 @@ +id; + } + + public function getTitle(): ?string + { + return $this->title; + } + + public function setTitle(string $title): static + { + $this->title = $title; + + return $this; + } + + public function getText(): ?string + { + return $this->text; + } + + public function setText(string $text): static + { + $this->text = $text; + + return $this; + } + + public function getUrl(): ?string + { + return $this->url; + } + + public function setUrl(string $url): static + { + $this->url = $url; + + return $this; + } + + public function isPublished(): ?bool + { + return $this->published; + } + + public function setPublished(bool $published): static + { + $this->published = $published; + + return $this; + } +} diff --git a/src/Entity/Photo.php b/src/Entity/Photo.php new file mode 100644 index 0000000..96c2011 --- /dev/null +++ b/src/Entity/Photo.php @@ -0,0 +1,126 @@ +id; + } + + public function getFile(): ?string + { + return $this->file; + } + + public function setFile(string $file): static + { + $this->file = $file; + + return $this; + } + + public function getEquipment(): ?string + { + return $this->equipment; + } + + public function setEquipment(string $equipment): static + { + $this->equipment = $equipment; + + return $this; + } + + public function getLocation(): ?string + { + return $this->location; + } + + public function setLocation(string $location): static + { + $this->location = $location; + + return $this; + } + + public function getCaption(): ?string + { + return $this->caption; + } + + public function setCaption(string $caption): static + { + $this->caption = $caption; + + return $this; + } + + public function getDate(): ?\DateTime + { + return $this->date; + } + + public function setDate(\DateTime $date): static + { + $this->date = $date; + + return $this; + } + + public function getPhotos(): ?Photos + { + return $this->photos; + } + + public function setPhotos(?Photos $photos): static + { + $this->photos = $photos; + + return $this; + } + + public function getAltText(): ?string + { + return $this->alt_text; + } + + public function setAltText(string $alt_text): static + { + $this->alt_text = $alt_text; + + return $this; + } +} diff --git a/src/Entity/Photos.php b/src/Entity/Photos.php new file mode 100644 index 0000000..eb59b64 --- /dev/null +++ b/src/Entity/Photos.php @@ -0,0 +1,154 @@ + + */ + #[ORM\OneToMany(targetEntity: Photo::class, mappedBy: 'photos', cascade: ['persist'])] + private Collection $uploads; + + #[ORM\Column(type: Types::TEXT)] + private ?string $text = null; + + #[ORM\Column(length: 255)] + private ?string $url = null; + + #[ORM\Column(length: 255)] + private ?string $thumbnail = null; + + public function __construct() + { + $this->uploads = new ArrayCollection(); + } + + public function getId(): ?int + { + return $this->id; + } + + public function getTitle(): ?string + { + return $this->title; + } + + public function setTitle(string $title): static + { + $this->title = $title; + + return $this; + } + + public function getDate(): ?\DateTime + { + return $this->date; + } + + public function setDate(\DateTime $date): static + { + $this->date = $date; + + return $this; + } + + public function getCategory(): ?Category + { + return $this->category; + } + + public function setCategory(?Category $category): static + { + $this->category = $category; + + return $this; + } + + /** + * @return Collection + */ + public function getUploads(): Collection + { + return $this->uploads; + } + + public function addUpload(Photo $upload): static + { + if (!$this->uploads->contains($upload)) { + $this->uploads->add($upload); + $upload->setPhotos($this); + } + + return $this; + } + + public function removeUpload(Photo $upload): static + { + if ($this->uploads->removeElement($upload)) { + // set the owning side to null (unless already changed) + if ($upload->getPhotos() === $this) { + $upload->setPhotos(null); + } + } + + return $this; + } + + public function getText(): ?string + { + return $this->text; + } + + public function setText(string $text): static + { + $this->text = $text; + + return $this; + } + + public function getUrl(): ?string + { + return $this->url; + } + + public function setUrl(string $url): static + { + $this->url = $url; + + return $this; + } + + public function getThumbnail(): ?string + { + return $this->thumbnail; + } + + public function setThumbnail(string $thumbnail): static + { + $this->thumbnail = $thumbnail; + + return $this; + } +} diff --git a/src/Entity/Post.php b/src/Entity/Post.php new file mode 100644 index 0000000..f2fa15d --- /dev/null +++ b/src/Entity/Post.php @@ -0,0 +1,148 @@ + + */ + #[ORM\ManyToMany(targetEntity: Tag::class, inversedBy: 'posts')] + private Collection $tags; + + public function __construct() + { + $this->tags = new ArrayCollection(); + } + + public function getId(): ?int + { + return $this->id; + } + + public function getTitle(): ?string + { + return $this->title; + } + + public function setTitle(string $title): static + { + $this->title = $title; + + return $this; + } + + public function getDate(): ?\DateTime + { + return $this->date; + } + + public function setDate(\DateTime $date): static + { + $this->date = $date; + + return $this; + } + + public function getText(): ?string + { + return $this->text; + } + + public function setText(string $text): static + { + $this->text = $text; + + return $this; + } + + public function getUrl(): ?string + { + return $this->url; + } + + public function setUrl(string $url): static + { + $this->url = $url; + + return $this; + } + + public function isPublished(): ?bool + { + return $this->published; + } + + public function setPublished(bool $published): static + { + $this->published = $published; + + return $this; + } + + public function getCategory(): ?Category + { + return $this->category; + } + + public function setCategory(?Category $category): static + { + $this->category = $category; + + return $this; + } + + /** + * @return Collection + */ + public function getTags(): Collection + { + return $this->tags; + } + + public function addTag(Tag $tag): static + { + if (!$this->tags->contains($tag)) { + $this->tags->add($tag); + } + + return $this; + } + + public function removeTag(Tag $tag): static + { + $this->tags->removeElement($tag); + + return $this; + } +} diff --git a/src/Entity/Tag.php b/src/Entity/Tag.php new file mode 100644 index 0000000..b5420a9 --- /dev/null +++ b/src/Entity/Tag.php @@ -0,0 +1,75 @@ + + */ + #[ORM\ManyToMany(targetEntity: Post::class, mappedBy: 'tags')] + private Collection $posts; + + public function __construct() + { + $this->posts = new ArrayCollection(); + } + + public function getId(): ?int + { + return $this->id; + } + + public function getTitle(): ?string + { + return $this->title; + } + + public function setTitle(string $title): static + { + $this->title = $title; + + return $this; + } + + /** + * @return Collection + */ + public function getPosts(): Collection + { + return $this->posts; + } + + public function addPost(Post $post): static + { + if (!$this->posts->contains($post)) { + $this->posts->add($post); + $post->addTag($this); + } + + return $this; + } + + public function removePost(Post $post): static + { + if ($this->posts->removeElement($post)) { + $post->removeTag($this); + } + + return $this; + } +} diff --git a/src/Entity/User.php b/src/Entity/User.php new file mode 100644 index 0000000..288afdd --- /dev/null +++ b/src/Entity/User.php @@ -0,0 +1,112 @@ + The user roles + */ + #[ORM\Column] + private array $roles = []; + + /** + * @var string The hashed password + */ + #[ORM\Column] + private ?string $password = null; + + public function getId(): ?int + { + return $this->id; + } + + public function getUsername(): ?string + { + return $this->username; + } + + public function setUsername(string $username): static + { + $this->username = $username; + + return $this; + } + + /** + * A visual identifier that represents this user. + * + * @see UserInterface + */ + public function getUserIdentifier(): string + { + return (string) $this->username; + } + + /** + * @see UserInterface + */ + public function getRoles(): array + { + $roles = $this->roles; + // guarantee every user at least has ROLE_USER + $roles[] = 'ROLE_USER'; + $roles[] = 'ROLE_ADMIN'; + + return array_unique($roles); + } + + /** + * @param list $roles + */ + public function setRoles(array $roles): static + { + $this->roles = $roles; + + return $this; + } + + /** + * @see PasswordAuthenticatedUserInterface + */ + public function getPassword(): ?string + { + return $this->password; + } + + public function setPassword(string $password): static + { + $this->password = $password; + + return $this; + } + + /** + * Ensure the session doesn't contain actual password hashes by CRC32C-hashing them, as supported since Symfony 7.3. + */ + public function __serialize(): array + { + $data = (array) $this; + $data["\0".self::class."\0password"] = hash('crc32c', $this->password); + + return $data; + } +} diff --git a/src/Form/CategoryAutocompleteField.php b/src/Form/CategoryAutocompleteField.php new file mode 100644 index 0000000..35d043d --- /dev/null +++ b/src/Form/CategoryAutocompleteField.php @@ -0,0 +1,34 @@ +setDefaults([ + 'class' => Category::class, + 'searchable_fields' => ['title'], + 'label' => 'Category', + 'choice_label' => 'title', + 'multiple' => false, + 'tom_select_options' => [ + 'create' => true, + ] + ]); + } + + public function getParent(): string + { + return BaseEntityAutocompleteType::class; + } +} \ No newline at end of file diff --git a/src/Form/DataTransformer/UploadDataTransformer.php b/src/Form/DataTransformer/UploadDataTransformer.php new file mode 100644 index 0000000..39750df --- /dev/null +++ b/src/Form/DataTransformer/UploadDataTransformer.php @@ -0,0 +1,45 @@ +entityManager->getRepository(Photo::class)->findOneBy(['file' => $filename]); + + $directoryName = $photo->getPhotos()->getTitle(); + + $directoryName = 'photos/' . strtolower(str_replace(' ', '_', $directoryName)); + + $file = new File($directoryName . '/' . $filename); + + if ($file === null) { + throw new TransformationFailedException(sprintf('Photo with the filename "%s" does not exist!', $filename)); + } + + return $file; + } +} \ No newline at end of file diff --git a/src/Form/PageType.php b/src/Form/PageType.php new file mode 100644 index 0000000..34d0020 --- /dev/null +++ b/src/Form/PageType.php @@ -0,0 +1,31 @@ +add('title') + ->add('text') + ->add('url') + ->add('published') + ->add('save', SubmitType::class, ['label' => 'Save']) + ; + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => Page::class, + ]); + } +} diff --git a/src/Form/PhotoType.php b/src/Form/PhotoType.php new file mode 100644 index 0000000..0cc1975 --- /dev/null +++ b/src/Form/PhotoType.php @@ -0,0 +1,43 @@ +add('file', FileType::class, [ + 'label' => 'Photo', + 'constraints' => [ + new Assert\File( + maxSize: '8192k', + extensions: ['jpg', 'png'], + ), + ], + ]) + ->add('alt_text') + ->add('date') + ->add('equipment') + ->add('location') + ->add('caption') + ; + + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => Photo::class, + ]); + } +} diff --git a/src/Form/PhotosType.php b/src/Form/PhotosType.php new file mode 100644 index 0000000..77f83b1 --- /dev/null +++ b/src/Form/PhotosType.php @@ -0,0 +1,52 @@ +add('title') + ->add('date', DateType::class) + ->add('category', CategoryAutocompleteField::class) + ->add('text') + ->add('thumbnail', FileType::class, [ + 'label' => 'Thumbnail', + ]) + ->add('uploads', CollectionType::class, [ + 'entry_type' => PhotoType::class, + 'entry_options' => ['label' => false], + 'allow_add' => true, + 'by_reference' => false, + + ]) + ->add('url') + ->add('save', SubmitType::class, ['label' => 'Save']) + ; + + //$builder->get('uploads')->addModelTransformer($this->transformer); + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => Photos::class, + ]); + } +} diff --git a/src/Form/PostType.php b/src/Form/PostType.php new file mode 100644 index 0000000..4d7a923 --- /dev/null +++ b/src/Form/PostType.php @@ -0,0 +1,48 @@ +add('title', TextType::class) + ->add('date', DateType::class) + ->add('text', TextareaType::class) + ->add('category', CategoryAutocompleteField::class) + //->add('tags', TagAutocompleteField::class, ['required' => false]) + ->add('url', TextType::class) + ->add('published') + ->add('save', SubmitType::class, ['label' => 'Save']) + ; + + //$builder->get('tags')->resetViewTransformers(); + + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => Post::class, + 'validation_groups' => false, + ]); + } +} diff --git a/src/Form/RegistrationFormType.php b/src/Form/RegistrationFormType.php new file mode 100644 index 0000000..681bbef --- /dev/null +++ b/src/Form/RegistrationFormType.php @@ -0,0 +1,47 @@ +add('username') + ->add('plainPassword', PasswordType::class, [ + // instead of being set onto the object directly, + // this is read and encoded in the controller + 'mapped' => false, + 'attr' => ['autocomplete' => 'new-password'], + 'constraints' => [ + new NotBlank( + message: 'Please enter a password', + ), + new Length( + min: 6, + minMessage: 'Your password should be at least {{ limit }} characters', + // max length allowed by Symfony for security reasons + max: 4096, + ), + ], + ]) + ; + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => User::class, + ]); + } +} diff --git a/src/Form/TagAutocompleteField.php b/src/Form/TagAutocompleteField.php new file mode 100644 index 0000000..627deff --- /dev/null +++ b/src/Form/TagAutocompleteField.php @@ -0,0 +1,39 @@ +setDefaults([ + 'class' => Tag::class, + 'searchable_fields' => ['title'], + 'label' => 'Tag', + 'choice_label' => 'title', + 'multiple' => true, + 'required' => false, + /* TODO this isn't natively supported collections/choice type + so we're going to manually do it for now + */ + /*'tom_select_options' => [ + 'create' => true, + ] */ + ]); + } + + public function getParent(): string + { + return BaseEntityAutocompleteType::class; + } +} \ No newline at end of file diff --git a/src/Repository/BrainPageRepository.php b/src/Repository/BrainPageRepository.php new file mode 100644 index 0000000..ad6cf51 --- /dev/null +++ b/src/Repository/BrainPageRepository.php @@ -0,0 +1,43 @@ + + */ +class BrainPageRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, BrainPage::class); + } + + // /** + // * @return BrainPage[] Returns an array of BrainPage objects + // */ + // public function findByExampleField($value): array + // { + // return $this->createQueryBuilder('b') + // ->andWhere('b.exampleField = :val') + // ->setParameter('val', $value) + // ->orderBy('b.id', 'ASC') + // ->setMaxResults(10) + // ->getQuery() + // ->getResult() + // ; + // } + + // public function findOneBySomeField($value): ?BrainPage + // { + // return $this->createQueryBuilder('b') + // ->andWhere('b.exampleField = :val') + // ->setParameter('val', $value) + // ->getQuery() + // ->getOneOrNullResult() + // ; + // } +} diff --git a/src/Repository/CategoryRepository.php b/src/Repository/CategoryRepository.php new file mode 100644 index 0000000..2ea6ad9 --- /dev/null +++ b/src/Repository/CategoryRepository.php @@ -0,0 +1,43 @@ + + */ +class CategoryRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Category::class); + } + + // /** + // * @return Category[] Returns an array of Category objects + // */ + // public function findByExampleField($value): array + // { + // return $this->createQueryBuilder('c') + // ->andWhere('c.exampleField = :val') + // ->setParameter('val', $value) + // ->orderBy('c.id', 'ASC') + // ->setMaxResults(10) + // ->getQuery() + // ->getResult() + // ; + // } + + // public function findOneBySomeField($value): ?Category + // { + // return $this->createQueryBuilder('c') + // ->andWhere('c.exampleField = :val') + // ->setParameter('val', $value) + // ->getQuery() + // ->getOneOrNullResult() + // ; + // } +} diff --git a/src/Repository/PageRepository.php b/src/Repository/PageRepository.php new file mode 100644 index 0000000..af4f1e3 --- /dev/null +++ b/src/Repository/PageRepository.php @@ -0,0 +1,43 @@ + + */ +class PageRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Page::class); + } + + // /** + // * @return Page[] Returns an array of Page objects + // */ + // public function findByExampleField($value): array + // { + // return $this->createQueryBuilder('p') + // ->andWhere('p.exampleField = :val') + // ->setParameter('val', $value) + // ->orderBy('p.id', 'ASC') + // ->setMaxResults(10) + // ->getQuery() + // ->getResult() + // ; + // } + + // public function findOneBySomeField($value): ?Page + // { + // return $this->createQueryBuilder('p') + // ->andWhere('p.exampleField = :val') + // ->setParameter('val', $value) + // ->getQuery() + // ->getOneOrNullResult() + // ; + // } +} diff --git a/src/Repository/PhotoRepository.php b/src/Repository/PhotoRepository.php new file mode 100644 index 0000000..5344c03 --- /dev/null +++ b/src/Repository/PhotoRepository.php @@ -0,0 +1,43 @@ + + */ +class PhotoRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Photo::class); + } + + // /** + // * @return Photo[] Returns an array of Photo objects + // */ + // public function findByExampleField($value): array + // { + // return $this->createQueryBuilder('p') + // ->andWhere('p.exampleField = :val') + // ->setParameter('val', $value) + // ->orderBy('p.id', 'ASC') + // ->setMaxResults(10) + // ->getQuery() + // ->getResult() + // ; + // } + + // public function findOneBySomeField($value): ?Photo + // { + // return $this->createQueryBuilder('p') + // ->andWhere('p.exampleField = :val') + // ->setParameter('val', $value) + // ->getQuery() + // ->getOneOrNullResult() + // ; + // } +} diff --git a/src/Repository/PhotosRepository.php b/src/Repository/PhotosRepository.php new file mode 100644 index 0000000..75c2908 --- /dev/null +++ b/src/Repository/PhotosRepository.php @@ -0,0 +1,50 @@ + + */ +class PhotosRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Photos::class); + } + + public function findAllOrderByLatest(): ?array { + return $this->createQueryBuilder('photos') + ->orderBy('photos.date', 'DESC') + ->getQuery() + ->getResult(); + } + + // /** + // * @return Photos[] Returns an array of Photos objects + // */ + // public function findByExampleField($value): array + // { + // return $this->createQueryBuilder('p') + // ->andWhere('p.exampleField = :val') + // ->setParameter('val', $value) + // ->orderBy('p.id', 'ASC') + // ->setMaxResults(10) + // ->getQuery() + // ->getResult() + // ; + // } + + // public function findOneBySomeField($value): ?Photos + // { + // return $this->createQueryBuilder('p') + // ->andWhere('p.exampleField = :val') + // ->setParameter('val', $value) + // ->getQuery() + // ->getOneOrNullResult() + // ; + // } +} diff --git a/src/Repository/PostRepository.php b/src/Repository/PostRepository.php new file mode 100644 index 0000000..0ca26a9 --- /dev/null +++ b/src/Repository/PostRepository.php @@ -0,0 +1,49 @@ + + */ +class PostRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Post::class); + } + + public function findAllOrderByLatest(): array { + return $this->createQueryBuilder('post') + ->orderBy('post.date', 'DESC') + ->getQuery() + ->getResult(); + } + // /** + // * @return Post[] Returns an array of Post objects + // */ + // public function findByExampleField($value): array + // { + // return $this->createQueryBuilder('p') + // ->andWhere('p.exampleField = :val') + // ->setParameter('val', $value) + // ->orderBy('p.id', 'ASC') + // ->setMaxResults(10) + // ->getQuery() + // ->getResult() + // ; + // } + + // public function findOneBySomeField($value): ?Post + // { + // return $this->createQueryBuilder('p') + // ->andWhere('p.exampleField = :val') + // ->setParameter('val', $value) + // ->getQuery() + // ->getOneOrNullResult() + // ; + // } +} diff --git a/src/Repository/TagRepository.php b/src/Repository/TagRepository.php new file mode 100644 index 0000000..1b3c116 --- /dev/null +++ b/src/Repository/TagRepository.php @@ -0,0 +1,43 @@ + + */ +class TagRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Tag::class); + } + + // /** + // * @return Tag[] Returns an array of Tag objects + // */ + // public function findByExampleField($value): array + // { + // return $this->createQueryBuilder('t') + // ->andWhere('t.exampleField = :val') + // ->setParameter('val', $value) + // ->orderBy('t.id', 'ASC') + // ->setMaxResults(10) + // ->getQuery() + // ->getResult() + // ; + // } + + // public function findOneBySomeField($value): ?Tag + // { + // return $this->createQueryBuilder('t') + // ->andWhere('t.exampleField = :val') + // ->setParameter('val', $value) + // ->getQuery() + // ->getOneOrNullResult() + // ; + // } +} diff --git a/src/Repository/UserRepository.php b/src/Repository/UserRepository.php new file mode 100644 index 0000000..4f2804e --- /dev/null +++ b/src/Repository/UserRepository.php @@ -0,0 +1,60 @@ + + */ +class UserRepository extends ServiceEntityRepository implements PasswordUpgraderInterface +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, User::class); + } + + /** + * Used to upgrade (rehash) the user's password automatically over time. + */ + public function upgradePassword(PasswordAuthenticatedUserInterface $user, string $newHashedPassword): void + { + if (!$user instanceof User) { + throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', $user::class)); + } + + $user->setPassword($newHashedPassword); + $this->getEntityManager()->persist($user); + $this->getEntityManager()->flush(); + } + + // /** + // * @return User[] Returns an array of User objects + // */ + // public function findByExampleField($value): array + // { + // return $this->createQueryBuilder('u') + // ->andWhere('u.exampleField = :val') + // ->setParameter('val', $value) + // ->orderBy('u.id', 'ASC') + // ->setMaxResults(10) + // ->getQuery() + // ->getResult() + // ; + // } + + // public function findOneBySomeField($value): ?User + // { + // return $this->createQueryBuilder('u') + // ->andWhere('u.exampleField = :val') + // ->setParameter('val', $value) + // ->getQuery() + // ->getOneOrNullResult() + // ; + // } +} diff --git a/src/Service/PhotoUploader.php b/src/Service/PhotoUploader.php new file mode 100644 index 0000000..91b3eda --- /dev/null +++ b/src/Service/PhotoUploader.php @@ -0,0 +1,37 @@ +setTargetDirectory('photos/' . strtolower(str_replace(' ', '_', $galleryName))); + $originalFilename = pathInfo($file->getClientOriginalName(), PATHINFO_FILENAME); + $safeFilename = $this->slugger->slug($originalFilename); + $filename = $safeFilename . '.' . $file->guessExtension(); + + try { + $file->move($this->getTargetDirectory(), $filename); + } catch (FileException $e) { + //todo + } + + return $filename; + } + + public function getTargetDirectory() : string { + return $this->targetDirectory; + } + + public function setTargetDirectory(string $directory) : void { + $this->targetDirectory = $directory; + } +} \ No newline at end of file diff --git a/symfony.lock b/symfony.lock index 8ac143a..99800b6 100644 --- a/symfony.lock +++ b/symfony.lock @@ -270,6 +270,18 @@ "templates/base.html.twig" ] }, + "symfony/ux-autocomplete": { + "version": "3.0", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "2.6", + "ref": "07d9602b7231ba355f484305d6cea58310c01741" + }, + "files": [ + "config/routes/ux_autocomplete.yaml" + ] + }, "symfony/ux-turbo": { "version": "3.0", "recipe": { diff --git a/templates/base.html.twig b/templates/base.html.twig index a9cdfb3..df12c32 100644 --- a/templates/base.html.twig +++ b/templates/base.html.twig @@ -3,14 +3,17 @@ {% block title %}Welcome!{% endblock %} - + {% block stylesheets %} {% endblock %} {% block javascripts %} - {% block importmap %}{{ importmap('app') }}{% endblock %} + {% block importmap %}{{ importmap('main') }}{% endblock %} {% endblock %} + + + {% set frankenphpHotReload = app.request.server.get('FRANKENPHP_HOT_RELOAD') %} {% if frankenphpHotReload %} @@ -18,7 +21,17 @@ {% endif %} - - {% block body %}{% endblock %} + +
+
+ {% block menu %} + {{ include('front/menu/menu.html.twig') }} + {% endblock %} +
+
+ {% block body %}{% endblock %} +
+
+
diff --git a/templates/brain/base.html.twig b/templates/brain/base.html.twig new file mode 100644 index 0000000..540684c --- /dev/null +++ b/templates/brain/base.html.twig @@ -0,0 +1,45 @@ + + + + + {% block title %}Welcome!{% endblock %} + + {% block stylesheets %} + {% endblock %} + + + + + + + + {% block javascripts %} + {% block importmap %}{{ importmap(['brain']) }}{% endblock %} + {% endblock %} + + {% set frankenphpHotReload = app.request.server.get('FRANKENPHP_HOT_RELOAD') %} + {% if frankenphpHotReload %} + + + + {% endif %} + + + +
+
+ {% block admin_menu %} + {{ include('brain/menu/menu.html.twig') }} + {% endblock %} +
+
+ {% block page_title %}{% endblock %} + {% block actions %}{% endblock %} + {% block admin %}{% endblock %} +
+
+ + diff --git a/templates/brain/home/index.html.twig b/templates/brain/home/index.html.twig new file mode 100644 index 0000000..3c38351 --- /dev/null +++ b/templates/brain/home/index.html.twig @@ -0,0 +1,15 @@ +{% extends 'brain/base.html.twig' %} + +{% block title %}Brain{% endblock %} + +{% block page_title %} +

Brain

+{% endblock %} + +{% block actions %} + this will be some global admin actions +{% endblock %} + +{% block admin %} +

This will be a dashboard of sorts

+{% endblock %} diff --git a/templates/brain/menu/menu.html.twig b/templates/brain/menu/menu.html.twig new file mode 100644 index 0000000..4d5e28a --- /dev/null +++ b/templates/brain/menu/menu.html.twig @@ -0,0 +1,31 @@ + \ No newline at end of file diff --git a/templates/brain/page/create.html.twig b/templates/brain/page/create.html.twig new file mode 100644 index 0000000..9b244ab --- /dev/null +++ b/templates/brain/page/create.html.twig @@ -0,0 +1,32 @@ +{% extends 'brain/base.html.twig' %} + +{% block title %}{{ action|capitalize}} Page{% endblock %} + +{% block page_title %}

Add New Page

{% endblock %} + +{# {% block actions%}Actions here{% endblock %} #} + +{% block admin %} +
+ {{ form_start(form) }} +
+ {{ form_errors(form) }} +
+
+ {{ form_row(form.title) }} +
+
+ {{ form_row(form.text) }} +
+
+ {{ form_row(form.url) }} +
+
+ {{ form_row(form.published) }} +
+
+ {{ form_rest(form) }} +
+ {{ form_end(form) }} +
+{% endblock %} diff --git a/templates/brain/page/index.html.twig b/templates/brain/page/index.html.twig new file mode 100644 index 0000000..b157f03 --- /dev/null +++ b/templates/brain/page/index.html.twig @@ -0,0 +1,33 @@ +{% extends 'brain/base.html.twig' %} + +{% block title %}Pages{% endblock %} + +{% block page_title %}

All pages

{% endblock %} + +{# {% block actions%}Actions here{% endblock %} #} + +{% block admin %} +
+

New Page

+ + + + + + + + + + + {% for page in pages %} + + + + + + {% endfor %} + +
TitleEditViewPublished
{{page.title}}EditView + {{page.published == 1 ? 'Yes' : 'No'}}
+
+{% endblock %} diff --git a/templates/brain/photos/create.html.twig b/templates/brain/photos/create.html.twig new file mode 100644 index 0000000..f20baab --- /dev/null +++ b/templates/brain/photos/create.html.twig @@ -0,0 +1,42 @@ +{% extends 'brain/base.html.twig' %} + +{% block title %}{{ action|capitalize}} Photos{% endblock %} + +{% block page_title %}

Add New Photos

{% endblock %} + + +{% block admin %} +
+ {{ form_start(form) }} +
+ {{ form_errors(form) }} +
+
+ {{ form_row(form.title) }} +
+
+ {{ form_row(form.date) }} +
+
+ {{ form_row(form.category) }} +
+
+ {{ form_row(form.thumbnail) }} +
+
+ {{ form_row(form.text)}} +
+
+ {{ form_row(form.uploads)}} + +
+
+ {{ form_row(form.url) }} +
+
+ {{ form_row(form.save)}} + {{ form_row(form._token)}} +
+ {{ form_end(form) }} +
+{% endblock %} diff --git a/templates/brain/photos/index.html.twig b/templates/brain/photos/index.html.twig new file mode 100644 index 0000000..9058925 --- /dev/null +++ b/templates/brain/photos/index.html.twig @@ -0,0 +1,35 @@ +{% extends 'brain/base.html.twig' %} + +{% block title %}Photos{% endblock %} + +{% block page_title %}

All Photos

{% endblock %} + +{# {% block actions%}Actions here{% endblock %} #} + +{% block admin %} +
+

New Photos

+ + + + + + + + + + + + {% for photo in photos %} + + + + + + + {% endfor %} + +
TitleDateCategoryEditView
{{photo.title}}{{photo.getDate()|date('m/d/Y')}}{{photo.category.getTitle()}}EditView +
+
+{% endblock %} diff --git a/templates/brain/post/create.html.twig b/templates/brain/post/create.html.twig new file mode 100644 index 0000000..2a1498c --- /dev/null +++ b/templates/brain/post/create.html.twig @@ -0,0 +1,42 @@ +{% extends 'brain/base.html.twig' %} + +{% block title %}{{ action|capitalize}} Post{% endblock %} + +{% block page_title %}

Add New Post

{% endblock %} + +{# {% block actions%}Actions here{% endblock %} #} + +{% block admin %} +
+ {{ form_start(form) }} +
+ {{ form_errors(form) }} +
+ +
+ {{ form_row(form.title) }} +
+
+ {{ form_row(form.date) }} +
+
+ {{ form_row(form.text) }} +
+
+ {{ form_row(form.category) }} +
+ {#
+ {{ form_row(form.tags) }} +
#} +
+ {{ form_row(form.url) }} +
+
+ {{ form_row(form.published) }} +
+
+ {{ form_rest(form) }} +
+ {{ form_end(form) }} +
+{% endblock %} diff --git a/templates/brain/post/index.html.twig b/templates/brain/post/index.html.twig new file mode 100644 index 0000000..7c37ea5 --- /dev/null +++ b/templates/brain/post/index.html.twig @@ -0,0 +1,37 @@ +{% extends 'brain/base.html.twig' %} + +{% block title %}Posts {% endblock %} + +{% block page_title %}

All Posts

{% endblock %} + +{# {% block actions%}Actions here{% endblock %} #} + +{% block admin %} +
+

New Post

+ + + + + + + + + + + + + {% for post in posts %} + + + + + + + + {% endfor %} + +
TitleDateCategoryEditViewPublished
{{post.title}}{{post.getDate()|date('m/d/Y')}}{{post.category.getTitle()}}EditView + {{post.published == 1 ? 'Published' : 'Unpublished'}}
+
+{% endblock %} diff --git a/templates/front/category/detail.html.twig b/templates/front/category/detail.html.twig new file mode 100644 index 0000000..f3b0cad --- /dev/null +++ b/templates/front/category/detail.html.twig @@ -0,0 +1,28 @@ +{% extends 'base.html.twig' %} + +{% block title %}Categories | Alex Daniels{% endblock %} + +{% block body %} +
+ {% if posts|length %} +
+

Posts

+ +
+ {% endif %} + {% if photos|length %} +
+

Photos

+ +
+ {% endif %} +
+{% endblock %} diff --git a/templates/front/category/index.html.twig b/templates/front/category/index.html.twig new file mode 100644 index 0000000..d1c7655 --- /dev/null +++ b/templates/front/category/index.html.twig @@ -0,0 +1,16 @@ +{% extends 'base.html.twig' %} + +{% block title %}Categories | Alex Daniels{% endblock %} + +{% block body %} +
+

Categories

+ +
+{% endblock %} diff --git a/templates/front/home/index.html.twig b/templates/front/home/index.html.twig new file mode 100644 index 0000000..7a389cf --- /dev/null +++ b/templates/front/home/index.html.twig @@ -0,0 +1,138 @@ +{% extends 'home.html.twig' %} + +{% block title %}My Own Corner Of The Internet | Alex Daniels{% endblock %} + + +{% block nav %} + +{% endblock %} + + +{% block intro %} +
+

 cat ./about.md

+
+{% endblock %} + +{% block body %} +
+

+ hello, i'm alex
+ i'm a web developer based in portland, oregon

+ in my free time i enjoy hiking, camping, reading, photography, and more

+ welcome to my little corner of the internet +

+
+{% endblock %} + +{% block outro %} +
+

 ls ./menu

+ +
+
+{% endblock %} + +{% block underFold %} +
+

Some Cool Stuff

+
+
+ +

Item 1

+ +

I took a 6 week road trip across the united states

+ Road Trip +
+
+ +

Item 2

+ +

Some text about a thing longer text asdf 1234

+ Project +
+
+ +

Item 3

+ +

Some text about a thing

+ Project +
+
+
+
+

Work

+
+
+

Experience

+
+
+

Engine Room Technology Company

+

2021-2026 - Remote

+
+
+

Eastern Standard

+

2016-2021 - Philadelphia, PA

+
+
+
+
+

Highlights

+
+
+
    +
  • + item 1 +
  • +
  • + item 2 +
  • +
  • + item 3 +
  • +
+
+
+
    +
  • + 2 item 1 +
  • +
  • + 2 item 2 +
  • +
  • + 2 item 3 +
  • +
+
+
+
+
+
+
+

Contact

+
+ +
+
+{% endblock %} + +{% block footer %} +

© 2026 Alex Daniels

+{% endblock %} \ No newline at end of file diff --git a/templates/front/home/menu.html.twig b/templates/front/home/menu.html.twig new file mode 100644 index 0000000..0999ff5 --- /dev/null +++ b/templates/front/home/menu.html.twig @@ -0,0 +1,14 @@ +{% block menu %} + +{% endblock %} \ No newline at end of file diff --git a/templates/front/menu/menu.html.twig b/templates/front/menu/menu.html.twig new file mode 100644 index 0000000..da675d9 --- /dev/null +++ b/templates/front/menu/menu.html.twig @@ -0,0 +1,16 @@ + \ No newline at end of file diff --git a/templates/front/page/index.html.twig b/templates/front/page/index.html.twig new file mode 100644 index 0000000..ac9f0a1 --- /dev/null +++ b/templates/front/page/index.html.twig @@ -0,0 +1,16 @@ +{% extends 'base.html.twig' %} + +{% block title %}{{page.title}} | Alex Daniels{% endblock %} + +{% block body %} +
+

{{page.title}}

+ {% if app.user %} + Edit
+ {% endif %} + +
+ {{ page.text|raw}} +
+
+{% endblock %} diff --git a/templates/front/photos/detail.html.twig b/templates/front/photos/detail.html.twig new file mode 100644 index 0000000..555b0a5 --- /dev/null +++ b/templates/front/photos/detail.html.twig @@ -0,0 +1,33 @@ +{% extends 'base.html.twig' %} + +{% block title %}{{photos['title']}} - Photography | Alex Daniels{% endblock %} + +{% block body %} +
+

{{photos['title']}}

+
+

{{ photos['date']|date('l M d Y')}}

+

Filed Under: {{photos['category']}}

+
+
+ {{ photos['text']|raw }} +
+
    + {% for photo in photos['uploads'] %} +
  • + {{photo['alt']}} +
  • + {% endfor %} +
+
+
+ X + +
+

+

+

+

+
+
+{% endblock body %} \ No newline at end of file diff --git a/templates/front/photos/index.html.twig b/templates/front/photos/index.html.twig new file mode 100644 index 0000000..1d4e611 --- /dev/null +++ b/templates/front/photos/index.html.twig @@ -0,0 +1,25 @@ +{% extends 'base.html.twig' %} + +{% block title %}Photography | Alex Daniels{% endblock %} + +{% block body %} +

Photography

+
+ {% if app.user %} + + {% endif %} +
+{% endblock body %} \ No newline at end of file diff --git a/templates/front/post/detail.html.twig b/templates/front/post/detail.html.twig new file mode 100644 index 0000000..bdd664a --- /dev/null +++ b/templates/front/post/detail.html.twig @@ -0,0 +1,21 @@ +{% extends 'base.html.twig' %} + +{% block title %}{{post.title}} - Writing | Alex Daniels{% endblock %} + +{% block body %} +
+

{{post.title}}

+
+ {% if app.user %} +
+ Edit +
+ {% endif %} +

Filed under: {{ post.category.getTitle() }}

+ +
+
+ {{ post.text|raw }} +
+
+{% endblock %} diff --git a/templates/front/post/index.html.twig b/templates/front/post/index.html.twig new file mode 100644 index 0000000..8176baf --- /dev/null +++ b/templates/front/post/index.html.twig @@ -0,0 +1,24 @@ +{% extends 'base.html.twig' %} + +{% block title %}Writing | Alex Daniels{% endblock %} + +{% block body %} +
+

Writing

+

A truly random smattering of thoughts and feelings. Things may not always be relevant, but they will always be irreverant.

+
+

Recent

+ +
+
+{% endblock %} diff --git a/templates/front/styleguide/styleguide.html.twig b/templates/front/styleguide/styleguide.html.twig new file mode 100644 index 0000000..38fdcf8 --- /dev/null +++ b/templates/front/styleguide/styleguide.html.twig @@ -0,0 +1,116 @@ +{% extends 'base.html.twig' %} + +{% block body %} + +
+ +
+
+

H1. This is a Page Title.

+

H2. This is a header.

+

H3. This is a medium header.

+

H4. This is a sidebar header.

+
H5. This is a small header.
+
H6. This is a tiny header.
+

A general paragraph will look like this.

+
+ +
+

This is a text link

+

Strong is used to indicate strong importance

+ +

The b element is stylistically different text from normal text, without any special importance

+ +

The i element is text that is set off from the normal text

+ +

The u element is text with an unarticulated, though explicitly rendered, non-textual annotation

+ +

The s element is text with a strike through denoting cancelization

+ +

This small text is small for for fine print, etc.

+ +

This text is a short inline quotation

+ +

This is a citation +

+ + +{# +
+ COLORS +
+
+ +
    +
  • +
    #C7D6BA
    +
  • +
  • +
    #BAE3C2
    +
  • +
  • +
    #C7EDC2
    +
  • +
  • +
    #E5EDC2
    +
  • +
  • +
    #E3E1BA
    +
  • +
#} + +{#
+ FORM ELEMENTS +
+
#} + +{#
+
+
+ +
+
+ +
+
+ +
+ +
+ +
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+ + +
+
+
#} +{% endblock %} \ No newline at end of file diff --git a/templates/home.html.twig b/templates/home.html.twig new file mode 100644 index 0000000..bdfd94d --- /dev/null +++ b/templates/home.html.twig @@ -0,0 +1,46 @@ + + + + + {% block title %}Alex Daniels{% endblock %} + + {% block stylesheets %} + {% endblock %} + + {% block javascripts %} + {% block importmap %}{{ importmap('landing') }}{% endblock %} + {% endblock %} + + + + + {% set frankenphpHotReload = app.request.server.get('FRANKENPHP_HOT_RELOAD') %} + {% if frankenphpHotReload %} + + + + {% endif %} + + +
+ {% block nav %}{% endblock %} +
+
+
+
+ {% block intro %}{% endblock %} + {% block body %}{% endblock %} + {% block outro %}{% endblock %} +
+
+
+
+ {% block underFold %}{% endblock %} +
+
+
+
+ {% block footer %}{% endblock %} +
+ + diff --git a/templates/registration/register.html.twig b/templates/registration/register.html.twig new file mode 100644 index 0000000..2ef7a3d --- /dev/null +++ b/templates/registration/register.html.twig @@ -0,0 +1,18 @@ +{% extends 'base.html.twig' %} + +{% block title %}Register{% endblock %} + +{% block body %} +

Register

+ + {{ form_errors(registrationForm) }} + + {{ form_start(registrationForm) }} + {{ form_row(registrationForm.username) }} + {{ form_row(registrationForm.plainPassword, { + label: 'Password' + }) }} + + + {{ form_end(registrationForm) }} +{% endblock %} diff --git a/templates/security/login.html.twig b/templates/security/login.html.twig new file mode 100644 index 0000000..d7b4bff --- /dev/null +++ b/templates/security/login.html.twig @@ -0,0 +1,38 @@ +{% extends 'base.html.twig' %} + +{% block title %}Log in!{% endblock %} + +{% block body %} +
+ {% if error %} +
{{ error.messageKey|trans(error.messageData, 'security') }}
+ {% endif %} + + {% if app.user %} +
+ You are logged in as {{ app.user.userIdentifier }}, Logout +
+ {% endif %} + +

Please sign in

+ + + + + + + {# + Uncomment this section and add a remember_me option below your firewall to activate remember me functionality. + See https://symfony.com/doc/current/security/remember_me.html + +
+ + +
+ #} + + +
+{% endblock %}