You've already forked wp-bootstrap
v0.1.1 - Bootstrap frontend rendering via Twig templates
Replace FSE block markup on the frontend with proper Bootstrap 5 HTML rendered through Twig templates. The Site Editor remains functional for admin editing while the public site outputs Bootstrap navbar, cards, pagination, grid layout, and responsive components. New PHP classes: TemplateController, ContextBuilder, NavWalker New Twig templates: 20 files (base, pages, partials, components) Enhanced TwigService with WordPress functions and globals Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
39
views/partials/comment-item.html.twig
Normal file
39
views/partials/comment-item.html.twig
Normal file
@@ -0,0 +1,39 @@
|
||||
<div class="comment d-flex gap-3 mb-4{% if depth > 0 %} ms-5{% endif %}" id="comment-{{ comment.id }}">
|
||||
<div class="flex-shrink-0">
|
||||
<img src="{{ comment.avatar_url }}" alt="{{ comment.author }}"
|
||||
class="rounded-circle" width="40" height="40">
|
||||
</div>
|
||||
<div class="flex-grow-1">
|
||||
<div class="d-flex align-items-center gap-2 mb-1">
|
||||
<strong class="small">
|
||||
{% if comment.author_url %}
|
||||
<a href="{{ comment.author_url }}" class="text-decoration-none text-body" rel="nofollow">
|
||||
{{ comment.author }}
|
||||
</a>
|
||||
{% else %}
|
||||
{{ comment.author }}
|
||||
{% endif %}
|
||||
</strong>
|
||||
<time class="text-body-secondary small" datetime="{{ comment.date_iso }}">
|
||||
{{ comment.date }}
|
||||
</time>
|
||||
{% if comment.edit_url %}
|
||||
<a href="{{ comment.edit_url }}" class="text-body-secondary small">{{ __('Edit') }}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="comment-content small">
|
||||
{{ comment.content|raw }}
|
||||
</div>
|
||||
{% if comment.reply_url %}
|
||||
<div class="mt-1">
|
||||
{{ comment.reply_url|raw }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if comment.children|length > 0 %}
|
||||
{% for child in comment.children %}
|
||||
{% include 'partials/comment-item.html.twig' with {'comment': child, 'depth': depth + 1} only %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
19
views/partials/comments.html.twig
Normal file
19
views/partials/comments.html.twig
Normal file
@@ -0,0 +1,19 @@
|
||||
{% if comments is defined and (comments.is_open or comments.count > 0) %}
|
||||
<section class="comments-section border-top pt-5 mt-5" id="comments">
|
||||
<h2 class="h4 mb-4">{{ comments.title }}</h2>
|
||||
|
||||
{% if comments.list|length > 0 %}
|
||||
<div class="comment-list mb-4">
|
||||
{% for comment in comments.list %}
|
||||
{% include 'partials/comment-item.html.twig' with {'comment': comment, 'depth': 0} only %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if comments.is_open %}
|
||||
<div class="comment-form mt-4">
|
||||
{{ comments.form|raw }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</section>
|
||||
{% endif %}
|
||||
21
views/partials/dark-mode-toggle.html.twig
Normal file
21
views/partials/dark-mode-toggle.html.twig
Normal file
@@ -0,0 +1,21 @@
|
||||
<button type="button" class="wp-bootstrap-dark-mode-toggle ms-2"
|
||||
data-bs-theme-toggle
|
||||
aria-label="{{ __('Switch to dark mode') }}"
|
||||
data-label-dark="{{ __('Switch to dark mode') }}"
|
||||
data-label-light="{{ __('Switch to light mode') }}"
|
||||
aria-pressed="false">
|
||||
<svg class="wp-bootstrap-sun-icon" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:none;" aria-hidden="true">
|
||||
<circle cx="12" cy="12" r="5"/>
|
||||
<line x1="12" y1="1" x2="12" y2="3"/>
|
||||
<line x1="12" y1="21" x2="12" y2="23"/>
|
||||
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/>
|
||||
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/>
|
||||
<line x1="1" y1="12" x2="3" y2="12"/>
|
||||
<line x1="21" y1="12" x2="23" y2="12"/>
|
||||
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/>
|
||||
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/>
|
||||
</svg>
|
||||
<svg class="wp-bootstrap-moon-icon" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
|
||||
</svg>
|
||||
</button>
|
||||
34
views/partials/footer.html.twig
Normal file
34
views/partials/footer.html.twig
Normal file
@@ -0,0 +1,34 @@
|
||||
<footer class="bg-body-tertiary mt-auto">
|
||||
<div class="container py-5">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h5 class="fw-bold">{{ site.name }}</h5>
|
||||
<p class="text-body-secondary">{{ site.description }}</p>
|
||||
</div>
|
||||
<div class="col-md-6 text-md-end">
|
||||
{% if footer_menu|length > 0 %}
|
||||
<ul class="list-unstyled">
|
||||
{% for item in footer_menu %}
|
||||
<li>
|
||||
<a href="{{ item.url }}" class="text-body-secondary text-decoration-none">
|
||||
{{ item.title }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row align-items-center">
|
||||
<div class="col-md-6">
|
||||
<p class="text-body-secondary small mb-0">© {{ current_year }} {{ site.name }}</p>
|
||||
</div>
|
||||
<div class="col-md-6 text-md-end">
|
||||
<p class="text-body-secondary small mb-0">
|
||||
{{ __('Powered by %s')|format('<a href="https://wordpress.org" rel="nofollow" class="text-body-secondary">WordPress</a>')|raw }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
56
views/partials/header.html.twig
Normal file
56
views/partials/header.html.twig
Normal file
@@ -0,0 +1,56 @@
|
||||
<header>
|
||||
<nav class="navbar navbar-expand-lg bg-body-tertiary">
|
||||
<div class="container">
|
||||
<a class="navbar-brand fw-bold" href="{{ site.url }}">
|
||||
{{ site.name }}
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button"
|
||||
data-bs-toggle="collapse" data-bs-target="#navbarMain"
|
||||
aria-controls="navbarMain" aria-expanded="false"
|
||||
aria-label="{{ __('Toggle navigation') }}">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarMain">
|
||||
<ul class="navbar-nav ms-auto mb-2 mb-lg-0">
|
||||
{% for item in menu %}
|
||||
{% if item.children|length > 0 %}
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle{{ item.active ? ' active' : '' }}"
|
||||
href="{{ item.url }}" role="button"
|
||||
data-bs-toggle="dropdown" aria-expanded="false">
|
||||
{{ item.title }}
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
{% for child in item.children %}
|
||||
<li>
|
||||
<a class="dropdown-item{{ child.active ? ' active' : '' }}"
|
||||
href="{{ child.url }}"
|
||||
{% if child.target %}target="{{ child.target }}"{% endif %}>
|
||||
{{ child.title }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link{{ item.active ? ' active' : '' }}"
|
||||
href="{{ item.url }}"
|
||||
{% if item.active %}aria-current="page"{% endif %}
|
||||
{% if item.target %}target="{{ item.target }}"{% endif %}>
|
||||
{{ item.title }}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
{% if dark_mode %}
|
||||
{% include 'partials/dark-mode-toggle.html.twig' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
11
views/partials/meta.html.twig
Normal file
11
views/partials/meta.html.twig
Normal file
@@ -0,0 +1,11 @@
|
||||
<div class="text-body-secondary small mb-3">
|
||||
<time datetime="{{ post.date_iso }}">{{ post.date }}</time>
|
||||
<span class="mx-1">·</span>
|
||||
<a href="{{ post.author.url }}" class="text-body-secondary text-decoration-none">{{ post.author.name }}</a>
|
||||
{% if post.categories is defined and post.categories|length > 0 %}
|
||||
<span class="mx-1">·</span>
|
||||
{% for cat in post.categories %}
|
||||
<a href="{{ cat.url }}" class="text-body-secondary text-decoration-none">{{ cat.name }}</a>{% if not loop.last %}, {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
26
views/partials/pagination.html.twig
Normal file
26
views/partials/pagination.html.twig
Normal file
@@ -0,0 +1,26 @@
|
||||
{% if pagination and pagination.pages is defined and pagination.pages|length > 1 %}
|
||||
<nav aria-label="{{ __('Page navigation') }}" class="my-5">
|
||||
<ul class="pagination justify-content-center">
|
||||
<li class="page-item{{ pagination.prev_url is null ? ' disabled' : '' }}">
|
||||
<a class="page-link" href="{{ pagination.prev_url ?? '#' }}"
|
||||
{% if pagination.prev_url is null %}tabindex="-1" aria-disabled="true"{% endif %}>
|
||||
{{ pagination.prev_text }}
|
||||
</a>
|
||||
</li>
|
||||
{% for page in pagination.pages %}
|
||||
<li class="page-item{{ page.is_current ? ' active' : '' }}">
|
||||
<a class="page-link" href="{{ page.url }}"
|
||||
{% if page.is_current %}aria-current="page"{% endif %}>
|
||||
{{ page.number }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
<li class="page-item{{ pagination.next_url is null ? ' disabled' : '' }}">
|
||||
<a class="page-link" href="{{ pagination.next_url ?? '#' }}"
|
||||
{% if pagination.next_url is null %}tabindex="-1" aria-disabled="true"{% endif %}>
|
||||
{{ pagination.next_text }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
{% endif %}
|
||||
22
views/partials/post-navigation.html.twig
Normal file
22
views/partials/post-navigation.html.twig
Normal file
@@ -0,0 +1,22 @@
|
||||
{% if post_navigation is defined and post_navigation|length > 0 %}
|
||||
<nav class="border-top border-bottom py-4 my-4" aria-label="{{ __('Post navigation') }}">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
{% if post_navigation.previous is defined %}
|
||||
<small class="text-body-secondary d-block mb-1">{{ __('Previous') }}</small>
|
||||
<a href="{{ post_navigation.previous.url }}" class="text-decoration-none">
|
||||
← {{ post_navigation.previous.title }}
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-6 text-end">
|
||||
{% if post_navigation.next is defined %}
|
||||
<small class="text-body-secondary d-block mb-1">{{ __('Next') }}</small>
|
||||
<a href="{{ post_navigation.next.url }}" class="text-decoration-none">
|
||||
{{ post_navigation.next.title }} →
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
{% endif %}
|
||||
11
views/partials/search-form.html.twig
Normal file
11
views/partials/search-form.html.twig
Normal file
@@ -0,0 +1,11 @@
|
||||
<form role="search" method="get" action="{{ site.url }}" class="mb-4">
|
||||
<div class="input-group">
|
||||
<input type="search" class="form-control" name="s"
|
||||
placeholder="{{ __('Search...') }}"
|
||||
value="{{ search_query is defined ? search_query : '' }}"
|
||||
aria-label="{{ __('Search') }}">
|
||||
<button class="btn btn-primary" type="submit">
|
||||
{{ __('Search') }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
44
views/partials/sidebar.html.twig
Normal file
44
views/partials/sidebar.html.twig
Normal file
@@ -0,0 +1,44 @@
|
||||
<aside>
|
||||
{% if sidebar.recent_posts is defined and sidebar.recent_posts|length > 0 %}
|
||||
<div class="mb-4">
|
||||
<h3 class="h6 text-uppercase fw-semibold" style="letter-spacing: 1.6px">
|
||||
{{ __('Recent Posts') }}
|
||||
</h3>
|
||||
<ul class="list-unstyled">
|
||||
{% for post in sidebar.recent_posts %}
|
||||
<li class="mb-2">
|
||||
<a href="{{ post.url }}" class="text-decoration-none">{{ post.title }}</a>
|
||||
<br>
|
||||
<small class="text-body-secondary">{{ post.date }}</small>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
{% endif %}
|
||||
|
||||
<div class="mb-4">
|
||||
<h3 class="h6 text-uppercase fw-semibold" style="letter-spacing: 1.6px">
|
||||
{{ __('Search') }}
|
||||
</h3>
|
||||
{% include 'partials/search-form.html.twig' %}
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
{% if sidebar.tags is defined and sidebar.tags|length > 0 %}
|
||||
<div class="mb-4">
|
||||
<h3 class="h6 text-uppercase fw-semibold" style="letter-spacing: 1.6px">
|
||||
{{ __('Tags') }}
|
||||
</h3>
|
||||
<div>
|
||||
{% for tag in sidebar.tags %}
|
||||
<a href="{{ tag.url }}" class="badge bg-secondary text-decoration-none me-1 mb-1">
|
||||
{{ tag.name }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</aside>
|
||||
Reference in New Issue
Block a user