Официальный сайт SLAED CMS
Журнал изменений
The site builder moves on by two steps of its plan: the panel screen "Конструктор сайта" edits a draft of the layout and of the blocks - structure, frame of the page, inspector, library, settings and palette - and the button "Опубликовать" carries that draft to the site in one transaction of the layout, the addresses of its pages and the rows of _blocks. A second editor or a site changed meanwhile is refused instead of overwritten, an unsure commit is finished by a witness row, and the last ten publications can be brought back into the draft.
Core changes:
The panel screen of the builder (admin/modules/layout.php, config/modules.php, partials/layout-*.html, fragments/layout-field.html, assets/css/layout.css, assets/js/layout.js, layouts/admin.html):
the module layout of the super administrator, every write a POST through checkAdminPost('layout'); the screen covers the window (is_full drops the shell of the panel) with the tree, the frame of the draft and the inspector
the draft lives in storage/layout/draft.json: the layout, the changed, new and deleted blocks with the rows they began from, the name and the logo of the site, and fifty steps of Undo and Redo
the frame shows the page by the signed link of the draft and reloads where it stood after every write; a pick fetches the inspector, a write swaps the tree, the inspector and the state out of band
the fields take their types from Field, the kinds of the builder (markdown, file, focus, icon, tone, choice) their own checks; the library of sections, the settings with the screens that keep the rest, one Ctrl+K
The entries and the canon the screen takes (fragments/dock.html of both themes, menu-grid-item.html, menu-list-item.html, assets/css/theme.css and base.css, plugins/system/slaed.js, core/system.php):
- "Конструктор сайта" is an app of the floating menu after the app of the page
- a card of the grid may carry the schema of a section, a row of the list a level and attributes of its own
the capsule of the editors gets a state shown at once, a window held at its top; a select of pictures keeps its preview after a swap of htmx
The publication (core/classes/layout.php, core/system.php, core/classes/update.php, admin/modules/layout.php, partials/layout-state.html):
layout joins the shared areas of setConfigFile(), so config/layout.php is written in the Closure form with its native types; Update::SHARED takes it outside the check that a shared pack brings node.php
Layout::setPublish() checks the published file against the checksum the screen opened with, writes the blocks through the module (each row against the row the draft began from), marks the addresses of deleted pages gone, moves a renamed page with its former address kept for 301, and saves the layout with the path each page got
- the proof of the operation is the first written row whose fingerprint changed (Layout::getWitnessHash(), a row
of _blocks or the rows of _routes of a page); setConfigRestore() reads it FOR UPDATE as it reads the type row
of Node, and a row matching neither side keeps the marker
- the name and the logo of the site follow by the string form into config/global.php; a failed write keeps them
in the draft and says so
refusals with nothing written: a block changed in "Блоки и баннеры", a site changed after the screen opened, an address the registry does not take
- the restore screen of the configuration names the proof of a publication
Two editors and the history (admin/modules/layout.php, partials/layout-screen.html, partials/layout-story.html, assets/js/layout.js):
the draft carries its revision, its time, its writer and the screen that wrote it; every write posts the screen and the revision it saw, and a write over the change of another screen is refused by name and time
the last ten publications are files pub-<n>.json with the author, the layout, the blocks and the name and logo of the site; the window "История публикаций" brings one back into the draft as a step with Undo
- Languages, help, docs and tests (admin/lang, lang, admin/info/layout, docs, tests, tools):
- the words of the screen and of the publication in six locales
- the help of the builder in its current state; docs/NODE.md and docs/UPDATE.md for the five shared areas
LayoutDraftTest over the lifted functions of the module; LayoutPublishTest over real requests of route_probe.php publish: the refusals, the publication, the addresses, the history and an unsure commit both ways; ConfigFileTest over the five areas and the witness row; the audit baseline and the contrast registry
Benefits:
- A site is changed in one step that either lands whole or not at all, never half a layout with old blocks
- A second administrator or a screen left open cannot write over another one's work unnoticed
- Every publication can be taken back from the history
Technical notes:
- Stored data: storage/layout/ holds the draft and the history, outside the document root and never in a package
- config/layout.php is now written with native types; the reader still takes the text form an older save left
- The stand keeps its own config/layout.php outside this commit
The site builder moves on by three steps of its plan: the header, the menus and the footer of lite are drawn from the layout and the places the theme describes, the blocks get one writer of their position and order with a Node type choosing its own columns, and the panel has one drag for the rows of a table and of a list, which the menu of the panel takes for an order of each administrator. Beside it the lamp of the cockpit becomes a disc of glass with the count of the passed checks and a bar for each, rests in a lull on a quiet site, and the demo series of the monitor and the statistic follow it.
Core changes:
The chrome of lite from the layout (public/templates/lite/places.json, partials/site-header.html, partials/site-footer.html, partials/menu.html, index.php, blocks/menu.php, core/classes/layout.php, config/layout.php):
places.json describes the parts of lite with their fields, the two menus with their depth and the zones of blocks; its labels are language constants
the header, the line under the logo, the top links, the band before the footer, the contacts, the marks of the footer and the side tabs are drawn from the layout; sitename and site_logo stay in config/global.php
blocks/menu.php prints the main menu of the layout; the shipped layout carries neutral menus of the site's own sections and no data of slaed.net
- the marks of the technologies move from templates/lite/images/tmp/ to uploads/presentation/brand/tech/
Blocks (core/admin.php, core/system.php, admin/modules/blocks.php, blocks/node.php, public/index.php, storage/update/sql/table_update6_3.sql):
setBlockOrder() is the one writer of the position and the order of _blocks: add, save, delete, fix and the drag order go through it, a zone numbered from 1 and closed up behind a row that left it
getBlockWhich() and isBlockShown() read which as the columns do; the pages of the builder (page-<key>) are places of "Отображать блок в модулях"; a block with a lost file or a place no page answers is marked in the list
- the positions b and f are gone: the update moves their rows to the end of the centre below
a Node type keeps the columns of its pages in its settings (view.side and view.top, config/node.php, the profiles, NodeQuery::filterViewRule()); the node block takes a list of types
[block=id] prints its free block in a trusted rendering and is kept from every writer but the super administrator (filterTrustedTags(), Parser::filterFreeBlocks())
One drag of the panel (public/templates/admin/assets/js/admin-ui.js, fragments/menu-list-item.html, partials/block-sidebar.html, admin/index.php, core/system.php, assets/css/theme.css):
a row is any [data-sl-drag-id] taken by its sl-drag-handle; a list with data-sl-drag-url posts its order and swaps in the answer, a list with data-sl-drag-event raises that event with the id, the new order and the order before
- a row moves within its own list and group, anywhere else it shows the mark of a refusal
the sidebar menu raises sl:menu-order and keeps the order of its administrator in the cookie menu through op option; getAdminSectionList() sorts by it, so the sidebar, the cards of the home and "Все разделы панели" follow
the handle of a menu row lies over its icon under the pointer and in focus, a click on it opens the section, the rail has none; the drop marks of a menu row stand beside its plate
The lamp of the cockpit (core/monitor.php, partials/cockpit.html, assets/css/base.css and theme.css of both themes, modules/presentation/index.php):
a disc of glass (--sl-gauge-bg, --sl-gauge-shadow) with the mark, the passed checks of fourteen, a bar for each check and the word of the state
- getCockpitTone(): the worst signal, and with every check passed a lull while the hour counts under twenty pages
- the hero of the presentation shows the same lamp with every check passed
- the link words of the Toast UI editor take the link of the theme, which holds 4.5:1
The demo series of the monitor and the statistic (public/demo/mon-.html, st-02-cockpit.html, assets/mon., assets/st.*, demo/admin/):
the cockpit of the stand draws the lamp of the theme with its pace of the running hour; the own rules of the admin demo that the theme now carries are gone
- Languages, help and tests (admin/lang, lang, admin/info, modules/node/admin/info, docs, tests, tools):
the labels of the places of lite, the marks of a lost block file or place, the lull and "Пройдено N из M" in six locales
the help of the panel, of "Блоки и баннеры", of the configuration, of the monitor and of a Node type in their current state; docs/ARCHITECTURE.md, docs/NODE.md and docs/PARSER.md
BlocksTest on the probe, LayoutTest, the route probe, AdminGuardTest over the order of the menu, CockpitTest over the lull; ui-contract.php and the contrast registry
Benefits:
- No data of slaed.net ships in a theme, and a site keeps its chrome across a change of theme
- One writer of the place of a block, so no screen leaves a zone with gaps or two rows on one number
- One drag mechanism for the tables, the menu and the tree of the builder to come
Technical notes:
- Stored data: the update moves the blocks of b and f; a Node type gains view.side and view.top
The cookie menu holds module keys only, no more than the modules of the site; without it the order is that of config/modules.php
- config/layout.php carries the neutral shipped default; the stand keeps its own layout outside this commit
The site builder moves on by three steps of its plan: a page of the layout is a row of the address registry at the root of the site, the theme lite draws sixteen types of section on the classes of its presentation, and a module brings a type of its own with a provider and a default fragment. Beside it the demo stand gets two series of the panel, the statistic redrawn eight ways and the monitor four ways, the cockpit of the monitor carrying the pulse of the server, and the chart of the presentation gets washes under its lines.
Core changes:
The page of the layout at its address (core/classes/route.php, core/classes/layout.php, public/index.php, core/system.php, core/security.php):
the kind page of Route lives at the root: its own check of the name under the grammar of a slug, the empty prefix in addRouteRow() and isRouteReserved(), 301 from a former path and 410 for a deleted page
a page of the layout carries the name page-<key> in $conf['name'], its title, description, og:image, robots and canonical address through setHead(), and its entry in the sitemap
- the page 404 of the layout answers through setError() with the code kept; a page may be for users only
the read-only link of the draft: a signed token with a term over storage/layout/draft.json, noindex, the mark "Черновик" and the answer 403 for a dead link; storage/layout/ is ignored by git
- The sections of lite (public/templates/lite/sections/, fragments/section.html, assets/css/presentation.css):
- "Основа": hero, features, media, text, steps and cta, each a description sections/<type>.json and a fragment
the other groups: gallery and video, stats, voices and team, faq, prices and map, embed and own HTML
- the fragments of the feed, the record and the block wait for their data without a description
- every section stands in the frame of a presentation section with its number, anchor, devices and dates
- the alt of a picture, its point of focus (--sl-d-focus), Markdown through Parser::filterDoc() with the module layout
the own rules sl-sec-* only where the presentation has no form: the picture beside a text, the claim, the columns, the frame of an outside service, the cards of the contacts
- The rendering of a section (core/classes/layout.php, core/classes/template.php, public/plugins/system/slaed.js):
the kinds code, video, page and point: raw HTML of the super administrator, the privacy mode of YouTube or a film of the uploads, a page of https alone with its host, a map of OpenStreetMap from one field "lat, lon"
an outside frame waits behind a placeholder, the picture of the section or its icon with a button, and asks the outside server only after the click; slaed.js puts the frame of the template in its place
- every fragment gets the values of the theme of the layout as parts and every item is_first
- a section whose fragment prints nothing loses its frame and its number
Template::getHtmlSection() renders the default fragment a module brings where the theme has none, held inside the folder of that module
- The showcase of sites as a type of the module presentation (modules/presentation/):
sections/sites.json, the provider sites.php and the default fragment sites.html; lite draws it on fragments/presentation-site.html
getPresentationSites(), getPresentationBrand(), getPresentationDna() and getPresentationVoices() move into common.php, so the provider never runs the module
- The chart of the presentation (public/plugins/presentation/presentation.js, partials/presentation-rhythm.html):
- a chart marked data-sl-pres-fill="all" lays a wash and a soft shade under every line, as the monitor of the panel
The demo series of the statistic and the monitor (public/demo/st-.html, mon-.html, assets/st., assets/mon., assets/demo.js, README.md):
- the statistic: eight faces of admin.php?name=statistic on one engine and one corpus of the counter
the monitor: four faces of admin.php?name=monitor on the engine of the statistic, the findings of the live page drawn mended
- the lamp, the state and the checks follow thirteen signals of the server and its programs, not the checks of SLAED
- the lamp of the cockpit shows the pulse of the server: the heart, the rate, a running cardiogram and the mood in
the tone of the state, with the scene "Ночь" of the stand
- Languages and tests (admin/lang, lang, modules/presentation/lang, tests):
- the labels of the sections in six locales, the words of the draft and of the outside frames on the site
LayoutTest holds the shape, the kinds, the outside frames and the type of the module; RoutePageTest and RouteRegistryTest hold the page at the root
Benefits:
- a page of sections is a page of the site with its address, SEO and sitemap, without a module of its own
- a section of a site visits no outside server before the visitor asks for it
- a theme brings only markup and a schema, a module brings its own types with their data
Technical notes:
- config/layout.php stays version 1; a page of the builder is a row of _routes of the kind page with its number as oid
- tools/ui-contract.php declares --sl-d-focus and --sl-d-frame
- no change of the database schema; the stand database and uploads/ are unchanged
The cockpit of the panel home made the site slow: every poll ran its own PowerShell probes, parallel polls ran them at once and each held the session of the administrator while it did. The server is now sampled by one writer under a lock into storage/logs/monitor.json, every poll lets the session go, and the load of a page becomes part of the statistic, so the panel shows its history by day and by hour. The layout of the site arrives with its own class.
Core changes:
- One writer of the server sample (core/monitor.php, admin/modules/monitor.php, core/system.php):
getMonitorSample() retakes a sample older than ten seconds under the non-blocking lock monitor-sample.lock
- a request that does not get the lock reads the file as it stands, so no probe ever runs twice at once
- the cockpit poll and the HTMX polls of the monitor ask for a fresh sample, the monitor page and the
presentation only read
- the monitor job takes the same sample once a minute and fails when it is older than a minute
the sample holds CPU, memory, disk, network and disk-io rates with timed histories, uptime, cores, the server software and the uploads size, retaken once an hour instead of on every monitor page
- monitor.json is written once per sample: the history functions take and return the sample
- the chart labels each point by its stored time; the live chip of the cockpit shows the age of the sample
- One PowerShell run per sample on Windows (core/monitor.php):
getWindowsProbe() reads load, cores, clock, memory and boot time in one run through proc_open()
- killed after ten seconds, so a hung WMI query never holds the lock
- a run that gave nothing writes no sample: the old figures stay and age instead of turning into zeros
- every OS check is PHP_OS_FAMILY; stristr(PHP_OS, 'WIN') also matched Darwin, so macOS had no CPU figure
- the duplicate open_basedir closures of getCpuLoad() give way to isPathAllowed() and getFileSafe()
- the Linux CPU share is loadavg / cores 100; it was 10 and showed a full server at ten per cent
- the cpu_details and memory caches leave, the WMIC fallbacks send their errors to NUL
- Polls release the session (core/security.php, public/index.php):
a request carrying X-SL-Poll calls session_write_close() right after the idle check
- the cockpit, the queue bell, the private message poll and the HTMX polls hold no other request of the visitor
- no poll handler writes the session after that point, checked handler by handler
- The load of a page in the statistic (core/system.php, admin/modules/statistic.php, statistic-extended.html):
updateStatsTrack() adds generation (ms), queries and peak memory (KB) of the page to hour fields 17-19 of statistic.log, beside the hits by hour, so they roll into days.log and the month archives
- the statistic page shows the average page per day with a total row and an average generation by hour chart
- the strip of the cockpit shows the average page of the running hour instead of the figures of its own poll
The layout of the site (core/classes/layout.php, config/layout.php, public/index.php, core/system.php, core/classes/template.php, core/classes/update.php):
- Layout reads config/layout.php: pages with their sections, the module slot, menus and the places of the theme
- the home page and the page of a module render through it; getBlocks() asks Layout::isViewShown() for the scale
- Template renders a section of the theme, sections/<type>.html
- an update adds new keys of layout.theme but never a page or a menu item the site deleted
- Help, documents and tests (admin/info, docs/ARCHITECTURE.md, docs/UPDATE.md, tests):
- the help of the monitor, the scheduler and the statistic describes the sample, the poll rule and the load columns
- CockpitTest holds the strip of the hour, LayoutTest the layout
Benefits:
- a cockpit poll costs 20-90 ms instead of 1.5-6.8 s, a page of the same session no longer waits behind it
- a sample costs about 1.7 s of PowerShell at most every ten seconds instead of several runs per poll
- the monitor page with expired extras renders in about 0.3 s instead of 4.3 s
- administrators see the load history of the site in the statistic
Technical notes:
- statistic.log gains fields 17, 18 and 19, twenty-four sums each; readers address fields by number, older days show a dash
- monitor.json gains cpu_p, cpu, mem, net, diskio, sys_hist_time, uploads and uploads_at
- the hours already counted on the day of the update carry no load and lower that day's average
- the rule that a poll handler never writes the session is documented, not held by a test
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