Официальный сайт SLAED CMS
Query controls move into a single-row .sl-search-panel; results render as a divider list (.sl-search-line) with breadcrumb, title, clamped snippet and meta chips. Adds fragments/search-form.html and a demo/ reference page.
One H1 per page: page/module titles render H1, de-polluted pager/footer/ sidebar/related/category headings down to their proper level, and view sub-headings normalized. Heading sizes tokenized (--sl-h1..--sl-h4 in base.css) with framework classes wired to them in theme.css; getModuleNavi gains an is_heading flag so view pages do not emit a second H1.
home.html and app.html were ~98% duplicate; the common chrome moves into partials/site-header.html and partials/site-footer.html, slimming both layouts to include stubs. Footer/admin home links point at "/" instead of "index.php"; app.html marks the content region with a <main> landmark.
Portable, PHP-level redirects in core/security.php (proxy-aware via X-Forwarded-Proto, GET-only, default off):
- bare /index.php -> / (301) to kill the duplicate homepage URL
- opt-in forcessl (http->https) and forcehost (www->canonical homeurl host)
Admin config SEO tab gains forcessl/forcehost toggles (constants in all 6 languages); getPublicUrl() returns root with trailing slash; help doc admin/info/config/ru.md documents canonical behavior and the new toggles.
Rename the Magistral webfont from Magistral-Book.woff2 to magistral.woff2 and update the @font-face src plus the PERFORMANCE.md caching example to match. Same binary, lowercase/simpler name.
Core changes:
- Font asset (templates/lite/assets/css):
- Rename fonts/Magistral-Book.woff2 to fonts/magistral.woff2
- base.css @font-face src updated to fonts/magistral.woff2
- Docs (docs/PERFORMANCE.md):
- Update font caching-caveat example to magistral.woff2
Technical notes:
- Byte-identical file (26808 bytes); no remaining refs to old name
Move hardcoded & and hand-built HTMX markup out of PHP: URL producers now pass a raw & URL as data, and fragments escape it once at the output boundary via {{ }}. Removes the last inconsistency where URL-bearing HTMX attributes still followed the legacy escape-at-source + markup-in-PHP pattern.
Core changes:
- Link/tab/button fragments (templates/{lite,admin}/fragments):
- tabs-link.html: add hx_get/hx_target/hx_swap block, URL escaped via {{ }}
button.html: add hx-post block (hx_post/hx_include/hx_target/hx_swap/ hx_on_click/hx_on_after), URL escaped; JS validation stays raw passthrough
- link fragment already had is_htmx (hx-get="{{ href }}") — reused as-is
- PHP producers now emit data, not markup:
- core/admin.php: upload file links use is_htmx + hx_target (drops & blob)
- admin/modules/uploads.php: upload tabs pass raw hx_get/hx_target
- core/user.php: comment/PM submit forms pass raw hx_post + hx_* fields
- Docs:
- Remove docs/PROMPT_HREF_AMPERSAND.md (task complete)
Benefits:
- Single escape at the sink; &amp; structurally impossible
- Unified hx_* field vocabulary across link/tabs-link/button fragments
- Removes duplicated URL (href + hand-built hx-get) in upload links
Technical notes:
- getSafe() = htmlspecialchars(ENT_QUOTES|ENT_SUBSTITUTE, UTF-8)
- Verified live: comment form, admin upload tabs — single &, zero &amp;
- Additive change; legacy link_attr/input_attr passthrough kept for other uses
Track the Magistral-Book.woff2 asset referenced by the base.css @font-face declaration, completing the font migration whose base.css update and legacy WOFF2 removal landed in the previous commit.
URLs are now treated as data: every producer emits a raw & and the template layer escapes exactly once at the output boundary via {{ href }}. This removes the previous mix of producer-side & encoding and raw {{{ }}} output and eliminates latent single/double-escape inconsistencies across the site.
Core changes:
- URL producers to raw & (blocks, modules, admin/modules, core):
- Front-end SEO links built via getSeoUrl() (raw &, SEO-friendly URLs under rewrite)
- Admin afile.php?..., htmx go=...&op=... tails, absolute/redirect URLs to raw &
- getQueryString() always emits raw & (dropped the obsolete $html parameter)
- Template output boundaries (81 flips, lite + admin fragments/partials):
- href/src/action/hx-get/hx-post URL attributes: {{{ x }}} to {{ x }}
- Kept raw ({{{ }}}): _html and _attr blobs, inline-JS onclick (reset_url, reload_query)
- Removed runtime URL pre-encoders exposed by the boundary flip:
$alink session-monitor URL, RSS source href, and files-admin download href no longer wrapped in htmlspecialchars() (the boundary now escapes)
- domain() html_entity_decode()s stored referer URLs before building the link
Benefits:
- Single source of truth for escaping; no more &amp; risk
- Redirects/Location and htmx keep a raw &; HTML output is uniformly &
- Blocks now honor rewrite / SEO-friendly URLs like the modules do
Technical notes:
Left untouched: parser entity decoders, config/* content cache, setup legacy HTML echoes, sitemap XML content encoder
Pre-existing/out-of-scope: _referer stores double-encoded anchor data; config.replace link URLs are stored with a bare &
Verified: php -l (85 files), phpunit 8/8, guest + admin real-HTTP render with zero app-generated &amp;
Remove legacy raster icons from the admin and lite themes in favour of Bootstrap Icons, add the bootstrap-icon fragment, and normalize admin and module handlers, config, and styles across the board.
Add the breadcrumb variant galleries under demo/ and a task prompt for the site-wide URL escaping migration (escape at the HTML output boundary, keep getSeoUrl raw).