Официальный сайт SLAED CMS
Журнал изменений
The builder of the demo stand showed what a site owner edits in one place; the owner now judges it as the panel screen it is to become. Its chrome is the canon of the panel, the fields are the fields of the panel forms, the publication carries checks, a note and a history, and the screen opens its own manual, as every panel screen does.
Core changes:
- The chrome (public/demo/sb-01-builder.html, assets/sb.css):
The tools stand in the capsules of the editors (sl-editor-pill, sl-editor-grp, sl-modal-act) by their groups, the widths in the segmented control, the state as a chip, the help and the settings last at the edge
The windows of the screen: the manual, the settings with the file of the layout read in the code editor of the panel, the link of the draft, the history, the checks, the palette
- Editing (assets/sb.js, assets/sb-data.js):
The fields of the panel forms: the switch and the segmented control with flipped answers, the checkbox list, the swatches, the file field with the file manager, the logos of the theme, a focus grid for a cropped picture
- Markdown texts in the editor window of the panel, raw markup in its code editor, each shown by its beginning
A field that differs from the site carries the way back to its published value; the guest view, the neighbours of a pick, the address of a section by its anchor
The library of sections with "Мои секции", "Недавние" and the groups as a filter; a type a page holds once, the slot of a module, has no twin and answers at the module's address with its SEO
- Publication (assets/sb.js):
Checks of every field and of the links and pictures inside the Markdown texts, the count of changes in words, a note of the author, the blocks published with the layout, ten versions and the way back to the site
- The canvas and the manual (assets/sb-site.js, assets/sb-site.css, sb-site.html, assets/sb-help.md):
- The sections drawn on the tokens of the theme lite, the slot of a module and the pages of the builder by address
sb-help.md is the manual the window "Руководство" renders: how to open the builder, the screen, pages, sections, menus, theme parts, blocks, the draft and the publication, in Russian like the help of the panel
Benefits:
- The owner judges the builder in the look and with the mechanics the panel screen will have
Technical notes:
- The stand is outside the release (export-ignore); the draft lives in localStorage, no request but the manual
- The demo loads ../plugins/system/editor.js and the CodeMirror stylesheet of the plugins for its editor windows
The stored texts are Markdown since the update converts them, so the writers stop escaping what they store and the parser stops reading the BB it no longer meets: every store keeps the typed text, the editor mounts it unchanged, the bracket layer reads [hide], [tabs], [attach], [usehtml], [usephp] and [block] alone. The full run of update.php on a copy of the production dump found two faults of the updater and the writers; both are fixed, the run is proven, and what lasts of it is reference in docs/.
Core changes:
One storage of a typed text (core/security.php, core/classes/, core/helpers.php, core/user.php, admin/modules/, modules/):
filterSourceText() turns a typed text into the stored source: CRLF to LF, the trusted tags, the censor list, never HTML-escaped, as the parser escapes at render
- the blocks, the admin messages, the newsletters, the signatures and own blocks, the contact text, the forum, the
comments, the private messages and Node read the field raw and store through it
- Comment and Privat lose their own copies of the censor (filterCommentBody(), filterMessageText())
- getTplTextarea() mounts the stored source as it is: no <br> turned into a hard break, no entity decoded
The forum, the signatures, the own blocks, the blocks, the admin messages, the newsletters, the contact text and the preview of the editor render safe with trust, as a Node material does
- The reply quote of a private message and of a forum post quotes the stored Markdown as it is
The admin message form keeps an empty language; the snippet of a private message drops the quote markers of every depth and the escapes (filterSnippet() of Privat)
- The parser reads the SLAED tags alone (core/classes/parser.php, public/templates/*/fragments/, lang/):
The handlers of the converted and removed BB tags, ed2k and the smilies go, with images/smilies/ of both themes and _SMILIE of the six lang files
parser-inline.html, parser-block.html, parser-image.html and blockquote.html of both themes lose the parts only those tags drew
- The read-only editor (core/classes/editor.php, public/plugins/system/editor.js, fragments/editor-*.html, theme.css):
Editor::getFrame() takes readonly; the frame marks its area, the kit marks every tool that changes a text with the need edit, and editor.js keeps CodeMirror read-only and without files
- .sl-markdown table of the admin theme draws the tables of the help
- The update (public/update.php):
Points, ratings and fields whose mark is set and whose manifest is missing ran on the site before and answer done; they stopped the whole run on production, so no table was dropped
The guard of getMigrateAttach() keeps an image inside a link to another site with text or a hard break beside it in the label, so a repeat no longer rewrites it
- The comment edit form of the panel (admin/modules/comments.php):
- The author and the IP are escaped once
- Help and documents (admin/info/, modules/contact/admin/info/, docs/):
The help of the configuration, the blocks, the admins, the comments, the monitor and the contact text in the new state, the tables of the help readable
docs/PARSER.md: the engine, the measurement, the grammar of the SLAED tags, what is no markup and the conversion of the BB era; docs/EDITORS.md: the stored text on mount and save
docs/NODE.md: a site of an early 6.3 build, its folder moves, the address step of the migration, the columns no parser call renders; docs/UPDATE.md: moving slaed.net to 8.0, from the copy to the live check
- docs/VERSIONS.md: both changes
- Tests (tests/):
ParserFixturesTest without the BB fixtures, EditorBreakTest on the storage of every writer, EditorFormatTest on the read-only frame, PrivatClassTest on the snippet
UpdatePointsTest, UpdateRatingsTest, UpdateFieldsTest on a mark without a manifest, UpdateAttachTest on the label around a linked image
Benefits:
- A save without a change keeps every byte of a text; what an author types is what the store keeps
- One rendering path for every Markdown text of the site
- The move of slaed.net is a proven, repeatable run with its order written down
Technical notes:
Breaking: [u], [color], [size], [family], the alignment tags, the alignment of an image, ed2k and the smilies
-
keep their text and lose the formatting; images/smilies/ and _SMILIE are gone- No schema change; the stored texts were converted by the text unit of update.php
What a site owner changes today only by editing HTML - the home page, the main and the footer menu, the slogan, the badge and the social links of the header, the strip before the footer, the contacts - is gathered into one editor and one layout, which in the system would be one file config/layout.php. The stand shows it before any line of the core is written, as the decisions of the owner of 2026-10-26 describe.
Core changes:
- The editor (public/demo/sb-01-builder.html, assets/sb.js, assets/sb.css):
- Three tabs over one layout: the page with its header, sections and footer, the two menus, the theme parts
The page in a device frame in the middle: hover names a part, a click selects it everywhere, a double click edits the text in place; the selected section moves, copies, hides, deletes and adds below through the library
Undo by gesture, a draft and a publication, a check before publishing, ten published versions, anchors, the device switch, page presets, Ctrl+K, the export and import of layout.json, menu items from the modules
Blocks by the model of the system: the four zones a theme prints, "where to show" read as getBlocks() reads it and written as editsave() writes it, the order of a position, a drag on the tree and on the page
The chrome of the editor is the mechanics of the panel: canon windows, setToast(), the tabs, the icon window, the drag marks and the buttons of the panel
- The canvas (public/demo/sb-site.html, assets/sb-site.js, assets/sb-site.css, assets/sb-data.js):
The sections of the theme lite on its tokens with the live header and footer of the site; inside the frame of the editor it is the page in edit mode, alone it is the published site with the pill "Edit page"
sb-data.js holds what both share: the section catalogue with its field schema, the theme parts, the menus and the layout of a fresh site
- The ways in (public/demo/admin/, public/demo/site/, assets/demo.js):
- The panel reference: "Site builder" in the menu "Administrator" and a card on the home (mark D13)
- The site reference: "Edit page" in the floating menu (mark C15)
- The manifest gets the series "Site builder"
- The stand description (public/demo/README.md):
The series, the files, the owner's decisions with the mechanics of the system each part of the chrome reuses, the twelve accepted features and the open point of the new "which" value page:<key>
Benefits:
- The owner judges the builder on a working page before the core class, the fragments and the panel screen exist
Technical notes:
The stand is outside the release; the draft lives in localStorage (sb.draft, sb.live, sb.history), no request reaches the server but the header and footer of index.php?name=presentation
The places of a block listed the site modules alone, so a block could not be shown on the pages of one Node type: those pages carry the name of their type in $name, and the module node itself is never a page name. The list now offers every type beside the modules.
Core changes:
- The places of a block (admin/modules/blocks.php):
- getBlockWhereItems() lists the site modules and every type of config/node.php, sorted by name, and leaves "node" out
- The popover of a box names what it is, module or type, with its code
- Help (admin/info/blocks/ru.md):
- The places list the modules and each type, and a block marked at a type shows on the pages of that type
- Tests (tests/Unit/NodeIntegTest.php, tests/Support/route_probe.php):
- The block form offers the type "docs" and no "node", and a save keeps the type the block was bound to
Benefits:
- A block meant for documentation or news pages shows there and nowhere else, without a module of its own
Technical notes:
- The stored value is the same list of names in _blocks.which; a type name is matched as the page name already is
The stored texts become Markdown, so the code that still produced BB moves with them: the reply quotes, the inserts of the editors and the file window, and the shipped contact text. The meta image of a text is read from a Markdown image. Bare addresses are linked by the GFM autolinks of the parser at render, which leaves the write-time rewrite into [url] and [mail] and the settings that steered it nothing to do.
Core changes:
- Reply quotes (core/user.php, modules/forum/index.php):
The reply to a private message and the quote of a forum post are the text as "> " lines and a blank line after them; the branch for an HTML editor goes, as those editors serve the panel alone and both forms are site forms
- Inserts of the editors (public/plugins/system/, public/plugins/editors/toastui/):
- getEditorInsertText() of slaed.js writes name, with its Markdown characters escaped, and
editor.js writes a Markdown image in every field; filemanager.js writes one through addSource(), the side-taking [img=...] of addImage() goes, and the side choice of the insert window hides for a picture
- data-sl-opts="align" moves to the wrapper of the choice in window-body-insert.html of both themes, as size has it
The quote button of Toast UI goes, Toast keeps its own; _EQUOTE leaves the six lang/*.php, its icon leaves skin.css of both themes
- The meta image (core/system.php):
- getImgText() takes [attach] first, then the Markdown image with an <address> or a bare one; the two [img] forms go
- The link rewrite (core/security.php, core/classes/, admin/modules/, config/):
- filterClickable(), getEd2kLink() and filterCut() go; filterHtml() loses the argument that only switched it off
- Comment and Privat lose the switch and the link flag: getLinkFlag(), the 'click' setting
The setting "Convert addresses into hyperlinks?" of the configuration and "Prohibition of the automatic conversion of links" of the comments go with _CLICABLE, _CLICABLEINFO, _NOALINKP and the keys clickable and alink
- The update and the shipped settings (public/update.php, config/contact.php):
- setUpdateConfig() drops clickable of a 6.2 global and alink of 6.2 comments; setUpdateMerge() retires both
- The shipped contact text is Markdown, equal to what the converter makes of the former BB one
- Help and documents (admin/info/, docs/):
- The help of the configuration and of the comments loses the two settings
- docs/EDITORS.md: a picture enters as a Markdown image without a side; docs/NODE.md names the retired keys
- Tests (tests/):
FileAccessTest: the reply form offers the quote as Markdown lines and a quoting reply binds the quoted name; the meta image of a topic is its attachment or its Markdown image
- PrivatClassTest: a bare address is stored as typed and linked in the rendering
- UpdateConfigTest and UpdateArchiveTest: both keys leave on the 6.2 and on the 6.3 path
- EditorWindowTest follows the Markdown image writer of the shell
Benefits:
- No code of the site writes BB any more; what an author or a reply produces is Markdown the standard reads
- One way a bare address becomes a link, at render, instead of two that disagreed
Technical notes:
Breaking: the settings clickable and alink are gone; a bare http(s)://, www. or e-mail address is always a link, for guests too, as the parser renders it since the GFM autolinks
- The stored texts are not touched here; their conversion is the text unit of update.php
The stored texts are moving off BB onto Markdown, so the parser that renders them has to read Markdown by the standard and not by its own habits. The examples of both specifications are now fixtures, and the parser was rebuilt on a block tree and an inline tree until every one of them passes in the trusted and in the safe mode.
Core changes:
- Conformance fixtures (tests/Fixtures/spec/, tests/Unit/ParserFixturesTest.php):
commonmark.json holds the 652 examples of spec.json 0.31.2 as published, gfm.json the 24 extension examples of GFM 0.29-gfm (cmark-gfm 0.29.0.gfm.13), the two task list examples marked disabled there included
filterDocMeetsTheSpec() runs every example at $safe = false, and at $safe = true every one but those carrying raw HTML or a link of a scheme the safe rendering refuses
- the comparison removes only the markup of the theme: heading ids, theme classes, the code figure, the
broken-image fallback, the cell alignment style and the disk check of a local image (Parser::$fileoff)
- the CommonMark examples run with the tag filter and the extended autolinks off (Parser::$gfmoff), the GFM ones
with them on, as the spec runner of cmark-gfm does; code is measured in the shipped highlighter mode 2
failing.json is the baseline of examples that fail; a listed example that passes fails the test, so the list only shrinks, and it is empty: trusted 676 of 676, safe 591 of 591
- The engine (core/classes/parser.php):
getBlockTree() reads the block structure one line at a time: indented and fenced code, HTML blocks of the seven kinds, link reference definitions, setext headings, lazy continuation, tight and loose lists, GFM tables
getInlineTree() reads inline content with the delimiter and bracket stacks of the specification: flanking rules, code spans, references, autolinks, entities, hard breaks, GFM strikethrough and extended autolinks, mark
getBlockHtml() and getInlineHtml() render the tree through the fragments; the regex passes filterCode(), filterBlocks(), filterList(), filterTable() and the Markdown tail of filterBbInline() are gone
The bracket layer reads the copy of filterMask(), which a scan of the same parse masks; a raw pair whose opener the scan leaves visible is taken back whole, since its content is no Markdown
A safe rendering keeps an address without a scheme and one of http, https or mailto; data:, javascript: and vbscript: die in every mode; a line of <br> opens an HTML block as any complete tag does
- Parentheses in a link target are bounded at 32 levels, as cmark bounds them
- Fragments of both themes (public/templates/*/fragments/):
- list takes has_start and start_num for <ol start>, parser-table drops <tbody> without body rows
- Documents (docs/PARSER.md):
The standard, the comparison, the SLAED extensions on top of it and the bracket layer; the Markdown list names everything CommonMark and GFM define; the safe and the trusted mode as the engine reads them
Benefits:
- A text renders as every CommonMark and GFM tool renders it, which the conversion of the stored BB relies on
- The two known defects are gone: fenced code inside a quote or a list item, and <https://...> and <name@host>
Technical notes:
Measured on the 28344 renderable texts of the stand: both parsers render them in the same time (8 to 10 s), the slowest text 43 ms, no warning; 6637 render differently, each by the standard
- The plain format keeps its own path; no render call of the site passes it
The texts the parser renders are moving off the legacy BB layer onto CommonMark with GFM. update.php now converts them on the copy of a site: a text of the BB era is escaped so it renders what its author typed, a text that is Markdown by origin converts only its tags, and a text the site renders trusted keeps its raw HTML as markup.
Core changes:
- The converter (public/update.php):
getMigrateMarkdown() turns balanced pairs of the known tags into Markdown: emphasis, links and autolinks, mail, images, quotes, code fences and spans, rules, the bullet of • , smilies
-
as emoji, <br /> as a hard break- the tags without an equivalent keep their text, the special tags keep their tokens around a converted content,
[usehtml] and [usephp] stay as written
- an unpaired, crossed or misspelled tag and an empty or unsafe address (javascript, data, ed2k) stay text
- the forms the old parser rendered convert too: [code=] as [code], whitespace around a value or an alternative text
- a text of the BB era has every text run escaped by CommonMark; bare addresses stay as written
getMigrateHtml() writes Markdown through it: known HTML becomes the BB of the converter or a finished Markdown piece, an unknown block becomes [usehtml]
getMigrateAttach() reads the Markdown link, linked thumb and autolink; it and getMigrateForeign() keep the examples of fenced code and code spans
- The text unit (public/update.php):
setUpdateTexts() runs after the archive unit over Node texts, comments, forum posts, private and admin messages, newsletters, blocks without a feed, signatures, own blocks, textarea fields and the contact text
- Markdown by origin: Node texts, and on a 6.3 site the help replies and the rows of forum, comments and private
messages from 2026-07-13 on
- a source rendered trusted (blocks, admin messages, newsletters, forum, signatures, own blocks, contact) takes
getMigrateHtml()
A batch of 200 rows is named in the manifest with the hashes of its new texts before its transaction; a stopped run neither converts a committed batch again nor loses one that rolled back, a verified unit is skipped
The dry run of the first stage ("Count the changes") counts per column and the forms met, and writes nothing; a text too long for its column stays BB and the report names it
- The second stage converts the field values it appends to a carried text
- Documents (docs/NODE.md):
The run order names the text unit, the dry run counts both units, the migration of the second stage writes Markdown, and UpdateTextTest joins the table of the update tests
- Tests (tests/):
UpdateTextTest: the converter on BB, Markdown and 6.2 HTML; the unit with dry run, write, repeat, a dry run after it and a batch stopped before and after its commit, through update_probe.php in mode texts
UpdateAttachTest takes the Markdown forms; UpdateSiteTest expects the forum post and the private message of the 6.2 fixture in Markdown
Benefits:
- The production texts reach the standard the parser is brought to, with no BB left for it to read
- A stopped conversion can be run again without escaping an escape
Technical notes:
- Measured as a dry run on a copy of production: 16906 texts change, none too long for its column
- update.php is the owner's tool and never ships in a release
The production site runs a development build of early October whose Node texts point into the archive of the first migration and whose schema, settings and tables lag behind the release. update.php now brings such a site forward on a copy without migrating its content again, drops the tables of the modules gone for good and every source table whose rows are in Node, and carries jokes and media into Node for any other 6.2 site.
Core changes:
- Catch-up of a 6.3 site (public/update.php, storage/update/sql/table_update6_3.sql):
setUpdateArchive() rewrites the uploads/archive/<module>/ and old folder addresses of Node texts and their comments into [attach] or the file address of the material, and an archive address elsewhere into the address of the published material that carries the name
- a dry run (POST dry=1, "Count the file addresses") counts per column and writes nothing
- a manifest with counts, cursors and state; a stopped run continues, a verified unit is skipped
setUpdateMerge() takes the retired keys out of a 6.3 site and adds every shipped option it lacks from storage/backup/release/config/; without that folder the step refuses
The eight time columns of the early-October tables reach the forms of table.sql through runiftype(), each moment kept; a 6.3 db.php is written in the collation of the release
- Drop of the tables (public/update.php):
setUpdateTables(), at the end of the first stage, drops the tables of auto_links, clients, clients_down, money, order, partners, products and whois, and every source table of Node whose rows are all materials
- a published row by its _node_legacy row, a pending row by a material of its type with its title and creation time
- an empty table at once; a table with a row matched by neither stays, the report names up to ten ids
deleteMigrateTables() drops the table of a module right after its data step, once every row is a key of the map of the manifest and every material of the map is in _nodes; a manifest of another database keeps the table with a note
- The page of the second stage shows a carried module from its manifest
- Jokes and media (public/update.php, storage/update/sql/table_update6_3.sql):
- Both join getMigrateMap(); "Batch X" renames their 6.2 columns
The twelve own columns of media land in the extra fields of its profile, every http(s) address of its links becomes a resource of the download role, ed2k and other schemes leave a note
- The rating balances of both are carried
- Text of the second stage (lang/*.php):
- _NODE_MIGINFO says that the table of a module is dropped once its materials are carried, in all six locales
- Tests (tests/):
UpdateArchiveTest with the archive unit, the settings merge and the drop on a site of early October (a cp1251 table, a pending row, a row no address names)
The update62 fixture gains the 6.2 tables of jokes and media with a rated joke and a film; UpdateSiteTest checks their materials, fields, resources and ratings, the tables left after each stage, and a stale table that stays
- The probe adds its help request before the first run, because an empty source table drops there
- SchemaUpdateValidationTest skips jokes and media like the other source tables
- isTreeSkipped() no longer enters uploads/, whose copy of a site carries the PHP of old releases; TreeWalkTest holds it
- Reference (docs/NODE.md):
The run order, the schema file, the tests and the migration of the removed modules describe the catch-up, the drop and the two new modules
Benefits:
- The production database moves to the current code keeping every row and id it holds
- No table of a gone or carried module is left behind, and none is dropped while a row of it is not in Node
Technical notes:
- Drops tables with no archive: the gone modules for good, the source tables only once their rows are materials
- update.php remains the maintainer's tool and is not shipped in a release
The files under uploads/ belong to a site, not to the release; a copy of a production site laid out on the stand for the move to the current code would otherwise show as hundreds of megabytes of untracked files, private ones among them, one careless add away from GitHub.
Core changes:
- Ignore rules (.gitignore):
- /uploads/* ignores every folder and file of the upload tree
- !/uploads/presentation/ keeps the shipped presentation assets (brand, dna, sites) tracked as before
Benefits:
- No upload of a site, the production copy included, can reach the repository by accident
Technical notes:
The 214 tracked files under uploads/presentation/ stay tracked; a new shipped file outside that folder needs its own exception
- No code, schema or behaviour change
The multi-line comment blocks left in the remaining classes of core/classes/, the modules and panel screens, the CSS of both themes, the PHP entries and the JavaScript the release writes itself are cut to the one line the comment rule asks for: a fact outside the code, a decision that looks like a mistake, or a change that must not be made. With this commit no multi-line block is left; no line of code changed.
Core changes:
Remaining classes of core/ (core/classes/.php, core/classes/api/.php, core/system.php, core/apply.php, core/rescue.php):
the parser, feed, field, point, rating, cache, backup, editor, update, template, logger, quick, pdo and route classes and the API router and error cut to one line per function
- core/system.php, core/apply.php and core/rescue.php lose the blocks that retold their code
Modules and panel screens (modules/account, modules/forum, modules/presentation, modules/search, admin/modules/config.php, fields.php, monitor.php, newsletter.php):
- the blocks above the handlers of the modules and of the four panel screens cut to one line
- modules/presentation/index.php: the block of 26 lines above the collector of the page figures cut to one line
- CSS of both themes (public/templates/admin/assets/css, public/templates/lite/assets/css, the Toast UI skins):
- base.css, theme.css, dock.css, presentation.css and the two skin.css files keep one line where a rule needs a reason
- reasoning that retold the declarations below it, measurements of past rig runs and history are gone
Entries and own JavaScript (public/index.php, public/admin.php, public/templates/lite/index.php, public/plugins/system/*.js, public/plugins/presentation/presentation.js, public/plugins/altcha/altcha-init.js, the two CodeMirror build modes, public/templates/admin/assets/js/admin-ui.js):
- the blocks of the two PHP entries and of the theme entry cut to one line
slaed.js, filemanager.js, emoji.js, global-func.js, presentation.js, altcha-init.js and admin-ui.js keep one line per function
Benefits:
- A comment line is a claim worth checking rather than a retelling to skip
- The comment rule now holds across the whole release, PHP, CSS and JavaScript alike
Technical notes:
- Comments only: with comments and whitespace removed, HEAD and the commit are identical in all 51 files
- php -l passes on the 33 PHP files
- No schema, URL, API or behaviour change