You've already forked wp-bootstrap
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9904bf508a | |||
| 77778860ab | |||
| 0902c5e1a5 | |||
| 1a0a1fa63a | |||
| 576922160e |
35
CHANGELOG.md
35
CHANGELOG.md
@@ -2,6 +2,41 @@
|
|||||||
|
|
||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
## [1.0.12] - 2026-02-28
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- **Admin bar offcanvas padding on desktop** (`functions.php`): Scoped the admin bar offcanvas padding fix to mobile viewports only (`max-width: 991.98px`) so the extra padding does not appear on wide screens where the offcanvas renders inline as a regular navbar.
|
||||||
|
|
||||||
|
## [1.0.11] - 2026-02-28
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **Offcanvas mobile navigation**: Default header now uses `header-offcanvas.html.twig` instead of `header.html.twig`. Mobile navigation slides in as an offcanvas panel from the right instead of collapsing downward.
|
||||||
|
- **User avatar in offcanvas header**: When logged in, the offcanvas header displays the user's Gravatar and display name linking to the WooCommerce My Account page (or WP admin profile as fallback). Falls back to the site name when logged out.
|
||||||
|
- **Dark mode toggle repositioned**: Moved from the offcanvas body to the offcanvas footer on mobile. Desktop toggle remains in the navbar.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- **User context data** (`inc/Template/ContextBuilder.php`): New `getUserData()` method exposing `user.logged_in`, `user.display_name`, `user.avatar`, and `user.account_url` to all Twig templates.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- **Admin bar overlapping offcanvas** (`functions.php`): Inline CSS via `wp_add_inline_style()` adds `padding-top` matching the admin bar height to `.offcanvas` when the admin bar is visible, preventing content overlap.
|
||||||
|
|
||||||
|
## [1.0.10] - 2026-02-25
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- **Title double-encoding in Twig templates** (`inc/Template/ContextBuilder.php`): WordPress's `get_the_title()` pre-encodes `&` as `&`. When passed to Twig with autoescape enabled, the `&` in `&` was escaped again to `&`, rendering as literal `&` in the browser (e.g. "Bewerbungen & Nachrichten" instead of "Bewerbungen & Nachrichten"). Fixed by wrapping all 6 `get_the_title()` calls with `wp_specialchars_decode()` to decode WordPress entities before Twig. Twig autoescape then properly re-encodes `&` → `&`. This is XSS-safe because Twig still escapes all output.
|
||||||
|
|
||||||
|
## [1.0.9] - 2026-02-19
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
|
||||||
|
- **Color variation CSS transient caching** (`functions.php`): `wp_bootstrap_variation_colors()` now caches the generated inline CSS in a 24-hour WordPress transient keyed by `wp_bootstrap_variation_css_` + an MD5 of the active stylesheet slug. Previously the palette iteration and CSS string building ran on every frontend page load. The transient is immediately invalidated on `switch_theme` and `save_post_wp_global_styles`, so changes made via the Design Editor are reflected instantly.
|
||||||
|
- **Twig template recompilation gated behind `WP_DEBUG`** (`inc/Twig/TwigService.php`): `auto_reload` in the Twig `Environment` constructor was hardcoded to `true`, causing Twig to stat every compiled template file on every request to check for source changes. Changed to `WP_DEBUG` so template recompilation only occurs during development. In production (`WP_DEBUG = false`) compiled Twig templates are served from cache without filesystem mtime checks.
|
||||||
|
|
||||||
## [1.0.8] - 2026-02-19
|
## [1.0.8] - 2026-02-19
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|||||||
83
CLAUDE.md
83
CLAUDE.md
@@ -34,7 +34,7 @@ This project is proudly **"vibe-coded"** using Claude.AI - the entire codebase w
|
|||||||
|
|
||||||
**Note for AI Assistants:** Clean this section after the specific features are done or new releases are made. Effective changes are tracked in `CHANGELOG.md`. Do not add completed versions here - document them in the Session History section at the end of this file.
|
**Note for AI Assistants:** Clean this section after the specific features are done or new releases are made. Effective changes are tracked in `CHANGELOG.md`. Do not add completed versions here - document them in the Session History section at the end of this file.
|
||||||
|
|
||||||
Current version is **v1.0.5**. See `PLAN.md` for details.
|
Current version is **v1.0.11**. See `PLAN.md` for details.
|
||||||
|
|
||||||
## Technical Stack
|
## Technical Stack
|
||||||
|
|
||||||
@@ -98,6 +98,29 @@ Compiled .mo files are built by the Gitea CI/CD pipeline during releases. For lo
|
|||||||
for po in languages/wp-bootstrap-*.po; do msgfmt -o "${po%.po}.mo" "$po"; done
|
for po in languages/wp-bootstrap-*.po; do msgfmt -o "${po%.po}.mo" "$po"; done
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Updating Translations
|
||||||
|
|
||||||
|
When new strings are added to PHP sources, use the fast JSON workflow documented in
|
||||||
|
`wp-jobroom-theme/CLAUDE.md → Updating Translations (Fast JSON Workflow)`. That
|
||||||
|
document contains the full step-by-step process including the `patch-po.py` patcher script
|
||||||
|
(located in `wp-jobroom-theme/languages/patch-po.py`) which patches **both** `wp-bootstrap`
|
||||||
|
and `wp-jobroom-theme` `.po` files in a single pass.
|
||||||
|
|
||||||
|
**Quick reference for wp-bootstrap POT regeneration:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker exec jobroom-wordpress wp i18n make-pot \
|
||||||
|
/var/www/html/wp-content/themes/wp-bootstrap \
|
||||||
|
/var/www/html/wp-content/themes/wp-bootstrap/languages/wp-bootstrap.pot \
|
||||||
|
--allow-root
|
||||||
|
|
||||||
|
# Then merge into all .po files:
|
||||||
|
for locale in de_CH de_CH_informal de_DE de_DE_informal en_GB es_ES fr_CH fr_FR it_CH it_IT nl_NL pl_PL pt_PT; do
|
||||||
|
msgmerge --update --backup=none --no-fuzzy-matching \
|
||||||
|
languages/wp-bootstrap-${locale}.po languages/wp-bootstrap.pot
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
### Create Releases
|
### Create Releases
|
||||||
|
|
||||||
**Important Git Notes:**
|
**Important Git Notes:**
|
||||||
@@ -211,6 +234,64 @@ Build steps (in order):
|
|||||||
|
|
||||||
## Session History
|
## Session History
|
||||||
|
|
||||||
|
### Session 17 — v1.0.11 Offcanvas Navigation & User Context (2026-02-28)
|
||||||
|
|
||||||
|
**Completed:** Switched mobile navigation from Bootstrap collapse to offcanvas, added logged-in user context to the header, and fixed admin bar overlap.
|
||||||
|
|
||||||
|
**What was changed:**
|
||||||
|
|
||||||
|
- **Offcanvas navigation** (`views/base.html.twig`): Default header include switched from `partials/header.html.twig` (collapse) to `partials/header-offcanvas.html.twig` (offcanvas slide-in from right). The offcanvas variant already existed in the theme.
|
||||||
|
- **Offcanvas header with user avatar** (`views/partials/header-offcanvas.html.twig`): When logged in, the offcanvas header shows the user's Gravatar avatar and display name linking to the WooCommerce My Account page. Falls back to the site name when logged out.
|
||||||
|
- **Dark mode toggle repositioned**: Moved from the offcanvas body to the offcanvas footer (`d-lg-none`) on mobile. On desktop (≥lg), the toggle remains visible next to the navbar via a separate `d-none d-lg-block` wrapper.
|
||||||
|
- **User context in ContextBuilder** (`inc/Template/ContextBuilder.php`): New `getUserData()` method providing `user.logged_in`, `user.display_name`, `user.avatar` (rendered `<img>` with `rounded-circle` class), and `user.account_url` (WooCommerce My Account or WP admin profile fallback).
|
||||||
|
- **Admin bar offcanvas overlap fix** (`functions.php`): Inline CSS injected via `wp_add_inline_style()` when `is_admin_bar_showing()` is true. Adds `padding-top: var(--wp-admin--admin-bar--height, 32px)` to `.offcanvas` so the offcanvas content clears the admin bar.
|
||||||
|
|
||||||
|
**Files modified:**
|
||||||
|
|
||||||
|
- `views/base.html.twig` — header include changed to offcanvas variant
|
||||||
|
- `views/partials/header-offcanvas.html.twig` — user avatar header, dark mode toggle in footer
|
||||||
|
- `inc/Template/ContextBuilder.php` — `getUserData()` method, `user` key in context
|
||||||
|
- `functions.php` — admin bar offcanvas padding inline style
|
||||||
|
- `style.css` — version bump to 1.0.11
|
||||||
|
- `CHANGELOG.md` — v1.0.11 entry
|
||||||
|
|
||||||
|
**Key learnings:**
|
||||||
|
|
||||||
|
- Bootstrap offcanvas inside `navbar-expand-lg` uses `position: fixed; top: 0` which is covered by the WordPress admin bar (`z-index: 99999`). Since the offcanvas z-index (1045) is lower, adjusting `top` alone doesn't help visually — `padding-top` on the offcanvas content is the practical fix.
|
||||||
|
- `wp_add_inline_style()` bypasses file-level browser caching, making it more reliable for conditional CSS rules than editing the main stylesheet.
|
||||||
|
- WordPress's `--wp-admin--admin-bar--height` CSS custom property (set on `:root`) adjusts between 32px (desktop) and 46px (mobile ≤782px), making it the ideal value for admin bar offset calculations.
|
||||||
|
- `get_avatar()` accepts an `$args` array where CSS classes can be passed via the `class` key, avoiding post-processing of the HTML output.
|
||||||
|
|
||||||
|
### Session 16 — v1.0.10 Title Double-Encoding Fix (2026-02-25)
|
||||||
|
|
||||||
|
**Completed:** Fixed double-encoding of HTML entities in page titles rendered through Twig.
|
||||||
|
|
||||||
|
**Root cause:** WordPress's `get_the_title()` returns titles with HTML entities pre-encoded (e.g. `&` → `&`). `ContextBuilder` passed these pre-encoded strings to Twig as template variables. Twig's autoescape then re-encoded the `&` in `&` to `&#038;`, which browsers rendered as the literal text `&` instead of `&`. Affected all pages with `&` in their title (e.g. help pages "Bewerbungen & Nachrichten", "Konto & Sicherheit", "Abonnements & Abrechnung").
|
||||||
|
|
||||||
|
**Fix:** Wrapped all 6 `get_the_title()` calls in `ContextBuilder.php` with `wp_specialchars_decode()`. This decodes WordPress entities back to raw characters before Twig, allowing Twig autoescape to properly encode them once. XSS-safe because Twig still escapes all output.
|
||||||
|
|
||||||
|
**Files modified:**
|
||||||
|
|
||||||
|
- `inc/Template/ContextBuilder.php` — `wp_specialchars_decode()` on all 6 `get_the_title()` calls
|
||||||
|
- `style.css` — version bump to 1.0.10
|
||||||
|
- `CHANGELOG.md` — v1.0.10 entry
|
||||||
|
|
||||||
|
### Session 15 — v1.0.9 Performance Optimization (2026-02-19)
|
||||||
|
|
||||||
|
**Completed:** Two targeted performance fixes for production environments.
|
||||||
|
|
||||||
|
**Changes made:**
|
||||||
|
|
||||||
|
- **Color variation CSS transient caching** (`functions.php`): `wp_bootstrap_variation_colors()` now caches the generated Bootstrap CSS variable overrides in a 24-hour transient keyed by `wp_bootstrap_variation_css_` + `md5(get_stylesheet())`. Previously the palette loop and CSS string building executed on every frontend request. Transient is invalidated on `switch_theme` and `save_post_wp_global_styles` hooks so Design Editor changes apply immediately.
|
||||||
|
- **Twig `auto_reload` gated behind `WP_DEBUG`** (`inc/Twig/TwigService.php`): Hardcoded `auto_reload => true` caused Twig to `stat()` each compiled template file on every request to detect source file changes. Changed to `auto_reload => WP_DEBUG` so stat checks only occur during development. In production, compiled templates are served from cache unconditionally.
|
||||||
|
|
||||||
|
**Files modified:**
|
||||||
|
|
||||||
|
- `functions.php` — transient caching and invalidation for variation CSS
|
||||||
|
- `inc/Twig/TwigService.php` — `auto_reload => WP_DEBUG`
|
||||||
|
- `style.css` — version bump to 1.0.9
|
||||||
|
- `CHANGELOG.md` — v1.0.9 entry
|
||||||
|
|
||||||
### Session 14 — v1.0.8 Security Audit & Hardening (2026-02-19)
|
### Session 14 — v1.0.8 Security Audit & Hardening (2026-02-19)
|
||||||
|
|
||||||
**Completed:** Comprehensive OWASP-aligned security audit. Two parallel background agents reviewed all PHP (functions.php, ContextBuilder, NavWalker, TemplateController, TwigService, all patterns) and JavaScript/Twig templates. Four targeted security fixes applied.
|
**Completed:** Comprehensive OWASP-aligned security audit. Two parallel background agents reviewed all PHP (functions.php, ContextBuilder, NavWalker, TemplateController, TwigService, all patterns) and JavaScript/Twig templates. Four targeted security fixes applied.
|
||||||
|
|||||||
@@ -83,6 +83,13 @@ if ( ! function_exists( 'wp_bootstrap_enqueue_scripts' ) ) :
|
|||||||
$theme_version
|
$theme_version
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Push offcanvas below the WP admin bar when logged in.
|
||||||
|
if ( is_admin_bar_showing() ) {
|
||||||
|
wp_add_inline_style( 'wp-bootstrap-style',
|
||||||
|
'@media (max-width: 991.98px) { .offcanvas { padding-top: var(--wp-admin--admin-bar--height, 32px); } }'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Enqueue Bootstrap JS bundle (includes Popper).
|
// Enqueue Bootstrap JS bundle (includes Popper).
|
||||||
wp_enqueue_script(
|
wp_enqueue_script(
|
||||||
'wp-bootstrap-js',
|
'wp-bootstrap-js',
|
||||||
@@ -175,6 +182,17 @@ add_action( 'wp_enqueue_scripts', 'wp_bootstrap_rtl_styles', 20 );
|
|||||||
*/
|
*/
|
||||||
if ( ! function_exists( 'wp_bootstrap_variation_colors' ) ) :
|
if ( ! function_exists( 'wp_bootstrap_variation_colors' ) ) :
|
||||||
function wp_bootstrap_variation_colors() {
|
function wp_bootstrap_variation_colors() {
|
||||||
|
$transient_key = 'wp_bootstrap_variation_css_' . md5( get_stylesheet() );
|
||||||
|
$cached_css = get_transient( $transient_key );
|
||||||
|
|
||||||
|
if ( false !== $cached_css ) {
|
||||||
|
// '' means default palette (no inline CSS needed); non-empty string is the computed CSS.
|
||||||
|
if ( '' !== $cached_css ) {
|
||||||
|
wp_add_inline_style( 'wp-bootstrap-style', $cached_css );
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Read the theme origin palette — this contains the base theme.json
|
// Read the theme origin palette — this contains the base theme.json
|
||||||
// colors merged with the active style variation (if any).
|
// colors merged with the active style variation (if any).
|
||||||
$theme_palette = wp_get_global_settings( array( 'color', 'palette', 'theme' ) );
|
$theme_palette = wp_get_global_settings( array( 'color', 'palette', 'theme' ) );
|
||||||
@@ -205,10 +223,12 @@ if ( ! function_exists( 'wp_bootstrap_variation_colors' ) ) :
|
|||||||
|
|
||||||
// No variation active — let Bootstrap's compiled CSS handle both modes.
|
// No variation active — let Bootstrap's compiled CSS handle both modes.
|
||||||
if ( $is_default ) {
|
if ( $is_default ) {
|
||||||
|
set_transient( $transient_key, '', DAY_IN_SECONDS );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( empty( $colors['base'] ) || empty( $colors['contrast'] ) ) {
|
if ( empty( $colors['base'] ) || empty( $colors['contrast'] ) ) {
|
||||||
|
set_transient( $transient_key, '', DAY_IN_SECONDS );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,6 +300,9 @@ if ( ! function_exists( 'wp_bootstrap_variation_colors' ) ) :
|
|||||||
. '[data-bs-theme=light]{' . $light_css . '}'
|
. '[data-bs-theme=light]{' . $light_css . '}'
|
||||||
. '[data-bs-theme=dark]{' . $dark_css . '}';
|
. '[data-bs-theme=dark]{' . $dark_css . '}';
|
||||||
|
|
||||||
|
// Cache for 24 hours; invalidated on theme switch or global-styles save.
|
||||||
|
set_transient( $transient_key, $css, DAY_IN_SECONDS );
|
||||||
|
|
||||||
// Attach after the compiled stylesheet so variation values override
|
// Attach after the compiled stylesheet so variation values override
|
||||||
// Bootstrap's hardcoded dark-mode defaults via source order.
|
// Bootstrap's hardcoded dark-mode defaults via source order.
|
||||||
wp_add_inline_style( 'wp-bootstrap-style', $css );
|
wp_add_inline_style( 'wp-bootstrap-style', $css );
|
||||||
@@ -287,6 +310,16 @@ if ( ! function_exists( 'wp_bootstrap_variation_colors' ) ) :
|
|||||||
endif;
|
endif;
|
||||||
add_action( 'wp_enqueue_scripts', 'wp_bootstrap_variation_colors', 30 );
|
add_action( 'wp_enqueue_scripts', 'wp_bootstrap_variation_colors', 30 );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidate the color variation CSS transient when global styles or theme change.
|
||||||
|
*/
|
||||||
|
add_action( 'switch_theme', function () {
|
||||||
|
delete_transient( 'wp_bootstrap_variation_css_' . md5( get_stylesheet() ) );
|
||||||
|
} );
|
||||||
|
add_action( 'save_post_wp_global_styles', function () {
|
||||||
|
delete_transient( 'wp_bootstrap_variation_css_' . md5( get_stylesheet() ) );
|
||||||
|
} );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build Bootstrap surface CSS variables for a given background/foreground pair.
|
* Build Bootstrap surface CSS variables for a given background/foreground pair.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ class ContextBuilder
|
|||||||
'layout' => 'default',
|
'layout' => 'default',
|
||||||
'header_variant' => $this->getHeaderVariant(),
|
'header_variant' => $this->getHeaderVariant(),
|
||||||
'footer_variant' => $this->getFooterVariant(),
|
'footer_variant' => $this->getFooterVariant(),
|
||||||
|
'user' => $this->getUserData(),
|
||||||
];
|
];
|
||||||
|
|
||||||
if (is_singular()) {
|
if (is_singular()) {
|
||||||
@@ -93,6 +94,28 @@ class ContextBuilder
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current user data for header/navigation.
|
||||||
|
*/
|
||||||
|
private function getUserData(): array
|
||||||
|
{
|
||||||
|
if (! is_user_logged_in()) {
|
||||||
|
return ['logged_in' => false];
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = wp_get_current_user();
|
||||||
|
$account_url = function_exists('wc_get_page_permalink')
|
||||||
|
? wc_get_page_permalink('myaccount')
|
||||||
|
: admin_url('profile.php');
|
||||||
|
|
||||||
|
return [
|
||||||
|
'logged_in' => true,
|
||||||
|
'display_name' => $user->display_name,
|
||||||
|
'avatar' => get_avatar($user->ID, 32, '', '', ['class' => 'rounded-circle']),
|
||||||
|
'account_url' => $account_url,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get navigation menu items for a location.
|
* Get navigation menu items for a location.
|
||||||
*/
|
*/
|
||||||
@@ -153,7 +176,7 @@ class ContextBuilder
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
'id' => $post->ID,
|
'id' => $post->ID,
|
||||||
'title' => get_the_title(),
|
'title' => wp_specialchars_decode( get_the_title() ),
|
||||||
'url' => get_permalink(),
|
'url' => get_permalink(),
|
||||||
'content' => apply_filters('the_content', get_the_content()),
|
'content' => apply_filters('the_content', get_the_content()),
|
||||||
'excerpt' => get_the_excerpt(),
|
'excerpt' => get_the_excerpt(),
|
||||||
@@ -184,7 +207,7 @@ class ContextBuilder
|
|||||||
$wp_query->the_post();
|
$wp_query->the_post();
|
||||||
$posts[] = [
|
$posts[] = [
|
||||||
'id' => get_the_ID(),
|
'id' => get_the_ID(),
|
||||||
'title' => get_the_title(),
|
'title' => wp_specialchars_decode( get_the_title() ),
|
||||||
'url' => get_permalink(),
|
'url' => get_permalink(),
|
||||||
'excerpt' => get_the_excerpt(),
|
'excerpt' => get_the_excerpt(),
|
||||||
'date' => get_the_date(),
|
'date' => get_the_date(),
|
||||||
@@ -349,14 +372,14 @@ class ContextBuilder
|
|||||||
|
|
||||||
if ($prev) {
|
if ($prev) {
|
||||||
$navigation['previous'] = [
|
$navigation['previous'] = [
|
||||||
'title' => get_the_title($prev),
|
'title' => wp_specialchars_decode( get_the_title($prev) ),
|
||||||
'url' => get_permalink($prev),
|
'url' => get_permalink($prev),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($next) {
|
if ($next) {
|
||||||
$navigation['next'] = [
|
$navigation['next'] = [
|
||||||
'title' => get_the_title($next),
|
'title' => wp_specialchars_decode( get_the_title($next) ),
|
||||||
'url' => get_permalink($next),
|
'url' => get_permalink($next),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -384,7 +407,7 @@ class ContextBuilder
|
|||||||
$query->the_post();
|
$query->the_post();
|
||||||
$posts[] = [
|
$posts[] = [
|
||||||
'id' => get_the_ID(),
|
'id' => get_the_ID(),
|
||||||
'title' => get_the_title(),
|
'title' => wp_specialchars_decode( get_the_title() ),
|
||||||
'url' => get_permalink(),
|
'url' => get_permalink(),
|
||||||
'date' => get_the_date(),
|
'date' => get_the_date(),
|
||||||
'date_iso' => get_the_date('c'),
|
'date_iso' => get_the_date('c'),
|
||||||
@@ -438,7 +461,7 @@ class ContextBuilder
|
|||||||
while ($query->have_posts()) {
|
while ($query->have_posts()) {
|
||||||
$query->the_post();
|
$query->the_post();
|
||||||
$posts[] = [
|
$posts[] = [
|
||||||
'title' => get_the_title(),
|
'title' => wp_specialchars_decode( get_the_title() ),
|
||||||
'url' => get_permalink(),
|
'url' => get_permalink(),
|
||||||
'date' => get_the_date(),
|
'date' => get_the_date(),
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class TwigService
|
|||||||
$this->twig = new Environment($loader, [
|
$this->twig = new Environment($loader, [
|
||||||
'cache' => WP_DEBUG ? false : $cacheDir,
|
'cache' => WP_DEBUG ? false : $cacheDir,
|
||||||
'debug' => WP_DEBUG,
|
'debug' => WP_DEBUG,
|
||||||
'auto_reload' => true,
|
'auto_reload' => WP_DEBUG,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->registerWordPressFunctions();
|
$this->registerWordPressFunctions();
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ Description: A modern WordPress Block Theme built from scratch with Bootstrap 5.
|
|||||||
Requires at least: 6.7
|
Requires at least: 6.7
|
||||||
Tested up to: 6.7
|
Tested up to: 6.7
|
||||||
Requires PHP: 8.3
|
Requires PHP: 8.3
|
||||||
Version: 1.0.8
|
Version: 1.0.12
|
||||||
License: GNU General Public License v2 or later
|
License: GNU General Public License v2 or later
|
||||||
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
||||||
Text Domain: wp-bootstrap
|
Text Domain: wp-bootstrap
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
<a class="wp-bootstrap-skip-link" href="#main-content">{{ __('Skip to main content') }}</a>
|
<a class="wp-bootstrap-skip-link" href="#main-content">{{ __('Skip to main content') }}</a>
|
||||||
|
|
||||||
{% block header %}
|
{% block header %}
|
||||||
{% include 'partials/header.html.twig' %}
|
{% include 'partials/header-offcanvas.html.twig' %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
<main id="main-content" class="{% block main_class %}py-4{% endblock %}">
|
<main id="main-content" class="{% block main_class %}py-4{% endblock %}">
|
||||||
|
|||||||
@@ -15,7 +15,14 @@
|
|||||||
<div class="offcanvas offcanvas-end" tabindex="-1" id="navbarOffcanvas"
|
<div class="offcanvas offcanvas-end" tabindex="-1" id="navbarOffcanvas"
|
||||||
aria-labelledby="navbarOffcanvasLabel">
|
aria-labelledby="navbarOffcanvasLabel">
|
||||||
<div class="offcanvas-header">
|
<div class="offcanvas-header">
|
||||||
|
{% if user.logged_in %}
|
||||||
|
<a href="{{ user.account_url }}" class="d-flex align-items-center text-decoration-none">
|
||||||
|
{{ user.avatar|raw }}
|
||||||
|
<span class="ms-2 fw-semibold">{{ user.display_name|esc_html }}</span>
|
||||||
|
</a>
|
||||||
|
{% else %}
|
||||||
<h5 class="offcanvas-title" id="navbarOffcanvasLabel">{{ site.name }}</h5>
|
<h5 class="offcanvas-title" id="navbarOffcanvasLabel">{{ site.name }}</h5>
|
||||||
|
{% endif %}
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="offcanvas"
|
<button type="button" class="btn-close" data-bs-dismiss="offcanvas"
|
||||||
aria-label="{{ __('Close') }}"></button>
|
aria-label="{{ __('Close') }}"></button>
|
||||||
</div>
|
</div>
|
||||||
@@ -54,12 +61,19 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
</div>
|
||||||
{% if dark_mode %}
|
{% if dark_mode %}
|
||||||
|
<div class="offcanvas-footer d-lg-none border-top p-3">
|
||||||
{% include 'partials/dark-mode-toggle.html.twig' %}
|
{% include 'partials/dark-mode-toggle.html.twig' %}
|
||||||
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{%- if dark_mode %}
|
||||||
|
<div class="d-none d-lg-block ms-2">
|
||||||
|
{% include 'partials/dark-mode-toggle.html.twig' %}
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
|
|||||||
Reference in New Issue
Block a user