predefinedBlocks changelog
==========================

0.5.0-beta (2026-10-21)
- New: custom block field types file and files (documents with link text,
  upload with drag and drop, pick from the library, sorting); system setting
  predefinedblocks.file_media_source; upload connector parameter kind
  (image | file).
- Fixed: on Windows an absolute custom path (C:/...) was treated as relative,
  so custom block types were not found.
- Fixed: an image or file whose name contains two dots (e.g. "d._o._o..JPG")
  was dropped on save; only a ".." path segment is refused now.
- Fixed: an upgrade with "Use plugin CSS" reset a custom frontend_css or
  frontend_js (e.g. a copy in the theme) to the plugin's file; it now only
  fills an empty setting.
- Fixed (security): rich text was saved and rendered as sent, so an editor
  without edit_snippet could add <script>, on* attributes or javascript: links
  by posting past the RTE. Rich text fields (also in repeaters) are now
  sanitized on save and on render (Service::sanitizeRichtext); HTML without
  anything suspicious stays byte-identical.
- Fixed: saving a page wrote every shared block (a clone, or an original with
  clones) back as the editor had loaded it, so an edit made meanwhile on the
  other page was silently undone, even when the block was not touched. The
  editor now sends a fingerprint of the content it loaded (base); an untouched
  shared block is not written, and a changed one whose content was changed
  meanwhile by someone else is refused (pb.err_conflict).
- Fixed: "Duplicate with children" copied the blocks of the top page only;
  the copied child pages had no blocks (MODX fires OnResourceDuplicate once).
  The blocks of all duplicated descendants are copied now.
- Fixed: restoring an older version in VersionX restores the content and
  properties but not the blocks, so the restored content was silently replaced
  by the current blocks at the next save or rebuild. The block editor now
  compares the content with a render of the blocks and shows a notice when
  they differ (pb.ui.out_of_sync). The blocks are still not versioned.
- Fixed: when reading the blocks failed during mediaFal usage collection, the
  scan was stored without the block images, so mediaFal counted them as
  unused. The plugin now reports the failure (usage->fail(), when mediaFal
  supports it) and mediaFal keeps the previous usage rows.
- Fixed: the render fingerprint did not include the lexicon or the media
  sources, so changing pb.decimal_sep or a source's baseUrl did not re-render
  the pages on Clear cache. Both are part of templateHash() now.
- Fixed: pages were not re-rendered when a mediaFal file they use was replaced
  or renamed; rebuild() now also renders pages whose file changed after their
  last render (property rendered_at).
- Fixed: Clear cache rendered every out-of-date page in one request and could
  exceed max_execution_time after an upgrade. OnSiteRefresh now stops after
  half of max_execution_time (at most 20 s) and logs how many are left.
- Fixed: invalid UTF-8 in block settings or data made json_encode() return
  false and the block was saved empty; it is substituted (U+FFFD) now, and any
  other encoding error rolls the save back.
- New (accessibility): a Heading block that skips levels (e.g. h2 followed by
  h5; the page has h1, headings in rich text count too) shows a warning in the
  editor: choose the next level and enter the smaller look in Heading CSS
  (e.g. h3 + "h5"). The output stays as chosen.
- New: table header option "First column is header" and "First row and first
  column" (<th scope="row">); the caption field explains what it is for.
- Fixed (accessibility): an embed without a title from the provider was named
  "Video" in English; the name comes from the lexicon (pb.embed.fallback_title)
  and is also added to an oEmbed iframe without a title. The link shown for an
  unsupported embed no longer opens a new window.
- Fixed (accessibility): images and files could only be reordered by
  dragging; they have move buttons now. The file remove button said "Remove"
  (image) and the block up/down buttons had no aria-label.

0.4.2-beta (2026-10-20)
- Fixed: the block editor did not open when creating a new resource (e.g.
  Collections "add child", a template set with &template); the plain Content
  field was shown instead. MODX does not pass the resource to
  OnDocFormPrerender on create; the editor now uses the create controller's
  resource.

0.4.1-beta (2026-10-18)
- Fixed: TinyMCE RTE with the autoresize plugin in Firefox: the editor height
  flickered (text drawn twice, fields below shaking) because of the fixed
  content_style html {overflow-y: auto} of TinyMCE RTE.

0.4.0-beta (2026-10-18)
- New: template properties pb.blocks (blocks offered in the catalog; blocks
  already on a page stay editable), pb.image_max_width (content width for
  images), pb.frontend_css / pb.frontend_js (override the system settings,
  empty = nothing). Useful for e-mail templates.
- New: template property pb.custom_types (Custom block types offered in the
  type selector; existing blocks of other types stay editable and rendered).
- New: image and images fields of custom blocks are resized ({$image.src};
  {$image.url} stays the original); header options size=<px> and
  ratio=<w:h>.
- Changed: the example type pricing.tpl outputs the resized image
  ({$image.src}, size=440).

0.3.0-beta (2026-10-15)
- New: Layouts and sections (template property pb.layout, file
  layouts/<name>.tpl). Sections are tabs in the editor; the whole layout is
  rendered into the page content; empty sections are ''. Blocks of unknown
  sections are shown in the tab "Unassigned" and are not rendered. Example
  layout sidebar.tpl.
- Fix: a clone could change the original on a page the user may not save;
  such clones are now read-only, and moving a block from another page checks
  that page's permission.
- Fix: a database error while saving blocks was not detected (PDO silent
  mode) and could save half of the blocks; now nothing is saved and the
  editor shows the error.
- Fix: saving while images were uploading lost those images; saving with an
  unfinished Clone block silently dropped it. Saving is now stopped with a
  message.
- Fix: editor requests ignored HTTP errors and expired sessions.
- Fix: original and clone on the same page overwrote each other; only the
  first one is editable now.
- Fix: front-end blocks.js toggled every collapse element on the page (e.g.
  the theme's navbar); it now handles only the plugin's accordions.
- Fix: table row/column buttons before a cell was focused, image preview
  after paste, memory leaks (media browser, Ace), select default "0",
  javascript: links in the mini editor, cut of an unsaved block.
- Template fingerprint includes the plugin version and the layout, so Clear
  cache re-renders all pages after an update.
- Fix: a read error (e.g. table not yet upgraded) emptied the content of
  pages on re-render; now nothing is changed and the error is logged. Pages
  copied by "Duplicate with children" no longer lose their content at a
  publish deadline.
- Fix: installer upgrade works on MySQL 8 (no MariaDB-only ALTER syntax).
- Security: javascript: links with control characters, embed links that are
  not http(s), changing "Do not parse tags" without edit_snippet, moving or
  purging blocks on pages without save permission, very large images (memory).
- New DB column pb_block.section (added on install/upgrade).
- Security: SVG files can no longer be uploaded from the block editor (an SVG
  can contain scripts); uploads must be real images and respect the MODX
  setting upload_images. Existing SVGs can still be chosen from the library.
- The content of a page with blocks can only be changed in the block editor:
  Quick Update and other saves that change it are rejected with a message
  (the change would be lost at the next render).
- Text and images: responsive layout (col-md-*; on phones images and text are
  stacked, at most 2 gallery columns, 3 for 6 columns).
- Images are uploaded through the media source (uploadObjectsToContainer), so
  sources with their own index (e.g. mediaFal: virtual folders, duplicates)
  register them; errors of the source are shown to the editor. New upload
  path token {folderId} (435 -> 4/3/5).
- Custom block: repeater fields in the header (indented item fields, max,
  item_label), types without fields (always rendered, e.g. a MODX tag that
  runs on the page), text option accent (*part* -> <span class="accent">).
- Link fields accept a page ID with an anchor (22#parents -> [[~22]]#parents).
- mediaFal (optional): images in blocks are reported to its file usage
  tracking (event OnMediaFalCollectUsage). No dependency on mediaFal.
- Re-rendering a page is locked (GET_LOCK), so a publish deadline, Clear
  cache and an editor save do not overwrite each other.

0.2.0-beta (2026-10-12)
- New: Custom block. Developers add section types as Fenom templates
  <name>.tpl in a custom folder (template property pb.custom_path, or the
  general folder in the setting predefinedblocks.custom_path); the fields are
  listed in the template header. Editors choose the type and fill in the
  fields. Two example types included: "Call to action (example)" and
  "Pricing package (example)". Until a type is chosen, the block shows the
  folders it reads (and a warning when there are no types).
- New field types: textarea, link (page ID or URL); field option width (1-12)
  in the editor.
- Bootstrap is optional: plugin stylesheet blocks.css and accordion script
  blocks.js are added to pages with blocks (settings
  predefinedblocks.frontend_css / frontend_js). Install option: plugin CSS or
  Bootstrap.

0.1.0-alpha (2026-10-07)
- First public alpha.
- Blocks: Heading, Text and images (text, images beside text or gallery,
  columns, aspect ratio, enlarge on click), Table, List, Embed (video:
  YouTube, Vimeo, Dailymotion, TED), Chunk / Snippet / Html, Wrapper
  (variant Accordion), Clone.
- Block editor instead of the Content field: drag and drop, arrows, copy / cut /
  paste between pages, visibility and publish / unpublish date per block.
- Fenom block templates with per-template override folder and fallback.
- Pages re-rendered on "Clear cache" when block templates change.
- Known limitations: unsaved block changes are lost when the template is
  switched in the form; blocks of child pages are not copied on "duplicate
  with children"; old resized images are not removed; no ContentBlocks
  migration; no multilingual (Babel) support yet.
