Журнал изменений

Официальный сайт SLAED CMS

Журнал изменений

Фильтр и поиск

Всего: 1148 Доступных коммитов | Отфильтровано: 1148 Коммиты | Страница: 1 / 115
Сегодня (28.08.2026)
Feature: the settings page becomes one page, and the password stops shouting itself
Автор: Eduard Laas | Дата: 12:02 28.08.2026

The account settings page stopped being four tabs hiding four independent POST endpoints and became one form saved by one button, with the password form and the OAuth unlink buttons standing beside it as siblings. On the way the password handler lost a CSRF gate that checked nothing, stopped mailing the new password in clear text and stopped logging the member out of an account whose password had just changed.

Core changes:

  1. Password handling (modules/account/index.php):
  2. savepass() gates on the token check it already performed

    • checkSiteToken() wrote into $stop and the function never read it, so a forged
token changed the password
  • The UPDATE became the only gate: nothing happens before it succeeds

    • the mail was queued and the result of the write was never read, so a failed
write still announced a successful change
  • The session survives the change

    • the account cookie carries the password hash, so the new hash is written into
it with the same six-element shape savehome() uses, and the member returns to
the settings page instead of the login form
  • The mail no longer carries the password

    • _PASSESEND lost its fourth argument and every locale renumbered its
positional placeholders
  • The three password fields became type="password" with autocomplete
  • One form and one handler (modules/account/index.php):
  • edithome() builds one form-add carrying the profile, the avatar and the presets

    • getNaviTabs() left the function: the password form and the unlink buttons live
inside tab panels, and wrapping the tabs in a form would nest one form in
another, which the parser drops silently
  • The preset gallery stopped being 127 forms and became one radio field

    • the page carries one token instead of 128, and every thumbnail is lazy
  • savehome() took over the avatar with three explicit branches

    • a preset, a file that was offered at all, or neither
    • neither is UPLOAD_ERR_NO_FILE alone, so an ordinary save with no file attached
no longer tells the member a file was not selected
  • a rejected upload does not roll back the profile
  • saveavatar() and its route are gone
  • Each $stop entry carries the section it belongs to
  • Radio group helper (core/helpers.php):
  • getTplRadioGroup() forwards label_html, which fragments/radio.html already supported, so an option can be labelled by an image

  • Upload adapter contract (tests/Unit/UploadIntegrationTest.php):
  • The account adapter is savehome(), the handler that now publishes

Benefits:

  • A forged token can no longer change a password
  • A password is no longer sent by mail in clear text
  • Changing the password no longer ends the session
  • One POST and one token instead of four endpoints and 128 tokens
  • 127 lazy thumbnails instead of 127 eager ones inside 127 forms

Technical notes:

  • The screenshot manifest gained the settings route, which it never covered
  • The avatar is written by its own UPDATE, never folded into the profile write
  • _PASSTEXT no longer promises a dropped session; rewritten in all six locales
  • No schema change, no route change apart from the removed op=saveavatar
  • Breaking change: op=saveavatar is gone; the avatar now travels with op=savehome
Вчера (27.08.2026)
Refactor: a form row says what it is, and the read-only pair stops pretending to be one
Автор: Eduard Laas | Дата: 22:37 27.08.2026

The field standard tied captions to controls but left four kinds of row unnamed: a radio group, an editor and a hint carried no accessible name at all, and the value row was a label labelling nothing. One helper now owns the three ids a row needs, every group, editor and hint is tied to what belongs to it, and a row folds on the box it stands in rather than on the window.

Core changes:

  1. Field identity (core/helpers.php):
  2. getFieldIds() answers the control, caption and hint ids of one row

    • The id is taken and never derived from the field name: this tree writes ids by hand and the mapping is no rule
    • Only a row whose field has no labelable control mints one, from the seed the caller names and a per-request counter
  3. getTplRadioGroup(), getTplTextarea(), getTplModuleSelect() and getTplRefreshTimeSelect() carry a caption id and a hint id down
  4. getTplAddFieldRows() gives its dynamic controls an id and the row a for
  5. Row markup (templates/*/fragments/div-row.html, label.html, form-field-row.html):
  6. hint_html, hint_id and label_id are row keys; the hint leaves the label element and keeps its cell

    • A caption that swallowed the hint read the explanation out as the name of the field
  7. label-hint.html is gone and its 98 call sites carry caption and hint apart
  8. lite renders a span where a row has no for, instead of a label labelling nothing
  9. Radio groups (core/helpers.php, block-content.html, partials/div.html):
  10. Every .sl-radio-group carries role="group" and aria-labelledby to its own caption
  11. The switch variant and the checkbox lists built through the div partial take the same two attributes
  12. Editors (core/classes/editor.php, plugins/editors/*/driver.php):
  13. Editor::getNameData() settles the name once, so four drivers cannot answer it four ways

    • A caption is pointed at; a row without one is named by its own text
  14. plain writes the name onto its textarea; toastui and ckeditor onto the mount, and their JS moves it to the element holding role="textbox"
  15. TinyMCE takes aria-label only: its editable body is a second document and an IDREF does not cross that boundary
  16. EditorPlain::getWidget() uses the declared fragment keys instead of a hand-built attribute string
  17. Hints (core/admin.php, admin/modules/.php, modules//admin/index.php):
  18. aria-describedby ties every hint to the control, or to the group, of its own row
  19. catacess() and getMailRow() learned to take an id, so the rows they build can be pointed at
  20. Read-only value row (templates/*/fragments/field-value.html, assets/css/theme.css):
  21. Own vocabulary: .sl-value-row, .sl-value-label, .sl-value-text, and the caption is a span
  22. The panel row gains the fold it never had; .sl-form-* now means the editable row and nothing else
  23. Container fold (templates/*/assets/css/theme.css):
  24. A grid nested in another row's field cell folds unconditionally: measured 496 to 816px at the four rig widths, it never has room for two columns
  25. .sl-oauth-form and .sl-pmf-reply declare a container, so a card in a minmax(280px, 1fr) column and a composer in a split pane fold while the window is wide
  26. The crawl and its baseline (tools/label-audit.mjs, tools/label-audit-baseline.json):
  27. npm run ui:label walks the panel, the site as a member and the site as a guest, and asks of every rendered document what no count in a file can ask
  28. 417 baseline entries fell to 20: what remains is 15 duplicate ids, four codemirror editors and one for that reaches no labelable element, each recorded on purpose

Benefits:

  • A screen reader announces the question a radio group answers, the caption an editor carries and the sentence that explains a field, none of which it could before
  • One owner for the three ids of a row, so a caption, a group and a hint cannot disagree about the name that joins them
  • The panel value row folds on a phone instead of holding a 160px caption column down to it
  • A form row in a narrow box reads the box, so the OAuth card stops drawing two columns in 342px

Technical notes:

  • fragments/label-hint.html is removed. A theme package outside this repository that renders it must move to the hint_html row key
  • getMailRow() in admin/modules/config.php takes the id triple as its fifth argument; catacess() and getTplModuleSelect() gained optional id and description arguments and stay compatible with every existing call
  • --sl-form-label-width keeps its name although the rule it serves was renamed: the admin API block is frozen and a distributed theme reads that name
  • No count reported by tools/ui-audit.php moved; tools/ui-contrast.json was regenerated from the final tree
  • docs/FORM-FIELDS-2026.md is deleted, and what outlives it is in docs/TEMPLATES.md under Form Row Contract and Label crawl
Feature: the design stand grows two more series
Автор: Eduard Laas | Дата: 01:27 27.08.2026

The stand carried one series, the presentation page. It now carries three: the account settings section and the file upload form join it, each drawn as whole pages in the real site shell rather than as descriptions of an idea.

Core changes:

  1. The gallery (demo/index.html, demo/assets/demo.js):
  2. The stand presents its variants as series instead of one flat list
  3. DEMO_SERIES holds the three of them, and a file finds its own neighbours and its own gallery section through it

  4. The panel arrows walk inside a series and wrap, so a series is a subject of its own and not a continuation of the one beside it

  5. The settings series (demo/set-01-deck.html through demo/set-10-bridge.html):
  6. Ten variants of index.php?name=account&op=edithome
  7. The upload series (demo/up-01-drop.html through demo/up-06-inline.html):
  8. Six variants of index.php?name=files&op=add
  9. The shared rhythm (demo/assets/demo.css, demo/README.md):
  10. The stand stylesheet gains what the two new series ask of it
  11. The readme describes all three series, the numbering of each and the file names they follow

Benefits:

  • Two more decisions can be compared as whole pages under the real theme
  • Numbering restarts per series, so a variant is named by what it answers

Technical notes:

  • The stand is not part of a release and lives only in the development tree
  • Every variant keeps whatever it needs beyond the theme in a single style block inside its own file, and adds nothing to the lite theme

  • The content inside a series is identical to the letter, so a comparison reads the composition and never the text

Refactor: one field standard for the whole system, and the caption meets its control
Автор: Eduard Laas | Дата: 01:27 27.08.2026

Every form row on both sides now puts its caption in the left column and its control in the right one, an editor takes the whole row, and the colon that separated the two is gone. The caption is tied to its control by an explicit for and id, which no row in this tree carried before.

Core changes:

  1. The row (fragments/form-field-row.html, fragments/div-row.html):
  2. The site row is a two-track grid, a quarter to the caption and three quarters to the field, folding to one track under 900px

    • The label cell is rendered unconditionally, so a row with no caption leaves
the left track empty instead of sliding the field into it
  • hide_label is gone: 91 call sites hid the caption and showed a placeholder
in its place
  • An editor row drops to a single track with the caption above it, which is the only exception to the two-column rule

  • A tall field is read from its first line, so the caption meets it there rather than floating at half its height

  • The panel row wraps its caption in a label when the row names a control
  • The colon (assets/css/theme.css of both themes):
  • Every ::after rule that drew the separator is removed
  • With it go the mechanisms that existed only to cancel it: sl-no-colon with its important override, and the is_action_label flag with its sl-action-label class

  • The link from caption to control (143 site rows, 890 panel cells):
  • 527 rows carry label_for beside input_id, or selectid on a panel select
  • getTplCategorySelect() emits an id of its own
  • fragments/label.html, select.html and textarea.html gained the keys the link needs, and the panel hint became a span so the caption above it can be a label without holding block content

  • Two forms that were written by hand now follow the standard:
  • The OAuth link and create forms, which had no captions at all
  • The private message composer, which hid its captions from sight
  • Defects the work uncovered:
  • sl-hidden lost to the display the row itself set, so a row marked hidden stayed visible: fifteen link rows in the media form, the GitHub fields of the changelog configuration

  • The panel media form gave its rows and its inputs overlapping ids
  • The suggested nickname of the OAuth form was escaped twice
  • Contrast (templates/lite/assets/css/theme.css, tools/ui-contrast.json):
  • The two edge tabs drew white on a pastel plate at 1.68:1 and 1.86:1, below AA along the whole plate; they now take the strong text tone at 7.66:1 and 6.92:1

  • The pair registry is regenerated and no longer names a deleted class

Benefits:

  • One field standard instead of two conventions, so a new form has a shape to follow rather than a choice to make

  • A caption that names its control to assistive technology and focuses it on click, which no row did before

  • Two hidden-row defects, one duplicate-id defect and one double-escape gone

Technical notes:

  • Ids read f-<name>; ten rows resolve theirs conditionally, because the author row shows a plain value to a member and an input to a guest

  • No schema, route or op name changed, and every form posts what it posted
  • Verified by walking 24 site pages and 252 panel pages: every for resolves to a labelable element, no id repeats on a page, no label nests inside another

  • What the standard still owes, and why radio groups, editors and hints have no accessible name yet, is planned in docs/FORM-FIELDS-2026.md

Эта неделя (26.08.2026)
Refactor: one window frame for the whole system, and the file manager grows up
Автор: Eduard Laas | Дата: 15:43 26.08.2026

Every dialog of the project is now built from a single frame fragment instead of nine hand-written copies, and both file managers gain sorting, whole-page listings, per-file insert options and the properties they were missing.

Core changes:

  1. The window frame (fragments/window.html):
  2. One fragment owns the canon: plate, optional command bar, body, optional foot

    • Size, tone, static and the close control are its parameters
    • Nine dialogs removed: confirm, share, QR, gallery, settings, icon picker,
source editor, insert options
  • getWindowSet() and getWindowShot() (core/helpers.php) build the windows a page carries, and the layouts print one variable instead of naming each window

  • getAdminIconWindow() (core/admin.php) replaces four identical call sites
  • The source editor (core/admin.php, admin-ui.js):
  • Opens as a window over the browser instead of replacing the file list
  • The directory stays drawn underneath, the guard against unsaved work is kept
  • Sorting (theme.css, file-browser-list.html, editor-upload.js):
  • The admin table opts into the existing Tablesort mechanism and gains a type column; size and date sort by the raw figure and not by their printed text

  • The editor catalogue reuses the same three indicator classes by hand
  • Sort marks are drawn in the icon font; the admin theme had lost the escape of all three and printed a control character with the hex beside it

  • The file manager of the editor (editor-upload.js, driver.php):
  • Paging removed: the expanded catalogue is drawn whole and scrolls
  • Insert asks side and caption per file through the options window
  • Upload marks what it brought in; nothing is inserted without a confirmation
  • The properties panel carries the fan of the object and opens the gallery
  • File descriptors (core/classes/filemanager.php, core/system.php):
  • The descriptor answers the mode and the account of an object
  • Both reach a module moderator only, and the account only on a POSIX host
  • Theme fixes (base.css, theme.css, toastui/skin.css):
  • The three white marks collapse onto one token: band, edge tab and dial chip
  • The typing surface of the editor takes the theme colour; the vendor painted it #222 in both themes and dark text was unreadable on a dark page

  • The mode tabs of the editor wear the frame of the theme and stop shrinking
  • Controls of a window inside the editor root take back the height, corner, type and tone the vendor stylesheet claimed from them

Benefits:

  • One place decides what a window looks like, so the canon cannot drift again
  • The two file managers answer the same way for sorting, actions and preview
  • A moderator sees what the server holds; an author is not shown server details

Technical notes:

  • No schema, URL or op name changed; every route answers as before
  • Six locales gained the labels the new controls need
  • The file manager and the emoji panel still carry their own dialog: neither has a canon body, so moving them needs a markup pass of its own

Эта неделя (25.08.2026)
Fix: the block setting of a module is read again, and the content takes back the width it frees
Автор: Eduard Laas | Дата: 22:39 25.08.2026

The side and top keys a module carries have decided nothing since the modules moved off their table: the two globals the foot reads by were never assigned, so every page rendered all four block positions. The reading is restored, and the grid stops holding a column it was no longer given.

Core changes:

  1. The module block setting reaches the renderer (index.php):
  2. $blocks and $blocks_c are assigned from $mconf beside active and view

    • setFoot() reads both by global and skips the sides a module switched off
    • They were declared in the global list of setFoot() and assigned in no file of the tree
    • A null global compares equal to the empty string, so the first branch of all four won always
  3. The line lost in the migration read the columns blocks and blocks_c of the modules table

    • The keys are now side and top of $conf['modules'][$name], the values unchanged: 0 both, 1 first, 2 second, 3 neither
    • The four conditions of setFoot() are the ones 6.2 shipped and needed no edit
  4. The home branch stays as it is, which is what 6.2 did: a random module never decided the blocks of the front page
  5. The content grid follows the columns that exist (theme.css):
  6. #container declares one column, and a side track only under :has() of the rail it belongs to

    • Left alone, right alone, both, neither - four rules, each naming its own template
    • The empty right track cost the content 400px of width and 24px of gutter on every page without blocks
    • #leftbar had no track at all: with left blocks the content would have landed in the sidebar column
  7. The three rules sit inside @media (width > 900px) rather than at the top level

    • :has(#sidebar) carries the specificity of an id, which would outrank the narrow-screen reset
    • The two queries are complementary, so the stacked layout below 900px is untouched
  8. The narrow-screen rule drops its grid-template-columns: it repeated the base, and 1fr is minmax(auto, 1fr)

Benefits:

  • A setting the panel has been saving for years does what its label says
  • A module without blocks reads across the full measure instead of against a 424px margin of nothing
  • The layout answers the markup, so a left rail needs no second rule the day a left block is written

Technical notes:

  • Behaviour: every module whose side or top is not 0 changes appearance, not only the one that was edited
  • API: no token added or moved; both rules read --sl-layout-sidebar and --sl-layout-gutter as before
  • Compatibility: :has() is already load-bearing in this theme; without it the page degrades to one column
  • Gates: ui-audit clean per theme and global, counters identical to HEAD, ui:gates 193 green, phpunit 915 green
  • Not run: the screenshot pair, for want of SLAED_UI_USER and SLAED_UI_PASS on the stand
Feature: the presentation page gets a stand of twenty three designs, and the implementation catalogue its real screenshots back
Автор: Eduard Laas | Дата: 15:32 25.08.2026

The stand for index.php?name=main is rebuilt from the band studies it used to hold into twenty three whole-page designs, every one of them carrying the same content in the real site chrome. The implementation section stops showing theme banners and shows what it is meant to show: the seventy one client sites of the project catalogue.

Core changes:

  1. Real implementation screenshots (uploads/screens/):
  2. Seventy one pairs restored from the reference site, thumbnails and full pages

    • The live carousel on the presentation page fills again: it reads uploads/screens/thumb at request time
    • Sizes are 260 wide by 166 to 455 tall for a thumbnail, 865 to 1024 wide for a full page
  3. The stand reads twelve of them from one list in demo.js, never from its own markup

    • data-demo-sites builds the cards, data-demo-sites-skip offsets, data-demo-sites-natural keeps own height
    • Twelve entries at one address cannot drift apart across twenty three files
  4. Two laws about pictures (demo/assets/demo.css):
  5. A screenshot is never wider than its 260 and never taller than its own height

    • An even row is made by cropping the tall ones, never by stretching the short ones
    • The column is sized to the picture, not the picture to the column
  6. A theme photograph is 1920x440, so a band may not exceed 440 * width / 1920

    • d-band-art paints the picture at its own pixels: full width to 1920, then centred
    • This is what made the previous glass variant look cheap, and it is now impossible to repeat
  7. The glass direction, developed into four (13, 19, 20, 21):
  8. 13 rebuilt: the band is exactly the height of its photograph and the panel overhangs its lower edge
  9. 19 liquid glass: progressive blur in three masked layers, so the photograph dissolves instead of ending

    • One layer cannot do it - a masked backdrop-filter fades its opacity, not its radius
  10. 20 client showcase: a real client site at full size in a browser frame, four of them on a rail
  11. 21 layers: a stuck scene where the four pillars arrive as sheets in perspective

    • Driven by a named view-timeline on the tall block, read by its four descendants
  12. Two designs outside the glass (22, 23):
  13. 22 anti-grid: no shadow, no blur, no radius, no gradient - hard rule, monospace, deliberately broken columns
  14. 23 wall of work: a masonry wall where every screenshot keeps its own height, built with columns
  15. The stand itself (demo/):
  16. Eighteen band studies and fourteen footer studies replaced by twenty three page designs
  17. assets/demo.js carries the manifest, the site chrome, the control rail and five shared behaviours
  18. assets/demo.css carries one section rhythm (d-*) so a variant is judged by what it does differently
  19. A variant adds nothing to the theme: its own CSS is one <style> block under v-* names

Benefits:

  • The presentation page can be chosen from real alternatives rather than described in words
  • The implementation catalogue argues with the sites built on the system instead of with stock banners
  • No design on the stand can ship an upscaled picture, which is the one flaw that cannot be styled away
  • Every variant is the same content in the same chrome, so the comparison is of design and nothing else

Technical notes:

  • Storage: uploads/screens gains 142 files, 28 MB, the same set the production site serves
  • API: nothing in templates, core, modules or plugins is touched; the stand does not ship
  • Compatibility: scroll-driven variants degrade through @supports to static, readable sections
  • Gates: ui-audit clean per theme and global, demo/ is outside its scope; PHP suites not run, no PHP changed
Feature: the photo bands carry a light beam, the footer menu reads by icon, and the season art ships as WebP
Автор: Eduard Laas | Дата: 13:03 25.08.2026

The two photo bands of the front page gain a slow beam and a veil the dark mode alone puts on, the lower menu is laid out by icons at every width and closes the page on the same 50px edge the top bar opens it with, and every season and slider photograph now ships as WebP at a third of the weight.

Core changes:

  1. Light beam on both photo bands (base.css, theme.css):
  2. Four tokens carry the whole effect, all declared through light-dark() in the API block

    • --sl-band-bg is the veil: transparent in light, half-strength ink in dark
    • --sl-beam-width, --sl-beam-dur and --sl-beam-bg are the shaft, its pass and its light
  3. The darkening lives in the alpha of the colour, not in an opacity layer

    • The opacity ladder carries no even half, and an alpha inside a colour is part of the colour
  4. The beam travels upright at an even rate: eight seconds, three and a half of travel, four and a half at rest

    • It starts its own width left of the band and ends a window past it, which holds at any width
    • No literal outside the API block: calc() off the width token, 100vw, and the named layer tokens
  5. Season photographs cover their band again (theme.css):
  6. The ten season rules set the background with longhands instead of the background shorthand

    • The shorthand reset background-size, and with it the cover the base rules declare
    • On a narrow screen the band grew taller than the photo, which then hung as a strip
  7. #head-content restates its own position, because its base rule centres on 50% 0
  8. Season and slider art in WebP (images/, theme.css, index.php, main-slider.html):
  9. Seventeen season files and four slider files replaced, 668 KB down to 248 KB
  10. Every reference follows: seventeen url() in the theme, the LCP preload builder, the slider partial
  11. ViewBridgeSmokeTest asserts the slider paths by name and moves with them
  12. Footer menu as an icon grid (site-footer.html, base.css, theme.css, ui-contract.php):
  13. Each destination carries its icon in the markup, never in an nth-child rule

    • A rule keyed on position drifts from the labels the first time a section is added
  14. Three shapes of one idea: one row above 1200, four columns to 768, two columns below
  15. --sl-fmenu-min-height is one thumb target and one row height, because it is one decision
  16. --sl-fmenu-height reads --sl-topbar-height, so the page closes on the edge it opens with

    • Both are floors rather than fixed heights: below the wide step both blocks grow with content
  17. The bar separator survives only in the single row, where a line break cannot strand it
  18. Component names beam, fmenu declared in the contract
  19. Prototype stands (demo/):
  20. demo/ gains the hybrid of beam and season particles, and its beam variant matches what shipped
  21. demo/footer/ is a new stand: fourteen treatments of the lower menu, each one <style> block

    • A variant renders inside an iframe of a chosen width, because the theme answers the viewport

Benefits:

  • The dark mode stops asking white text to stand on a photograph shot for daylight
  • A phone no longer meets a hanging separator, a 23px tap target or a stranded advertising line
  • Four fewer JPEG kilobytes on every page view, and a third off the theme image payload
  • Both bands and the footer are described by tokens, so the next theme repaints them from one block

Technical notes:

  • Storage: seventeen season JPEG and four slider JPEG deleted; their WebP counterparts keep the pixel sizes
  • API: --sl-sep-height stays declared and read, because a frozen API may gain a name and never lose one
  • Compatibility: WebP needs no fallback at the theme baseline (Chrome 123, Safari 17.5, Firefox 120)
  • Gates: ui-audit clean per theme and global, phpunit 915 tests green, ratchet re-stored
Эта неделя (24.08.2026)
Feature: the settings window comes back after the post it starts, and demo/ carries sixteen band treatments
Автор: Eduard Laas | Дата: 23:12 24.08.2026

The settings window posted a row and the browser closed the dialog on the navigation that followed, so a second answer needed the window opened again by hand. It now names itself before the form leaves and comes back on the next load. Alongside it, demo/ carries sixteen prototype treatments of #head-content and #demo-line for the dark mode, where the seasonal photo keeps its full brightness while the page around it turns over.

Core changes:

  1. Settings window (core/admin.php):
  2. One row of the window submits through requestSubmit() with submit() as the fallback

    • requestSubmit() fires the submit event, which is what marks the window as open
    • submit() stays for a browser that does not carry it
  3. The comments over getAdminSettingsRow() say the same thing in fewer words
  4. Window reopening (plugins/system/slaed.js):
  5. A form inside a dialog marks that window in sessionStorage before it navigates

    • Only a window carrying an id is marked, because only such a window can be found again
    • A form driven by htmx swaps in place and is skipped, or it would open a window later
  6. setWindowBack() reads the mark once on the next load, clears it and opens that window
  7. Locale switch note (core/security.php):
  8. The comment over setLangChoice() is shortened; no behaviour change
  9. Band treatments (demo/):
  10. Sixteen self-contained pages: the live band markup, the real theme CSS, one style block each

    • The dial darkens the photo in the dark mode alone; every effect is independent of it
    • Motion runs on transforms, so the compositor carries it instead of the painter
    • The photo moves as its own layer through background-image: inherit, so the five season rules stay in one place
  11. assets/demo.js holds the manifest, the page chrome and the control rail; index.html is the gallery
  12. README.md records how to view them and what the migration into the theme will require

Benefits:

  • An administrator changes two settings in a row without reopening the window between them
  • The candidate treatments can be compared side by side before any of them touches the theme
  • Nothing in demo/ is read by the site: they are prototypes, outside the theme and its gates

Technical notes:

  • sessionStorage carries one key, slaed-window:reopen, written before a navigation and cleared on read
  • demo/ holds literal CSS values by design, which is why it sits outside templates/
  • No schema, URL or API contract changes
Feature: the settings window answers for all three axes, and the language switch stops answering to a link
Автор: Eduard Laas | Дата: 21:15 24.08.2026

The panel settings window landed in 7e864723 with three rows built three ways, one of them posting without a token; the locale switch answered to any GET that carried newlang. This commit closes both, collapses the rows onto one builder, and follows the RSS feed the same way: declared where a reader looks for it, stable where it was random.

Core changes:

  1. Settings window (core/admin.php, templates/admin/fragments/settings-row.html):
  2. getAdminSettingsRow() takes the axis and returns the row

    • getAdminLanguagePick() and getAdminEditorPick() collapse into it
    • the panel stops drawing a mode row of its own, so templates/admin/fragments/
mode-switch.html and its fork entry in tools/ui-contract.php are gone
  • the sl-mode class moves onto settings-row.html behind an is_mode flag, which
keeps --sl-mode-width and --sl-mode-height read and the frozen API intact
  • hidden fields settle on fragments/hidden.html for all three rows
  • the sidebar editor block leaves getAdminInfo(); the window is the only place the editor is offered, and the function loses three globals and gains a return type

  • CSRF on the editor and the locale (admin/index.php, core/security.php, index.php):
  • updateAdminEditor() refuses a request without checkAdminPost('changeeditor')
  • setLang() only reads the cookie now; setLangChoice() does the writing

    • a token check cannot live in setLang(): it runs before the session, the database
and the parser exist, and every admin POST came back as the login page
  • both op=newlang handlers call it and redirect, so the POST turns back into a GET
  • scope newlang joins the token allowlist of checkDynamicMark(), because the site block sits on cacheable pages and needs getPageToken()

  • Language producers (blocks/languages.php, templates/lite/fragments/lang-switch.html):
  • the flags became submit buttons of one form, the select became a POST of the same
  • the geo redirect writes the cookie directly instead of handing itself ?newlang=
  • getAdminLanguageLinks() is gone: the panel renders with the admin theme, whose layout has no admin_langs, so the strip was computed on every load and discarded

  • RSS feed (core/user.php, core/system.php):
  • the site declares its own feed with <link rel="alternate"> in the head
  • <atom:link rel="self"> and dc:creator replace an antispam@antispam.com placeholder
  • ?go=rss without a name answers with the first module instead of a random one
  • Route handler names (admin/index.php, core/system.php, modules/account/index.php):
  • every handler carries a verb prefix now: updateAdminEditor, setAdminThemeMode, setAdminLanguage, deleteAdminSession, getAdminLoginForm, checkAdminLogin, addAdminAccount, and login_report becomes addLoginReport

  • the op strings and token scopes they answer to are untouched
  • Login journal (core/system.php):
  • addLoginReport() reads the flag before the kind becomes a string

    • a non-empty string is true either way, so log_u was unreachable and log_a alone
decided both journals, which wrote user passwords the operator had switched off
  1. Removals and site header (docs/, demo/, templates/lite/partials/site-header.html):
  2. docs/SETTINGS-FIXES-2026.md and demo/ are deleted, no code referenced either
  3. the RSS button leaves the header, browsers have not rendered a feed since 2018; the remaining tones shift back onto a contiguous position % 6 cycle

  4. --sl-wordmark-img-width 145px -> 150px and a quoting fix in ThemeCreationTest.php ride along, both unrelated to the rest and included on request

Benefits:

  • One builder and one fragment for a row instead of three constructions
  • Two handlers that changed state without a token now refuse one that lacks it
  • A locale change no longer happens because a prefetcher followed a link
  • Readers find the feed without being handed its address

Technical notes:

  • Breaking: log_u now means what it says. With log_a on and log_u off, user logins stop being written to log_user.log, and the attempted passwords with them

  • Breaking: RSS <author> becomes <dc:creator>; a parser reading <author> loses the name
  • Breaking: ?newlang= as a GET no longer switches the locale anywhere
  • The site language switch returns to the referring page rather than to the home page
  • No storage, schema or route changed: every op string and token scope is as it was

Всего: 1148 на 115 страницах по 10 на каждой странице

1 2 3 4 5 6 7 8 9 10 115
Хотите опробовать SLAED CMS в действии?
Идеи и предложения
Обратная связь
Подтверждение

Поделиться
QR-код

Предварительный просмотр