Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d9ffaa942 |
@@ -1,7 +1,3 @@
|
|||||||
# Dependencies
|
|
||||||
node_modules/
|
|
||||||
package-lock.json
|
|
||||||
|
|
||||||
# Build outputs
|
# Build outputs
|
||||||
*.log
|
*.log
|
||||||
.DS_Store
|
.DS_Store
|
||||||
@@ -15,7 +11,6 @@ Thumbs.db
|
|||||||
|
|
||||||
# Cache & Storage
|
# Cache & Storage
|
||||||
.cache/
|
.cache/
|
||||||
.sass-cache/
|
|
||||||
admin/storage/cache/
|
admin/storage/cache/
|
||||||
admin/storage/geoip/
|
admin/storage/geoip/
|
||||||
admin/storage/stats.json
|
admin/storage/stats.json
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
# Disable directory listing globally
|
|
||||||
Options -Indexes
|
|
||||||
|
|
||||||
# Security - Block access to entire application
|
|
||||||
<Files ~ "^\.">
|
|
||||||
Order allow,deny
|
|
||||||
Deny from all
|
|
||||||
</Files>
|
|
||||||
|
|
||||||
<FilesMatch "\.(php|ini|log|conf|config|md|map)$">
|
|
||||||
Order allow,deny
|
|
||||||
Deny from all
|
|
||||||
</FilesMatch>
|
|
||||||
|
|
||||||
# Block access to backup files
|
|
||||||
<FilesMatch "\.(backup|bak|old|orig|swp|save)$">
|
|
||||||
Order allow,deny
|
|
||||||
Deny from all
|
|
||||||
</FilesMatch>
|
|
||||||
|
|
||||||
# Block access to all application files
|
|
||||||
<IfModule mod_authz_core.c>
|
|
||||||
Require all denied
|
|
||||||
</IfModule>
|
|
||||||
|
|
||||||
# Directory protection - Block all access
|
|
||||||
<Directory />
|
|
||||||
Order allow,deny
|
|
||||||
Deny from all
|
|
||||||
</Directory>
|
|
||||||
|
|
||||||
# Only allow access to public directory
|
|
||||||
<Directory "public">
|
|
||||||
Order allow,deny
|
|
||||||
Allow from all
|
|
||||||
Require all granted
|
|
||||||
</Directory>
|
|
||||||
|
|
||||||
# Set default directory to public
|
|
||||||
DirectoryIndex public/index.php
|
|
||||||
|
|
||||||
# Redirect root to public directory
|
|
||||||
<IfModule mod_rewrite.c>
|
|
||||||
RewriteEngine On
|
|
||||||
RewriteBase /
|
|
||||||
|
|
||||||
# Redirect root to public
|
|
||||||
RewriteRule ^$ public/ [L]
|
|
||||||
|
|
||||||
# Redirect all other requests to public
|
|
||||||
RewriteCond %{REQUEST_URI} !^/public/
|
|
||||||
RewriteRule ^(.*)$ public/$1 [L]
|
|
||||||
</IfModule>
|
|
||||||
@@ -1,115 +0,0 @@
|
|||||||
# Agent Instructions for CodePress CMS
|
|
||||||
|
|
||||||
## AI Model
|
|
||||||
- **Huidig model**: `claude-opus-4-6` (OpenCode / `opencode/claude-opus-4-6`)
|
|
||||||
- Sessie gestart: 16 feb 2026
|
|
||||||
|
|
||||||
## Build & Run
|
|
||||||
- **Run Server**: `php -S localhost:8080 cms/router.php` (router nodig voor clean URLs)
|
|
||||||
- **Lint PHP**: `find . -name "*.php" -not -path "./vendor/*" -exec php -l {} \;`
|
|
||||||
- **Dependencies**: Composer vereist voor CommonMark, Twig en scssphp. Geen NPM.
|
|
||||||
- **Admin Console**: Toegankelijk op `/admin.php` (standaard login: `admin` / `admin`)
|
|
||||||
|
|
||||||
## Project Structuur
|
|
||||||
```
|
|
||||||
codepress/
|
|
||||||
├── cms/ # Core CMS engine
|
|
||||||
│ ├── core/
|
|
||||||
│ │ ├── class/
|
|
||||||
│ │ │ ├── CodePressCMS.php # Hoofd CMS class
|
|
||||||
│ │ │ ├── ThemeManager.php # Thema-resolver + Twig render + SCSS compile
|
|
||||||
│ │ │ └── Logger.php # Logging systeem
|
|
||||||
│ │ ├── plugin/
|
|
||||||
│ │ │ ├── PluginManager.php # Plugin loader
|
|
||||||
│ │ │ └── CMSAPI.php # API voor plugins
|
|
||||||
│ │ ├── config.php # Config loader (leest config.json)
|
|
||||||
│ │ └── index.php # Bootstrap (autoloader, requires)
|
|
||||||
│ └── router.php # PHP dev server router (serveert ook /themes/)
|
|
||||||
├── language/ # Taalbestanden (nl/, en/, de/ — elk met site.php + admin.php)
|
|
||||||
├── themes/ # Dynamische thema's (volledig zelfstandig)
|
|
||||||
│ ├── default/ # Standaard thema
|
|
||||||
│ │ ├── theme.json # { title, default_layout, layout→.twig mapping, kleuren }
|
|
||||||
│ │ ├── base.twig # Hoofd layout (head, header, nav, footer)
|
|
||||||
│ │ ├── full_content.twig # Layout: volledige breedte
|
|
||||||
│ │ ├── left_sidebar.twig # Layout: sidebar links
|
|
||||||
│ │ ├── right_sidebar.twig # Layout: sidebar rechts
|
|
||||||
│ │ ├── custom1.twig # Layout: custom
|
|
||||||
│ │ ├── guide.twig # Layout: handleiding
|
|
||||||
│ │ ├── partials/ # header.twig, navigation.twig, footer.twig
|
|
||||||
│ │ ├── assets/scss/theme.scss # SCSS bron (runtime gecompileerd)
|
|
||||||
│ │ └── assets/js/ # app.js, bootstrap.bundle.min.js
|
|
||||||
│ ├── demo/ # Demo thema (zelfde structuur, andere look)
|
|
||||||
├── admin/ # Admin paneel
|
|
||||||
│ ├── config/
|
|
||||||
│ │ ├── app.php # Admin app configuratie
|
|
||||||
│ │ ├── admin.json # Gebruikers & security (file-based, gitignored)
|
|
||||||
│ │ └── admin.json.example # Voorbeeld met placeholder-wachtwoord
|
|
||||||
│ ├── src/
|
|
||||||
│ │ └── AdminAuth.php # Authenticatie (sessies, bcrypt, CSRF, lockout)
|
|
||||||
│ ├── theme/default/views/ # Twig templates
|
|
||||||
│ │ ├── login.twig # Login pagina
|
|
||||||
│ │ ├── layouts/admin.twig # Admin layout met sidebar
|
|
||||||
│ │ └── pages/ # dashboard, content, content-edit, config, plugins, theme, users, statistics, logs, security, update, guide, media, etc.
|
|
||||||
│ └── storage/logs/ # Admin logs (gedeeld met front-end)
|
|
||||||
├── cli/ # CLI scripts & tests
|
|
||||||
│ └── test/
|
|
||||||
│ ├── accessibility.sh # WCAG 2.1 AA test suite
|
|
||||||
│ ├── enhanced-suite.sh # Enhanced test suite
|
|
||||||
│ ├── functional/ # Functionele testen
|
|
||||||
│ └── pentest/ # Penetratietesten
|
|
||||||
├── plugins/ # CMS plugins
|
|
||||||
│ ├── HTMLBlock/
|
|
||||||
│ └── Navigation/
|
|
||||||
├── public/ # Web root
|
|
||||||
│ ├── assets/css/js/
|
|
||||||
│ ├── index.php # Website entry point
|
|
||||||
│ └── admin.php # Admin entry point + router
|
|
||||||
├── content/ # Content bestanden
|
|
||||||
├── guide/ # Handleidingen (nl/en)
|
|
||||||
├── docs/ # Documentatie
|
|
||||||
├── config.json # Site configuratie
|
|
||||||
└── AGENTS.md # Dit bestand
|
|
||||||
```
|
|
||||||
|
|
||||||
## Code Style & Conventions
|
|
||||||
- **PHP Standards**: Follow PSR-12. Use 4 spaces for indentation.
|
|
||||||
- **Naming**: Classes `PascalCase` (e.g., `CodePressCMS`), methods `camelCase` (e.g., `renderMenu`), variables `camelCase`, config keys `snake_case`.
|
|
||||||
- **Architecture**:
|
|
||||||
- Core CMS logic in `cms/core/class/CodePressCMS.php`
|
|
||||||
- Bootstrap/requires in `cms/core/index.php`
|
|
||||||
- Configuration loaded from `config.json` via `cms/core/config.php`
|
|
||||||
- Public website entry point: `public/index.php`
|
|
||||||
- Admin entry point + routing: `public/admin.php`
|
|
||||||
- Admin authenticatie: `admin/src/AdminAuth.php`
|
|
||||||
- **Content**: Stored in `content/`. Supports `.md` (Markdown), `.php` (Dynamic), `.html` (Static).
|
|
||||||
- **Templating**: Twig templates in `themes/<naam>/`. `ThemeManager` rendert via Twig en compileert `assets/scss/theme.scss` runtime naar `public/themes/<naam>/theme.css`. Layout gekozen via frontmatter `layout:` key; onbekende layouts vallen terug op `default_layout` in `theme.json`.
|
|
||||||
- **Navigation**: Auto-generated from directory structure. Folders require an index file to be clickable in breadcrumbs.
|
|
||||||
- **Security**:
|
|
||||||
- Always use `htmlspecialchars()` for outputting user/content data
|
|
||||||
- Use `realpath()` + prefix-check for path traversal prevention
|
|
||||||
- Admin forms require CSRF tokens via `AdminAuth::verifyCsrf()`
|
|
||||||
- Passwords stored as bcrypt hashes in `admin.json`
|
|
||||||
- **Git**: `main` is the clean CMS core. `development` is de actieve development branch. `e.noorlander` bevat persoonlijke content. Niet mixen.
|
|
||||||
|
|
||||||
## Admin Console
|
|
||||||
- **File-based**: Geen database. Gebruikers opgeslagen in `admin/config/admin.json`
|
|
||||||
- **Routing**: Via `?route=` parameter in `public/admin.php`
|
|
||||||
- **Routes**: `login`, `logout`, `dashboard`, `content`, `content-edit`, `content-new`, `content-delete`, `content-dir-create`, `content-dir-rename`, `content-dir-delete`, `content-move`, `config`, `plugins`, `plugins-new`, `plugins-edit`, `plugins-config`, `plugins-toggle`, `plugins-delete`, `theme`, `theme-new`, `users`, `security`, `statistics`, `logs`, `guide`, `media`, `update`
|
|
||||||
- **Auth**: Session-based. `AdminAuth` class handelt login, logout, CSRF, brute-force lockout af
|
|
||||||
- **Templates**: Twig templates in `admin/theme/default/views/`. Layout in `layouts/admin.twig`
|
|
||||||
|
|
||||||
## Important: Title vs File/Directory Name Logic
|
|
||||||
- **CRITICAL**: When user asks for "title" corrections, they usually mean **FILE/DIRECTORY NAME WITHOUT LANGUAGE PREFIX AND EXTENSIONS**, not the HTML title from content!
|
|
||||||
- **Examples**:
|
|
||||||
- `nl.test.md` → display as "Test" (not content title)
|
|
||||||
- `nl.test/` directory → display as "Test" (not H1 content)
|
|
||||||
- `en.php-testen` → display as "Php Testen" (not "ICT")
|
|
||||||
- **Method**: Use `formatDisplayName()` to process file/directory names correctly
|
|
||||||
- **Priority**: Directory names take precedence over file names when both exist
|
|
||||||
- **Language prefixes**: Dynamisch verwijderd op basis van beschikbare talen via `getAvailableLanguages()`
|
|
||||||
|
|
||||||
## Bekende aandachtspunten
|
|
||||||
- LSP errors over "Undefined function" in PHP files zijn vals-positief (standaard PHP functies worden niet herkend door de LSP). Negeer deze.
|
|
||||||
- Zie `TODO.md` voor alle openstaande verbeteringen en nieuwe features.
|
|
||||||
- `vendor/` map bevat Composer dependencies (CommonMark, Twig, scssphp, GeoIP2). Niet handmatig wijzigen.
|
|
||||||
- `admin/config/admin.json` bevat wachtwoord-hashes. Niet committen met echte productie-wachtwoorden.
|
|
||||||
+132
-4
@@ -4,13 +4,13 @@
|
|||||||
|
|
||||||
A lightweight, file-based content management system built with PHP (≥8.0).
|
A lightweight, file-based content management system built with PHP (≥8.0).
|
||||||
|
|
||||||
**Version:** 2.5.1 | **License:** AGPL v3 / Commercial
|
**Version:** 2.6.1 | **License:** AGPL v3 / Commercial
|
||||||
|
|
||||||
## ✨ Features
|
## ✨ Features
|
||||||
|
|
||||||
- 📝 **Multi-format Content** - Markdown, PHP and HTML files
|
- 📝 **Multi-format Content** - Markdown, PHP and HTML files
|
||||||
- 🧭 **Dynamic Navigation** - Automatic menu generation
|
- 🧭 **Dynamic Navigation** - Automatic menu generation
|
||||||
- 🌍 **Multi-language** - NL/EN/DE/FR support
|
- 🌍 **Multi-language** - NL/EN/DE support
|
||||||
- 🔍 **Search** - Full-text search
|
- 🔍 **Search** - Full-text search
|
||||||
- 📱 **Responsive** - Bootstrap 5 themes
|
- 📱 **Responsive** - Bootstrap 5 themes
|
||||||
- 🔒 **Security** - 100/100 pentest score
|
- 🔒 **Security** - 100/100 pentest score
|
||||||
@@ -27,13 +27,141 @@ A lightweight, file-based content management system built with PHP (≥8.0).
|
|||||||
# Install dependencies
|
# Install dependencies
|
||||||
composer install
|
composer install
|
||||||
|
|
||||||
# Start server with router for clean URLs
|
# Start server with router for clean URLs (local only)
|
||||||
php -S localhost:8080 cms/router.php
|
php -S localhost:8080 cms/router.php
|
||||||
```
|
```
|
||||||
|
|
||||||
**Website:** `http://localhost:8080`
|
**Website:** `http://localhost:8080`
|
||||||
**Admin:** `http://localhost:8080/admin` (login: `admin` / `admin`)
|
**Admin:** `http://localhost:8080/admin` (login: `admin` / `admin`)
|
||||||
|
|
||||||
|
## 📦 Installation
|
||||||
|
|
||||||
|
### Requirements
|
||||||
|
|
||||||
|
- **PHP** ≥ 8.0 with extensions: `json`, `mbstring`
|
||||||
|
- **Composer** (PHP dependency manager)
|
||||||
|
- Web server: **Apache 2.4+** with `mod_rewrite` or **Nginx** with PHP-FPM
|
||||||
|
- Optional: `opcache` (recommended for performance), `git` (for content versioning), `zip` extension (for ZIP backup/restore)
|
||||||
|
|
||||||
|
### Step 1 — Code and dependencies
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone <repository-url> codepress
|
||||||
|
cd codepress
|
||||||
|
composer install
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 2 — Configuration
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp config.json.example config.json
|
||||||
|
cp admin/config/admin.json.example admin/config/admin.json
|
||||||
|
```
|
||||||
|
|
||||||
|
Edit `config.json` with your site title, language and plugins. Change the admin password in `admin/config/admin.json` (default `admin`/`admin`).
|
||||||
|
|
||||||
|
### Step 3a — Apache 2.4+
|
||||||
|
|
||||||
|
The webroot is the `public/` directory. Example vhost (`/etc/apache2/sites-available/codepress.conf`):
|
||||||
|
|
||||||
|
```apache
|
||||||
|
<VirtualHost *:80>
|
||||||
|
ServerName example.com
|
||||||
|
DocumentRoot /var/www/codepress/public
|
||||||
|
|
||||||
|
<Directory /var/www/codepress/public>
|
||||||
|
AllowOverride All
|
||||||
|
Require all granted
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
ErrorLog ${APACHE_LOG_DIR}/codepress_error.log
|
||||||
|
CustomLog ${APACHE_LOG_DIR}/codepress_access.log combined
|
||||||
|
</VirtualHost>
|
||||||
|
```
|
||||||
|
|
||||||
|
Required Apache modules:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo a2enmod rewrite headers
|
||||||
|
sudo systemctl restart apache2
|
||||||
|
```
|
||||||
|
|
||||||
|
- `mod_rewrite` — for clean URLs (`/nl/page`) and asset-serving
|
||||||
|
- `mod_headers` — for security headers
|
||||||
|
- `AllowOverride All` — so the `.htaccess` in `public/` is applied
|
||||||
|
|
||||||
|
### Step 3b — Nginx
|
||||||
|
|
||||||
|
Example server block (`/etc/nginx/sites-available/codepress`):
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name example.com;
|
||||||
|
root /var/www/codepress/public;
|
||||||
|
index index.php;
|
||||||
|
|
||||||
|
# Clean URLs: language-prefixed pages
|
||||||
|
location ~ ^/(nl|en|de)(/(.+))?$ {
|
||||||
|
try_files $uri /index.php?lang=$1&page=$2;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Admin routes
|
||||||
|
location /admin {
|
||||||
|
try_files $uri /admin.php?$args;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Asset-serving via asset.php (themes/plugins/admin outside webroot)
|
||||||
|
location ~ ^/(themes|plugins)/([^/]+)/assets/(.+)$ {
|
||||||
|
try_files $uri /asset.php;
|
||||||
|
}
|
||||||
|
location ~ ^/admin/assets/(.+)$ {
|
||||||
|
try_files $uri /asset.php;
|
||||||
|
}
|
||||||
|
|
||||||
|
# PHP via FPM
|
||||||
|
location ~ \.php$ {
|
||||||
|
fastcgi_pass unix:/run/php/php8.0-fpm.sock;
|
||||||
|
fastcgi_index index.php;
|
||||||
|
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||||
|
include fastcgi_params;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Security: block access to sensitive directories
|
||||||
|
location ~ ^/(content|cms|admin/src|admin/config|admin/storage|var|vendor)/ {
|
||||||
|
deny all;
|
||||||
|
return 403;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~ /\.(git|htaccess) {
|
||||||
|
deny all;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note:** Nginx does not use `.htaccess`. Security headers must be set in the Nginx config:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
add_header X-Content-Type-Options nosniff;
|
||||||
|
add_header X-Frame-Options SAMEORIGIN;
|
||||||
|
add_header X-XSS-Protection "1; mode=block";
|
||||||
|
add_header Referrer-Policy strict-origin-when-cross-origin;
|
||||||
|
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self';";
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 4 — Directory permissions
|
||||||
|
|
||||||
|
Make sure the web server has write access to the runtime directories:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chown -R www-data:www-data var/ admin/storage/ content/
|
||||||
|
chmod -R 755 .
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 5 — Test
|
||||||
|
|
||||||
|
Open the website in your browser. With an empty content directory you'll see a welcome page. The admin console is available at `/admin` (login `admin`/`admin`).
|
||||||
|
|
||||||
## 📚 Documentation
|
## 📚 Documentation
|
||||||
|
|
||||||
See **[guide/](guide/)** for extensive documentation per role:
|
See **[guide/](guide/)** for extensive documentation per role:
|
||||||
@@ -68,6 +196,7 @@ codepress/
|
|||||||
├── admin/ # Admin console
|
├── admin/ # Admin console
|
||||||
│ ├── config/ # Admin configuration (admin.json)
|
│ ├── config/ # Admin configuration (admin.json)
|
||||||
│ ├── src/AdminAuth.php # Authentication, roles, permissions
|
│ ├── src/AdminAuth.php # Authentication, roles, permissions
|
||||||
|
│ ├── static/ # Static files (404.html)
|
||||||
│ ├── storage/ # Logs, cache, geoip
|
│ ├── storage/ # Logs, cache, geoip
|
||||||
│ └── theme/default/ # Admin theme
|
│ └── theme/default/ # Admin theme
|
||||||
│ ├── assets/ # CSS, JS, fonts, codemirror
|
│ ├── assets/ # CSS, JS, fonts, codemirror
|
||||||
@@ -80,7 +209,6 @@ codepress/
|
|||||||
│ │ ├── *.twig # Layout templates
|
│ │ ├── *.twig # Layout templates
|
||||||
│ │ ├── partials/ # Header, navigation, footer
|
│ │ ├── partials/ # Header, navigation, footer
|
||||||
│ │ └── assets/ # SCSS, CSS, JS, img
|
│ │ └── assets/ # SCSS, CSS, JS, img
|
||||||
│ └── demo/ # Demo theme
|
|
||||||
├── plugins/ # Plugins
|
├── plugins/ # Plugins
|
||||||
│ ├── HTMLBlock/ # Example sidebar plugin
|
│ ├── HTMLBlock/ # Example sidebar plugin
|
||||||
│ └── Navigation/ # Essential navigation plugin (protected)
|
│ └── Navigation/ # Essential navigation plugin (protected)
|
||||||
|
|||||||
@@ -4,13 +4,13 @@
|
|||||||
|
|
||||||
Een lichtgewicht, file-based content management systeem gebouwd met PHP (≥8.0).
|
Een lichtgewicht, file-based content management systeem gebouwd met PHP (≥8.0).
|
||||||
|
|
||||||
**Versie:** 2.5.0 | **Licentie:** AGPL v3 / Commercial
|
**Versie:** 2.6.1 | **Licentie:** AGPL v3 / Commercial
|
||||||
|
|
||||||
## ✨ Features
|
## ✨ Features
|
||||||
|
|
||||||
- 📝 **Multi-format Content** - Markdown, PHP en HTML bestanden
|
- 📝 **Multi-format Content** - Markdown, PHP en HTML bestanden
|
||||||
- 🧭 **Dynamic Navigation** - Automatische menu generatie
|
- 🧭 **Dynamic Navigation** - Automatische menu generatie
|
||||||
- 🌍 **Multi-language** - NL/EN/DE/FR ondersteuning
|
- 🌍 **Multi-language** - NL/EN/DE ondersteuning
|
||||||
- 🔍 **Search** - Volledige tekst zoekfunctie
|
- 🔍 **Search** - Volledige tekst zoekfunctie
|
||||||
- 📱 **Responsive** - Bootstrap 5 thema's
|
- 📱 **Responsive** - Bootstrap 5 thema's
|
||||||
- 🔒 **Security** - 100/100 pentest score
|
- 🔒 **Security** - 100/100 pentest score
|
||||||
@@ -27,13 +27,141 @@ Een lichtgewicht, file-based content management systeem gebouwd met PHP (≥8.0)
|
|||||||
# Installeer dependencies
|
# Installeer dependencies
|
||||||
composer install
|
composer install
|
||||||
|
|
||||||
# Start server met router voor schone URLs
|
# Start server met router voor schone URLs (alleen lokaal)
|
||||||
php -S localhost:8080 cms/router.php
|
php -S localhost:8080 cms/router.php
|
||||||
```
|
```
|
||||||
|
|
||||||
**Website:** `http://localhost:8080`
|
**Website:** `http://localhost:8080`
|
||||||
**Admin:** `http://localhost:8080/admin` (login: `admin` / `admin`)
|
**Admin:** `http://localhost:8080/admin` (login: `admin` / `admin`)
|
||||||
|
|
||||||
|
## 📦 Installatie
|
||||||
|
|
||||||
|
### Vereisten
|
||||||
|
|
||||||
|
- **PHP** ≥ 8.0 met extensies: `json`, `mbstring`
|
||||||
|
- **Composer** (PHP dependency manager)
|
||||||
|
- Webserver: **Apache 2.4+** met `mod_rewrite` of **Nginx** met PHP-FPM
|
||||||
|
- Optioneel: `opcache` (aanbevolen voor performance), `git` (voor content versioning), `zip` extensie (voor ZIP backup/restore)
|
||||||
|
|
||||||
|
### Stap 1 — Code en dependencies
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone <repository-url> codepress
|
||||||
|
cd codepress
|
||||||
|
composer install
|
||||||
|
```
|
||||||
|
|
||||||
|
### Stap 2 — Configuratie
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp config.json.example config.json
|
||||||
|
cp admin/config/admin.json.example admin/config/admin.json
|
||||||
|
```
|
||||||
|
|
||||||
|
Pas `config.json` aan met je site titel, taal en plugins. Wijzig het admin wachtwoord in `admin/config/admin.json` (standaard `admin`/`admin`).
|
||||||
|
|
||||||
|
### Stap 3a — Apache 2.4+
|
||||||
|
|
||||||
|
De webroot is de `public/` map. Voorbeeld vhost (`/etc/apache2/sites-available/codepress.conf`):
|
||||||
|
|
||||||
|
```apache
|
||||||
|
<VirtualHost *:80>
|
||||||
|
ServerName example.com
|
||||||
|
DocumentRoot /var/www/codepress/public
|
||||||
|
|
||||||
|
<Directory /var/www/codepress/public>
|
||||||
|
AllowOverride All
|
||||||
|
Require all granted
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
ErrorLog ${APACHE_LOG_DIR}/codepress_error.log
|
||||||
|
CustomLog ${APACHE_LOG_DIR}/codepress_access.log combined
|
||||||
|
</VirtualHost>
|
||||||
|
```
|
||||||
|
|
||||||
|
Benodigde Apache modules:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo a2enmod rewrite headers
|
||||||
|
sudo systemctl restart apache2
|
||||||
|
```
|
||||||
|
|
||||||
|
- `mod_rewrite` — voor clean URLs (`/nl/pagina`) en asset-serving
|
||||||
|
- `mod_headers` — voor security headers
|
||||||
|
- `AllowOverride All` — zodat `.htaccess` in `public/` wordt toegepast
|
||||||
|
|
||||||
|
### Stap 3b — Nginx
|
||||||
|
|
||||||
|
Voorbeeld server block (`/etc/nginx/sites-available/codepress`):
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name example.com;
|
||||||
|
root /var/www/codepress/public;
|
||||||
|
index index.php;
|
||||||
|
|
||||||
|
# Clean URLs: taal-prefixed pagina's
|
||||||
|
location ~ ^/(nl|en|de)(/(.+))?$ {
|
||||||
|
try_files $uri /index.php?lang=$1&page=$2;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Admin routes
|
||||||
|
location /admin {
|
||||||
|
try_files $uri /admin.php?$args;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Asset-serving via asset.php (themes/plugins/admin buiten webroot)
|
||||||
|
location ~ ^/(themes|plugins)/([^/]+)/assets/(.+)$ {
|
||||||
|
try_files $uri /asset.php;
|
||||||
|
}
|
||||||
|
location ~ ^/admin/assets/(.+)$ {
|
||||||
|
try_files $uri /asset.php;
|
||||||
|
}
|
||||||
|
|
||||||
|
# PHP via FPM
|
||||||
|
location ~ \.php$ {
|
||||||
|
fastcgi_pass unix:/run/php/php8.0-fpm.sock;
|
||||||
|
fastcgi_index index.php;
|
||||||
|
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||||
|
include fastcgi_params;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Beveiliging: blokkeer toegang tot gevoelige mappen
|
||||||
|
location ~ ^/(content|cms|admin/src|admin/config|admin/storage|var|vendor)/ {
|
||||||
|
deny all;
|
||||||
|
return 403;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~ /\.(git|htaccess) {
|
||||||
|
deny all;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Let op:** Nginx gebruikt geen `.htaccess`. De security headers moeten in de Nginx config worden gezet:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
add_header X-Content-Type-Options nosniff;
|
||||||
|
add_header X-Frame-Options SAMEORIGIN;
|
||||||
|
add_header X-XSS-Protection "1; mode=block";
|
||||||
|
add_header Referrer-Policy strict-origin-when-cross-origin;
|
||||||
|
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self';";
|
||||||
|
```
|
||||||
|
|
||||||
|
### Stap 4 — Mappen rechten
|
||||||
|
|
||||||
|
Zorg dat de webserver schrijfrechten heeft op de runtime mappen:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chown -R www-data:www-data var/ admin/storage/ content/
|
||||||
|
chmod -R 755 .
|
||||||
|
```
|
||||||
|
|
||||||
|
### Stap 5 — Test
|
||||||
|
|
||||||
|
Open de website in je browser. Bij een lege content-map zie je een welkomstpagina. De admin console is bereikbaar via `/admin` (login `admin`/`admin`).
|
||||||
|
|
||||||
## 📚 Handleidingen
|
## 📚 Handleidingen
|
||||||
|
|
||||||
Zie **[guide/](guide/)** voor uitgebreide documentatie per rol:
|
Zie **[guide/](guide/)** voor uitgebreide documentatie per rol:
|
||||||
@@ -68,6 +196,7 @@ codepress/
|
|||||||
├── admin/ # Admin console
|
├── admin/ # Admin console
|
||||||
│ ├── config/ # Admin configuratie (admin.json)
|
│ ├── config/ # Admin configuratie (admin.json)
|
||||||
│ ├── src/AdminAuth.php # Authenticatie, rollen, permissies
|
│ ├── src/AdminAuth.php # Authenticatie, rollen, permissies
|
||||||
|
│ ├── static/ # Statische bestanden (404.html)
|
||||||
│ ├── storage/ # Logs, cache, geoip
|
│ ├── storage/ # Logs, cache, geoip
|
||||||
│ └── theme/default/ # Admin thema
|
│ └── theme/default/ # Admin thema
|
||||||
│ ├── assets/ # CSS, JS, fonts, codemirror
|
│ ├── assets/ # CSS, JS, fonts, codemirror
|
||||||
@@ -80,7 +209,6 @@ codepress/
|
|||||||
│ │ ├── *.twig # Layout templates
|
│ │ ├── *.twig # Layout templates
|
||||||
│ │ ├── partials/ # Header, navigation, footer
|
│ │ ├── partials/ # Header, navigation, footer
|
||||||
│ │ └── assets/ # SCSS, CSS, JS, img
|
│ │ └── assets/ # SCSS, CSS, JS, img
|
||||||
│ └── demo/ # Demo thema
|
|
||||||
├── plugins/ # Plugins
|
├── plugins/ # Plugins
|
||||||
│ ├── HTMLBlock/ # Voorbeeld sidebar plugin
|
│ ├── HTMLBlock/ # Voorbeeld sidebar plugin
|
||||||
│ └── Navigation/ # Essentiële navigatie plugin (beschermd)
|
│ └── Navigation/ # Essentiële navigatie plugin (beschermd)
|
||||||
|
|||||||
@@ -49,6 +49,15 @@
|
|||||||
- [x] Pentest controles uitgevoerd (30/30 tests geslaagd — 0 vulnerabilities)
|
- [x] Pentest controles uitgevoerd (30/30 tests geslaagd — 0 vulnerabilities)
|
||||||
- [x] WCAG 2.1 AA accessibility tests (25/25 tests geslaagd — 100% compliance, test-script verbeterd met min/max checks en grep -E)
|
- [x] WCAG 2.1 AA accessibility tests (25/25 tests geslaagd — 100% compliance, test-script verbeterd met min/max checks en grep -E)
|
||||||
|
|
||||||
|
## v2.6.1 (2026-08-17) ✅
|
||||||
|
- [x] Pentest controles uitgevoerd (30/30)
|
||||||
|
- [x] WCAG 2.1 AA accessibility tests (25/25)
|
||||||
|
- [x] README.md en handleidingen in guide/ doorgeloken en bijgewerkt
|
||||||
|
- [x] Installatie instructies toegevoegd aan README (Apache2/Nginx/PHP/composer)
|
||||||
|
- [x] Verwijderde vendor packages: php-mqtt/client, mustache/mustache (uit composer + autoloader)
|
||||||
|
- [x] Verslag gemaakt (docs/release-notes/v2.6.1.md)
|
||||||
|
- [x] Versie verhoogd naar 2.6.1
|
||||||
|
|
||||||
## v2.6.0 (2026-08-15) ✅
|
## v2.6.0 (2026-08-15) ✅
|
||||||
- [x] Pentest controles uitgevoerd (30/30)
|
- [x] Pentest controles uitgevoerd (30/30)
|
||||||
- [x] WCAG 2.1 AA accessibility tests (25/25)
|
- [x] WCAG 2.1 AA accessibility tests (25/25)
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<div class="error-page text-center py-5">
|
||||||
|
<div class="error-code display-1 fw-bold text-primary mb-3">404</div>
|
||||||
|
<h1 class="h2 mb-3">Pagina niet gevonden</h1>
|
||||||
|
<p class="text-muted mb-4">De pagina die u zoekt bestaat niet of is verplaatst.</p>
|
||||||
|
<a href="/" class="btn btn-primary">
|
||||||
|
<i class="bi bi-house me-1" aria-hidden="true"></i>
|
||||||
|
Terug naar de hoofdpagina
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
# WCAG 2.1 AA Accessibility Test Suite for CodePress CMS
|
# WCAG 2.1 AA Accessibility Test Suite for CodePress CMS
|
||||||
# Tests for web accessibility compliance
|
# Tests for web accessibility compliance
|
||||||
|
|
||||||
BASE_URL="http://localhost:8080"
|
BASE_URL="http://development.codepress.noorlander.info"
|
||||||
TOTAL_TESTS=0
|
TOTAL_TESTS=0
|
||||||
PASSED_TESTS=0
|
PASSED_TESTS=0
|
||||||
FAILED_TESTS=0
|
FAILED_TESTS=0
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
# CodePress CMS Functional Test Suite v1.5.0
|
# CodePress CMS Functional Test Suite v1.5.0
|
||||||
# Tests core functionality, new features, and regressions
|
# Tests core functionality, new features, and regressions
|
||||||
|
|
||||||
BASE_URL="http://localhost:8080"
|
BASE_URL="http://development.codepress.noorlander.info"
|
||||||
TEST_DATE=$(date '+%Y-%m-%d %H:%M:%S')
|
TEST_DATE=$(date '+%Y-%m-%d %H:%M:%S')
|
||||||
TOTAL_TESTS=0
|
TOTAL_TESTS=0
|
||||||
PASSED_TESTS=0
|
PASSED_TESTS=0
|
||||||
@@ -80,14 +80,11 @@ echo ""
|
|||||||
echo "2. CONTENT RENDERING TESTS"
|
echo "2. CONTENT RENDERING TESTS"
|
||||||
echo "--------------------------"
|
echo "--------------------------"
|
||||||
|
|
||||||
# Test Markdown content
|
# Test Markdown content (guide page uses Markdown)
|
||||||
run_test "Markdown rendering" "curl -s '$BASE_URL/?page=demo/content-only' | grep -c '<h1>'" "1"
|
run_test "Markdown rendering" "curl -s '$BASE_URL/?guide' | grep -c '<h1>'" "1"
|
||||||
|
|
||||||
# Test HTML content
|
# Test 404 handling for non-existent pages
|
||||||
run_test "HTML content" "curl -s '$BASE_URL/?page=demo/html-demo' | grep -c '<h1>'" "1"
|
run_test "404 content handling" "curl -s '$BASE_URL/?page=nonexistent' | grep -c '404'" "1"
|
||||||
|
|
||||||
# Test PHP content
|
|
||||||
run_test "PHP content" "curl -s '$BASE_URL/?page=demo/php-demo' | grep -c 'PHP Version'" "1"
|
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "3. NAVIGATION TESTS"
|
echo "3. NAVIGATION TESTS"
|
||||||
@@ -97,7 +94,7 @@ echo "-------------------"
|
|||||||
run_test "Menu generation" "curl -s '$BASE_URL/' | grep -c 'nav-item'" "2"
|
run_test "Menu generation" "curl -s '$BASE_URL/' | grep -c 'nav-item'" "2"
|
||||||
|
|
||||||
# Test breadcrumb navigation
|
# Test breadcrumb navigation
|
||||||
run_test "Breadcrumb navigation" "curl -s '$BASE_URL/?page=demo/content-only' | grep -c 'breadcrumb'" "1"
|
run_test "Breadcrumb navigation" "curl -s '$BASE_URL/?guide' | grep -c 'breadcrumb'" "1"
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "4. TEMPLATE SYSTEM TESTS"
|
echo "4. TEMPLATE SYSTEM TESTS"
|
||||||
@@ -243,7 +240,6 @@ Functional testing performed on CodePress CMS v1.5.0 covering core functionality
|
|||||||
|
|
||||||
### Plugin System
|
### Plugin System
|
||||||
- **HTMLBlock Plugin**: Custom HTML blocks in sidebar
|
- **HTMLBlock Plugin**: Custom HTML blocks in sidebar
|
||||||
- **MQTTTracker Plugin**: Real-time analytics and tracking
|
|
||||||
- **Plugin Manager**: Centralized plugin loading system
|
- **Plugin Manager**: Centralized plugin loading system
|
||||||
|
|
||||||
### Enhanced Documentation
|
### Enhanced Documentation
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# CodePress CMS Penetration Test Script
|
# CodePress CMS Penetration Test Script
|
||||||
# WARNING: Only run this on systems you have permission to test!
|
# WARNING: Only run this on systems you have permission to test!
|
||||||
|
|
||||||
TARGET="http://localhost:8080"
|
TARGET="http://development.codepress.noorlander.info"
|
||||||
RESULTS_FILE="pentest_results.txt"
|
RESULTS_FILE="pentest_results.txt"
|
||||||
|
|
||||||
echo "🔒 CodePress CMS Penetration Test" > $RESULTS_FILE
|
echo "🔒 CodePress CMS Penetration Test" > $RESULTS_FILE
|
||||||
|
|||||||
@@ -449,10 +449,29 @@ class CodePressCMS {
|
|||||||
if (isset($_GET['guide']) || $pageCheck === 'guide') {
|
if (isset($_GET['guide']) || $pageCheck === 'guide') {
|
||||||
return $this->getGuidePage();
|
return $this->getGuidePage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Determine if the request has a valid language prefix
|
||||||
|
$availableLangs = array_keys($this->getAvailableLanguages());
|
||||||
|
$requestPath = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH) ?? '/';
|
||||||
|
$requestPath = ltrim($requestPath, '/');
|
||||||
|
$langFromUrl = '';
|
||||||
|
if ($requestPath !== '' && in_array(explode('/', $requestPath)[0], $availableLangs, true)) {
|
||||||
|
$langFromUrl = explode('/', $requestPath)[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// No language prefix and not the root → 404
|
||||||
|
if ($langFromUrl === '' && $requestPath !== '' && $requestPath !== 'favicon.ico') {
|
||||||
|
return $this->getError404();
|
||||||
|
}
|
||||||
|
|
||||||
// Check if content directory is empty
|
// Check if content directory is empty — show welcome page for new installations
|
||||||
if ($this->isContentDirEmpty()) {
|
if ($this->isContentDirEmpty()) {
|
||||||
return $this->getGuidePage();
|
$requestedPage = $_GET['page'] ?? '';
|
||||||
|
// Only show welcome page on the home URL; everything else is a 404
|
||||||
|
if (empty($requestedPage) || $requestedPage === $this->getEffectiveDefaultPage()) {
|
||||||
|
return $this->getWelcomePage();
|
||||||
|
}
|
||||||
|
return $this->getError404();
|
||||||
}
|
}
|
||||||
|
|
||||||
$page = $_GET['page'] ?? $this->getEffectiveDefaultPage();
|
$page = $_GET['page'] ?? $this->getEffectiveDefaultPage();
|
||||||
@@ -1048,9 +1067,60 @@ class CodePressCMS {
|
|||||||
$files = scandir($contentDir);
|
$files = scandir($contentDir);
|
||||||
$files = array_diff($files, ['.', '..']);
|
$files = array_diff($files, ['.', '..']);
|
||||||
|
|
||||||
|
// Filter out hidden files (e.g. .gitkeep) — only count visible content
|
||||||
|
$files = array_filter($files, function($f) {
|
||||||
|
return $f[0] !== '.';
|
||||||
|
});
|
||||||
|
|
||||||
return empty($files);
|
return empty($files);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get welcome page content for new installations (empty content directory)
|
||||||
|
*
|
||||||
|
* Shows a clear "new installation" message with next steps when the
|
||||||
|
* content directory has no content files yet.
|
||||||
|
*
|
||||||
|
* @return array Welcome page data
|
||||||
|
*/
|
||||||
|
private function getWelcomePage() {
|
||||||
|
$adminUrl = $this->buildAdminUrl();
|
||||||
|
$guideUrl = '/' . $this->currentLanguage . '/guide';
|
||||||
|
|
||||||
|
$content = '<div class="welcome-page">';
|
||||||
|
$content .= '<h1>' . htmlspecialchars($this->t('welcome_title')) . '</h1>';
|
||||||
|
$content .= '<p class="alert alert-info" role="alert">';
|
||||||
|
$content .= '<i class="bi bi-info-circle me-2" aria-hidden="true"></i>';
|
||||||
|
$content .= htmlspecialchars($this->t('welcome_intro'));
|
||||||
|
$content .= '</p>';
|
||||||
|
|
||||||
|
$content .= '<h2>' . htmlspecialchars($this->t('welcome_next_steps')) . '</h2>';
|
||||||
|
$content .= '<ol class="list-group list-group-numbered mb-4">';
|
||||||
|
$content .= '<li class="list-group-item">' . htmlspecialchars($this->t('welcome_step_1')) . '</li>';
|
||||||
|
$content .= '<li class="list-group-item">' . htmlspecialchars($this->t('welcome_step_2')) . '</li>';
|
||||||
|
$content .= '<li class="list-group-item">' . htmlspecialchars($this->t('welcome_step_3')) . '</li>';
|
||||||
|
$content .= '</ol>';
|
||||||
|
|
||||||
|
$content .= '<div class="d-flex flex-column flex-md-row gap-2 mb-4">';
|
||||||
|
$content .= '<a href="' . htmlspecialchars($adminUrl) . '" class="btn btn-primary">';
|
||||||
|
$content .= '<i class="bi bi-gear me-1" aria-hidden="true"></i> ';
|
||||||
|
$content .= htmlspecialchars($this->t('welcome_admin_link'));
|
||||||
|
$content .= '</a>';
|
||||||
|
$content .= '<a href="' . htmlspecialchars($guideUrl) . '" class="btn btn-outline-secondary">';
|
||||||
|
$content .= '<i class="bi bi-book me-1" aria-hidden="true"></i> ';
|
||||||
|
$content .= htmlspecialchars($this->t('welcome_guide_link'));
|
||||||
|
$content .= '</a>';
|
||||||
|
$content .= '</div>';
|
||||||
|
$content .= '</div>';
|
||||||
|
|
||||||
|
return [
|
||||||
|
'title' => $this->t('welcome_title'),
|
||||||
|
'content' => $content,
|
||||||
|
'layout' => 'full_content',
|
||||||
|
'metadata' => [],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get guide page content based on user language
|
* Get guide page content based on user language
|
||||||
*
|
*
|
||||||
@@ -1228,9 +1298,17 @@ class CodePressCMS {
|
|||||||
* @return array 404 page data
|
* @return array 404 page data
|
||||||
*/
|
*/
|
||||||
private function getError404() {
|
private function getError404() {
|
||||||
|
$staticFile = __DIR__ . '/../../../admin/static/404.html';
|
||||||
|
$body = file_exists($staticFile)
|
||||||
|
? file_get_contents($staticFile)
|
||||||
|
: '<h1>404 - ' . $this->t('page_not_found') . '</h1><p>' . $this->t('page_not_found_text') . '</p>';
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'title' => $this->t('page_not_found'),
|
'title' => $this->t('page_not_found'),
|
||||||
'content' => '<h1>404 - ' . $this->t('page_not_found') . '</h1><p>' . $this->t('page_not_found_text') . '</p>'
|
'content' => $body,
|
||||||
|
'layout' => 'full_content',
|
||||||
|
'metadata' => [],
|
||||||
|
'is_404' => true,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1252,6 +1330,11 @@ class CodePressCMS {
|
|||||||
$page = $this->getPage();
|
$page = $this->getPage();
|
||||||
$this->pluginManager->doAction('onPageLoad', $page);
|
$this->pluginManager->doAction('onPageLoad', $page);
|
||||||
$this->pluginManager->doAction('onBeforeRender');
|
$this->pluginManager->doAction('onBeforeRender');
|
||||||
|
|
||||||
|
// Set 404 status for not-found pages (rendered through the theme)
|
||||||
|
if (!empty($page['is_404'])) {
|
||||||
|
http_response_code(404);
|
||||||
|
}
|
||||||
|
|
||||||
$menu = $this->getMenu();
|
$menu = $this->getMenu();
|
||||||
|
|
||||||
|
|||||||
Generated
+3
-113
@@ -697,59 +697,6 @@
|
|||||||
},
|
},
|
||||||
"time": "2026-01-13T17:56:03+00:00"
|
"time": "2026-01-13T17:56:03+00:00"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "mustache/mustache",
|
|
||||||
"version": "v3.0.0",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/bobthecow/mustache.php.git",
|
|
||||||
"reference": "176b6b21d68516dd5107a63ab71b0050e518b7a4"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/bobthecow/mustache.php/zipball/176b6b21d68516dd5107a63ab71b0050e518b7a4",
|
|
||||||
"reference": "176b6b21d68516dd5107a63ab71b0050e518b7a4",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": ">=5.6"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"friendsofphp/php-cs-fixer": "~2.19.3",
|
|
||||||
"yoast/phpunit-polyfills": "^2.0"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Mustache\\": "src/"
|
|
||||||
},
|
|
||||||
"classmap": [
|
|
||||||
"src/compat.php"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Justin Hileman",
|
|
||||||
"email": "justin@justinhileman.info",
|
|
||||||
"homepage": "http://justinhileman.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "A Mustache implementation in PHP.",
|
|
||||||
"homepage": "https://github.com/bobthecow/mustache.php",
|
|
||||||
"keywords": [
|
|
||||||
"mustache",
|
|
||||||
"templating"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/bobthecow/mustache.php/issues",
|
|
||||||
"source": "https://github.com/bobthecow/mustache.php/tree/v3.0.0"
|
|
||||||
},
|
|
||||||
"time": "2025-06-28T18:28:20+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "myclabs/php-enum",
|
"name": "myclabs/php-enum",
|
||||||
"version": "1.8.5",
|
"version": "1.8.5",
|
||||||
@@ -967,63 +914,6 @@
|
|||||||
},
|
},
|
||||||
"time": "2025-10-31T00:45:47+00:00"
|
"time": "2025-10-31T00:45:47+00:00"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "php-mqtt/client",
|
|
||||||
"version": "v2.3.0",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/php-mqtt/client.git",
|
|
||||||
"reference": "3d141846753a0adee265680ae073cfb9030f2390"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/php-mqtt/client/zipball/3d141846753a0adee265680ae073cfb9030f2390",
|
|
||||||
"reference": "3d141846753a0adee265680ae073cfb9030f2390",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"myclabs/php-enum": "^1.7",
|
|
||||||
"php": "^8.0",
|
|
||||||
"psr/log": "^1.1|^2.0|^3.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"phpunit/php-invoker": "^3.0",
|
|
||||||
"phpunit/phpunit": "^9.0",
|
|
||||||
"squizlabs/php_codesniffer": "^3.5"
|
|
||||||
},
|
|
||||||
"suggest": {
|
|
||||||
"ext-redis": "Required for the RedisRepository"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"PhpMqtt\\Client\\": "src"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Marvin Mall",
|
|
||||||
"email": "marvin-mall@msn.com",
|
|
||||||
"role": "developer"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "An MQTT client written in and for PHP.",
|
|
||||||
"keywords": [
|
|
||||||
"client",
|
|
||||||
"mqtt",
|
|
||||||
"publish",
|
|
||||||
"subscribe"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/php-mqtt/client/issues",
|
|
||||||
"source": "https://github.com/php-mqtt/client/tree/v2.3.0"
|
|
||||||
},
|
|
||||||
"time": "2025-09-30T17:53:34+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "psr/event-dispatcher",
|
"name": "psr/event-dispatcher",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
@@ -1837,10 +1727,10 @@
|
|||||||
"packages-dev": [],
|
"packages-dev": [],
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"minimum-stability": "stable",
|
"minimum-stability": "stable",
|
||||||
"stability-flags": {},
|
"stability-flags": [],
|
||||||
"prefer-stable": false,
|
"prefer-stable": false,
|
||||||
"prefer-lowest": false,
|
"prefer-lowest": false,
|
||||||
"platform": {},
|
"platform": [],
|
||||||
"platform-dev": {},
|
"platform-dev": [],
|
||||||
"plugin-api-version": "2.9.0"
|
"plugin-api-version": "2.9.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,114 @@
|
|||||||
|
# CodePress CMS v2.6.1 — Release Notes
|
||||||
|
|
||||||
|
**Release datum:** 2026-08-17
|
||||||
|
**Codename:** Lyra
|
||||||
|
**Status:** stable
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Nieuwe features
|
||||||
|
|
||||||
|
### Welkomstpagina bij lege content-map (nieuwe installatie)
|
||||||
|
- Wanneer de `content/` map leeg is (nieuwe installatie), toont de CMS nu een duidelijke welkomstpagina
|
||||||
|
- De pagina bevat een introductietekst, een lijst met volgende stappen en knoppen naar de admin console en handleiding
|
||||||
|
- Vertaald in NL, EN en DE (`welcome_*` keys in `language/*/site.php`)
|
||||||
|
- `isContentDirEmpty()` filtert nu verborgen bestanden (zoals `.gitkeep`) zodat een map met alleen een `.gitkeep` als leeg wordt herkend
|
||||||
|
|
||||||
|
### 404-afhandeling binnen het actieve theme
|
||||||
|
- Nieuwe statische 404 pagina in `admin/static/404.html` met een link naar de home pagina
|
||||||
|
- De 404 inhoud wordt binnen het actieve theme gerenderd (met header, navigatie, footer en Bootstrap styling)
|
||||||
|
- `getError404()` laadt de inhoud uit `admin/static/404.html` en geeft deze als page content terug (layout `full_content`)
|
||||||
|
- `render()` zet de juiste `http_response_code(404)` status bij niet-gevonden pagina's
|
||||||
|
|
||||||
|
### HTTP 404 status bij onbekende pagina's en missende taalprefix
|
||||||
|
- `getPage()` geeft een 404 als de URL geen geldige taalprefix bevat (bijv. `/random-page` in plaats van `/nl/random-page`)
|
||||||
|
- Niet-bestaande pagina's binnen een taal (`/nl/nonexistent`) geven nu ook een 404 in plaats van HTTP 200
|
||||||
|
- Eerder werd bij een lege content-map altijd de welkomstpagina getoond, ook voor niet-bestaande pagina's — dit is nu beperkt tot de home URL
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Verbeteringen
|
||||||
|
|
||||||
|
### Test scripts
|
||||||
|
- Test scripts (`pentest.sh`, `accessibility.sh`, `run-tests.sh`) gebruiken nu de Apache-URL (`http://development.codepress.noorlander.info`) in plaats van `localhost:8080`
|
||||||
|
- Functionele tests opgeschoond: tests die naar niet-bestaande `demo/` content pagina's verwezen vervangen door werkende tests
|
||||||
|
|
||||||
|
### Documentatie
|
||||||
|
- `README.md` en `README.en.md` bijgewerkt: versie naar 2.6.1, multi-language talen gecorrigeerd (NL/EN/DE), `admin/static/` map toegevoegd aan project structuur
|
||||||
|
- Guide index bestanden (`guide/nl/index.md`, `guide/en/index.md`) bijgewerkt naar versie 2.6.1
|
||||||
|
- `guide/*/codepress-developer.md` versie referenties bijgewerkt naar 2.6.1
|
||||||
|
- `AGENTS.md` samengevoegd naar de root map (`./AGENTS.md`); `./development/AGENTS.md` is verwijderd
|
||||||
|
- AGENTS.md verduidelijkt welke URL bij welke map hoort en dat tests via Apache draaien (niet via PHP dev server)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Opschoning
|
||||||
|
|
||||||
|
### Verwijderde ongebruikte bestanden
|
||||||
|
- `package.json` — was voor NPM build (`npm run build:css`), runtime gebruikt scssphp (PHP) voor SCSS compilatie
|
||||||
|
- `src/scss/` map — was voor NPM sass build, overbodig na verwijderen van `package.json`
|
||||||
|
- `.htaccess` (root) — Apache docroot is `public/`, deze root `.htaccess` werd niet geserveerd
|
||||||
|
- `themes/demo/` — niet actief in `config.json` (gebruikt `default`), alleen genoemd als voorbeeld
|
||||||
|
|
||||||
|
### Opschoning referenties
|
||||||
|
- `README.md` en `README.en.md` — demo theme referenties verwijderd uit project structuur
|
||||||
|
- `guide/*/codepress-developer/architectuur.md` — demo verwijdering uit mappenstructuur boom
|
||||||
|
- `themes/gen-preview.sh` — hardcoded `default demo test` loop vervangen door dynamische `*/` loop
|
||||||
|
- `.gitignore` — `node_modules/`, `package-lock.json` en `.sass-cache/` regels verwijderd (NPM niet meer gebruikt)
|
||||||
|
|
||||||
|
### Verwijderde vendor packages
|
||||||
|
- `mustache/mustache` — niet meer gebruikt (Twig is de template engine)
|
||||||
|
- `php-mqtt/client` — niet meer gebruikt
|
||||||
|
- Beide packages verwijderd uit `composer.lock`, `vendor/composer/installed.json`, `installed.php`, en de autoloader bestanden
|
||||||
|
- `MQTTTracker` referentie verwijderd uit functionele test script
|
||||||
|
|
||||||
|
### Installatie documentatie
|
||||||
|
- `README.md` en `README.en.md` bevatten nu een volledige installatie sectie met:
|
||||||
|
- Vereisten (PHP ≥8.0, composer, extensies)
|
||||||
|
- Apache 2.4+ vhost voorbeeld met `mod_rewrite`, `mod_headers`, `AllowOverride All`
|
||||||
|
- Nginx server block voorbeeld met PHP-FPM, clean URLs, asset-serving en security headers
|
||||||
|
- Mappen rechten en test instructies
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Beveiliging
|
||||||
|
- Pentest suite: 30/30 tests geslaagd (XSS, path traversal, PHP injection, null byte, command injection, template injection, HTTP header injection, information disclosure, security headers, DoS)
|
||||||
|
- Security headers aanwezig: X-Frame-Options, Content-Security-Policy, X-Content-Type-Options
|
||||||
|
- Geen vulnerabilities gedetecteerd
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Accessibility
|
||||||
|
- WCAG 2.1 AA: 25/25 tests geslaagd (100%)
|
||||||
|
- ARIA landmarks aanwezig (24 per pagina)
|
||||||
|
- Semantic HTML structuur (header, nav, main, footer)
|
||||||
|
- Skip-to-content links, focus indicators, screen reader support
|
||||||
|
- Mobile viewport en touch targets aanwezig
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Systeem vereisten
|
||||||
|
- PHP >= 8.0
|
||||||
|
- Extensies: json, mbstring
|
||||||
|
- Optioneel: opcache (aanbevolen voor performance)
|
||||||
|
- Git (optioneel, voor content versioning feature)
|
||||||
|
- ZipArchive (optioneel, voor ZIP backup/restore feature)
|
||||||
|
- Apache met `mod_rewrite` en `AllowOverride All` (voor clean URLs en asset-serving)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Upgraden
|
||||||
|
1. Maak een backup van de huidige content map
|
||||||
|
2. Pull de nieuwe code
|
||||||
|
3. Run `composer install` om dependencies bij te werken
|
||||||
|
4. Test de website
|
||||||
|
5. Optioneel: initialiseer git in content/ via Admin → Backup & Restore → Git init
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Test resultaten samenvatting
|
||||||
|
|
||||||
|
| Test | Resultaat |
|
||||||
|
|------|----------|
|
||||||
|
| Pentest | 30/30 geslaagd, 0 vulnerabilities |
|
||||||
|
| WCAG 2.1 AA Accessibility | 25/25 geslaagd, 100% compliance |
|
||||||
@@ -11,7 +11,7 @@ The CodePress developer guide contains the following topics:
|
|||||||
- **Debugging** — Logging and cache
|
- **Debugging** — Logging and cache
|
||||||
- **Performance** — OPcache and SCSS caching
|
- **Performance** — OPcache and SCSS caching
|
||||||
|
|
||||||
Important concepts in CodePress 2.5.2:
|
Important concepts in CodePress 2.6.1:
|
||||||
|
|
||||||
- **Plugin types** — Content plugins (sidebar) and system plugins (admin menu, routes, API)
|
- **Plugin types** — Content plugins (sidebar) and system plugins (admin menu, routes, API)
|
||||||
- **Admin plugin API** — System plugins can register admin menu items and routes
|
- **Admin plugin API** — System plugins can register admin menu items and routes
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ codepress/
|
|||||||
│ ├── config/ # app.php, admin.json
|
│ ├── config/ # app.php, admin.json
|
||||||
│ ├── src/ # AdminAuth
|
│ ├── src/ # AdminAuth
|
||||||
│ └── theme/default/views/ # Twig templates
|
│ └── theme/default/views/ # Twig templates
|
||||||
├── themes/ # Themes (default, demo, ...)
|
├── themes/ # Themes (default, ...)
|
||||||
├── plugins/ # Plugins (Dashboard, HTMLBlock, Navigation, ...)
|
├── plugins/ # Plugins (Dashboard, HTMLBlock, Navigation, ...)
|
||||||
├── content/ # Content files (.md, .php, .html)
|
├── content/ # Content files (.md, .php, .html)
|
||||||
├── language/ # Language files (nl/, en/, de/)
|
├── language/ # Language files (nl/, en/, de/)
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
# Manual
|
# Manual
|
||||||
|
|
||||||
Welcome to the CodePress CMS manual (version 2.5.2). CodePress is a file-based CMS without a database — content, configuration and users are stored in files.
|
Welcome to the CodePress CMS manual (version 2.6.1). CodePress is a file-based CMS without a database — content, configuration and users are stored in files.
|
||||||
|
|
||||||
The manual is divided into four sections:
|
The manual is divided into four sections:
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ De CodePress developer handleiding bevat de volgende onderwerpen:
|
|||||||
- **Debugging** — Logging en cache
|
- **Debugging** — Logging en cache
|
||||||
- **Performance** — OPcache en SCSS caching
|
- **Performance** — OPcache en SCSS caching
|
||||||
|
|
||||||
Belangrijke concepten in CodePress 2.5.2:
|
Belangrijke concepten in CodePress 2.6.1:
|
||||||
|
|
||||||
- **Plugin types** — Content plugins (sidebar) en systeem plugins (admin menu, routes, API)
|
- **Plugin types** — Content plugins (sidebar) en systeem plugins (admin menu, routes, API)
|
||||||
- **Admin plugin API** — Systeem plugins kunnen admin menu items en routes registreren
|
- **Admin plugin API** — Systeem plugins kunnen admin menu items en routes registreren
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ codepress/
|
|||||||
│ ├── config/ # app.php, admin.json
|
│ ├── config/ # app.php, admin.json
|
||||||
│ ├── src/ # AdminAuth
|
│ ├── src/ # AdminAuth
|
||||||
│ └── theme/default/views/ # Twig templates
|
│ └── theme/default/views/ # Twig templates
|
||||||
├── themes/ # Thema's (default, demo, ...)
|
├── themes/ # Thema's (default, ...)
|
||||||
├── plugins/ # Plugins (Dashboard, HTMLBlock, Navigation, ...)
|
├── plugins/ # Plugins (Dashboard, HTMLBlock, Navigation, ...)
|
||||||
├── content/ # Content bestanden (.md, .php, .html)
|
├── content/ # Content bestanden (.md, .php, .html)
|
||||||
├── language/ # Taalbestanden (nl/, en/, de/)
|
├── language/ # Taalbestanden (nl/, en/, de/)
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
# Handleiding
|
# Handleiding
|
||||||
|
|
||||||
Welkom bij de CodePress CMS handleiding (versie 2.5.2). CodePress is een file-based CMS zonder database — content, configuratie en gebruikers worden opgeslagen in bestanden.
|
Welkom bij de CodePress CMS handleiding (versie 2.6.1). CodePress is een file-based CMS zonder database — content, configuratie en gebruikers worden opgeslagen in bestanden.
|
||||||
|
|
||||||
De handleiding is verdeeld in vier secties:
|
De handleiding is verdeeld in vier secties:
|
||||||
|
|
||||||
|
|||||||
@@ -35,4 +35,14 @@ return [
|
|||||||
'plugin_development' => 'Plugin Entwicklung',
|
'plugin_development' => 'Plugin Entwicklung',
|
||||||
'template_system' => 'Template System',
|
'template_system' => 'Template System',
|
||||||
'go_to' => 'Gehe zu',
|
'go_to' => 'Gehe zu',
|
||||||
|
'welcome_title' => 'Willkommen bei CodePress CMS',
|
||||||
|
'welcome_new_install' => 'Neue Installation',
|
||||||
|
'welcome_intro' => 'Sie sehen diese Seite, weil das Inhaltsverzeichnis noch leer ist. Dies ist eine neue Installation von CodePress CMS.',
|
||||||
|
'welcome_next_steps' => 'Nächste Schritte',
|
||||||
|
'welcome_step_1' => 'Melden Sie sich über die Admin-Konsole an, um Inhalte zu verwalten',
|
||||||
|
'welcome_step_2' => 'Fügen Sie Markdown-, PHP- oder HTML-Dateien zum Inhaltsverzeichnis hinzu',
|
||||||
|
'welcome_step_3' => 'Lesen Sie das Handbuch für die vollständige Dokumentation',
|
||||||
|
'welcome_admin_link' => 'Zur Admin-Konsole',
|
||||||
|
'welcome_guide_link' => 'Handbuch ansehen',
|
||||||
|
'welcome_content_empty' => 'Das Inhaltsverzeichnis ist leer',
|
||||||
];
|
];
|
||||||
@@ -35,4 +35,14 @@ return [
|
|||||||
'plugin_development' => 'Plugin Development',
|
'plugin_development' => 'Plugin Development',
|
||||||
'template_system' => 'Template System',
|
'template_system' => 'Template System',
|
||||||
'go_to' => 'Go to',
|
'go_to' => 'Go to',
|
||||||
|
'welcome_title' => 'Welcome to CodePress CMS',
|
||||||
|
'welcome_new_install' => 'New installation',
|
||||||
|
'welcome_intro' => 'You are seeing this page because the content directory is still empty. This is a new installation of CodePress CMS.',
|
||||||
|
'welcome_next_steps' => 'Next steps',
|
||||||
|
'welcome_step_1' => 'Log in via the admin console to manage content',
|
||||||
|
'welcome_step_2' => 'Add Markdown, PHP or HTML files to the content directory',
|
||||||
|
'welcome_step_3' => 'Read the manual for full documentation',
|
||||||
|
'welcome_admin_link' => 'Go to admin console',
|
||||||
|
'welcome_guide_link' => 'View manual',
|
||||||
|
'welcome_content_empty' => 'The content directory is empty',
|
||||||
];
|
];
|
||||||
@@ -35,4 +35,14 @@ return [
|
|||||||
'plugin_development' => 'Plugin Ontwikkeling',
|
'plugin_development' => 'Plugin Ontwikkeling',
|
||||||
'template_system' => 'Template Systeem',
|
'template_system' => 'Template Systeem',
|
||||||
'go_to' => 'Ga naar',
|
'go_to' => 'Ga naar',
|
||||||
|
'welcome_title' => 'Welkom bij CodePress CMS',
|
||||||
|
'welcome_new_install' => 'Nieuwe installatie',
|
||||||
|
'welcome_intro' => 'U ziet deze pagina omdat de content-map nog leeg is. Dit is een nieuwe installatie van CodePress CMS.',
|
||||||
|
'welcome_next_steps' => 'Volgende stappen',
|
||||||
|
'welcome_step_1' => 'Log in via de admin console om content te beheren',
|
||||||
|
'welcome_step_2' => 'Voeg Markdown-, PHP- of HTML-bestanden toe in de content-map',
|
||||||
|
'welcome_step_3' => 'Bekijk de handleiding voor uitgebreide documentatie',
|
||||||
|
'welcome_admin_link' => 'Naar de admin console',
|
||||||
|
'welcome_guide_link' => 'Handleiding bekijken',
|
||||||
|
'welcome_content_empty' => 'De content-map is leeg',
|
||||||
];
|
];
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "codepress",
|
|
||||||
"version": "1.7.1",
|
|
||||||
"description": "A lightweight, file-based Content Management System built with PHP and Bootstrap.",
|
|
||||||
"main": "index.js",
|
|
||||||
"scripts": {
|
|
||||||
"build:css": "npx sass --load-path=node_modules src/scss/main.scss public/assets/css/style.css --style=compressed",
|
|
||||||
"watch:css": "npx sass --load-path=node_modules --watch src/scss/main.scss public/assets/css/style.css",
|
|
||||||
"build": "npm run build:css",
|
|
||||||
"clean": "rm -rf node_modules package-lock.json",
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://git.noorlander.info/E.Noorlander/CodePress.git"
|
|
||||||
},
|
|
||||||
"keywords": [],
|
|
||||||
"author": "",
|
|
||||||
"license": "ISC",
|
|
||||||
"type": "commonjs",
|
|
||||||
"dependencies": {
|
|
||||||
"bootstrap": "^5.3.8",
|
|
||||||
"sass": "^1.94.2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,361 +0,0 @@
|
|||||||
// Custom variables (must come before Bootstrap import)
|
|
||||||
$primary: #0d6efd;
|
|
||||||
$navigation-opacity: 0.5; // 50% opacity
|
|
||||||
|
|
||||||
// Import Bootstrap
|
|
||||||
@import "bootstrap/scss/bootstrap";
|
|
||||||
|
|
||||||
// Custom navigation background with 50% opacity of primary color
|
|
||||||
.navigation-50-opacity {
|
|
||||||
background-color: rgba($primary, $navigation-opacity) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Custom CodePress styles
|
|
||||||
* {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
html, body {
|
|
||||||
height: 100%;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
min-height: 100vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Header */
|
|
||||||
header.navbar {
|
|
||||||
flex-shrink: 0;
|
|
||||||
height: 66px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Navigation section */
|
|
||||||
.navigation-section {
|
|
||||||
background-color: #ffffff;
|
|
||||||
border-bottom: 1px solid #dee2e6;
|
|
||||||
padding: 0.5rem 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tab styling */
|
|
||||||
.nav-tabs {
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-tabs .nav-link {
|
|
||||||
border: 1px solid transparent;
|
|
||||||
border-bottom: none;
|
|
||||||
border-radius: 0; // Geen ronde hoeken
|
|
||||||
color: #6c757d;
|
|
||||||
background-color: transparent; // Transparante achtergrond voor eerste laag
|
|
||||||
margin-right: 0.25rem;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-tabs .nav-link:hover {
|
|
||||||
color: #495057;
|
|
||||||
background-color: rgba(0, 0, 0, 0.05); // Subtiel hover effect
|
|
||||||
border-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-tabs .nav-link.active {
|
|
||||||
color: #495057;
|
|
||||||
background-color: #ffffff; // Alleen active heeft witte achtergrond
|
|
||||||
border-color: #dee2e6 #dee2e6 transparent;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dropdown in tabs - eerste laag */
|
|
||||||
.nav-tabs .nav-item.dropdown .nav-link {
|
|
||||||
background-color: transparent; // Transparante achtergrond
|
|
||||||
border: 1px solid transparent;
|
|
||||||
border-radius: 0; // Geen ronde hoeken
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-tabs .nav-item.dropdown .nav-link:hover {
|
|
||||||
background-color: rgba(0, 0, 0, 0.05); // Subtiel hover effect
|
|
||||||
border-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dropdown menu styling */
|
|
||||||
.nav-tabs .dropdown-menu {
|
|
||||||
margin-top: 0.25rem;
|
|
||||||
border-radius: 0.375rem;
|
|
||||||
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
|
|
||||||
min-width: 200px;
|
|
||||||
max-width: 300px;
|
|
||||||
width: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dropdown items styling */
|
|
||||||
.nav-tabs .dropdown-menu .dropdown-item {
|
|
||||||
white-space: normal;
|
|
||||||
padding: 0.5rem 1rem;
|
|
||||||
line-height: 1.4;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Long text truncation for very long titles */
|
|
||||||
.nav-tabs .dropdown-menu .dropdown-item {
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
max-width: 280px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Breadcrumb section */
|
|
||||||
.breadcrumb-section {
|
|
||||||
background-color: #f8f9fa;
|
|
||||||
border-bottom: 1px solid #dee2e6;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Breadcrumb styling consistency */
|
|
||||||
.breadcrumb-section .breadcrumb {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.breadcrumb-section .breadcrumb-item {
|
|
||||||
color: #6c757d !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.breadcrumb-section .breadcrumb-item a {
|
|
||||||
color: #0d6efd !important;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.breadcrumb-section .breadcrumb-item a:hover {
|
|
||||||
color: #0a58ca !important;
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
.breadcrumb-section .breadcrumb-item.active {
|
|
||||||
color: #6c757d !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Main content area */
|
|
||||||
.main-content {
|
|
||||||
flex: 1;
|
|
||||||
overflow-y: auto;
|
|
||||||
padding: 1rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Content specific styling */
|
|
||||||
.markdown-content,
|
|
||||||
.php-content,
|
|
||||||
.html-content {
|
|
||||||
margin-bottom: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.markdown-content .content-body,
|
|
||||||
.php-content .content-body,
|
|
||||||
.html-content .content-body {
|
|
||||||
padding: 2rem;
|
|
||||||
line-height: 1.6;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Footer */
|
|
||||||
footer {
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Navigation dropdown styling */
|
|
||||||
.navigation-section .btn {
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navigation-section .collapse .nav-link {
|
|
||||||
color: #495057;
|
|
||||||
padding: 0.375rem 0.75rem;
|
|
||||||
border-radius: 0.25rem;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navigation-section .collapse .nav-link:hover {
|
|
||||||
background-color: #e9ecef;
|
|
||||||
color: #212529;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navigation-section .collapse .nav-link.active {
|
|
||||||
background-color: #0d6efd;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navigation-section .collapse .nav-link i {
|
|
||||||
margin-right: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* File info styling */
|
|
||||||
.file-info {
|
|
||||||
font-size: 0.9rem;
|
|
||||||
color: #6c757d;
|
|
||||||
flex: 1;
|
|
||||||
min-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.file-info i {
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-title {
|
|
||||||
color: #6c757d;
|
|
||||||
max-width: 250px;
|
|
||||||
display: inline-block;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
vertical-align: middle;
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-title:hover {
|
|
||||||
color: #495057;
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
.file-details {
|
|
||||||
color: #6c757d;
|
|
||||||
font-size: 0.85rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.site-info a {
|
|
||||||
color: #0d6efd;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.site-info a:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
.guide-link {
|
|
||||||
color: #6c757d !important;
|
|
||||||
text-decoration: none;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.guide-link:hover {
|
|
||||||
color: #0d6efd !important;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.guide-link i {
|
|
||||||
font-size: 1rem;
|
|
||||||
color: #6c757d !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.guide-link:hover i {
|
|
||||||
color: #0d6efd !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.auto-link {
|
|
||||||
color: #0d6efd;
|
|
||||||
text-decoration: none;
|
|
||||||
border-bottom: 2px dashed #0d6efd;
|
|
||||||
font-weight: 500;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.auto-link:hover {
|
|
||||||
color: #0a58ca;
|
|
||||||
text-decoration: none;
|
|
||||||
border-bottom-style: solid;
|
|
||||||
border-bottom-color: #0a58ca;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Search form */
|
|
||||||
.search-form {
|
|
||||||
max-width: 300px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Search input text color - override navbar form-control styling */
|
|
||||||
.navbar .form-control.search-input {
|
|
||||||
color: #000000 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar .form-control.search-input::placeholder {
|
|
||||||
color: #6c757d !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Card styling */
|
|
||||||
.card-title a {
|
|
||||||
text-decoration: none;
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-title a:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dropdown submenu styling */
|
|
||||||
.dropdown-menu .dropdown-menu {
|
|
||||||
top: 0;
|
|
||||||
left: 100%;
|
|
||||||
margin-top: -1px;
|
|
||||||
margin-left: -1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Show nested dropdowns on hover */
|
|
||||||
.dropdown-submenu {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-submenu .dropdown-menu {
|
|
||||||
top: 0;
|
|
||||||
left: 100%;
|
|
||||||
margin-top: -1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-submenu:hover > .dropdown-menu {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For touch devices - click to open */
|
|
||||||
.dropdown-submenu > .dropdown-toggle:active::after {
|
|
||||||
transform: rotate(90deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Responsive adjustments */
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.main-content {
|
|
||||||
padding-top: 120px; /* More space for mobile */
|
|
||||||
}
|
|
||||||
|
|
||||||
.markdown-content .content-body,
|
|
||||||
.php-content .content-body,
|
|
||||||
.html-content .content-body {
|
|
||||||
padding: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-tabs .dropdown-menu {
|
|
||||||
min-width: 180px;
|
|
||||||
max-width: 250px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-tabs .dropdown-menu .dropdown-item {
|
|
||||||
max-width: 230px;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 576px) {
|
|
||||||
.markdown-content .content-body,
|
|
||||||
.php-content .content-body,
|
|
||||||
.html-content .content-body {
|
|
||||||
padding: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-tabs .dropdown-menu {
|
|
||||||
min-width: 160px;
|
|
||||||
max-width: 200px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-tabs .dropdown-menu .dropdown-item {
|
|
||||||
max-width: 180px;
|
|
||||||
font-size: 0.85rem;
|
|
||||||
padding: 0.4rem 0.8rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-2078
File diff suppressed because it is too large
Load Diff
-5
File diff suppressed because one or more lines are too long
@@ -1,54 +0,0 @@
|
|||||||
/* Mobile search improvements */
|
|
||||||
@media (max-width: 991.98px) {
|
|
||||||
.navbar {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hide desktop elements on mobile */
|
|
||||||
.d-none.d-lg-flex {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
#mobileSearch {
|
|
||||||
position: absolute;
|
|
||||||
top: 100%;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
background: var(--header-bg);
|
|
||||||
z-index: 1030;
|
|
||||||
}
|
|
||||||
|
|
||||||
#mobileSearch.show {
|
|
||||||
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ensure navigation doesn't overlap with expanded search */
|
|
||||||
.navigation-section {
|
|
||||||
margin-top: 0;
|
|
||||||
border: none !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Desktop improvements */
|
|
||||||
@media (min-width: 992px) {
|
|
||||||
/* Hide mobile elements on desktop */
|
|
||||||
.d-lg-none {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hide mobile search on desktop */
|
|
||||||
#mobileSearch {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Search form improvements */
|
|
||||||
.form-control[type="search"] {
|
|
||||||
min-width: 200px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 576px) {
|
|
||||||
.form-control[type="search"] {
|
|
||||||
min-width: 150px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
/*!
|
|
||||||
* Bootstrap v5.3.8 (https://getbootstrap.com/)
|
|
||||||
* Copyright 2011-2025 The Bootstrap Authors
|
|
||||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 31 KiB |
@@ -1,11 +0,0 @@
|
|||||||
<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<!-- < -->
|
|
||||||
<path d="M8 8 L3 16 L8 24" stroke="#ffffff" stroke-width="3" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
|
|
||||||
<!-- / -->
|
|
||||||
<path d="M12 24 L18 8" stroke="#ffffff" stroke-width="3" stroke-linecap="round"/>
|
|
||||||
|
|
||||||
<!-- .. -->
|
|
||||||
<circle cx="22" cy="20" r="2" fill="#ffffff"/>
|
|
||||||
<circle cx="28" cy="20" r="2" fill="#ffffff"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 442 B |
@@ -1,11 +0,0 @@
|
|||||||
<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<!-- < -->
|
|
||||||
<path d="M8 8 L3 16 L8 24" stroke="#ffffff" stroke-width="3" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
|
|
||||||
<!-- / -->
|
|
||||||
<path d="M12 24 L18 8" stroke="#ffffff" stroke-width="3" stroke-linecap="round"/>
|
|
||||||
|
|
||||||
<!-- .. -->
|
|
||||||
<circle cx="22" cy="20" r="2" fill="#ffffff"/>
|
|
||||||
<circle cx="28" cy="20" r="2" fill="#ffffff"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 442 B |
@@ -1,94 +0,0 @@
|
|||||||
// Main application JavaScript
|
|
||||||
// This file contains general application functionality
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Toggle sidebar visibility (open/close)
|
|
||||||
*/
|
|
||||||
function toggleSidebar() {
|
|
||||||
const sidebar = document.getElementById('site-sidebar');
|
|
||||||
const contentCol = sidebar ? sidebar.nextElementSibling || sidebar.parentElement.querySelector('.content-column') : null;
|
|
||||||
const btn = document.querySelector('.sidebar-toggle-btn');
|
|
||||||
const icon = btn ? btn.querySelector('i') : null;
|
|
||||||
|
|
||||||
if (!sidebar) return;
|
|
||||||
|
|
||||||
sidebar.classList.toggle('sidebar-hidden');
|
|
||||||
|
|
||||||
// Adjust content column width, toggle icon, and update aria-expanded
|
|
||||||
if (sidebar.classList.contains('sidebar-hidden')) {
|
|
||||||
if (contentCol) {
|
|
||||||
contentCol.classList.remove('col-lg-9', 'col-md-8');
|
|
||||||
contentCol.classList.add('col-12');
|
|
||||||
}
|
|
||||||
if (icon) {
|
|
||||||
icon.classList.remove('bi-layout-sidebar-inset');
|
|
||||||
icon.classList.add('bi-layout-sidebar');
|
|
||||||
}
|
|
||||||
if (btn) {
|
|
||||||
btn.setAttribute('aria-expanded', 'false');
|
|
||||||
}
|
|
||||||
sessionStorage.setItem('sidebarHidden', 'true');
|
|
||||||
} else {
|
|
||||||
if (contentCol) {
|
|
||||||
contentCol.classList.remove('col-12');
|
|
||||||
contentCol.classList.add('col-lg-9', 'col-md-8');
|
|
||||||
}
|
|
||||||
if (icon) {
|
|
||||||
icon.classList.remove('bi-layout-sidebar');
|
|
||||||
icon.classList.add('bi-layout-sidebar-inset');
|
|
||||||
}
|
|
||||||
if (btn) {
|
|
||||||
btn.setAttribute('aria-expanded', 'true');
|
|
||||||
}
|
|
||||||
sessionStorage.setItem('sidebarHidden', 'false');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Restore sidebar state from sessionStorage on page load
|
|
||||||
*/
|
|
||||||
function restoreSidebarState() {
|
|
||||||
if (sessionStorage.getItem('sidebarHidden') === 'true') {
|
|
||||||
const sidebar = document.getElementById('site-sidebar');
|
|
||||||
if (sidebar) {
|
|
||||||
toggleSidebar();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize application when DOM is ready
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
// Restore sidebar state
|
|
||||||
restoreSidebarState();
|
|
||||||
|
|
||||||
// Handle nested dropdowns for touch devices using event delegation
|
|
||||||
document.addEventListener('click', function(e) {
|
|
||||||
const toggle = e.target.closest('.dropdown-submenu .dropdown-toggle');
|
|
||||||
|
|
||||||
if (toggle) {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
|
|
||||||
const submenu = toggle.closest('.dropdown-submenu');
|
|
||||||
const dropdown = submenu.querySelector('.dropdown-menu');
|
|
||||||
|
|
||||||
// Close other submenus at the same level
|
|
||||||
const parent = submenu.parentElement;
|
|
||||||
parent.querySelectorAll('.dropdown-submenu').forEach(function(sibling) {
|
|
||||||
if (sibling !== submenu) {
|
|
||||||
var siblingMenu = sibling.querySelector('.dropdown-menu');
|
|
||||||
if (siblingMenu) siblingMenu.classList.remove('show');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Toggle current submenu
|
|
||||||
if (dropdown) dropdown.classList.toggle('show');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close all open submenus when clicking outside
|
|
||||||
document.querySelectorAll('.dropdown-submenu .dropdown-menu.show').forEach(function(menu) {
|
|
||||||
menu.classList.remove('show');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,333 +0,0 @@
|
|||||||
// CodePress demo theme styles
|
|
||||||
// A distinct look to demonstrate that themes are fully swappable.
|
|
||||||
|
|
||||||
// Theme color variables (defined per theme; used by the CSS custom properties below)
|
|
||||||
$header-bg: #613583;
|
|
||||||
$header-font: #ffffff;
|
|
||||||
$header-height: 120px;
|
|
||||||
$nav-bg: #813d9c;
|
|
||||||
$nav-font: #ffffff;
|
|
||||||
$nav-height: 50px;
|
|
||||||
$sidebar-bg: #f3e8f7;
|
|
||||||
$sidebar-border: #d8b4e0;
|
|
||||||
|
|
||||||
// Optional header background image and overlay opacity
|
|
||||||
$header-bg-image: none;
|
|
||||||
$header-bg-opacity: 1;
|
|
||||||
|
|
||||||
:root {
|
|
||||||
--header-bg: #{$header-bg};
|
|
||||||
--header-font: #{$header-font};
|
|
||||||
--header-height: #{$header-height};
|
|
||||||
--nav-bg: #{$nav-bg};
|
|
||||||
--nav-font: #{$nav-font};
|
|
||||||
--nav-height: #{$nav-height};
|
|
||||||
--sidebar-bg: #{$sidebar-bg};
|
|
||||||
--sidebar-border: #{$sidebar-border};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Header background (optional background image via $header-bg-image)
|
|
||||||
#site-header {
|
|
||||||
background-image: $header-bg-image;
|
|
||||||
background-size: cover;
|
|
||||||
background-position: center;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
@if $header-bg-image != 'none' {
|
|
||||||
#site-header::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
background-color: var(--header-bg);
|
|
||||||
opacity: $header-bg-opacity;
|
|
||||||
pointer-events: none;
|
|
||||||
z-index: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rounded, softer header
|
|
||||||
.navbar {
|
|
||||||
background-color: var(--header-bg) !important;
|
|
||||||
min-height: var(--header-height);
|
|
||||||
border-bottom: 4px solid var(--nav-bg) !important;
|
|
||||||
|
|
||||||
.navbar-brand,
|
|
||||||
.navbar-text,
|
|
||||||
.form-control,
|
|
||||||
.btn {
|
|
||||||
color: var(--header-font) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-control::placeholder {
|
|
||||||
color: rgba(255, 255, 255, 0.7) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-outline-light {
|
|
||||||
border-color: var(--header-font) !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Language dropdown styling
|
|
||||||
.dropdown-menu {
|
|
||||||
background-color: var(--header-bg) !important;
|
|
||||||
border: 1px solid var(--header-font) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-item {
|
|
||||||
color: var(--header-font) !important;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: rgba(255, 255, 255, 0.1) !important;
|
|
||||||
color: var(--header-font) !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-toggle::after {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-outline-light {
|
|
||||||
color: var(--header-font) !important;
|
|
||||||
border-color: var(--header-font) !important;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: rgba(255, 255, 255, 0.1) !important;
|
|
||||||
color: var(--header-font) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:focus,
|
|
||||||
&:active,
|
|
||||||
.show > &.dropdown-toggle {
|
|
||||||
background-color: rgba(255, 255, 255, 0.1) !important;
|
|
||||||
color: var(--header-font) !important;
|
|
||||||
border-color: var(--header-font) !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.bi-chevron-down {
|
|
||||||
font-size: 0.75em;
|
|
||||||
margin-left: 0.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Breadcrumb
|
|
||||||
.breadcrumb-item + .breadcrumb-item::before {
|
|
||||||
content: "" !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.breadcrumb {
|
|
||||||
--bs-breadcrumb-divider: "";
|
|
||||||
--bs-breadcrumb-margin-bottom: 0;
|
|
||||||
margin-bottom: 0;
|
|
||||||
|
|
||||||
.breadcrumb-item {
|
|
||||||
color: var(--header-bg) !important;
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: var(--header-bg) !important;
|
|
||||||
text-decoration: none;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-toggle-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-right: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-toggle-btn {
|
|
||||||
padding: 0;
|
|
||||||
line-height: 1;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
color: var(--header-bg) !important;
|
|
||||||
border: none !important;
|
|
||||||
background: transparent !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-column {
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-hidden {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Navigation section background
|
|
||||||
.navigation-section {
|
|
||||||
background-color: var(--nav-bg) !important;
|
|
||||||
color: var(--nav-font) !important;
|
|
||||||
min-height: var(--nav-height);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Accessibility
|
|
||||||
.focus-visible:focus,
|
|
||||||
.btn:focus,
|
|
||||||
.form-control:focus,
|
|
||||||
.nav-link:focus {
|
|
||||||
outline: 3px solid #0056b3 !important;
|
|
||||||
outline-offset: 2px !important;
|
|
||||||
box-shadow: 0 0 0 1px #ffffff, 0 0 0 4px #0056b3 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
|
||||||
*,
|
|
||||||
*::before,
|
|
||||||
*::after {
|
|
||||||
animation-duration: 0.01ms !important;
|
|
||||||
animation-iteration-count: 1 !important;
|
|
||||||
transition-duration: 0.01ms !important;
|
|
||||||
scroll-behavior: auto !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-tabs {
|
|
||||||
background-color: transparent !important;
|
|
||||||
border: none !important;
|
|
||||||
|
|
||||||
.nav-link {
|
|
||||||
background-color: transparent !important;
|
|
||||||
border: none !important;
|
|
||||||
color: var(--nav-font) !important;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: rgba(255, 255, 255, 0.1) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
background-color: rgba(255, 255, 255, 0.2) !important;
|
|
||||||
border-bottom: 2px solid var(--nav-font) !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sidebar styling - rounded cards look
|
|
||||||
.sidebar-column {
|
|
||||||
background-color: var(--sidebar-bg) !important;
|
|
||||||
border-right: 1px solid var(--sidebar-border) !important;
|
|
||||||
position: sticky;
|
|
||||||
top: 0;
|
|
||||||
min-height: calc(100vh - var(--header-height) - var(--nav-height) - 42px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar {
|
|
||||||
padding: 1.5rem;
|
|
||||||
height: 100%;
|
|
||||||
overflow-y: auto;
|
|
||||||
|
|
||||||
.card {
|
|
||||||
border-radius: 1rem;
|
|
||||||
border: 1px solid var(--sidebar-border);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-column {
|
|
||||||
background-color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-wrapper {
|
|
||||||
padding: 2rem;
|
|
||||||
padding-bottom: 80px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-content {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mobile responsive
|
|
||||||
@media (max-width: 767.98px) {
|
|
||||||
.sidebar-column {
|
|
||||||
border-right: none !important;
|
|
||||||
border-top: 1px solid var(--sidebar-border) !important;
|
|
||||||
min-height: auto;
|
|
||||||
margin-top: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-wrapper {
|
|
||||||
min-height: auto;
|
|
||||||
padding-bottom: 2rem !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 991.98px) {
|
|
||||||
.sidebar-column {
|
|
||||||
order: 2 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-column {
|
|
||||||
order: 1 !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Code block styling
|
|
||||||
pre {
|
|
||||||
background: #f8f9fa;
|
|
||||||
padding: 1rem;
|
|
||||||
border-radius: 6px;
|
|
||||||
overflow-x: auto;
|
|
||||||
border: 1px solid #dee2e6;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
|
|
||||||
code {
|
|
||||||
background: none;
|
|
||||||
padding: 0;
|
|
||||||
color: #333;
|
|
||||||
font-size: 0.85rem;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
code {
|
|
||||||
background: #e8e8e8;
|
|
||||||
padding: 0.15rem 0.4rem;
|
|
||||||
border-radius: 3px;
|
|
||||||
font-size: 0.9em;
|
|
||||||
color: #d63384;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Footer icon hover effects
|
|
||||||
.footer-icon {
|
|
||||||
color: #6c757d;
|
|
||||||
text-decoration: none;
|
|
||||||
transition: all 0.2s ease-in-out;
|
|
||||||
display: inline-block;
|
|
||||||
padding: 2px;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #0d6efd;
|
|
||||||
transform: translateY(-1px);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.guide:hover {
|
|
||||||
color: #198754;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.cms:hover {
|
|
||||||
color: #dc3545;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.git:hover {
|
|
||||||
color: #6f42c1;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.website:hover {
|
|
||||||
color: #fd7e14;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,143 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="{{ current_lang }}">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>{{ page_title }} - {{ site_title }}</title>
|
|
||||||
|
|
||||||
<!-- Skip to content link for accessibility -->
|
|
||||||
<a href="#main-content" class="skip-link sr-only sr-only-focusable">Skip to main content</a>
|
|
||||||
|
|
||||||
<!-- CMS Meta Tags -->
|
|
||||||
<meta name="generator" content="{{ site_title }} CMS">
|
|
||||||
<meta name="application-name" content="{{ site_title }}">
|
|
||||||
<meta name="author" content="{{ author_name }}">
|
|
||||||
<meta name="creator" content="{{ author_name }}">
|
|
||||||
<meta name="publisher" content="{{ author_name }}">
|
|
||||||
|
|
||||||
<!-- SEO Meta Tags -->
|
|
||||||
<meta name="description" content="{{ seo_description }}">
|
|
||||||
<meta name="keywords" content="{{ seo_keywords }}">
|
|
||||||
{% if block_ai_bots %}
|
|
||||||
<meta name="robots" content="noai, noimageai">
|
|
||||||
<meta name="tdm-reservation" content="1">
|
|
||||||
{% endif %}
|
|
||||||
{% if block_search_engines %}
|
|
||||||
<meta name="robots" content="noindex, nofollow">
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<!-- Author Links -->
|
|
||||||
<link rel="author" href="{{ author_website }}">
|
|
||||||
<link rel="me" href="{{ author_git }}">
|
|
||||||
|
|
||||||
<!-- Favicon -->
|
|
||||||
<link rel="icon" href="{{ theme_base_url }}/assets/img/favicon.ico" sizes="any">
|
|
||||||
<link rel="icon" type="image/svg+xml" href="{{ theme_base_url }}/assets/img/favicon.svg">
|
|
||||||
<link rel="apple-touch-icon" href="{{ theme_base_url }}/assets/img/favicon.svg">
|
|
||||||
<link rel="manifest" href="/manifest.json">
|
|
||||||
<meta name="theme-color" content="{{ theme_config.header_color|default('#613583') }}">
|
|
||||||
|
|
||||||
<!-- Theme CSS -->
|
|
||||||
{% for cssFile in theme_css_files %}
|
|
||||||
<link href="{{ cssFile }}" rel="stylesheet">
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
<!-- Compiled theme CSS (if SCSS was used) -->
|
|
||||||
{% if theme_css_url %}
|
|
||||||
<link href="{{ theme_css_url }}" rel="stylesheet">
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<!-- Accessibility styles -->
|
|
||||||
<style>
|
|
||||||
.skip-link {
|
|
||||||
position: absolute;
|
|
||||||
top: -40px;
|
|
||||||
left: 6px;
|
|
||||||
background: #000;
|
|
||||||
color: #fff;
|
|
||||||
padding: 8px;
|
|
||||||
text-decoration: none;
|
|
||||||
z-index: 100;
|
|
||||||
}
|
|
||||||
.skip-link:focus {
|
|
||||||
top: 6px;
|
|
||||||
outline: 3px solid #0056b3;
|
|
||||||
outline-offset: 2px;
|
|
||||||
}
|
|
||||||
.sr-only {
|
|
||||||
position: absolute;
|
|
||||||
width: 1px;
|
|
||||||
height: 1px;
|
|
||||||
padding: 0;
|
|
||||||
margin: -1px;
|
|
||||||
overflow: hidden;
|
|
||||||
clip: rect(0, 0, 0, 0);
|
|
||||||
white-space: nowrap;
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
.sr-only-focusable:focus {
|
|
||||||
position: static;
|
|
||||||
width: auto;
|
|
||||||
height: auto;
|
|
||||||
padding: inherit;
|
|
||||||
margin: inherit;
|
|
||||||
overflow: visible;
|
|
||||||
clip: auto;
|
|
||||||
white-space: normal;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<!-- Dynamic theme styles -->
|
|
||||||
<style>
|
|
||||||
html, body {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
#site-header > * {
|
|
||||||
position: relative;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
{% include 'partials/header.twig' %}
|
|
||||||
|
|
||||||
<nav role="navigation" aria-label="Main navigation" id="site-navigation">
|
|
||||||
{% include 'partials/navigation.twig' %}
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<nav id="site-breadcrumb" class="breadcrumb-section bg-light border-bottom" aria-label="Breadcrumb navigation">
|
|
||||||
<div class="container-fluid">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-12 py-2">
|
|
||||||
<h2 class="sr-only">Breadcrumb Navigation</h2>
|
|
||||||
{{ breadcrumb|raw }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<main role="main" id="main-content" class="main-content" style="padding: 0;">
|
|
||||||
{% block content %}{% endblock %}
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<footer role="contentinfo" id="site-footer">
|
|
||||||
{% include 'partials/footer.twig' %}
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
<!-- Theme JS -->
|
|
||||||
{% for jsFile in theme_js_files %}
|
|
||||||
<script src="{{ jsFile }}"></script>
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
<!-- Theme-specific JS -->
|
|
||||||
{% if theme_js_url %}
|
|
||||||
<script src="{{ theme_js_url }}"></script>
|
|
||||||
{% endif %}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
{% extends 'base.twig' %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<div class="container-fluid">
|
|
||||||
<div class="row g-0">
|
|
||||||
<aside role="complementary" aria-label="Sidebar content" id="site-sidebar" class="col-12 sidebar-column">
|
|
||||||
<div class="sidebar">
|
|
||||||
{{ sidebar_content|raw }}
|
|
||||||
</div>
|
|
||||||
</aside>
|
|
||||||
<section id="site-content" class="col-12">
|
|
||||||
<div class="content-wrapper p-4">
|
|
||||||
{{ content|raw }}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
{% extends 'base.twig' %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<div class="container">
|
|
||||||
<section id="site-content" class="col-12">
|
|
||||||
<div class="content-wrapper p-4">
|
|
||||||
{{ content|raw }}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
{% extends 'base.twig' %}
|
|
||||||
|
|
||||||
{% block title %}{{ page.title }}{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
{% if sidebar_content %}
|
|
||||||
<div class="row g-0">
|
|
||||||
<aside role="complementary" aria-label="Handleiding navigatie" id="site-sidebar" class="col-lg-3 col-md-4 sidebar-column order-2 order-md-1">
|
|
||||||
<div class="sidebar h-100">
|
|
||||||
{{ sidebar_content|raw }}
|
|
||||||
</div>
|
|
||||||
</aside>
|
|
||||||
<section id="site-content" class="col-lg-9 col-md-8 content-column order-1 order-md-2">
|
|
||||||
<div class="content-wrapper p-4">
|
|
||||||
<div class="guide-content">
|
|
||||||
{{ content|raw }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
{% else %}
|
|
||||||
<div class="container">
|
|
||||||
<section id="site-content" class="col-12">
|
|
||||||
<div class="content-wrapper p-4">
|
|
||||||
<div class="guide-content">
|
|
||||||
{{ content|raw }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% endblock %}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
{% extends 'base.twig' %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
{% if sidebar_content %}
|
|
||||||
<div class="row g-0">
|
|
||||||
<aside role="complementary" aria-label="Sidebar content" id="site-sidebar" class="col-lg-3 col-md-4 sidebar-column order-2 order-md-1">
|
|
||||||
<div class="sidebar h-100">
|
|
||||||
{{ sidebar_content|raw }}
|
|
||||||
</div>
|
|
||||||
</aside>
|
|
||||||
<section id="site-content" class="col-lg-9 col-md-8 content-column order-1 order-md-2">
|
|
||||||
<div class="content-wrapper p-4">
|
|
||||||
{{ content|raw }}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
{% else %}
|
|
||||||
<div class="container">
|
|
||||||
<section id="site-content" class="col-12">
|
|
||||||
<div class="content-wrapper p-4">
|
|
||||||
{{ content|raw }}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% endblock %}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
<footer class="bg-light border-top py-1">
|
|
||||||
<div class="container-fluid">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-12">
|
|
||||||
<div class="d-flex flex-column flex-md-row justify-content-between align-items-start align-items-md-center">
|
|
||||||
<div class="file-info mb-2 mb-md-0">
|
|
||||||
<small class="text-muted">
|
|
||||||
<i class="bi bi-file-text footer-icon" title="{{ t_file_details }}: {{ page_title }}"></i>
|
|
||||||
<span class="page-title d-none d-lg-inline" title="{{ page_title }}">{{ page_title }}</span>
|
|
||||||
{% if file_info_block %}
|
|
||||||
<span class="ms-2">
|
|
||||||
{% if show_created %}
|
|
||||||
<i class="bi bi-calendar-plus footer-icon" title="{{ t_created }}: {{ created }}"></i>
|
|
||||||
<span class="file-created me-1" title="{{ t_created }}: {{ created }}">{{ created }}</span>
|
|
||||||
{% endif %}
|
|
||||||
<i class="bi bi-calendar-check footer-icon" title="{{ t_modified }}: {{ modified }}"></i>
|
|
||||||
<span class="file-modified" title="{{ t_modified }}: {{ modified }}">{{ modified }}</span>
|
|
||||||
</span>
|
|
||||||
{% endif %}
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
<div class="site-info">
|
|
||||||
<small class="text-muted">
|
|
||||||
<a href="/{{ current_lang }}/guide" class="footer-icon guide" title="{{ t_guide }}">
|
|
||||||
<i class="bi bi-book"></i>
|
|
||||||
</a>
|
|
||||||
<span class="ms-1">|</span>
|
|
||||||
{% if cms_version %}
|
|
||||||
<span class="ms-1 cms-version text-muted">{{ cms_version }}</span>
|
|
||||||
{% endif %}
|
|
||||||
<a href="https://git.noorlander.info/E.Noorlander/CodePress.git" target="_blank" rel="noopener noreferrer" class="footer-icon cms ms-1" title="{{ t_powered_by }} CodePress CMS">
|
|
||||||
<i class="bi bi-cpu"></i>
|
|
||||||
</a>
|
|
||||||
<span class="ms-1">|</span>
|
|
||||||
<a href="{{ author_website }}" target="_blank" rel="noopener noreferrer" class="footer-icon website" title="{{ t_author_website }}">
|
|
||||||
<i class="bi bi-globe"></i>
|
|
||||||
</a>
|
|
||||||
<span class="ms-1">|</span>
|
|
||||||
<a href="{{ author_git }}" target="_blank" rel="noopener noreferrer" class="footer-icon git" title="{{ t_author_git }}">
|
|
||||||
<i class="bi bi-git"></i>
|
|
||||||
</a>
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
<header id="site-header" class="navbar navbar-expand-lg navbar-dark" style="background-color: transparent;">
|
|
||||||
<div class="container-fluid">
|
|
||||||
<a class="navbar-brand" href="/{{ current_lang }}">
|
|
||||||
<img src="{{ theme_base_url }}/assets/img/icon.svg" alt="CodePress Logo" width="32" height="32" class="me-2">
|
|
||||||
{{ site_title }}
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Desktop search and language -->
|
|
||||||
<div class="d-none d-lg-flex ms-auto align-items-center">
|
|
||||||
<form class="d-flex me-3" method="GET" action="" role="search" aria-label="Site search">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="desktop-search-input" class="sr-only">{{ t_search_placeholder }}</label>
|
|
||||||
<input class="form-control me-2 search-input" type="search" id="desktop-search-input" name="search" placeholder="{{ t_search_placeholder }}" value="{{ search_query }}" aria-describedby="search-help">
|
|
||||||
<div id="search-help" class="sr-only">Enter keywords to search through the documentation</div>
|
|
||||||
</div>
|
|
||||||
<button class="btn btn-outline-light" type="submit" aria-label="{{ t_search_button }}">
|
|
||||||
<i class="bi bi-search" aria-hidden="true"></i>
|
|
||||||
<span class="sr-only">{{ t_search_button }}</span>
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<!-- Language switcher -->
|
|
||||||
<div class="dropdown">
|
|
||||||
<button class="btn btn-outline-light" type="button" data-bs-toggle="dropdown" aria-haspopup="menu" aria-expanded="false" aria-label="Select language - currently {{ current_lang_upper }}">
|
|
||||||
{{ current_lang_upper }} <i class="bi bi-chevron-down" aria-hidden="true"></i>
|
|
||||||
</button>
|
|
||||||
<ul class="dropdown-menu dropdown-menu-end" role="menu">
|
|
||||||
{% for lang in available_langs %}
|
|
||||||
<li role="none">
|
|
||||||
<a class="dropdown-item {{ lang.is_current ? 'active' : '' }}" href="{{ lang.url }}" role="menuitem" {% if lang.is_current %}aria-current="true"{% endif %} lang="{{ lang.code }}">
|
|
||||||
{{ lang.native_name }}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Mobile search and language toggle -->
|
|
||||||
<div class="d-lg-none">
|
|
||||||
<button class="btn btn-outline-light" type="button" data-bs-toggle="collapse" data-bs-target="#mobileSearch" aria-controls="mobileSearch" aria-expanded="false" aria-label="Toggle search">
|
|
||||||
<i class="bi bi-search"></i>
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-outline-light" type="button" data-bs-toggle="dropdown" aria-haspopup="menu" aria-expanded="false" aria-label="Select language - currently {{ current_lang_upper }}">
|
|
||||||
{{ current_lang_upper }} <i class="bi bi-chevron-down" aria-hidden="true"></i>
|
|
||||||
</button>
|
|
||||||
<ul class="dropdown-menu dropdown-menu-end" role="menu">
|
|
||||||
{% for lang in available_langs %}
|
|
||||||
<li role="none">
|
|
||||||
<a class="dropdown-item {{ lang.is_current ? 'active' : '' }}" href="{{ lang.url }}" role="menuitem" {% if lang.is_current %}aria-current="true"{% endif %} lang="{{ lang.code }}">
|
|
||||||
{{ lang.native_name }}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Mobile search bar -->
|
|
||||||
<div class="collapse navbar-collapse d-lg-none" id="mobileSearch">
|
|
||||||
<div class="container-fluid px-0">
|
|
||||||
<form class="d-flex px-3 pb-3" method="GET" action="" role="search" aria-label="Site search">
|
|
||||||
<div class="form-group w-100">
|
|
||||||
<label for="mobile-search-input" class="sr-only">{{ t_search_placeholder }}</label>
|
|
||||||
<input class="form-control me-2 search-input" type="search" id="mobile-search-input" name="search" placeholder="{{ t_search_placeholder }}" value="{{ search_query }}" aria-describedby="mobile-search-help">
|
|
||||||
<div id="mobile-search-help" class="sr-only">Enter keywords to search through the documentation</div>
|
|
||||||
</div>
|
|
||||||
<button class="btn btn-outline-light" type="submit" aria-label="{{ t_search_button }}">
|
|
||||||
<i class="bi bi-search" aria-hidden="true"></i>
|
|
||||||
<span class="sr-only">{{ t_search_button }}</span>
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
<nav class="navigation-section" role="navigation" aria-label="Main navigation">
|
|
||||||
<h2 class="sr-only">Site Navigation</h2>
|
|
||||||
<div class="container-fluid">
|
|
||||||
<div class="row align-items-center">
|
|
||||||
<div class="col">
|
|
||||||
<ul class="nav nav-tabs flex-wrap" role="menubar">
|
|
||||||
<li class="nav-item" role="none">
|
|
||||||
<a class="nav-link {{ home_active_class }}" href="/{{ current_lang }}" role="menuitem" {% if is_homepage %}aria-current="page"{% endif %}>
|
|
||||||
<i class="bi bi-house" aria-hidden="true"></i> {{ homepage_title }}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{{ menu|raw }}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
{% extends 'base.twig' %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
{% if sidebar_content %}
|
|
||||||
<div class="row g-0">
|
|
||||||
<section id="site-content" class="col-lg-9 col-md-8 content-column order-1">
|
|
||||||
<div class="content-wrapper p-4">
|
|
||||||
{{ content|raw }}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<aside role="complementary" aria-label="Sidebar content" id="site-sidebar" class="col-lg-3 col-md-4 sidebar-column order-2">
|
|
||||||
<div class="sidebar h-100">
|
|
||||||
{{ sidebar_content|raw }}
|
|
||||||
</div>
|
|
||||||
</aside>
|
|
||||||
</div>
|
|
||||||
{% else %}
|
|
||||||
<div class="container">
|
|
||||||
<section id="site-content" class="col-12">
|
|
||||||
<div class="content-wrapper p-4">
|
|
||||||
{{ content|raw }}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% endblock %}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"title": "demo",
|
|
||||||
"config": {
|
|
||||||
"default_template": "left_sidebar"
|
|
||||||
},
|
|
||||||
"template": {
|
|
||||||
"full_content": "full_content.twig",
|
|
||||||
"left_sidebar": "left_sidebar.twig",
|
|
||||||
"right_sidebar": "right_sidebar.twig",
|
|
||||||
"custom1": "custom1.twig",
|
|
||||||
"guide": "guide.twig"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 21 KiB |
@@ -40,8 +40,7 @@ gen_preview() {
|
|||||||
echo "Generated $dir/theme.png"
|
echo "Generated $dir/theme.png"
|
||||||
}
|
}
|
||||||
|
|
||||||
for d in default demo test; do
|
for d in */; do
|
||||||
if [[ -d "$d" ]]; then
|
d="${d%/}"
|
||||||
gen_preview "$d"
|
gen_preview "$d"
|
||||||
fi
|
|
||||||
done
|
done
|
||||||
|
|||||||
-33
@@ -8,39 +8,6 @@ $baseDir = dirname($vendorDir);
|
|||||||
return array(
|
return array(
|
||||||
'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
|
'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
|
||||||
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
||||||
'Mustache_Cache' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Cache_AbstractCache' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Cache_FilesystemCache' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Cache_NoopCache' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Compiler' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Context' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Engine' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Exception' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Exception_InvalidArgumentException' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Exception_LogicException' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Exception_RuntimeException' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Exception_SyntaxException' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Exception_UnknownFilterException' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Exception_UnknownHelperException' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Exception_UnknownTemplateException' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_HelperCollection' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_LambdaHelper' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Loader' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Loader_ArrayLoader' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Loader_CascadingLoader' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Loader_FilesystemLoader' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Loader_InlineLoader' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Loader_MutableLoader' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Loader_ProductionFilesystemLoader' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Loader_StringLoader' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Logger' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Logger_AbstractLogger' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Logger_StreamLogger' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Parser' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Source' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Source_FilesystemSource' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Template' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Tokenizer' => $vendorDir . '/mustache/mustache/src/compat.php',
|
|
||||||
'Nette\\ArgumentOutOfRangeException' => $vendorDir . '/nette/utils/src/exceptions.php',
|
'Nette\\ArgumentOutOfRangeException' => $vendorDir . '/nette/utils/src/exceptions.php',
|
||||||
'Nette\\DeprecatedException' => $vendorDir . '/nette/utils/src/exceptions.php',
|
'Nette\\DeprecatedException' => $vendorDir . '/nette/utils/src/exceptions.php',
|
||||||
'Nette\\DirectoryNotFoundException' => $vendorDir . '/nette/utils/src/exceptions.php',
|
'Nette\\DirectoryNotFoundException' => $vendorDir . '/nette/utils/src/exceptions.php',
|
||||||
|
|||||||
Vendored
+30
-72
@@ -18,11 +18,11 @@ class ComposerStaticInit071586d19f5409de22b3235d85d8476c
|
|||||||
);
|
);
|
||||||
|
|
||||||
public static $prefixLengthsPsr4 = array (
|
public static $prefixLengthsPsr4 = array (
|
||||||
'T' =>
|
'T' =>
|
||||||
array (
|
array (
|
||||||
'Twig\\' => 5,
|
'Twig\\' => 5,
|
||||||
),
|
),
|
||||||
'S' =>
|
'S' =>
|
||||||
array (
|
array (
|
||||||
'Symfony\\Polyfill\\Php80\\' => 23,
|
'Symfony\\Polyfill\\Php80\\' => 23,
|
||||||
'Symfony\\Polyfill\\Mbstring\\' => 26,
|
'Symfony\\Polyfill\\Mbstring\\' => 26,
|
||||||
@@ -31,18 +31,17 @@ class ComposerStaticInit071586d19f5409de22b3235d85d8476c
|
|||||||
'SourceSpan\\' => 11,
|
'SourceSpan\\' => 11,
|
||||||
'ScssPhp\\ScssPhp\\' => 16,
|
'ScssPhp\\ScssPhp\\' => 16,
|
||||||
),
|
),
|
||||||
'P' =>
|
'P' =>
|
||||||
array (
|
array (
|
||||||
'Psr\\Log\\' => 8,
|
'Psr\\Log\\' => 8,
|
||||||
'Psr\\Http\\Message\\' => 17,
|
'Psr\\Http\\Message\\' => 17,
|
||||||
'Psr\\EventDispatcher\\' => 20,
|
'Psr\\EventDispatcher\\' => 20,
|
||||||
'PhpMqtt\\Client\\' => 15,
|
|
||||||
),
|
),
|
||||||
'N' =>
|
'N' =>
|
||||||
array (
|
array (
|
||||||
'Nette\\' => 6,
|
'Nette\\' => 6,
|
||||||
),
|
),
|
||||||
'M' =>
|
'M' =>
|
||||||
array (
|
array (
|
||||||
'MyCLabs\\Enum\\' => 13,
|
'MyCLabs\\Enum\\' => 13,
|
||||||
'Mustache\\' => 9,
|
'Mustache\\' => 9,
|
||||||
@@ -50,119 +49,111 @@ class ComposerStaticInit071586d19f5409de22b3235d85d8476c
|
|||||||
'MaxMind\\Exception\\' => 18,
|
'MaxMind\\Exception\\' => 18,
|
||||||
'MaxMind\\Db\\' => 11,
|
'MaxMind\\Db\\' => 11,
|
||||||
),
|
),
|
||||||
'L' =>
|
'L' =>
|
||||||
array (
|
array (
|
||||||
'League\\Uri\\' => 11,
|
'League\\Uri\\' => 11,
|
||||||
'League\\Config\\' => 14,
|
'League\\Config\\' => 14,
|
||||||
'League\\CommonMark\\' => 18,
|
'League\\CommonMark\\' => 18,
|
||||||
),
|
),
|
||||||
'G' =>
|
'G' =>
|
||||||
array (
|
array (
|
||||||
'GeoIp2\\' => 7,
|
'GeoIp2\\' => 7,
|
||||||
),
|
),
|
||||||
'D' =>
|
'D' =>
|
||||||
array (
|
array (
|
||||||
'Dflydev\\DotAccessData\\' => 22,
|
'Dflydev\\DotAccessData\\' => 22,
|
||||||
),
|
),
|
||||||
'C' =>
|
'C' =>
|
||||||
array (
|
array (
|
||||||
'Composer\\CaBundle\\' => 18,
|
'Composer\\CaBundle\\' => 18,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
public static $prefixDirsPsr4 = array (
|
public static $prefixDirsPsr4 = array (
|
||||||
'Twig\\' =>
|
'Twig\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/twig/twig/src',
|
0 => __DIR__ . '/..' . '/twig/twig/src',
|
||||||
),
|
),
|
||||||
'Symfony\\Polyfill\\Php80\\' =>
|
'Symfony\\Polyfill\\Php80\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/symfony/polyfill-php80',
|
0 => __DIR__ . '/..' . '/symfony/polyfill-php80',
|
||||||
),
|
),
|
||||||
'Symfony\\Polyfill\\Mbstring\\' =>
|
'Symfony\\Polyfill\\Mbstring\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
|
0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
|
||||||
),
|
),
|
||||||
'Symfony\\Polyfill\\Ctype\\' =>
|
'Symfony\\Polyfill\\Ctype\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
|
0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
|
||||||
),
|
),
|
||||||
'Symfony\\Component\\Filesystem\\' =>
|
'Symfony\\Component\\Filesystem\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/symfony/filesystem',
|
0 => __DIR__ . '/..' . '/symfony/filesystem',
|
||||||
),
|
),
|
||||||
'SourceSpan\\' =>
|
'SourceSpan\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/scssphp/source-span/src',
|
0 => __DIR__ . '/..' . '/scssphp/source-span/src',
|
||||||
),
|
),
|
||||||
'ScssPhp\\ScssPhp\\' =>
|
'ScssPhp\\ScssPhp\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/scssphp/scssphp/src',
|
0 => __DIR__ . '/..' . '/scssphp/scssphp/src',
|
||||||
),
|
),
|
||||||
'Psr\\Log\\' =>
|
'Psr\\Log\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/psr/log/src',
|
0 => __DIR__ . '/..' . '/psr/log/src',
|
||||||
),
|
),
|
||||||
'Psr\\Http\\Message\\' =>
|
'Psr\\Http\\Message\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/psr/http-factory/src',
|
0 => __DIR__ . '/..' . '/psr/http-factory/src',
|
||||||
1 => __DIR__ . '/..' . '/psr/http-message/src',
|
1 => __DIR__ . '/..' . '/psr/http-message/src',
|
||||||
),
|
),
|
||||||
'Psr\\EventDispatcher\\' =>
|
'Psr\\EventDispatcher\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/psr/event-dispatcher/src',
|
0 => __DIR__ . '/..' . '/psr/event-dispatcher/src',
|
||||||
),
|
),
|
||||||
'PhpMqtt\\Client\\' =>
|
'Nette\\' =>
|
||||||
array (
|
|
||||||
0 => __DIR__ . '/..' . '/php-mqtt/client/src',
|
|
||||||
),
|
|
||||||
'Nette\\' =>
|
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/nette/schema/src',
|
0 => __DIR__ . '/..' . '/nette/schema/src',
|
||||||
1 => __DIR__ . '/..' . '/nette/utils/src',
|
1 => __DIR__ . '/..' . '/nette/utils/src',
|
||||||
),
|
),
|
||||||
'MyCLabs\\Enum\\' =>
|
'MyCLabs\\Enum\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/myclabs/php-enum/src',
|
0 => __DIR__ . '/..' . '/myclabs/php-enum/src',
|
||||||
),
|
),
|
||||||
'Mustache\\' =>
|
'MaxMind\\WebService\\' =>
|
||||||
array (
|
|
||||||
0 => __DIR__ . '/..' . '/mustache/mustache/src',
|
|
||||||
),
|
|
||||||
'MaxMind\\WebService\\' =>
|
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/maxmind/web-service-common/src/WebService',
|
0 => __DIR__ . '/..' . '/maxmind/web-service-common/src/WebService',
|
||||||
),
|
),
|
||||||
'MaxMind\\Exception\\' =>
|
'MaxMind\\Exception\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/maxmind/web-service-common/src/Exception',
|
0 => __DIR__ . '/..' . '/maxmind/web-service-common/src/Exception',
|
||||||
),
|
),
|
||||||
'MaxMind\\Db\\' =>
|
'MaxMind\\Db\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/maxmind-db/reader/src/MaxMind/Db',
|
0 => __DIR__ . '/..' . '/maxmind-db/reader/src/MaxMind/Db',
|
||||||
),
|
),
|
||||||
'League\\Uri\\' =>
|
'League\\Uri\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/league/uri',
|
0 => __DIR__ . '/..' . '/league/uri',
|
||||||
1 => __DIR__ . '/..' . '/league/uri-interfaces',
|
1 => __DIR__ . '/..' . '/league/uri-interfaces',
|
||||||
),
|
),
|
||||||
'League\\Config\\' =>
|
'League\\Config\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/league/config/src',
|
0 => __DIR__ . '/..' . '/league/config/src',
|
||||||
),
|
),
|
||||||
'League\\CommonMark\\' =>
|
'League\\CommonMark\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/league/commonmark/src',
|
0 => __DIR__ . '/..' . '/league/commonmark/src',
|
||||||
),
|
),
|
||||||
'GeoIp2\\' =>
|
'GeoIp2\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/geoip2/geoip2/src',
|
0 => __DIR__ . '/..' . '/geoip2/geoip2/src',
|
||||||
),
|
),
|
||||||
'Dflydev\\DotAccessData\\' =>
|
'Dflydev\\DotAccessData\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/dflydev/dot-access-data/src',
|
0 => __DIR__ . '/..' . '/dflydev/dot-access-data/src',
|
||||||
),
|
),
|
||||||
'Composer\\CaBundle\\' =>
|
'Composer\\CaBundle\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/composer/ca-bundle/src',
|
0 => __DIR__ . '/..' . '/composer/ca-bundle/src',
|
||||||
),
|
),
|
||||||
@@ -171,39 +162,6 @@ class ComposerStaticInit071586d19f5409de22b3235d85d8476c
|
|||||||
public static $classMap = array (
|
public static $classMap = array (
|
||||||
'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
|
'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
|
||||||
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
||||||
'Mustache_Cache' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Cache_AbstractCache' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Cache_FilesystemCache' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Cache_NoopCache' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Compiler' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Context' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Engine' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Exception' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Exception_InvalidArgumentException' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Exception_LogicException' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Exception_RuntimeException' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Exception_SyntaxException' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Exception_UnknownFilterException' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Exception_UnknownHelperException' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Exception_UnknownTemplateException' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_HelperCollection' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_LambdaHelper' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Loader' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Loader_ArrayLoader' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Loader_CascadingLoader' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Loader_FilesystemLoader' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Loader_InlineLoader' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Loader_MutableLoader' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Loader_ProductionFilesystemLoader' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Loader_StringLoader' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Logger' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Logger_AbstractLogger' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Logger_StreamLogger' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Parser' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Source' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Source_FilesystemSource' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Template' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Mustache_Tokenizer' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
|
||||||
'Nette\\ArgumentOutOfRangeException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php',
|
'Nette\\ArgumentOutOfRangeException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php',
|
||||||
'Nette\\DeprecatedException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php',
|
'Nette\\DeprecatedException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php',
|
||||||
'Nette\\DirectoryNotFoundException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php',
|
'Nette\\DirectoryNotFoundException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php',
|
||||||
|
|||||||
Vendored
+5
-121
@@ -1,5 +1,5 @@
|
|||||||
{
|
[
|
||||||
"packages": [
|
[
|
||||||
{
|
{
|
||||||
"name": "composer/ca-bundle",
|
"name": "composer/ca-bundle",
|
||||||
"version": "1.5.13",
|
"version": "1.5.13",
|
||||||
@@ -718,62 +718,6 @@
|
|||||||
},
|
},
|
||||||
"install-path": "../maxmind/web-service-common"
|
"install-path": "../maxmind/web-service-common"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "mustache/mustache",
|
|
||||||
"version": "v3.0.0",
|
|
||||||
"version_normalized": "3.0.0.0",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/bobthecow/mustache.php.git",
|
|
||||||
"reference": "176b6b21d68516dd5107a63ab71b0050e518b7a4"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/bobthecow/mustache.php/zipball/176b6b21d68516dd5107a63ab71b0050e518b7a4",
|
|
||||||
"reference": "176b6b21d68516dd5107a63ab71b0050e518b7a4",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": ">=5.6"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"friendsofphp/php-cs-fixer": "~2.19.3",
|
|
||||||
"yoast/phpunit-polyfills": "^2.0"
|
|
||||||
},
|
|
||||||
"time": "2025-06-28T18:28:20+00:00",
|
|
||||||
"type": "library",
|
|
||||||
"installation-source": "dist",
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Mustache\\": "src/"
|
|
||||||
},
|
|
||||||
"classmap": [
|
|
||||||
"src/compat.php"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Justin Hileman",
|
|
||||||
"email": "justin@justinhileman.info",
|
|
||||||
"homepage": "http://justinhileman.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "A Mustache implementation in PHP.",
|
|
||||||
"homepage": "https://github.com/bobthecow/mustache.php",
|
|
||||||
"keywords": [
|
|
||||||
"mustache",
|
|
||||||
"templating"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/bobthecow/mustache.php/issues",
|
|
||||||
"source": "https://github.com/bobthecow/mustache.php/tree/v3.0.0"
|
|
||||||
},
|
|
||||||
"install-path": "../mustache/mustache"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "myclabs/php-enum",
|
"name": "myclabs/php-enum",
|
||||||
"version": "1.8.5",
|
"version": "1.8.5",
|
||||||
@@ -1000,66 +944,6 @@
|
|||||||
},
|
},
|
||||||
"install-path": "../nette/utils"
|
"install-path": "../nette/utils"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "php-mqtt/client",
|
|
||||||
"version": "v2.3.0",
|
|
||||||
"version_normalized": "2.3.0.0",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/php-mqtt/client.git",
|
|
||||||
"reference": "3d141846753a0adee265680ae073cfb9030f2390"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/php-mqtt/client/zipball/3d141846753a0adee265680ae073cfb9030f2390",
|
|
||||||
"reference": "3d141846753a0adee265680ae073cfb9030f2390",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"myclabs/php-enum": "^1.7",
|
|
||||||
"php": "^8.0",
|
|
||||||
"psr/log": "^1.1|^2.0|^3.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"phpunit/php-invoker": "^3.0",
|
|
||||||
"phpunit/phpunit": "^9.0",
|
|
||||||
"squizlabs/php_codesniffer": "^3.5"
|
|
||||||
},
|
|
||||||
"suggest": {
|
|
||||||
"ext-redis": "Required for the RedisRepository"
|
|
||||||
},
|
|
||||||
"time": "2025-09-30T17:53:34+00:00",
|
|
||||||
"type": "library",
|
|
||||||
"installation-source": "dist",
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"PhpMqtt\\Client\\": "src"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Marvin Mall",
|
|
||||||
"email": "marvin-mall@msn.com",
|
|
||||||
"role": "developer"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "An MQTT client written in and for PHP.",
|
|
||||||
"keywords": [
|
|
||||||
"client",
|
|
||||||
"mqtt",
|
|
||||||
"publish",
|
|
||||||
"subscribe"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/php-mqtt/client/issues",
|
|
||||||
"source": "https://github.com/php-mqtt/client/tree/v2.3.0"
|
|
||||||
},
|
|
||||||
"install-path": "../php-mqtt/client"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "psr/event-dispatcher",
|
"name": "psr/event-dispatcher",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
@@ -1906,6 +1790,6 @@
|
|||||||
"install-path": "../twig/twig"
|
"install-path": "../twig/twig"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dev": true,
|
true,
|
||||||
"dev-package-names": []
|
[]
|
||||||
}
|
]
|
||||||
|
|||||||
Vendored
+6
-24
@@ -1,9 +1,9 @@
|
|||||||
<?php return array(
|
<?php return array(
|
||||||
'root' => array(
|
'root' => array(
|
||||||
'name' => '__root__',
|
'name' => '__root__',
|
||||||
'pretty_version' => 'dev-main',
|
'pretty_version' => '1.0.0+no-version-set',
|
||||||
'version' => 'dev-main',
|
'version' => '1.0.0.0',
|
||||||
'reference' => 'd453b8073f07afc24f2a03f94a982977263aa107',
|
'reference' => null,
|
||||||
'type' => 'library',
|
'type' => 'library',
|
||||||
'install_path' => __DIR__ . '/../../',
|
'install_path' => __DIR__ . '/../../',
|
||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
@@ -11,9 +11,9 @@
|
|||||||
),
|
),
|
||||||
'versions' => array(
|
'versions' => array(
|
||||||
'__root__' => array(
|
'__root__' => array(
|
||||||
'pretty_version' => 'dev-main',
|
'pretty_version' => '1.0.0+no-version-set',
|
||||||
'version' => 'dev-main',
|
'version' => '1.0.0.0',
|
||||||
'reference' => 'd453b8073f07afc24f2a03f94a982977263aa107',
|
'reference' => null,
|
||||||
'type' => 'library',
|
'type' => 'library',
|
||||||
'install_path' => __DIR__ . '/../../',
|
'install_path' => __DIR__ . '/../../',
|
||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
@@ -100,15 +100,6 @@
|
|||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
'dev_requirement' => false,
|
'dev_requirement' => false,
|
||||||
),
|
),
|
||||||
'mustache/mustache' => array(
|
|
||||||
'pretty_version' => 'v3.0.0',
|
|
||||||
'version' => '3.0.0.0',
|
|
||||||
'reference' => '176b6b21d68516dd5107a63ab71b0050e518b7a4',
|
|
||||||
'type' => 'library',
|
|
||||||
'install_path' => __DIR__ . '/../mustache/mustache',
|
|
||||||
'aliases' => array(),
|
|
||||||
'dev_requirement' => false,
|
|
||||||
),
|
|
||||||
'myclabs/php-enum' => array(
|
'myclabs/php-enum' => array(
|
||||||
'pretty_version' => '1.8.5',
|
'pretty_version' => '1.8.5',
|
||||||
'version' => '1.8.5.0',
|
'version' => '1.8.5.0',
|
||||||
@@ -136,15 +127,6 @@
|
|||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
'dev_requirement' => false,
|
'dev_requirement' => false,
|
||||||
),
|
),
|
||||||
'php-mqtt/client' => array(
|
|
||||||
'pretty_version' => 'v2.3.0',
|
|
||||||
'version' => '2.3.0.0',
|
|
||||||
'reference' => '3d141846753a0adee265680ae073cfb9030f2390',
|
|
||||||
'type' => 'library',
|
|
||||||
'install_path' => __DIR__ . '/../php-mqtt/client',
|
|
||||||
'aliases' => array(),
|
|
||||||
'dev_requirement' => false,
|
|
||||||
),
|
|
||||||
'psr/event-dispatcher' => array(
|
'psr/event-dispatcher' => array(
|
||||||
'pretty_version' => '1.0.0',
|
'pretty_version' => '1.0.0',
|
||||||
'version' => '1.0.0.0',
|
'version' => '1.0.0.0',
|
||||||
|
|||||||
+3
-3
@@ -4,9 +4,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'version' => '2.6.0',
|
'version' => '2.6.1',
|
||||||
'release_date' => '2026-08-15',
|
'release_date' => '2026-08-17',
|
||||||
'codename' => 'Atlas',
|
'codename' => 'Lyra',
|
||||||
'status' => 'stable',
|
'status' => 'stable',
|
||||||
|
|
||||||
'system_requirements' => [
|
'system_requirements' => [
|
||||||
|
|||||||
Reference in New Issue
Block a user