v2.5.1: Admin theme refactor, Navigation plugin, user roles, guide restructure
- Reorganize admin into admin/theme/default/ (views + assets) - Rename GuideNav to Navigation plugin (essential, protected) - Plugin assets support (SCSS/CSS) loaded after theme CSS - User roles: Admin, Content Manager, BI Manager, Site Admin - Role-based access control (RBAC) for admin routes and sidebar - Guide restructure: sub-topics in separate folders with sidebar nav - Dynamic breadcrumb for homepage and subdirectories - Fix theme path traversal (../../ -> ../) in admin.php - Fix CodeMirror mode load order (xml -> css -> js -> htmlmixed -> php) - Fix editor-toolbar.js null checks for plugin edit pages - Layout select from theme.json with live frontmatter update - Footer sticky at bottom of viewport (min-height: 100vh) - Breadcrumb color fix (var(--nav-font) -> var(--header-bg)) - Remove language switcher from guide pages - Update README.md and README.en.md - Bump version to 2.5.1
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
# Layouts
|
||||
|
||||
## Choosing a layout in content
|
||||
|
||||
```markdown
|
||||
---
|
||||
layout: left_sidebar
|
||||
---
|
||||
|
||||
# Page title
|
||||
|
||||
Content...
|
||||
```
|
||||
|
||||
## Layouts in theme.json
|
||||
|
||||
```json
|
||||
{
|
||||
"default_layout": "full_content",
|
||||
"layouts": {
|
||||
"full_content": "full_content.twig",
|
||||
"left_sidebar": "left_sidebar.twig",
|
||||
"right_sidebar": "right_sidebar.twig",
|
||||
"custom1": "custom1.twig"
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,25 @@
|
||||
# Creating a new theme
|
||||
|
||||
## Via Admin
|
||||
|
||||
1. Go to **Theme** → **New theme**
|
||||
2. Enter a name (e.g. `my-theme`)
|
||||
3. Theme is created with basic structure
|
||||
4. Edit `theme.json` and templates
|
||||
|
||||
## Manually
|
||||
|
||||
```bash
|
||||
mkdir themes/my-theme
|
||||
mkdir themes/my-theme/partials
|
||||
mkdir themes/my-theme/assets/{scss,css,js,fonts,img}
|
||||
```
|
||||
|
||||
Create basic files:
|
||||
|
||||
- `theme.json`
|
||||
- `base.twig`
|
||||
- `full_content.twig`
|
||||
- `partials/header.twig`
|
||||
- `partials/footer.twig`
|
||||
- `scss/theme.scss`
|
||||
@@ -0,0 +1,24 @@
|
||||
# SCSS styling
|
||||
|
||||
## Compiling theme.scss
|
||||
|
||||
1. Go to **Admin** → **Theme**
|
||||
2. Click **Compile SCSS** for your theme
|
||||
3. CSS is generated in `assets/css/theme.css`
|
||||
|
||||
## SCSS example
|
||||
|
||||
```scss
|
||||
$primary-color: #0a369d;
|
||||
$font-stack: Helvetica, Arial, sans-serif;
|
||||
|
||||
body {
|
||||
font-family: $font-stack;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.header {
|
||||
background: $primary-color;
|
||||
color: #fff;
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,21 @@
|
||||
# Theme structure
|
||||
|
||||
```
|
||||
themes/my-theme/
|
||||
├── theme.json # Theme configuration
|
||||
├── base.twig # Main layout
|
||||
├── full_content.twig # Layout: full-width
|
||||
├── left_sidebar.twig # Layout: left sidebar
|
||||
├── right_sidebar.twig # Layout: right sidebar
|
||||
├── custom.twig # Layout: custom
|
||||
├── partials/
|
||||
│ ├── header.twig
|
||||
│ ├── navigation.twig
|
||||
│ └── footer.twig
|
||||
└── assets/
|
||||
├── scss/theme.scss # SCSS source
|
||||
├── css/ # CSS files
|
||||
├── js/theme.js # JavaScript
|
||||
├── fonts/ # Fonts
|
||||
└── img/ # Images
|
||||
```
|
||||
@@ -0,0 +1,21 @@
|
||||
# theme.json
|
||||
|
||||
```json
|
||||
{
|
||||
"title": "My Theme",
|
||||
"default_layout": "full_content",
|
||||
"header_color": "#0a369d",
|
||||
"layouts": {
|
||||
"full_content": "full_content.twig",
|
||||
"left_sidebar": "left_sidebar.twig",
|
||||
"right_sidebar": "right_sidebar.twig"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Fields
|
||||
|
||||
- `title` - Display name in admin
|
||||
- `default_layout` - Default layout for new pages
|
||||
- `header_color` - Admin sidebar color
|
||||
- `layouts` - Mapping of layout names to .twig files
|
||||
@@ -0,0 +1,206 @@
|
||||
# Twig templates
|
||||
|
||||
## Basic syntax
|
||||
|
||||
```twig
|
||||
{# Comment #}
|
||||
{{ variable }}
|
||||
{{ variable|default('default') }}
|
||||
{% if condition %}...{% endif %}
|
||||
{% for item in items %}...{% endfor %}
|
||||
{% extends 'base.twig' %}
|
||||
{% block content %}{% endblock %}
|
||||
{% include 'partials/header.twig' %}
|
||||
```
|
||||
|
||||
## base.twig example
|
||||
|
||||
```twig
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ current_lang }}">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>{{ page_title }} - {{ site_title }}</title>
|
||||
<meta name="description" content="{{ seo_description }}">
|
||||
<link rel="stylesheet" href="{{ theme_css_url }}">
|
||||
</head>
|
||||
<body>
|
||||
{% include 'partials/header.twig' %}
|
||||
|
||||
{% block content %}{% endblock %}
|
||||
|
||||
{% include 'partials/footer.twig' %}
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
## Variables available in templates
|
||||
|
||||
### Page data
|
||||
|
||||
| Variable | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `page_title` | string | Current page title (HTML-escaped) |
|
||||
| `content` | string | Rendered page content (HTML) |
|
||||
| `page_metadata` | array | Frontmatter metadata of the page |
|
||||
| `layout` | string | Layout name (e.g. `full_content`) |
|
||||
| `sidebar_content` | string | Sidebar content from plugins (HTML) |
|
||||
| `breadcrumb` | string | Breadcrumb HTML (generated by CMS) |
|
||||
|
||||
### Site data
|
||||
|
||||
| Variable | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `site_title` | string | Site title from config.json |
|
||||
| `default_page` | string | Default page path |
|
||||
| `homepage` | string | Homepage path |
|
||||
| `homepage_title` | string | Homepage title |
|
||||
| `is_homepage` | bool | Whether current page is the homepage |
|
||||
| `is_guide_page` | bool | Whether current page is a guide page |
|
||||
| `has_content` | bool | Whether content directory is not empty |
|
||||
| `cms_version` | string | CMS version number |
|
||||
|
||||
### Menu & Navigation
|
||||
|
||||
| Variable | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `menu` | string | Rendered menu HTML |
|
||||
| `current_page` | string | Current page path |
|
||||
| `breadcrumb` | string | Breadcrumb HTML |
|
||||
|
||||
### Language
|
||||
|
||||
| Variable | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `current_lang` | string | Current language code (e.g. `nl`) |
|
||||
| `current_lang_upper` | string | Current language in uppercase |
|
||||
| `available_langs` | array | Available languages with `code`, `name`, `url`, `is_current` |
|
||||
|
||||
### SEO
|
||||
|
||||
| Variable | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `seo_description` | string | SEO description |
|
||||
| `seo_keywords` | string | SEO keywords |
|
||||
| `block_ai_bots` | bool | Block AI bots |
|
||||
| `block_search_engines` | bool | Block search engines |
|
||||
|
||||
### Author
|
||||
|
||||
| Variable | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `author_name` | string | Author name |
|
||||
| `author_website` | string | Author website URL |
|
||||
| `author_git` | string | Author Git URL |
|
||||
|
||||
### Theme
|
||||
|
||||
| Variable | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `theme_title` | string | Theme title |
|
||||
| `theme_css_url` | string | Compiled CSS URL |
|
||||
| `theme_js_url` | string | JavaScript URL |
|
||||
| `theme_config` | array | Theme configuration from theme.json |
|
||||
| `theme_base_url` | string | Theme base URL (e.g. `/themes/default`) |
|
||||
| `theme_css_files` | array | List of CSS files |
|
||||
| `theme_js_files` | array | List of JS files |
|
||||
| `theme_favicon` | string | Favicon URL |
|
||||
| `plugin_css_urls` | array | CSS URLs from plugins (loaded after theme CSS) |
|
||||
|
||||
### Theme colors
|
||||
|
||||
| Variable | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `header_color` | string | Header background color |
|
||||
| `header_font_color` | string | Header text color |
|
||||
| `header_height` | string | Header height in px |
|
||||
| `navigation_color` | string | Navigation background color |
|
||||
| `navigation_font_color` | string | Navigation text color |
|
||||
| `nav_height` | string | Navigation height in px |
|
||||
| `sidebar_background` | string | Sidebar background color |
|
||||
| `sidebar_border` | string | Sidebar border color |
|
||||
|
||||
### File info
|
||||
|
||||
| Variable | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `created` | string | File creation date |
|
||||
| `modified` | string | File modification date |
|
||||
| `show_created` | bool | Whether to show creation date |
|
||||
| `file_info_block` | bool | Whether to show file info block |
|
||||
|
||||
### Translations
|
||||
|
||||
| Variable | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `t_home` | string | "Home" translation |
|
||||
| `t_search` | string | "Search" translation |
|
||||
| `t_search_placeholder` | string | Search placeholder translation |
|
||||
| `t_search_button` | string | Search button translation |
|
||||
| `t_welcome` | string | "Welcome" translation |
|
||||
| `t_created` | string | "Created" translation |
|
||||
| `t_modified` | string | "Modified" translation |
|
||||
| `t_author` | string | "Author" translation |
|
||||
| `t_manual` | string | "Manual" translation |
|
||||
| `t_guide` | string | "Guide" translation |
|
||||
| `t_no_content` | string | "No content" translation |
|
||||
| `t_no_results` | string | "No results" translation |
|
||||
| `t_results_found` | string | "Results found" translation |
|
||||
| `t_powered_by` | string | "Powered by" translation |
|
||||
| `t_page_not_found` | string | "Page not found" translation |
|
||||
| `t_page_not_found_text` | string | "Page not found" text translation |
|
||||
| `t_mappen` | string | "Folders" translation |
|
||||
| `t_paginas` | string | "Pages" translation |
|
||||
|
||||
## Layouts and blocks
|
||||
|
||||
A layout template extends `base.twig` and fills the `content` block:
|
||||
|
||||
```twig
|
||||
{% extends 'base.twig' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
{{ content|raw }}
|
||||
</div>
|
||||
{% endblock %}
|
||||
```
|
||||
|
||||
## Conditional sidebar
|
||||
|
||||
```twig
|
||||
{% if sidebar_content %}
|
||||
<div class="row">
|
||||
<aside class="col-md-4">
|
||||
{{ sidebar_content|raw }}
|
||||
</aside>
|
||||
<main class="col-md-8">
|
||||
{{ content|raw }}
|
||||
</main>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="container">
|
||||
{{ content|raw }}
|
||||
</div>
|
||||
{% endif %}
|
||||
```
|
||||
|
||||
## Language switcher
|
||||
|
||||
```twig
|
||||
{% for lang in available_langs %}
|
||||
<a href="{{ lang.url }}" class="{{ lang.is_current ? 'active' : '' }}">
|
||||
{{ lang.name }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
```
|
||||
|
||||
## Plugin CSS loading
|
||||
|
||||
Plugin CSS is automatically loaded after theme CSS, so themes can override plugin styling:
|
||||
|
||||
```twig
|
||||
{% for cssUrl in plugin_css_urls|default([]) %}
|
||||
<link href="{{ cssUrl }}" rel="stylesheet">
|
||||
{% endfor %}
|
||||
```
|
||||
Reference in New Issue
Block a user