Перейти к содержимому
История версий

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

Следите за каждым улучшением, исправлением и новой функцией в развитии Blok

  1. v1.16.0Минорный7 окт. 2026 г.
    Ломающее изменение

    Saved rich text is segments — Rich fields in every host save now hold a RichText segment array instead of an HTML string.

    • Covers save(), onSave, BlockAPI.save(), onChange saves, getBlockData() and importMarkdown(), also with collaboration and dataModel: 'legacy'. getBlockData() returns a new .data object each call.
    • Input still accepts HTML. Read a field with richTextToHtml, and convert stored documents with migrateToRichText from @bloklabs/core/migrate.
    • ParagraphData and its siblings now type text as RichText. Tool subclasses use the new ParagraphToolData and siblings, with text: string.
    Ломающее изменение

    HTML and Markdown importers return segments — htmlToBlocks, markdownToBlocks, their WithReport forms and the .NET FromHtmlAsync and FromMarkdownAsync return rich data.text as segments.

    • Old: "a <b>b</b>". New: [{ text: 'a ' }, { text: 'b', marks: { bold: true } }].
    • Pass the output to the editor or the view as is, or read a field as HTML with richTextToHtml.
    Ломающее изменение

    Collaboration speaks format 2 — Rooms store rich text as formatted text, so the editor and the sync server must upgrade together.

    • The client ends a format-1 room with unsupported-format, drops format-1 offline copies and never sends format-1 outbox rows.
    • Blok.Server migrates a format-1 room once on open, under a new lineage. A third-party sync server must announce format 2 and mint a new lineage at epoch + 1 when it migrates.
    • The write-back PUT to your document endpoint now carries segments. List custom rich fields in --rich-text-fields or options.RichTextFields.
    Ломающее изменение

    Saved output keeps content it used to drop — Some documents now save blocks that earlier versions lost.

    • With dataModel: 'legacy', a legacy list keeps every item and saves in the 'auto' shape: one list block per root item, checklists as style: 'checklist'.
    • A table child that no cell names, with content, now saves at the root after its table. Empty ones are still removed.
    • Video Loop Off now saves loop: false. Treat false as off instead of checking for a missing loop.
    Ломающее изменение

    Tab sync is on by default — Tabs of one browser showing the same document now share one live copy, and only the leader tab saves.

    • Only the tab the user works in calls onSave and writes through persistence. Set tabSync: false to keep the old per-tab saving.
    • save() output now carries a top-level id, the document record id. Allow the new key if you compare OutputData strictly.
    • Locale, theme mode and width now follow across tabs. Set tabSync: { settings: false } to keep them per tab.
    Ломающее изменение

    Toggle open state is no longer saved — Toggles and toggle headings keep their open state per browser, and load collapsed by default.

    • isOpen is no longer read from input, written by save(), or part of ToggleData and HeaderData.
    • Expanding or collapsing no longer fires a document change.
    Ломающее изменение

    Blocks API keeps the tree in order — Placement calls now give a block the parent its position implies, and loaded data is reordered depth-first.

    • blocks.insert() at an index inside a container makes the block that container's child. Insert after the whole subtree, or call setBlockParent(id, null) afterwards.
    • blocks.setBlockParent() moves the block and its subtree to the end of the new parent's subtree, or just after the subtree it left. Re-read indexes after reparenting. blocks.insertInsideParent() clamps its index into the parent's subtree.
    • Block.isEmpty is true for empty toggles, toggle headings, list items, checklist items and code blocks, and false for any block with children.
    Ломающее изменение

    Two API calls now refuse instead of acting — blocks.convert() can reject, and undo or redo do nothing while read-only.

    • blocks.convert() rejects when a peer is editing the block, where it used to resolve and could overwrite their text. Await it and handle the rejection, or retry later.
    • history.undo() and history.redo() are no-ops in read-only mode. Call readOnly.set(false) first.
    Ломающее изменение

    Markdown and HTML output changed — Exports keep line breaks, table cells, quote captions and legacy blocks, so their text differs.

    • Markdown writes <br> as a hard break, escapes \*, \[, \# and \<, writes equations as $…$ and adds :---: alignment. Use markdownToBlocks instead of custom regexes.
    • importMarkdown reads GitHub alerts (> [!NOTE]) as callout blocks, not quote. A host without the callout tool should map them.
    • Legacy warning, linkTool, raw, attaches and toggleList blocks now render in /view. A legacy quote caption exports as an attribution line inside the quote. Update snapshot tests and warning-text matches.
    Ломающее изменение

    HTML table import reads more structure — htmlToBlocks reads cell colors, placement and widths, and treats a heading column more strictly.

    • Rows that all start with <th>, without <thead>, now import a heading column only, not also a heading row.
    • Cells carry color, textColor and placement from inline style. blocksToHtml can write data-blok-col-widths and data-blok-stretched.
    Ломающее изменение

    Loading skeleton is on by default — The editor shows a skeleton while persistence.load() runs or until the first collaboration sync.

    • When load() takes over 150 ms, isReady, onReady and autofocus resolve after the skeleton hands off, up to about 0.9 s later.
    • The wrapper carries aria-busy and an overlay child while loading.
    • Pass loader: false to keep the old timing and blank boot.
    Ломающее изменение

    Blok owns Cmd/Ctrl+F — Cmd/Ctrl+F inside an editor opens Blok's find bar, not the browser's.

    • This also applies on the page body when the page has one editor.
    • Pass find: false to keep the browser's find.
    Ломающее изменение

    Hints wait for hover — api.tooltip.show and api.tooltip.onHover never show a hint at once, and focus no longer opens one.

    • The default delay is 500 ms, and any delay below 300 ms becomes 300 ms.
    • For an always-visible label, render it yourself and set an aria-label for keyboard users.
    Ломающее изменение

    contentAlign follows the reading direction — In an RTL editor, 'left' and 'right' now mean the start and end of the line.

    • The default 'left' now puts an RTL content column on the right. LTR editors are unchanged.
    • To keep the old placement in RTL, swap 'left' and 'right'.
    Ломающее изменение

    Gray selected states and one focus ring — Default token values changed so selected and active states are gray and focus rings use one blue token.

    • Now gray: --blok-icon-active-bg, --blok-popover-icon-active-bg, --blok-item-focus-bg, --blok-item-focus-shadow and --blok-database-card-border-active. --blok-icon-active-text is primary ink, and --blok-audio-bar-head no longer mixes in the accent.
    • Focus rings are 2px --blok-focus-ring, and --blok-video-focus-ring defaults to it. The light --blok-table-heading-bg is #f7f6f3, not #f9fafb.
    • --blok-search-input-bg, --blok-search-input-border and --blok-search-input-focus-border no longer style search fields; override --blok-item-hover-bg and --blok-popover-border. Set the old values in style.tokens to keep the old look.
    Ломающее изменение

    Old radius tokens and IconMarker removed — The unordered radius scale, --blok-audio-radius and the IconMarker icon are gone.

    • --blok-radius-xs → --blok-radius-4, -md → --blok-radius-control, -lg → --blok-radius-12, -xl → --blok-radius-16, -md-plus → --blok-radius-8, -hairline → --blok-radius-notch, -none → 0, -sm → a role token.
    • Replace --blok-audio-radius with --blok-radius-block or --blok-radius-control.
    • Replace IconMarker from @bloklabs/core/icons with IconPaintRoller.
    Ломающее изменение

    Mermaid 12 renders code-block diagrams — Mermaid previews use ELK layout and mermaid 12's new look, so diagrams change layout and color.

    • Previews need Safari 17.4+, Chrome 117+ or Firefox 119+. Older browsers show an error instead of the diagram.
    • Saved data is unchanged, and there is no option yet to restore the old look.
    Ломающее изменение

    defineBlokSchema uses the editor's inline tool order — Inline sanitizer rules now compose in canonical editor order, not inlineToolbar or registration order.

    • If two inline tools have conflicting rules, check which one wins now.
    Ломающее изменение

    Blok.Server contract changes — Custom IBlokDocumentConverter implementations need new members, and /edit reads If-Match.

    • Implement GetPageIndexAsync, RemapPageDocumentAsync and the page-aware ToHtmlAsync and ToMarkdownAsync overloads, for example by forwarding to BlokDocuments.Create().
    • POST /sync/{doc}/edit with an If-Match header now gets 400, 412 or 428 instead of 204. Leave it out unless you want the precondition.
    • Collaboration document IDs with literal or encoded backslashes are rejected. Rename them first.
    Добавлено

    Page block — A Page block points at a sub-page your app owns, showing its icon and title and opening it through your host.

    • Configure create, resolve, href and open to connect it to your pages.
    • create may return { pageId } to use your backend's id instead of Blok's.
    • Pass rename, setIcon and peek to show Rename, Edit icon and side peek in the block menu.
    Добавлено

    Tabs block — A Notion-style tabs block holds tab children, each with a title, optional emoji and its own child blocks.

    • Drop a block onto a tab's pill to move it into that tab.
    • The open tab is per-editor UI state and is never saved.
    • Markdown, HTML, plain text and Notion paste all handle tabs.
    Добавлено

    Table of contents block — A table_of_contents block lists the page's headings live, indented by depth, with click and keyboard jumps.

    • blocksToHtml renders it as a <nav> of links to the saved headings.
    Добавлено

    Find and replace — Cmd/Ctrl+F opens a Notion-style find bar with match case, whole word and Replace / Replace all.

    • Matching ignores case, accents, curly quotes and dash kinds.
    • Replacements preview in the text before you apply them.
    • Set find: { placement, offset } to choose where the bar sits.
    Добавлено

    Live sync between browser tabs — Tabs of one browser showing the same document stay in sync live, with no server.

    • Set documentId when your app copies documents or serves every document at one path.
    Добавлено

    Loading skeleton — Placeholder rows show while persistence.load() or the first collaboration sync is pending, then hand off to the real blocks.

    • Choose the rows with loader: { skeleton } and the wait before showing with loader: { delay }.
    Добавлено

    Image darkroom — The image editor now crops, rotates, flips, straightens, adjusts brightness, contrast and saturation, and applies filters.

    • Every edit is non-destructive: saved as data and applied when the image is drawn.
    • Filters come with a strength slider.
    • filters in the image config picks, orders or adds looks, and [] hides the Filters tab.
    Добавлено

    Image markup — A Markup tab draws on photos with a pen and highlighter, adds text, and places shapes.

    • Marks turn and mirror with the photo.
    • Marks are saved in data.markup.
    Добавлено

    Failed image notices — Blok tells the user when an image fails to upload or load, and before they leave with lost uploads.

    • Each failed image gets its own toast card with Retry and Show.
    • onImageFailure reports failures to your app.
    • confirmLeave() shows a Retry / Show / Stay / Leave anyway banner and resolves to a boolean.
    Добавлено

    Media format variants — Uploaded images and videos can be converted into several formats in the background and rendered best-first.

    • Turn it on with media: { formats: { image, video } }.
    • Video conversion needs mediabunny: () => import('mediabunny'), which you install yourself.
    • Pass convert to use your own converter instead.
    Добавлено

    Upload error handling — Image, video, audio and file tools take onUploadError to change what a failed upload shows.

    • Return a string to show your own message, or false to return the block to its empty state.
    • A rejection from your own uploader now reaches the handler as UPLOAD_FAILED with the original error in cause.
    Добавлено

    Code block redesign — Code blocks gain an optional filename, a highlighted active line, a labelled Copy button and a language picker.

    • The picker suggests the detected and recent languages and recolors the code as you browse.
    • The new filename field is written to Markdown as a title="name" attribute on the code fence.
    Добавлено

    Toolbox hover previews — Hovering or arrowing to a toolbox entry shows a small animated drawing of the block with a one-line caption.

    • Custom tools can opt in with toolbox.preview, typed by the exported ToolboxPreviewConfig.
    Добавлено

    Concurrent typing in collaboration — Two people typing in the same paragraph now merge their text instead of one losing a burst.

    • Database row titles typed at once also merge.
    • A collaborator's selected text is now shaded, not drawn as a lone caret.
    Добавлено

    Host values in undo history — history.track(key, onChange) keeps a value your app owns, like a page title, in Blok's undo history.

    • Cmd+Z walks back through host and block edits in order.
    • Collaborators share the value, and it is not part of save().
    Добавлено

    Personal block state — api.viewState stores per-browser block state that is never saved in the document.

    • Toggles and toggle headings keep their open state here, so each reader's choice stays theirs.
    Добавлено

    Sibling-relative block placement — blocks.insertAt and blocks.moveTo place blocks by parent and sibling instead of a flat index.

    • Positions are 'start', 'end', { before } or { after }.
    • A bad place throws BlockPlacementError and changes nothing.
    • Block events carry parentId, previousSiblingId and an origin of 'local', 'tab' or 'remote'.
    Добавлено

    Rich text migration tool — @bloklabs/core/migrate converts stored HTML documents to rich-text segments offline, in Node with no DOM.

    • Use migrateToRichText, richTextToHtml and richTextToPlainText.
    • onLossy reports markup it could not map.
    Добавлено

    Smarter link field — An empty link field lists your three most recent links, the page's headings, and the link kinds it accepts.

    • Picking a heading links #<block id>, which survives a heading rename.
    • Set link.unfurl to show page titles for recent links, or let server fill it in.
    Добавлено

    Paste improvements — Pasted links and spreadsheets keep more of what you meant.

    • A URL pasted over selected text links that text instead of making a bookmark.
    • Excel cell bold, fills, colors and alignment survive paste.
    • List your own site's other hostnames in linkPaste.hostAliases so their links skip "Create bookmark".
    Добавлено

    Notion-style formatting menus — The inline toolbar is a Notion grid card, and text and background colors share one panel.

    • "Turn into" is a plain list with a checkmark on the current type, and now works on callouts.
    • Click an inline equation to edit it in a one-row menu with a live chip.
    Добавлено

    Bookmark and embed redesign — Bookmarks frame their cover in a leaning browser window with a favicon address pill.

    • Embed empty states draw each provider kind and morph as you type a link.
    • Embeds and the link paste menu show brand marks for covered providers.
    Добавлено

    Media empty and error states — Empty uploaders show a live preview of the block, and failures now look like the media they replace.

    • Failed video and audio cards offer a file picker to try again.
    • The video settings card shows speed, a speed ruler and a loop switch in one pane.
    • Right-click on page, bookmark, embed, file, image and video blocks opens their block menu.
    Добавлено

    Table alignment picker — Cell alignment picks from nine positions with a live preview of the cell.

    • Every row and column now has a stable id, so concurrent moves and deletes land on the right column.
    Добавлено

    Right-to-left export — blocksToHtml and BlokView take direction: 'ltr' | 'rtl' and stamp each block with its own text direction.

    Добавлено

    Server and .NET — The Blok server and Blok.Server gain page-aware exports, cross-page moves and C# ticket minting.

    • BlokTicket.Create mints ticket passes in C#.
    • --collab-journal adds durable /edit receipts for cross-page moves.
    • --rich-text-fields lists custom rich-text fields for the standalone host.
    Добавлено

    Tool author levers — New block tool statics replace per-tool workarounds.

    • isLayout and deletesChildren describe layout containers.
    • frameRadius rounds the selection fill to the block's frame.
    • prepareInsert lets a toolbox insert wait for data, and copyAsLink makes a copy carry a link.
    Исправлено

    insertMany and insertMarkdown deleted the rest of the document — Both replaced the whole shared document with the batch, so every other block vanished on the next load and for every peer.

    • The screen and save() still showed the old blocks, so nothing looked wrong until a reload.
    Исправлено

    Undo deleted a block someone else had typed in — Undoing your own insert removed the block with the other person's sentence inside it, on both screens.

    • Your own characters still go; theirs and the block stay.
    Исправлено

    A peer's edit swallowed the character you had just typed — A keystroke landing while a peer's change was applied to the same block was dropped on both sides, nested blocks included.

    Исправлено

    Two people filling one table cell lost a block — Each person's cell block list overwrote the other's, leaving one block orphaned and unreachable.

    Исправлено

    A full save deleted a key the other person had just added — A key a peer added during the save window, such as an image caption, was removed locally and then on their screen.

    Исправлено

    Two peers opening an empty document lost a whole paragraph — Both created the first block with the same id, and one person's typing was overwritten.

    • Two peers who open the same empty document at the same moment now get two empty paragraphs.
    Исправлено

    Every collaborative boot added another copy of a table's cells — Converted legacy cells reached the shared document but the table's references did not, so each boot converted them again.

    Исправлено

    A peer's edit threw your caret to the start of the block — Any remote update to the block you were typing in rebuilt its content and lost your selection.

    Исправлено

    Tools stayed half-dead after a collaborative boot — Blocks rendered read-only until the first sync never wired their editing when they turned editable.

    • Checklist ticks were not saved, code Tab and highlighting did nothing, and toggle placeholders and the database title stopped responding.
    Исправлено

    The last edit before destroy() never reached onSave — An edit inside the final save window was dropped on teardown, on an i18n repaint and when read-only turned on.

    • onSave, persistence.save, Vue update:data and the Angular outputs can now fire once after destroy() or unmount returns.
    • With only synchronous tools, the final onSave now runs inside destroy(). onSave can also fire once as read-only turns on.
    • Angular [(ngModel)] still misses the final save when any tool saves asynchronously.
    Исправлено

    Merged table cells lost styling and content — Merge, split, row and column operations dropped header styling, cell colours and alignment, and load deleted blocks left in covered cells.

    Исправлено

    Merging table cells misbehaved across the menu, reload and undo — The menu offered Merge instead of Split, block order in a merged cell changed on reload, and undoing a split left a ghost paragraph.

    • Malformed merge data is now repaired the same way in the editor, read-only mode and the view renderers.
    Исправлено

    Pasting into an existing table dropped everything around it — Only the pasted table was read; Excel, Google Sheets, LibreOffice and Word formatting was also lost.

    • The surrounding content now lands after the table, in order, as one undo step.
    Исправлено

    Pasted text lost its line breaks — Inline paste glued <br> lines together, and <div>-per-line HTML from Notion, Word, Gmail, Slack and Google Docs became one run.

    Исправлено

    Copying out of Blok lost bold, block breaks and code lines — Other apps received plain text for bold, merged blocks into one run, and collapsed code lines.

    • Marker colours are now written as the light preset colour, since Blok's CSS variables cannot resolve elsewhere.
    Исправлено

    Stored marks and plain text were stripped on load — Toggles lost bold and underline, sup and sub vanished when that inline tool was off, and media URLs were HTML-escaped.

    • Signed URLs containing & broke because they were saved as &amp;.
    Исправлено

    Legacy callout titles and table cell lists were lost on load — A callout's title was never read and the first save erased it, and lists inside legacy cells were flattened.

    Исправлено

    Converting text into a callout or a code block lost its lines — Line breaks and bold were stripped, and literal <b> in code turned into real bold.

    Исправлено

    Host data from blocks.insert reached the page unsanitized — insert, insertAt, insertMany, update and insertInsideParent let handler attributes and javascript: links reach the DOM and peers.

    Исправлено

    Markdown export could write a script link — href, image src and block URLs were written raw, so javascript: and crafted URLs became live links in unsanitized renderers.

    Исправлено

    Undoing moves pulled blocks into a toggle — Cmd+Shift+Up/Down moved blocks by a stale index, and undo restored a deleted block in the wrong place.

    • A keyboard move is now one undo step.
    Исправлено

    One table gesture took several undos and left phantom cells — Add-row and add-column drags split into extra steps, and added cells survived undo.

    Исправлено

    Toggles vanished, stuck or became columns when dragged — A block dropped below a collapsed toggle holding an open one was swallowed and hidden.

    Исправлено

    Text nested under a toggle child escaped the toggle — Collapsing the toggle left it visible, and inside a callout it rendered outside the box.

    • React, Vue and Angular containers mount these nested lines too.
    Исправлено

    Backspace could not merge a block that starts with bold, italic or a link — After Enter inside bold, the two halves could never be joined again.

    Исправлено

    An image's "…" menu deleted a different block — The menu opened for the block holding the caret, so Delete removed that block instead of the image.

    Исправлено

    A submenu stayed open after the pointer left — Its row stayed highlighted forever, and inline toolbar submenus slid under a fixed host header.

    Исправлено

    An RTL editor laid out left-to-right in production — The build lowered logical CSS into rules keyed on the page's lang, so an RTL editor on an English page broke.

    Исправлено

    RTL editing put controls and keys on the wrong side — Block controls covered the text, drag-to-nest nested almost every drop, and arrows stuck at block edges.

    • Popovers and submenus now open toward the inline end with mirrored chevrons and keys.
    Исправлено

    Blok.Server dropped edits held only in the working copy — A host-supplied journal or S3 working copy lost them when the journal started.

    • Blok-Doc-Lineage, Blok-Doc-Sequence and ETag are now exposed to browsers for If-Match retries.
    Изменено

    Yjs 13.6.33 and lib0 0.2.119, deduplicated — The bundled collaboration runtime moves up a patch and ships a single lib0 copy instead of two.

    Изменено

    KaTeX 0.18.10 — The bundled math renderer moves from 0.18.5.

    Изменено

    music-metadata 12 — The bundled audio title and artist reader moves up a major version.

    Изменено

    Office previews update docx-preview and @aiden0z/pptx-renderer — Word previews use 0.4.1 and PowerPoint previews use 1.3.0.

    Изменено

    Blok.Server takes AngleSharp 1.8.3 and Jint 4.16.4 — The NuGet package's HTML parser and JavaScript runtime move up a patch.

  2. v1.15.2Патч17 сент. 2026 г.
    Добавлено

    A server can tell a Blok document from any other JSON — BlokDocuments.LooksLikeADocument answers from the parse alone, with no engine and no instance.

    • ValidateAsync answered the same question only after walking every block, 294 ms on a 2000-block document.
    • It never throws, null included, and promises nothing about whether the blocks are readable.
    Добавлено

    Imported HTML keeps an image's width and alignment — FromHtmlAsync now fills the ImageData fields it already declared but never wrote.

    • Percentage widths, and float, margin or align alignment, land in the block.
    • A px width is skipped, because the container it was measured against is not in the HTML.
    Исправлено

    Escape out of a cross-block selection lost the selection — A selectionchange still queued from the drag reopened the inline toolbar, so the second Escape closed it again instead of selecting the blocks.

    • Re-selecting the same text, or pressing a formatting shortcut, still brings the toolbar back.
    Исправлено

    The Markdown exporter dropped four constructs without reporting them — A quote caption, an image's presentation fields, inline colour and highlight, and a table's merges, heading column and cell colours.

    • An image wrote its caption into the ![…] alt slot, hiding the author's alt text; the slot now carries data.alt.
    • Only non-default values are reported, so an ordinary document still reports nothing.
    Исправлено

    HTML import lost media inside single-field containers — A blockquote, a <summary> or a <figcaption> swallowed an image with no warning, and a <caption> was never read at all.

    • The image now follows as a block of its own, inside the toggle for a summary.
    • A table caption leads the table as a paragraph, reported as the downgrade it is.
    Исправлено

    An image inside a code block vanished on import — <pre> built its text from text nodes only, so the image left no block and no warning.

    Исправлено

    Legacy CMS bullets became one list per item — @bloklabs/core/preprocess read the newline between two block elements as a break in the bullet run.

    Исправлено

    The version-override extension could leave a page unarmed — Every status poll re-registered both content scripts, and a re-registration during the arming reload lost the payload.

    • The badge showed ON while the page still ran its own Blok.
    Изменено

    Blok.Server stops flowing BouncyCastle's compile assets — No public member takes or returns a BouncyCastle type, so no host needs it to compile.

    • A host that compiled against a BouncyCastle type through this package must now reference it directly.
    • macOS still loads it at runtime, because SslStream there drops X509ChainPolicy.DisableCertificateDownloads.
  3. v1.15.1Патч16 сент. 2026 г.
    Исправлено

    HTML import lost an image wrapped in an inline element — A Google Docs export wraps every image in a sized span, and the sanitizer dropped it with no warning.

    • Across eight legacy fixtures, 116 of 116 images now import, up from 93.
    • An image a list item carries in its text survives too.
    • An <a href> around an image is reported as degraded, because the image block has no link field.
    Исправлено

    An empty list item failed the whole import — <ul><li></li></ul> threw, and a .NET caller saw "This is not a usable Blok document" blaming the input.

    • An item holding only a nested list, a <br>, whitespace or a linked image failed the same way.
    Исправлено

    An element dropped from inside a paragraph was never reported — An <iframe>, <video>, <form> or unknown tag inside a <p> vanished in silence.

    • The same tag between two paragraphs already warned.
    • Block content inside a heading now converts through its own handler.
    Исправлено

    Sibling-nested lists and heading images were dropped — <ol><li>A</li><ol>…</ol></ol>, the shape Word and old CMSes emit, lost every item of the inner list.

    • Those items import one depth level in, where a browser renders them.
    • <h2>Title<img></h2> keeps the image, now split into a block of its own.
  4. v1.15.0Минорный16 сент. 2026 г.
    Ломающее изменение

    IBlokDocumentConverter gains three methods — Anyone implementing the interface must add FromHtmlAsync, ValidateAsync and ToPlainTextWithReportAsync.

    • Callers are unaffected. In practice this touches a test double.
    • There are no default implementations, because the only possible defaults would be silently wrong.
    Ломающее изменение

    A server timeout under 100 ms or an allocation budget under 8 MiB is rejected — Create and AddBlokDocuments throw ArgumentOutOfRangeException at the call.

    • Both floors sit below the measured failure points, so no value that worked now fails.
    • A host catching InvalidOperationException around construction no longer catches it.
    Добавлено

    HTML converts into blocks — FromHtmlAsync gives ToHtmlAsync an inverse, so a host importing legacy content needs no parser of its own.

    • Covers headings, lists with depth and start, tables with colspan and rowspan, images, details as a toggle, code with its language, and inline marks.
    • What it cannot represent is reported as a warning rather than dropped quietly, and the text always survives.
    Добавлено

    A server can say what a document is without converting it — ValidateAsync answers yes or no, and ToPlainTextWithReportAsync reports what the reader did not recognise.

    • A non-document is settled from the JSON in .NET, so no engine is spent on it.
    • ToPlainTextAsync is untouched, since '' stays the right answer for a preview caller.
    Добавлено

    The legacy CMS HTML cleaner ships as @bloklabs/core/preprocess — Standard DOM throughout, in both the string and the in-place form.

    Добавлено

    Three reachable-only-by-copying surfaces are published — matchEmbedService and buildEmbedUrl from ./tools, USE_BLOK_CONFIG_KEYS from the React adapter, and the four block mutation-type constants.

    • A stored link now migrates to exactly what a live paste produces.
    • The mutation-type constants had no runtime binding, so importing one type-checked and then resolved to undefined.
    Исправлено

    A table put every cell's blocks into the first cell when the editor booted detached — Every framework adapter mounts on a detached holder, where the anti-stealing veto went silent.

    • Users saw one cell holding every value and the rest empty, on every reload.
    • A container now claims a holder that descends from it, not only one that is connected.
    Исправлено

    A pasted table cell carried an invisible background — Word, Google Docs and legacy CMS HTML stamp the page background onto every td.

    • Near-white mapped to the grey preset, and white or transparent persisted into saved data.
    • A genuine light grey still maps to the preset.
    Исправлено

    The view renderer lost children declared only by content[] — A toggle's child rendered as a sibling in HTML, Markdown and plain text alike.

    • A content[] entry naming a block the document does not carry is now reported as a dropped construct.
    • Markdown import reports a URL it refuses instead of silently losing the image or the link target.
    Исправлено

    A paragraph holding only an image was deleted as an empty spacer — The legacy importer and the paste pipeline share one emptiness predicate now.

    • <p>&nbsp;</p> from Word or Summernote no longer arrives as a blank block.
    Исправлено

    Reduced motion did not reach navigation scrolling — scrollToBlock, the boot-time deep-link scroll and keyboard block navigation now skip the glide.

    Изменено

    A flaky CI attempt no longer strands a release tag — The mirror gate polls until CI is green or the hour is up.

    • v1.14.0 never reached the mirror, because the gate exited on the first terminal conclusion.
  5. v1.14.0Минорный16 сент. 2026 г.
    Ломающее изменение

    collaboration:status reports participants, not peers — One entry per person instead of one per connection, and the editor draws no presence stack.

    • Each participant carries lastActiveAt, clientIds and the verified userId. clientIds[0] is the old clientId.
    • CollaborationPeer is removed. user.name, user.color and blockId carry over unchanged.
    • [data-blok-presence-stack], [data-blok-presence-avatar] and [data-blok-presence-overflow] are gone. Draw your own stack from participants.
    Ломающее изменение

    Offline collaboration requires collaboration.offlineScope — The local copy belongs to a person now, not to the browser.

    • Pass a stable, opaque id for the signed-in account, such as offlineScope: currentUser.id.
    • Never pass anything that rotates. A ticket or a session id mints a new partition on every refresh.
    • collaboration: { doc, offline: true } without a scope rejects the editor's ready promise.
    Ломающее изменение

    A host onSave no longer replaces the persistence save queue — The two compose, so an endpoint configured under persistence is finally called.

    • Vue's v-model:data and Angular's [formControl] synthesize an onSave, so those adapters reached no endpoint at all before.
    • api.handlers.set() no longer overwrites the queue, which used to kill autosave for the rest of the session.
    Ломающее изменение

    19 duplicate icon exports are gone from @bloklabs/core/icons — Every icon is one drawing on a 20-unit canvas with a 1.25 stroke.

    • Import the survivor: IconMoveUp to IconArrowUp, IconZoomIn to IconPlus, IconCloseThick to IconCross, IconLinkCopy to IconLink.
    • The image-only aliases (IconCropImage, IconCaptionImage, IconImageAlignLeft and the rest) drop the Image suffix.
    • Survivors are 20x20 intrinsic where several removed icons were 14x14, so size them in CSS rather than relying on the intrinsic box.
    Ломающее изменение

    Asset deletion is paired with the uploader that stored the asset — A tool-level uploader's assets are no longer deleted through the editor-level one.

    • Add delete(url, ctx) to tools.<image|audio|video|file>.config.uploader, now typed, or its assets are never swept.
    • The server shorthand and the file tool's endpoints shorthand are unaffected.
    Ломающее изменение

    A block's lastEditedBy needs config.user.id — An edit made while config.user is unset now removes the previous author instead of leaving it.

    • Under collaboration, config.user.id is published to the room whenever collaboration.user.name is set.
    • Pass an opaque per-document token if an internal account key must not travel to peers.
    • A name a peer publishes about itself is unauthenticated, so it fills in only where resolveUser had nothing.
    Ломающее изменение

    Server conversions throw BlokDocumentConversionException — The JavaScript engine's own exception types no longer leave any IBlokDocumentConverter method.

    • Catch it and branch on its Reason. OperationCanceledException is unchanged.
    • ToPlainTextAsync takes includeHiddenText before the token, so a positional caller must name the token.
    • The allocation budget is 512 MiB and configurable, where 64 MiB failed on a 700 KB article.
    Ломающее изменение

    Readers see the text a media block carries but does not show — blocksToPlainText takes includeHiddenText, off by default.

    • An image's alt text, a media url, an embed source and a bookmark description can now reach a search index.
    • A quote's legacy caption is read by both readers unconditionally, so extractTexts yields one more string for such a document.
    • Re-extract before injecting, or the count check fails.
    Ломающее изменение

    markdownToBlocks imports a standalone image as an image block — It returned a paragraph carrying a raw <img> string.

    • Reference-style links and images resolve against their definitions instead of importing as nothing.
    • A legacy toggleList or columns reports action: 'degraded' where it wrongly said 'dropped', so match on action, not on the detail string.
    Добавлено

    Emoji from the keyboard — Typing : opens a picker inline, ranked by shortcode and then by keyword.

    • A closing colon commits an exact shortcode, and the insert is one undo step.
    • inlineEmoji: false turns the trigger off. The callout tool's icon picker uses the same component.
    • The picker has category icons, a tone switch, search, grid navigation and section jumps.
    Добавлено

    Collaboration says who is here and when they were last active — participants replaces peers, with a verified identity per person.

    • The room broadcasts verified identities, and each peer publishes an activity stamp about once a minute.
    • A block's settings menu names whoever actually edited it last.
    • Peers without a name draw as anonymous space silhouettes rather than a question mark.
    Добавлено

    The convert menu groups headings into families — A tab strip replaces one long list, with number strips for the levels.

    • Menu items outside the selected family stay hidden until you pick their tab.
    • The heading level is exposed on the menu item, so a host building its own menu can read it.
    Добавлено

    The block menus are laid out as one system — The inline toolbar is a single row, and the block menus are tiled with section separators.

    • Inline tools sit in a canonical order, whichever way they were registered.
    • The colour picker is split into Text and Background tabs.
    Добавлено

    A host can watch collaboration activity from the server — Blok.Server hands room activity to an observer you register.

    • HTTP edits and resets are journalled, so an edit that cannot be proven fails closed.
    • A member's presence is withdrawn when its tab leaves without saying goodbye.
    Добавлено

    The API reference reads in Russian — Every reference page is translated, not just the landing pages.

    Исправлено

    Autosave lost edits, wedged, and deleted live assets — Six defects in the save queue and the orphan sweep, each with a regression test written first.

    • The sweep deleted assets the live document still referenced, because an upload resolves before the payload naming it arrives.
    • A destroyed editor kept saving, deleting and reporting errors into an unmounted host.
    • onError never fired while the user kept typing, so a dead endpoint produced 75 rejections and no report.
    Исправлено

    A reload lost block positions, table text and undo under collaboration — The document is a projection of the shared state now, not a save receipt.

    • A prune-only flush is treated as normalisation rather than as an edit, so it no longer races a peer's write.
    • A stale-lineage sweep is no longer reported to the host as a server rejection.
    Исправлено

    The Markdown exporter destroyed what it exported — Conversion mutated the blocks it was handed.

    • Currency amounts no longer parse as maths, and a dropped footnote is reported rather than silently lost.
    Исправлено

    Focus rings appeared on mouse gestures — The keyboard-only gate did not reach, and where it did it stranded keyboard users.

    • The popover's focus cursor is drawn only for keyboard navigation.
    • A tabbable inside a hidden ancestor is skipped.
    Исправлено

    A submenu closed while the keyboard was inside it — The pointer grace period now stands down for a submenu the keyboard owns.

    Исправлено

    The toolbar's left-edge shield killed the plus button — The shield swallowed the click it was meant to protect.

    • The inline toolbar anchors to the selected text, keeps itself up for an unchanged selection, and no longer flickers on click.
    Исправлено

    A stored callout with no body rendered empty — The body paragraph is seeded on load, and the emoji trigger is rewired when read-only is turned off.

    Исправлено

    Legacy documents read wrong in the view renderer — Containment resolves from a container's content[], and a legacy embed's URL is read.

    • A table child that no cell references is indexed rather than dropped.
    Изменено

    Mutation testing runs against the whole source tree — A ratchet now fails the build, measured against a baseline built in batches.

    • A run is scoped by who imports a file rather than by what the file is named, and a reported mutant can be applied to its source by hand.
    • A sweep survives SIGKILL, reaps the workers a timeout leaves behind, and refuses to apply a mutant to a file that has drifted.
    Изменено

    blok-sync.v2 drains live — Writes are envelope-only, acknowledged by exact id, and quarantined on rejection.

    • Checkpoints publish on a committed-operation threshold, and a failed quarantine no longer loops the drain forever.
    • The v1 client is still what a browser negotiates. Do not build on the v2 frames yet.
    Изменено

    A release refuses to cut a tag whose workflows lack their secrets — The mirror gate and the delivery check are real checks now, not placeholders.

    Изменено

    Icons have a written house spec — src/components/icons/README.md records the canvas, the stroke and the shared frames, pinned by relationship tests.

    • The playground gallery previews every icon at 16, 20 and 24 px.
  6. v1.13.0Минорный3 сент. 2026 г.
    Добавлено

    Live collaboration — Real-time multiplayer editing, turned on with collaboration: { doc }.

    • Editors on the same doc see each other's edits, carets and avatars, named by collaboration.user.
    • offline: true survives a reload by writing document content to browser storage.
    • Every tool must support read-only, because a collaboration editor boots read-only.
    Добавлено

    persistence, server and ticket — The document wiring that used to be yours to write.

    • persistence: { load, save } loads on mount and saves as the document changes, against your endpoint.
    • Saves are queued, never parallel, and only the newest pending document is sent.
    • server fills in the uploader and preview endpoints. ticket names the endpoint minting an access pass.
    Добавлено

    Documents convert outside the browser — Blok.Server runs the editor's own serializer in-process.

    • AddBlokDocuments() registers it, and AddBlokServer already includes it.
    • IBlokDocumentConverter gives Markdown, HTML and plain text out, and Markdown in.
    • Markdown cannot express every block, so both directions report what changed.
    Добавлено

    Translate a document without handing a model its JSON — extractTexts and injectTexts move the prose past a model.

    • The model never sees the structure, so it cannot drop ids or reorder blocks.
    • URLs, file names and code blocks are left out of the list.
    • A list whose length does not match the document throws rather than misplacing a translation.
    Добавлено

    Markdown out of a saved document — blocksToMarkdown is the synchronous, DOM-free twin of markdownToBlocks.

    • Headings become #, lists - or 1., and tables GFM pipe grids.
    • blocksToMarkdownWithReport also names every construct dropped or emitted lossily.
    • Markup written into Markdown comes back as literal text, since Blok has no raw-HTML block.
    Добавлено

    A heading keeps the anchor its links point at — HeaderData.anchor renders as the heading's id.

    • It is captured from a pasted heading's own id, so in-document links survive a paste and a save.
    • restoreHeadingAnchors repairs documents already imported without it.
    • That pass reports every fragment it refused as no-match or ambiguous, rather than guessing.
    Добавлено

    An uploader can delete what it stored — delete?(url, ctx) is a third optional method on BlokUploader.

    • Blok sweeps the assets this session uploaded and then stopped using.
    • With the method absent nothing is ever deleted, which is what happened until now.
    • UploaderConfig.headers may now be a function, so a short-lived pass is minted per request.
    Добавлено

    Change a live document from outside the browser — POST /sync/{doc}/edit and /reset work over HTTP.

    • An edit inserts, updates or removes blocks, all-or-nothing, and reaches every open tab.
    • A reset reloads the document from your endpoint and tells every tab to pick it up.
    • Both require a pass with write: true naming that document.
    Исправлено

    Pasted HTML ran before anything sanitized it — A pasted <img src=x onerror=…> executed before clean() saw it.

    • Clipboard HTML was parsed into an element owned by the live document, which still loads resources.
    • Untrusted parses now use a document with no browsing context.
    • The URL scheme check moved inside clean(), so a pasted javascript: link is no longer clickable.
    Исправлено

    A long article could not be converted at all — An article that died on the server's engine now converts in milliseconds.

    • Both serializers reallocated the whole accumulated document for every block.
    • blocksToHtml also sent every inline field through a sanitizer that parsed twice.
    • Measured on the real engine: 600 KB went from failing outright to 7 ms.
    Исправлено

    A legacy document's nested content read as empty — Plain text, Markdown and HTML all dropped a legacy block's children.

    • Documents written before nesting moved to parent and content keep their children inside data.
    • Those shapes are now expanded once, in the document model, so every reader sees them.
    • One unreadable block is skipped and reported, rather than costing the caller the whole article.
    Исправлено

    Markdown export lost the fence language and the nesting — Code fences exported unlabelled, and Tab-nested paragraphs exported as code.

    • Four leading spaces after a blank line is an indented code block, so that indent survives only inside a list item.
    • A container rendered only its direct children, so a list inside a toggle lost every level below the first.
    • Lossy conversions now report what changed, instead of reading as "nothing was lost".
    Исправлено

    The caret did not survive a read-only round trip — Entering read-only remembers where the caret stood, and leaving it puts it back.

    • It holds on both the in-place toggle and the save, clear and render path.
    • The restore declines when the user focused something else, or when the block is gone.
    • A collaboration status blip that changes nothing no longer kills a live caret.
    Исправлено

    A link to somewhere on the same page opened a new tab — A bare #fragment reopened the whole document instead of moving inside it.

    • So did the absolute URL that "Copy link to block" hands out.
    • A fragment now scrolls, an identical URL does nothing, and a query-only difference navigates in place.
    • Following a link is reading, so the handler no longer unbinds in read-only.
    Изменено

    The server runs its own Yjs engine — Nothing it ships carries native code any more.

    • YDotNet and the native build matrix are replaced by a managed C# implementation.
    • Each wave was verified against a shared Yjs oracle rather than against itself.
    • A service account with no home directory now needs no configuration.
    Изменено

    blok-sync.v2 is on the wire, and deliberately not spoken yet — The service negotiates it, and the client still offers only v1.

    • The operation, acknowledgement and rejection codecs exist on both sides against pinned fixtures.
    • An operation id is settled and journalled before anyone can see the write.
    • Do not build on the v2 frames until the client negotiates them.
    Изменено

    The documentation site was one step from being indexed as its error state — A crawl recorded the homepage's only <h1> as "Application Error".

    • A component drew with Math.random() during render, so React 19 discarded the server HTML.
    • Docs had also not deployed for three days, blocked by a script demanding impossible release assets.
    • A post-deploy smoke test now asserts what the host actually serves.
    Изменено

    yarn serve starts the collaboration backend — The dev playground boots the sync service beside it.

    • Multiplayer is exercised locally by default.
    • Pass --no-server to run the playground alone.
    Изменено

    Gates and dependencies — The .NET solution keeps three test layers plus conformance and package smoke tests.

    • CI requires 80% line and branch coverage on merged production code.
    • It audits NuGet packages, scans for secrets, scans the built image, and analyzes C# with CodeQL.
    • Mutation testing runs on the diff alone, carrying surviving mutants between commits.
  7. v1.12.0Минорный26 авг. 2026 г.
    Добавлено

    @bloklabs/server is one C# implementation now, in two forms — The Go service that shipped in 1.11.0 is ASP.NET Core.

    • Blok.Server.AspNetCore runs the same handlers inside an app you already have, with no second process.
    • npx @bloklabs/server and ghcr.io/jackuait/blok-server still deliver the standalone host.
    • Routes, flags and every response wire are unchanged, pinned by a 58-case conformance suite.
    Добавлено

    Answers pasted from ChatGPT and Gemini keep their structure — A pasted formula used to arrive as roughly 870 layout spans.

    • Math is replaced by the <span data-latex> the equation tool already whitelists.
    • A code block collapses to one <pre><code>, and its language rides as data-blok-code-language.
    • There is deliberately no Claude branch: its share pages sit behind a bot check.
    Исправлено

    Markdown copied out of an AI answer lost half its structure — A code fence nested under a list item vanished without trace.

    • Nested content is emitted as sibling blocks, and later items carry start so markers do not restart at 1.
    • Fence languages are normalized through one module that knows the aliases models emit.
    • Bold, inline code and strikethrough inside a list item now survive a save.
    Изменено

    The Go implementation is gone, and the tag ships the C# one — It was removed only after the dual-target conformance gate passed unwaived.

    • The tag workflow packs both NuGet packages and proves them from an isolated feed.
    • It smoke-tests the archive and the container image before publishing anything.
    • The NuGet credential is minted over OIDC immediately before the push.
    Изменено

    Two gates that only CI could see — The dotnet format check was red on main from the day it landed.

    • The repository carried no .editorconfig, so the tool fell back to four-space indentation.
    • That produced 12689 whitespace complaints, and every step after it never ran.
    • The .NET tree now carries its own config, so a laptop and a runner agree.
  8. v1.11.0Минорный23 авг. 2026 г.
    Добавлено

    @bloklabs/presets — Ready-made uploaders, so config.uploader is no longer something every project writes.

    • supabaseStorage, presignedStorage, cloudinaryStorage, fetchStorage and indexedDBStorage.
    • Zero runtime dependencies: a vendor client is passed in, never imported, so your own auth session applies.
    • BlokUploader, UploadContext and UploadedAsset are now exported from @bloklabs/core.
    Добавлено

    @bloklabs/server — A sidecar handling file uploads and link previews, so you write no backend for either.

    • POST /upload, POST /upload-by-url and GET /unfurl, run through npx or the container image.
    • Uploaded bytes land in a local directory or any S3-compatible bucket.
    • Access modes none, proxy and ticket are enforced by startup interlocks rather than warnings.
    Добавлено

    Cross-block text selection — Dragging across blocks selects the characters under the pointer, not whole blocks.

    • Copy, cut, typing, Enter, paste and the mark engine all split the range per editing host.
    • It works in Firefox, which Notion's own implementation does not.
    • Escape promotes the text selection to a selection of the same blocks.
    Добавлено

    Block controls on either side — config.toolbarPosition: 'left' | 'right' moves the plus button and drag handle.

    • It is live through toolbar.setPosition(), and the reserved gutter width moves with it.
    • Logical tokens throughout, so RTL mirrors for free.
    • Before this, the only lever was hiding the controls entirely with hideToolbar.
    Добавлено

    Dev override seam — Every @bloklabs/core entry consults globalThis.__BLOK_DEV_OVERRIDE__ before its bundled implementation.

    • It is a passive, in-realm read: nothing is fetched, evaluated or resolved from a URL.
    • The editor root carries data-blok-version, so what is running is inspectable.
    • To drop the branch from your bundle, alias the newly exported ./dist/* subpath.
    Исправлено

    onChange fired late, or not at all — Sustained typing produced zero calls until the user paused.

    • Every mutation restarted the 400 ms window, which now opens on the first change and never extends.
    • onChange leads the window on the next microtask, and the rest coalesces into one trailing call.
    • onSave keeps the trailing edge only, since serializing the document is too expensive to front-run.
    Исправлено

    Selection beside a nested block — A lasso drawn beside a nested table selected the whole toggle section.

    • Selection now resolves which block owns a row through the same rule the toolbar uses.
    • A fast drag no longer drops every row above the first throttled mousemove.
    • One keystroke inside a nested block no longer runs the pipeline once per ancestor.
    Исправлено

    Empty-block placeholders displaced the caret — An empty paragraph painted its caret 315 px to the right.

    • A placeholder in normal flow consumes real inline advance at the start of the line box.
    • Placeholders now paint their text while claiming zero advance.
    • Media captions stay in normal flow, since a zero-width box would spill a centred caption sideways.
    Исправлено

    A bookmark that could not be previewed — It showed an error after the paste, and an ordinary card after a reload.

    • The error state never reached saved data.
    • A failed preview now degrades to a plain link on both paths.
    • Roughly 30% of sites publish no preview data, so this is the ordinary case rather than a fault.
    Исправлено

    Audio player card — Descenders in the title and artist lines were sliced flat.

    • text-overflow: ellipsis forces overflow: hidden, which clips at the padding box.
    • At a line height of exactly 1, that box is shorter than the font's content area.
    • Both lines now use the line-height token the file-name row already carries.
    Изменено

    Release and CI wiring — Nothing here iterates workspaces, so a package missing from a list drops out silently.

    • Both new packages are registered across all seven lists, from version lockstep to the publish gate.
    • The server's binaries and image ship from a tag-triggered workflow, not from a maintainer's laptop.
    • A compiler-API law fingerprints every type @bloklabs/presets hand-copies into its declaration.
    Изменено

    Docs — New /presets and /server pages, linked from the navigation and localized in both languages.

    • /server leads with the path that runs no service at all, and states its limits on the page.
    • A new page documents the dev override seam, its threat model and its opt-out.
    • SECURITY.md commits to acknowledging a report within five business days.
  9. v1.10.1Патч20 авг. 2026 г.
    Добавлено

    Toggle heading adoption — "Turn into → Toggle heading" now adopts the heading's section, matching Notion.

    • Every sibling up to the next heading of equal or higher rank becomes a child of the new toggle.
    • A heading inside a column adopts only within that column.
    • The adoption runs inside a move transaction, so undo restores the section.
    Добавлено

    Toggle disclosure arrows — The arrows now read as clickable.

    • The hover pill used to appear only once the pointer was already inside the 28 px square.
    • The chevron scales with its title's font size, so heading arrows grow with their level.
    • A localized Expand or Collapse tooltip is read from the state-synced aria-label.
    Исправлено

    Nested block menus — A block inside a toggle could never show its own menu.

    • A nested table's menu also jumped away the moment the pointer crossed onto the cell padding.
    • Hover and touch now share one resolver where the deepest block under the pointer owns the toolbar.
    • Hover detection stands down entirely over the toolbar.
    Исправлено

    Accessible names for icon-only controls — The entire inline toolbar was nameless to a screen reader.

    • A hint wired via aria-describedby describes a control but never names it.
    • An icon-only popover item now takes its name from its hint title, which repairs every one of them.
    • Colour swatches, captions and the embed iframe are named too, with no new i18n keys.
    Исправлено

    List and popover semantics — Every list item in the editor was an orphan.

    • Items declared role="listitem" but nothing declared the list, so the wrapper now carries role="list".
    • Toolbox section headers were separators inside a listbox, and are now presentational.
    • A popover is stamped as a menu only when it actually has menu items.
    Исправлено

    Table and database semantics — Add-row, add-column and the row and column grips were pointer-only.

    • They are now named, focusable buttons with keyboard activation.
    • Heading cells expose columnheader and rowheader, matching the <th> the view renderer emits.
    • The header toggle is a real role="switch", and database view tabs are a real tablist.
    Исправлено

    Escape no longer strands focus — Escape pressed inside the toolbar left focus on <body>.

    • The document handler stopped propagation in the capture phase, so the caret could never be restored.
    • It now stands down for targets inside the toolbar.
    • Modal dialogs return focus to the element that opened them, which fixes focus loss on WebKit.
    Исправлено

    Contrast — The grey text token cleared AA by 0.05 on white, so it failed on every tinted surface.

    • It is darkened, along with links and embed text, and inline code becomes its own token.
    • The Prism dark palette was dead: every rule was gated on a class nothing in Blok sets.
    • Database column pills move onto a dedicated on-pill colour.
    Изменено

    Accessibility suite — Two copy-pasted axe scans became a layered suite on Chromium, Firefox and WebKit.

    • It scans all 20 block tools in edit and read-only, plus the editor chrome.
    • No rule is waived, and every scan is preceded by a visibility assertion.
    • Two defects stay pinned with reasons, including the inline toolbar stranding focus.
  10. v1.10.0Минорный7 авг. 2026 г.
    Добавлено

    Framework adapters — useBlocks takes { within: blockId }, so a container re-renders only for its own subtree.

    • Unscoped, a page of N containers turned one keystroke into N re-renders.
    • childContentAttributes applies per-child decoration on each child's content wrapper.
    • toolbarAnchorRef and ctx.setToolbarAnchor answer getToolbarAnchorElement from inside the component tree.
    Добавлено

    View — renderLatex and createLatexRenderer are exported from @bloklabs/core/view.

    • The KaTeX chunk was already bundled, but hosts were told to add katex themselves.
    • Both apply the options Blok trusts for untrusted input, including trust: false.
    • createLatexRenderer() awaits the load once and hands back a synchronous renderer.
    Исправлено

    insertChild({ caret }) — The caret was permanently lost for a portal-rendered child.

    • A React, Vue or Angular child returns an empty host and commits its editable a frame later.
    • The block was not yet focusable, so the caret helper cleared the selection instead.
    • Placement now re-applies once the child's holder produces an input, one-shot.
    Изменено

    Adapter parity — The per-child decoration pass was triplicated across the adapters and is now one implementation.

    • Three architecture laws pin the new surface.
    • The view entry gained an export-to-declaration drift check.
  11. v1.9.0Минорный6 авг. 2026 г.
    Добавлено

    Container tools — Five things a container block used to hand-roll are now declared. static childTools = { allow?, deny? } lets any container state which tools may be its direct children, enforced by core on insert (a disallowed tool is demoted to allow[0], so Enter always produces a block), on a cross-boundary move (refused) and in the toolbox (hidden) — the selective, insert-aware counterpart to ownsChildren, and the generic form of the Table-only restrictedTools. data-blok-keyboard-owner marks a subtree whose keyboard belongs to the tool: block-level and editor-level keydown/input handling stand down inside it, tag-agnostically, replacing per-key stopPropagation handlers. BlockAPI.insertChild gained an options argument with the same vocabulary as the adapters' useBlocks insert (focus, caret, id, tunes, replace), threaded through insertInsideParent.

    Добавлено

    Inline tools — InlineToolConstructable.hydrate(root) is a declared contract, called by Block after render, after an in-place setData and after onPaste. Whatever a hook writes is marked data-blok-mutation-free, so re-rendering derived markup is not an edit.

    Добавлено

    View — blocksToHtml and <BlokView> accept inlineRenderers: tag-keyed, post-sanitize, output inserted verbatim — the inline counterpart of renderers. A DOM-free render can plug in katex.renderToString or a mention chip without Blok shipping either.

    Добавлено

    Block tree — { blocks: [...] } is now a spec node (BlockRunSpec), valid at the root or as a child of a tree node. A migration holding an already-flat saved document can splice it verbatim: ids are kept, only un-parented blocks are re-parented onto the enclosing node, and only those join its content. Passing a pre-flat block as a tree node throws instead of silently dropping its parent/content links.

    Исправлено

    Inline equations — A KaTeX span's markup is derived from data-latex, and the sanitizer dropped its tags while keeping their text, so E=mc^2 was persisted as E=mc2E=mc^2E=mc2. What was supposed to hide that — re-rendering on load — never ran: EquationInlineTool.hydrate() had zero call sites repo-wide, so equations went inert on every reload, in the editor and not just in the view. The sanitizer rule now rewrites an equation span's content back to its source on both the DOM and the parse5 pipeline, so new saves are clean and a load heals documents that already carry residue. htmlTextContent reads a mark's source, so previews, outline and search stop reading rendered fragments.

    Исправлено

    onChange arming — The documented "handler presence arms the change pipeline" contract was false: core defaulted onChange to a no-op unconditionally, so the gate could never disarm and all three adapters' careful handler-presence omission was pointless. Hosts were passing dummy handlers to arm a pipeline that was already armed — and an onSave one also forces a full serialization per change batch. The injection is gone, so the contract holds as written.

    Исправлено

    Published types — types/data-attributes.d.ts was hand-transcribed and had drifted: 17 attributes missing (including nestedBlocks, the container slot every nesting tool's stylesheet targets) and one phantom key the runtime never had. It is now generated from source and any drift fails an architecture test. The React BlokViewProps was also missing classes.

    Изменено

    Dependencies — postcss, brace-expansion, fast-uri, ip-address and undici bumped across the root and docs workspaces.

  12. v1.8.0Минорный6 авг. 2026 г.
    Добавлено

    Superscript / subscript — A new inline tool takes the tenth slot in the inline toolbar, bound to ⌘/Ctrl+Period and ⌘/Ctrl+Comma. The two modes are mutually exclusive, so applying one clears the other. Shipped with glyphs drawn into the shared inline-toolbar type system, translations in all 69 locales, and docs.

    Добавлено

    Toolbox — Slash-menu entries are grouped under labeled sections, so a long tool list is scannable instead of a flat run of items. Each entry declares its own section.

    Добавлено

    Tool contract — Blocks carry creation provenance (user/load/api/paste/convert/replay/probe), so a container can tell an author's gesture apart from a document load, a refetch or an undo replay. Enter's container-escape became a per-tool declaration instead of a hardcoded list of Blok's own tool names, so a custom container keeps Enter inside itself without an editor-global onEnter hook. insertInsideParent and BlockAPI.insertChild take an optional tool name, making an appended typed child one atomic operation and one undo entry.

    Добавлено

    Framework adapters — The React, Vue and Angular block spec gained a general statics passthrough (toolbar anchor, ownsChildren, conversionConfig, the new Enter policy), an api handle, child-tree reactivity, per-child decoration, and an onMounted signal backed by a block:childrenMounted event. Handler presence is runtime-settable through api.handlers.set(), so passing onEnter at all no longer permanently decides Enter's semantics.

    Добавлено

    Editor — A new opt-in captureClicksBelowEditor places the caret in the last block when the host clicks empty space below the editor. Off by default; registered as a config key in the React and Vue adapters too.

    Добавлено

    Link — The link field sizes itself to its content, capped at the previous fixed width, and its create, error and edit states were polished.

    Исправлено

    Nesting — setBlockParent no longer lets a container on the block's own ancestor or descendant chain veto a reparent; an enclosing container claiming a holder used to leave model and DOM permanently divergent (Enter inside a callout nested in another container), and a descendant doing the same nested every appended child inside its predecessor. mountChildBlocks now reclaims a holder stranded in any ancestor container, re-mounts it at its model position rather than last, and preserves the caret across the adoption. Depth indentation moved from an inline margin with a hardcoded exemption list to a depth multiplier resolved through --blok-block-indent-step, so a container tool declines the indent with ordinary CSS and no !important.

    Исправлено

    Block API — Every handed-out BlockAPI is live, so getChildren() can no longer answer [] for a populated container and setParent/insertChild/moveChild can no longer silently no-op. api.blocks.update() prefers a tool's in-place setData when there are no tunes to apply, so it stops composing a replacement block that destroyed the previous one's portal and left the holder permanently empty.

    Исправлено

    Inline toolbar — destroy() threw and aborted blok.destroy(), leaking listeners in every module torn down after it: hide() emits Closed synchronously, the handler then ran close(), which nulled the popover mid-teardown. The reference is now detached before hiding.

    Исправлено

    Popover — Control-less HTML items (the new toolbox section headers) are no longer keyboard focus stops, so a role="presentation" header can't steal initial focus, shift every Arrow/Tab, or be pointed at by aria-activedescendant. Sibling active states refresh after an item is activated, and clicking the item that opened a popover now does nothing instead of reopening it.

    Исправлено

    List — Tab/Shift+Tab moved the model but not the render: both handlers wrote depth into the tool's live data before calling api.blocks.update, whose in-place diff then saw no change, so save() and the DOM silently disagreed.

    Исправлено

    Events and data — Keydown from a native form control a tool renders is no longer claimed by the editor. The toolbox merge and the save() extraction stop mutating tool-owned objects, so a toolbox entry carrying data no longer throws on a frozen save() result. A load is not an edit: a block arriving without a timestamp is no longer stamped at construction, so a save round-trip equals the document it came from.

    Исправлено

    Adapters — The portal registries reject a teardown from a superseded instance, so a same-id re-register survives a late destroy; Vue additionally defined one wrapper component per tool *type*, so a re-register patched the superseded instance and rendered stale data — the wrapper is now per block instance. A React element toolbox icon serializes instead of rendering as [object Object], and the imperative handle keeps the controlled baseline in sync so restoring a draft after clear() is no longer swallowed as an echo.

    Исправлено

    Styles — The icon stroke is scoped to Blok's own icon markup instead of every path in the subtree. The column floor moved to --blok-column-min-width in CSS, and the static-gutter attribute plus the block-padding tokens are now declared.

    Изменено

    Build — scripts/build-angular.mjs derived its adapters contract from a hand-copied list that silently drifted whenever a staged module gained an import; it now derives it from src/adapters.ts, and the staging law test walks the same graph so drift fails at test time instead of build time.

    Изменено

    Tests — 23 red e2e tests were root-caused rather than weakened: three were real product bugs (fixed above) and four were stale specs asserting behaviour that later commits deliberately changed. A leaked 600ms language-detection debounce in the code-tool unit tests was also cancelled, removing a load-dependent flake.

  13. v1.7.0Минорный4 авг. 2026 г.
    Добавлено

    Embed — A stored generic embed the host hasn't allowed to be framed now renders as a clickable link card instead of the inert "No embed link" state, so the URL stays visible in both read and edit views and can never be silently lost. A new linkPaste.allowedEmbedOrigins hostname/wildcard trust list gives hosts fine-grained control as a middle ground before the all-or-nothing allowGenericEmbed flag. Tampered stored data stays fully inert, and no new iframe paths are introduced.

    Исправлено

    Editor — Queries for a block's first editable element now skip mutation-free markers such as a list item's bullet span, closing the remaining "marker ghost" sites where Enter could write an item's own HTML into the bullet and the toolbar centred on the marker's box instead of the text. An architecture test now enforces the guard on every contenteditable selector in the codebase.

  14. v1.6.2Патч2 авг. 2026 г.
    Исправлено

    Callout — Enter can leave the panel again. Previously it could only ever add another line inside, so every press stamped one more empty paragraph into the callout; those blanks are saved with the document, and the callout reloaded with its text pinned to the top of a panel padded out by invisible lines. Behaviour now matches Notion: Enter adds a line inside, Enter on an empty last line steps out. A callout nested in a column hands that block to the column rather than the document root, the exit block is saved in the position it renders in, and the whole exit is a single undo/redo step. Toggles and columns keep their existing behaviour.

  15. v1.6.1Патч2 авг. 2026 г.
    Исправлено

    Callout — The panel's vertical inset now reads its own --blok-callout-padding-block token (flat 5px default) instead of riding --blok-block-padding-top/-bottom, so a host's compact-rhythm override no longer collapses the callout card onto its text. The emoji button deliberately keeps reading the rhythm tokens so the glyph tracks the first text line under any rhythm a host sets. Defaults render byte-identically; hosts that wanted squashed callouts opt back in via --blok-callout-padding-block: 0.

    Изменено

    Docs — 151 verified inaccuracies root-caused and fixed across the docs site, a new guide explains how to set per-block font sizes correctly, and the docs test suite now resolves Blok's public members through the TypeScript compiler instead of a regex.

  16. v1.6.0Минорный1 авг. 2026 г.
    Добавлено

    Font size — config.style.fontSize now carries one entry per text scenario in every text-bearing block (paragraph, headings, quote, callout, code, toggle, list, checklist, table cells, captions, bookmark cards). Each entry writes that block's --blok-*-font-size custom property, so the same knob is reachable through style.tokens, editor.tokens.set() and plain CSS. An unconfigured editor renders byte-identically to before.

    Добавлено

    API — beginTransaction/endTransaction group operations spanning a pointer gesture into a single undo entry, for cases where the synchronous transact(fn) cannot reach across async boundaries.

    Добавлено

    Table corner drag — The bottom-right corner now behaves the way Notion documents it: the grid tracks the pointer through live geometry instead of a unit frozen at pointerdown, a Notion-style grip replaces the old 8px dot, hovering it explains the gesture, appended columns are full width, and the whole gesture commits as one undo entry.

    Добавлено

    Table auto-scroll — Holding the corner at the scroll container's edge or in the viewport's top/bottom band scrolls and grows the table as it goes. Growth follows the pointer — 8px/s for every pixel held past the edge — rather than a fixed clock.

    Добавлено

    Table selection — Dragging a row or column grip paints the entire dragged range instead of boxing only the focused cell.

    Добавлено

    Playground — A text-size slider (80%–150%) scales every style.fontSize scenario from its own CSS default.

    Исправлено

    Table — An inward corner drag stops at the first trailing row or column that holds content instead of deleting typed cells; the handle is anchored to the grid rather than the wrapper, so it no longer drifts inside the table as it grows; a caret click no longer leaves the corner handle and "+" buttons dead until the user clicks outside; clicking inside a merged cell boxes only that cell, and expanding a selection reaches merge origins, not just spans; a stale pointercancel listener no longer accumulates per completed drag.

    Исправлено

    Styles — Callout emoji and list markers stay aligned with their text as the font size scales, and the bookmark card's padding, line boxes, gaps and favicon scale with the card's own type. fontSize.callout now wins over fontSize.paragraph in the callout body.

    Исправлено

    Types — The public Blok class exposes its full API surface.

  17. v1.5.0Минорный27 июл. 2026 г.
    Добавлено

    View renderer — @bloklabs/core/view now reaches visual parity with the read-only editor: every core block (paragraph, header, quote, list, checklist, code, callout, toggle, divider, spacer) renders from single-sourced class modules shared with the editor, view.css is generated from those modules, and a soft isolation root plus reproduced block scaffolding keep the output pixel-equal. A class-parity gate and a view↔read-only visual parity gate now run in CI, and the playground gains a side-by-side Blok View comparison panel.

    Добавлено

    Paste — Google Docs layout tables are now recognized: multi-row two-column tables carrying photos convert into column blocks, and single-column layout tables unwrap into their content instead of arriving as one-cell tables.

    Добавлено

    Inline toolbar — The convert menu now opens sideways with its trigger marked selected, and the convert row is styled as the card's header.

    Добавлено

    Callout — A newly picked emoji jumps into the old one's place, and the emoji picker opens instantly without waiting on its dataset to download.

    Добавлено

    Tools — data-blok-tool is now stamped on code, callout, divider and spacer roots.

    Добавлено

    Docs — The docs site advertises its markdown mirrors and declares Content-Signal; the published @bloklabs/core/icons subpath is documented; the README is restructured around benefits, facts and a runnable example.

    Исправлено

    Security — Stored javascript: XSS closed on two sinks: media download hrefs are scheme-gated, and stored embed renders are gated on the provider registry rather than a bare https: check.

    Исправлено

    Drag & Drop — Drops on the seam between two blocks now resolve instead of dead-ending; the drop indicator no longer promises a nesting the drop would refuse; side-drops are gated on the columns tool actually being registered.

    Исправлено

    Columns — The drop animation no longer balloons the row while a block lands.

    Исправлено

    Code — In read-only mode the language label renders as plain text and the language dropdown toggle is hidden; the copy button keeps the same height in its "Copied!" state.

    Исправлено

    Toolbar — Multiple editors on one page now show one set of block controls instead of stacking duplicates; the slash-search caret is sized to the input, not the block.

    Исправлено

    Tooltip — A bubble is never parked in the viewport corner when its anchor stops rendering.

    Исправлено

    List — The checklist checkbox is centred on its text at any font size.

    Исправлено

    Embed — Provider popups (e.g. "open in app") can escape the iframe sandbox again.

    Исправлено

    Audio — Cover art uploads are routed to the image pipeline instead of the audio endpoint.

    Исправлено

    Shortcuts — BACKSLASH/SLASH render as \ and / in shortcut hints.

    Исправлено

    Dependencies — All 40 open Dependabot alerts remediated at their root causes.

  18. v1.4.5Патч25 июл. 2026 г.
    Добавлено

    Migrate — The legacy-format interpreter is now extensible from the host: rules entries are matched before the built-in grammar (so they can override it) while reusing container recursion, orphan re-parenting and 1:N splits; expanders may consume following siblings via { blocks, consumed }; and passing generateId makes migration pure, so a document migrates to an equal result twice. Adds migrate(data, options) composing the data-rule and grammar passes in the correct order, matchLegacyRule() for per-block matching, and a report carrying lossyFields/errors instead of console-only warnings. Editor.js list v2 meta fields (start, checked) are now read.

    Исправлено

    Migrate — config.migrations now runs before format analysis, so dataModel: 'auto' inspects post-migration blocks instead of collapsing the document back to its legacy shape on save.

    Исправлено

    Types — typesVersions now maps the migrate subpath, fixing TS2307 for consumers on moduleResolution: "node".

  19. v1.4.4Патч25 июл. 2026 г.
    Добавлено

    Migrate — Hosts can now declare per-block-type migration rules from the outside to upgrade stored blocks from an old data shape to a new one without editing the tool class. Rules are applied at load (after each tool's own upgradeData) and also exposed as a standalone migrateOutputData via @bloklabs/core/migrate for offline batch upgrades. Available on all three framework adapters.

  20. v1.4.3Патч24 июл. 2026 г.
    Добавлено

    API — The output-data helpers are promoted to a stable entry point, alongside new document-query utilities.

    Добавлено

    Types — Named config aliases and a BlokData interface adapter.

    Добавлено

    Tools — Type-safe tool authoring helpers, plus an explicit paste priority.

    Добавлено

    View — Root-caused view gaps #29–#33 and #35 from the hr-platform/KB audit.

    Добавлено

    i18n — Root-caused i18n audit gaps #36–#41.

    Добавлено

    Migrate / Tools / Paste — Root-caused hr-platform/KB gaps #50–#53.

    Исправлено

    Controlled editor — Five audit findings root-caused, followed by findings #7 and #9 (and the missing test for #8).

    Исправлено

    Marks / Paste — Four inline-tool and sanitizer audit findings root-caused.

    Исправлено

    Build (Angular) — toRenderableData is exported from the staged adapters-contract.

    Исправлено

    Types — Widened the exports cast so the string-valued ./view.css entry type-checks.

    Изменено

    i18n message files are named by locale.

    Изменено

    Repaired the test/build drift that blocked the release preflight.

  21. v1.4.2Патч23 июл. 2026 г.
    Исправлено

    Markdown — Typing a list marker (- , 1. ) inside a heading no longer converts the heading into a list; it stays a heading.

  22. v1.4.1Патч23 июл. 2026 г.
    Исправлено

    Editor — Enter now honours the IME composition and Shift contract; added an onError channel; data-blok-tool is opt-in.

    Исправлено

    Sanitize — Redundant inline markup is now collapsed on every path that stores HTML.

    Исправлено

    Video — Unplayable sources are surfaced to the user instead of rendering a black player.

    Исправлено

    View — Added a classList facade so MarkSpec inline tools render correctly in BlokView.

    Исправлено

    i18n — Localized video stats and database overflow, added tr() interpolation, and completed locale audits across Yiddish, Vietnamese, Traditional and Simplified Chinese, Urdu, Ukrainian, Uyghur, Turkish, Thai, Telugu, Tamil, Swahili, Serbian, Albanian and Slovenian.

  23. v1.4.0Минорный23 июл. 2026 г.
    Добавлено

    Marks — New range-aware api.marks inline-formatting engine, with the built-in bold/italic/underline/strikethrough tools migrated onto it. Exposes MarkSpec identity/family/transparent semantics for authoring custom inline tools.

    Добавлено

    View renderer — New synchronous, DOM-free view renderer published at @bloklabs/core/view (defineBlokSchema + a central dispatcher, plus a React BlokView), for rendering stored block content without booting a full editor.

    Добавлено

    i18n — New runtime editor.i18n.update() API that makes config.i18n live and repaints already-rendered block DOM, wired reactively through all three adapters.

    Добавлено

    Config — Reactive contract for readOnly, hideToolbar and inlineToolbar: setting them after construction now takes effect live across the React, Vue and Angular adapters (with sanitize-cache invalidation on inlineToolbar).

    Добавлено

    Readiness — Scoped, reactive editor readiness: whenAllReady({ within, settleOn }), readyState/subscribeReady, and a useBlokReady hook in all three adapters.

    Добавлено

    Docs — The documentation site is now crawlable (prerendered metadata, sitemap, AI mirrors) and carries Google Analytics coverage across pages.

    Добавлено

    Playground — Dev settings panel gains a language picker and an RTL toggle.

    Исправлено

    Marks — Fixed the trailing-whitespace extension eating later content when a mark ended on a boundary.

    Исправлено

    Styles — Surface background tokens (--blok-bg-light/-secondary/-tertiary) are now a test-enforced public contract; the gutter stays put in plain read-only so readOnly flips no longer shift layout.

    Исправлено

    Types — MarkSpec is now imported into the main declaration entry so it resolves for consumers.

    Исправлено

    Docs — Russian pages are headed by their localized H1; @bloklabs/core/view resolves in the docs build and React fixtures.

    Исправлено

    Release — The Angular README is now staged into the directory npm packs.

    Исправлено

    i18n — Locale audits completed across Slovak, Sinhala, Sindhi, Russian, Romanian, Portuguese, Pashto, Polish, Punjabi, Norwegian, Dutch, Nepali, Burmese, Malay, Marathi, Mongolian, Malayalam, Macedonian, Latvian, Lithuanian, Lao, Sorani, Korean and Kannada.

    Изменено

    Migrated the docs site to React Router framework mode.

    Изменено

    Renamed the default branch from master to main.

    Изменено

    Completed npm metadata across the package family and hardened the view/reactive-contract law tests.

  24. v1.3.0Минорный21 июл. 2026 г.
    Добавлено

    API — New public editor.tokens getter/setter for runtime --blok-* theme tokens, with replace semantics and pre-ready buffering (like theme/width/placeholder). Wired reactively through all three adapters: React style.tokens, Vue style.tokens, Angular [styleTokens]. --blok-content-max-width is now honored by database centring and toolbar control placement.

    Добавлено

    Tools — Custom-tool authoring fixes: tools.update(name, { toolbox }) now flips a tool's toolbox entry at runtime (permission-style insert gating no longer requires recreating the editor), including its insertion shortcut; React createReactBlock accepts a viewComponent rendered while the editor is read-only; React toolbox icons may be React elements; commit() echo idempotency is now a documented public contract.

    Добавлено

    Embed — Google Docs/Sheets/Slides/Forms/Drive embeds render at a user-adjustable pixel height with a bottom resize handle (200–2000px), persisted to data.height. Aspect-ratio media providers (YouTube, Vimeo, …) are unchanged.

    Исправлено

    CDN bundles — dist/blok.iife.js and dist/blok.umd.js shipped zero generated Tailwind utilities since the v3→v4 migration, so every unpkg/jsDelivr consumer loaded an unstyled editor. Both configs now run the Tailwind plugin (+34KB gzip each), guarded by a dist-level assertion.

    Исправлено

    Adapters — Five root causes from a downstream audit: a stale controlled-data echo no longer clobbers the caret (bounded echo window instead of last-payload-only dedup); equalsOutputData compares block ids only when both sides carry one; React inline tools accept a titleKey for localization; the zero-specificity gutter default is a test-enforced public contract.

    Исправлено

    Dependencies — Seven phantom dependencies (bare imports resolving only via hoisting, including @testing-library/jest-dom used by the global unit setup) are now declared, with a law test preventing new ones.

    Исправлено

    i18n — Review passes completing Armenian, Croatian, Dhivehi, Filipino, Georgian, Gujarati, Hebrew, Hungarian, Indonesian, Japanese, Kannada and Khmer, plus tool interpolation variable forwarding.

    Изменено

    Upgraded to Node 26, Angular 22 and TypeScript 6, then root-caused six defects the upgrade shipped green — most importantly the entire unit-angular vitest project loading zero tests (a fake green), and the docs test suite missing the Node 26 webstorage guard.

    Изменено

    Local E2E suite runtime cut from ~47.5 min to ~10 min (parallel/skip-when-fresh build:test, shared page per worker), plus broad E2E stabilization.

    Изменено

    Fixed ESLint cache poisoning that replayed stale errors in CI lint runs.

  25. v1.2.6Патч20 июл. 2026 г.
    Добавлено

    Paste — Google Docs tables used as fake column layouts (every row has exactly 2 or 3 cells) now paste as real column layouts instead of table blocks. Genuine tables (4+ columns, ragged rows, single column, Google Sheets, nested tables) still paste as tables.

    Добавлено

    API — Four first-class capabilities replacing host workarounds: a style.nativeSelection config opt-out for the forced ::selection repaint, public --blok-block-padding-top/-bottom/-inline tokens for compact read-only rendering, a static Blok.whenAllReady() collective-readiness aggregate, and createReactInlineTool in the React adapter with a full inline-tool destroy() lifecycle.

    Исправлено

    Data integrity — Three silent data-loss defects fixed: code containing < was corrupted on render and save (if (a<b) became if (a), empty code blocks were dropped on save, and a document whose only block was / saved as empty. Tools can now declare a field as literal text via a PLAINTEXT sanitizer rule.

    Исправлено

    Caret — Highlighting a non-focusable block now blurs stale input focus, so Chromium can no longer restore the current block from a stale collapsed range.

    Исправлено

    i18n — Locale audit corrections across dozens of locales, including Dutch color labels and shared toggle guidance.

  26. v1.2.5Патч20 июл. 2026 г.
    Добавлено

    i18n — New Taiwan Traditional Chinese locale (zh-TW) with its own emoji dictionary, bringing the corpus to 69 locale variants. A full audit pass over every shipped locale corrected terminology and localized previously hardcoded runtime strings (media captions, database defaults, emoji category scopes, recent color labels, action search, move announcements), with hardened locale validation.

    Добавлено

    Theming — New style.tokens config lets each editor instance pass --blok-* token overrides that also reach body-mounted UI (popovers, menus). The edit-mode gutter now defaults to 56px and is owned by Blok, checklists get a dedicated padding token (falling back to the list token), hideToolbar config now actually hides the toolbar and collapses the gutter, and --blok-placeholder-color is a public hook.

    Добавлено

    Inline toolbar — Restructured as a card with a convert row plus a five-column tool grid, including a new clear-format tool and redrawn toggle-heading icons.

    Добавлено

    Color — Text and background tunes merged into a single Color submenu; the color picker gained a Recently Used section remembering the last 5 colors; slash-menu color command titles are localized.

    Добавлено

    Table — Compact/comfortable text-size switch, grouped with density under a text-size submenu.

    Добавлено

    Header — Heading level converts are grouped under a heading submenu in block settings.

    Добавлено

    Image — Overlay controls use discrete size tiers (full/medium/compact) instead of fluid scaling, keeping them legible at small widths.

    Добавлено

    Data compatibility — Editor.js-shaped data is accepted losslessly: null-tolerant LooseOutputData inputs, public equalsOutputData/isEmptyOutputData utilities, echo-safe blocks.render() (re-rendering identical data is a no-op), and a synchronous isRendered flag.

    Исправлено

    Popovers — Block-settings menu placement fixes: the menu centers on the six-dots handle, stays attached to it near viewport edges, never touches the screen border, and submenus always open to the right and appear only when hovering the trigger or the submenu itself; page scroll is locked while the menu is open.

    Исправлено

    Editor — Toggle-heading level conversion no longer strands child blocks in a detached DOM (silent data loss); a save-time invariant gate now rejects stranded holders outright.

    Исправлено

    Adapters/Core — Six consumer runtime workarounds root-caused and fixed in core, types, and adapters.

    Исправлено

    UI — Inputs show a single focus indicator (no double border), and the popover search icon was removed.

    Исправлено

    Accessibility — Move and duplicate announcements are count-neutral and carry correct totals; search results announcements keep their context.

    Изменено

    CI — Shorter critical path (parallel build start, faster lint), with contract tests enforcing the workflow shape.

    Изменено

    Tests — Animation-frame APIs polyfilled for jsdom environments; extreme-position e2e sweeps guard menu placement at screen edges.

  27. v1.2.4Патч18 июл. 2026 г.
    Исправлено

    i18n — Capitalized toolNames keys (e.g. toolNames.TestTool) resolve again in the toolbox: the lookup now tries the raw tool name first, then the capitalized key, restoring the published contract that 1.2.3's raw-name lookup silently dropped. An empty toolbox title no longer short-circuits the fallback chain and renders a blank slash-menu item — it is treated as absent and falls back to the capitalized tool name.

    Изменено

    CI — The docs site now deploys only on package releases, and the deploy is gated by a verifier that checks the published packages (tied to the release version family) before the site goes live.

  28. v1.2.3Патч18 июл. 2026 г.
    Добавлено

    Theming — More host customization hooks: heading tokens (keyed off data-blok-heading-level) and embed tokens, a --blok-list-gap token for list spacing, and palette tokens declared at zero specificity via :where() so host overrides always win. --blok-content-max-width is now authoritative when the editor is in width: 'full' mode.

    Добавлено

    Read-only — The editor wrapper is stamped with data-blok-readonly as a public styling hook, and the block-controls gutter auto-collapses in read-only mode so content uses the full column.

    Добавлено

    Adapters — The three React-integration workarounds were removed by fixing their root causes in core.

    Исправлено

    i18n — Custom tool titles now localize via toolNames.<toolName> dictionary keys.

    Исправлено

    Image — GIF→video auto-conversion is skipped when no video tool is registered, instead of failing the upload.

    Изменено

    Build — dist/ output is now minified and JSON data is emitted as JSON.parse strings, cutting published bundle weight.

    Изменено

    Docs — Documented the theming hooks, data-blok-readonly attribute, contentAlign, toolbox: false gating, the GIF guard, the readOnly object form, and toolNames keys.

  29. v1.2.2Патч17 июл. 2026 г.
    Добавлено

    Theming — New public --blok-* custom properties let host apps customize editor layout without reaching into internals: --blok-content-max-width (content column cap), --blok-editor-gutter-start/--blok-editor-gutter-end (space reserved for the floating block controls, RTL-correct), --blok-list-padding-start (list indent), and --blok-search-input-placeholder (popover search placeholder color). Defaults preserve current behavior; documented in the docs-site Styles API section.

    Добавлено

    React — First-class block authoring: createReactBlock renders block tools authored as React components through a shared portal host inside the host app's React tree, so app-level context (providers, themes, stores) reaches block components directly — no more createRoot per block or context bridges. Every function in a tool's config (including nested ones like uploader.uploadByFile) is now re-bound to the latest render's closure, so inline closures work without freezing identities or recreating the editor.

    Исправлено

    Floating UI — A hardening sweep across every floating surface: popovers anchored inside nested scroll containers no longer drift or detach on scroll (snapshot anchors, virtual selection anchors, and fixed-position menus all track correctly); tooltips dismiss on nested scroll; the emoji picker and link hover card follow moving anchors; root boundary calculation is normalized for scrolled and 100vh host bodies. An architecture test now enforces that all floating UI goes through the central positioning module.

    Исправлено

    Renderer — Stored block data is now sanitized on render with the same per-tool sanitize config the Saver applies, closing stored-HTML injection for legacy data that never round-tripped through save (e.g. a raw <iframe width> baked into paragraph text overflowing its column). Fixed-width iframes/embeds are additionally capped at max-width: 100%.

    Исправлено

    Link — The hover card now requires actual pointer motion before opening, so it no longer opens when a link merely renders or scrolls under a stationary cursor.

    Изменено

    Release — Preflight (eslint ∥ tsc ∥ vitest) and build pipelines were parallelized (~2× faster wall clock), with per-step timeouts so a hung build can no longer stall a release. GitHub Packages mirror tarballs now rewrite @bloklabs/core specifiers in every shipped file (previously react/vue types/index.d.ts still referenced the npm scope, breaking consumer tsc on GHP-only installs).

  30. v1.2.1Патч16 июл. 2026 г.
    Добавлено

    Image — Images now display at the full width of the article by default. Previously an image without an explicit size preset rendered at the medium (520px) preset; the default is now the full preset. Images with an explicitly saved size are unaffected.

    Исправлено

    Popover — The search input's focus ring was clipped along its bottom edge by the context label's opaque background painting over it; the search wrapper now renders in the positioned paint layer so the full ring is visible. The gap between the search field and the context label was also widened slightly.

  31. v1.2.0Минорный16 июл. 2026 г.
    Добавлено

    Media — Playback speed and loop preferences now persist across audio and video blocks. They are stored in localStorage under shared per-media-type keys (blok:audio:rate/loop, blok:video:rate/loop), joining the existing shared volume and per-source position keys, and are restored when a player attaches — without dirtying block data.

    Исправлено

    Quote — Saving a quote block no longer strips href/target/rel from links (leaving dead anchors in stored content) or unwraps bold/italic marks. Quote now uses the same inline-text sanitize rules as paragraph and header, so links, formatting, and color styles survive save and conversion.

    Исправлено

    Audio — OneDrive share links from SPO-migrated accounts (the new /u/c/<cid> form) can't be resolved anonymously and produced a silently dead player; they now surface a clear "needs an uploader backend" error instead.

    Исправлено

    Toolbar — The plus button and drag handle no longer stay stuck at the wrong offset after the slash-command popover opens or closes; the toolbar repositions on toolbox open/close instead of relying on a resize side effect.

    Исправлено

    Toolbox — Opening the toolbox silenced the current block's mutation watching and never re-armed it, leaving the block permanently deaf to later content changes until re-render. Watching is now re-armed on both close paths, and the toolbar follows any inner-geometry change that doesn't resize the block holder.

    Изменено

    CI — The build artifact now ships the extracted packages/*/dist adapter bundles alongside dist/, fixing downstream unit and E2E jobs; yarn.lock was synced to the ^1.1.1 core peer range.

    Изменено

    Docs — README and the docs site updated for the @bloklabs/* package family; the rename notice was subsequently dropped from the README.

  32. v1.1.1Патч15 июл. 2026 г.
    Ломающее изменение

    @bloklabs/core has zero peer dependencies. The react/react-dom/vue optional peers are gone — installs no longer warn about frameworks you don't use, and the GitHub Packages peerDependenciesMeta-stripping bug (which forced Yarn Berry consumers to add a packageExtensions workaround) no longer applies. Delete that .yarnrc.yml entry after upgrading.

    Ломающее изменение

    Adapters declare hard, accurate peers: each requires its framework plus @bloklabs/core at the matching version.

    Ломающее изменение

    GitHub Packages mirrors: @dodopizza/blok remains the core mirror; adapters mirror as @dodopizza/blok-react, @dodopizza/blok-vue, @dodopizza/blok-angular; the CLI stays @dodopizza/blok-cli.

    Ломающее изменение

    Migration: the bundled codemod (npx -p @bloklabs/core migrate-from-editorjs) now also rewrites legacy @jackuait/* import specifiers and package.json dependency keys to the new names.

  33. v1.1.0Минорный15 июл. 2026 г.
    Добавлено

    Audio — Share links from seven more services — Dropbox, OneDrive, GitHub, GitLab, Hugging Face, Google Cloud Storage, and Internet Archive — are recognized and rewritten to their direct-content form, so they play in the browser with no backend. Google Drive share links (hotlink-blocked server-side) are normalized and routed through the consumer's uploadByUrl backend, with a Drive-specific error message when none is configured. The error state gets a styled callout with a retry button.

    Добавлено

    Read-only — readOnly now accepts an object form: { hideControls: true } enables read-only mode and suppresses the toolbar, block settings, and inline toolbar. Exposed via isControlsHidden, normalized across the React, Vue, and Angular adapters, and ReadOnlyModeConfig is exported from the types root.

    Добавлено

    Image — compress: { format: 'avif' } now produces real AVIF via WebCodecs when the canvas encoder cannot, and a new fallbackFormat option (e.g. 'webp') covers browsers with no AV1 encoder instead of silently uploading the original bytes.

    Исправлено

    Audio — Audio inserted by URL is now enriched like uploads: waveform, title/artist metadata, and cover art, failing soft to a plain scrubber when the host blocks the CORS fetch.

    Исправлено

    Table — Undo inside a table no longer duplicates cell blocks into invisible ghosts that reappear under the table after save; blocks placed at the top of a cell no longer drift to the bottom or become orphans on save. The Saver gains save-boundary guards for cell membership and cell block order (throw in dev/test, repair the emitted output in production).

    Исправлено

    Tooltip — The tooltip bubble is click-transparent, so it never swallows clicks on controls it covers (e.g. color-picker swatches under a bottom-row tooltip).

    Исправлено

    Popover — Nested popovers no longer collapse to their padding in WebKit; the marker color picker rendered as a 12px sliver in Safari.

    Исправлено

    Styles — Body-mounted UI (link hover card, notifier toasts, drag previews) now carries the scope attribute, so its styles survive in consumer apps; a new architecture test enforces the invariant for every document.body mount.

    Исправлено

    Angular — The ng-packagr build stages the readonly-config module, fixing a CI-only TS2307; an architecture test now walks the adapter's import graph to catch unstaged modules.

    Изменено

    Playground — Gallery empty states run the real tool per state (with per-state tool config) instead of static mockups, including a live Google Drive error demo.

    Изменено

    Tests — Adversarial table undo probes (merge undo, insert undo/redo), tooltip click-transparency lifecycle guards, and an exhaustive swatch hit-test sweep.

  34. v1.0.0Мажорный14 июл. 2026 г.
    Добавлено

    Header — Toggle headings are now offered at all six levels, staying in sync 1:1 with regular headings.

    Исправлено

    Migration — The legacy Editor.js grammar is now authored as ESM so consumer dev servers can load blok's source graph without a build step.

    Исправлено

    Columns — Blocks inserted via the plus button no longer save at the bottom of the column; saved order now matches the on-screen (WYSIWYG) order.

    Исправлено

    Styles — Injected utilities are scoped so a host application's CSS reset can't flatten the editor.

    Изменено

    Migration — Single-source LEGACY_GRAMMAR shared by both the runtime and the codemod; the codemod's source rewrite is now AST-guided (via the consumer's @babel/parser) to avoid mangling comments, strings, and unrelated identifiers.

    Изменено

    CI — Root-caused CI failures: scoped-utility drift on body-mounted UI, lint, and test flake fixes (webkit paste timing, six-level toggle-heading counts).

  35. v0.25.0Минорный13 июл. 2026 г.
    Добавлено

    Spacer — New adjustable-height spacer block. Drag either edge to resize (dual-edge grips), with a text-block-height floor, snap-to-sibling and snap-to-column alignment guidelines, an on-edge capsule resize pill, and accent hover cues. Fully invisible in read-only/published renders.

    Добавлено

    Image — Uploads are now automatically compressed and re-encoded (compress, on by default), with opt-in smaller output formats. In-cell images gain a resize floor and fluid chrome via container queries.

    Добавлено

    Toolbar — Cmd/Ctrl+Slash opens the block menu in read-only mode.

    Исправлено

    Table — Large batch of Notion-parity fixes: paste-header handling, the cell color picker, the cell menu, arrow-key navigation between cells, and column width reset. The cell box now follows the caret (instead of the pointer) and the resize handle no longer forces overflow. Focus stays inside a cell when its content is deleted, the caret stays put after clearing a multi-cell selection, multi-line cell selections merge into one rounded shape, drag-selecting several lines within a single cell works, and list items scale to the cell font instead of outsizing sibling paragraphs.

    Исправлено

    Columns — Stranded resize separators left behind by removing a column no longer render as a phantom column.

    Исправлено

    Core — Never Tab-indent a block into a tool-owned container.

    Исправлено

    Toolbox — Keep plus-button blocks on a table out of its cells, and anchor fuzzy search at word boundaries.

    Исправлено

    Selection — Stop hijacking intra-line text drags inside table cells.

    Исправлено

    Embed — Validate stored URLs at render time (stored-XSS guard).

    Исправлено

    List — Keep bullet markers non-editable so Enter never ghosts an item.

    Исправлено

    Toolbar — Read-only drag-handle refinements: announce it as a menu button, show a pointer cursor, and drop the ⌘/ and "Drag to move" hint lines; no read-only handle appears beside blocks that paint nothing.

    Исправлено

    Tunes — Hide the copy-link shortcut hint in read-only mode.

    Исправлено

    Styles — Right contentAlign no longer collapses into centering, and preflight resets are scoped to @layer base so Blok's own utilities win.

    Исправлено

    React — Guard against stale dist exports and a StrictMode readiness race.

  36. v0.24.3Патч10 июл. 2026 г.
    Добавлено

    Header — Opt-in anchorIds config derives stable heading anchor ids from heading text.

    Исправлено

    Link — Pad the edit-menu input wrapper so the focus ring isn't clipped, and enlarge the remove-link (trash) icon.

    Изменено

    CI — Fetch mirror tags before pushing to avoid creating over an existing tag.

  37. v0.24.2Патч9 июл. 2026 г.
    Добавлено

    Link — New link.transform config, a superset of transformHref: consumers can set per-anchor href/target/rel plus extra attributes (class/title/data-*) without post-processing the rendered DOM. Applies consistently across every anchor path (render, paste, and hand-created links); omitted fields fall back to existing defaults (including the same-page _self rule) and extra attributes never clobber the managed href/target/rel.

    Исправлено

    Columns — Keep the inter-column gutter in read-only/published renders. The gap was previously produced entirely by the (no-op in read-only) resize handles, so read-only columns rendered flush; the gutter is now decoupled from the resizers.

    Исправлено

    Link — Center the hover card under the pointer (shifting near viewport edges) with a fixed gap to the link, and stop the block toolbar leaking through the card when hovering top-layer chrome.

    Исправлено

    Notifier — Fix top-layer placement so the toast stays in its corner (no UA Canvas box or top-left jump), remove the in-pill dismiss cross (auto-dismiss/Escape still close it), and tighten the pill's vertical padding.

  38. v0.24.1Патч9 июл. 2026 г.
    Исправлено

    Types — Fixed a publishing defect (introduced in 0.24.0) where importing @dodopizza/blok/react — or @dodopizza/blok/markdown — made a consumer's TypeScript compiler follow the published declarations into raw src/ implementation, producing spurious errors about unresolved micromark-util-types / @types/mdast (TS2307) and implicit any (TS7006). The public types/*.d.ts surface is now self-contained and no longer re-exports from src/.

    Изменено

    Types — Mechanically enforce that no published types/*.d.ts re-exports or imports from src/, and generate the self-contained icon declarations from source (scripts/generate-icons-dts.mjs).

  39. v0.24.0Минорный9 июл. 2026 г.
    Добавлено

    Vue — New first-class @jackuait/blok/vue adapter: BlokEditor component, useBlok, and provideBlok, plus createVueBlock/useBlocks for authoring custom blocks and driving the block tree from Vue. Custom Vue blocks support read-only in-place toggling.

    Добавлено

    Angular — New first-class @jackuait/blok/angular adapter shipped as an Angular Package Format build (ng-packagr): the editor component/directive, a block portal registry, the BLOK_BLOCK_CONTEXT render-context token, createAngularBlock authoring, and the reactive injectBlocks block-tree API.

    Добавлено

    React — New useBlocks hook exported from @jackuait/blok/react: a reactive block-tree API with reads, insert (position + append-to-parent, explicit id, tunes, replace), move (before/after/toIndex), nest/unnest/remove/transact, insertMany, atomic insertTree for nested subtrees, and additive insertMarkdown. Block-creation semantics are hardened across hierarchy edges with compile-time drift guards against the core API.

    Добавлено

    Adapters — Closed React/Vue/Angular parity gaps across component paths and escape hatches; shared one blocks-api core so Vue's useBlocks reaches React parity, and extracted shared fillDefaults/PropSchema helpers. Custom-block authoring is now first-class on the public API surface.

    Добавлено

    Accessibility — Five-wave overhaul adapting shadcn/ui interaction patterns to Blok's UI primitives: dismissal-layer/popover teardown/scroll-lock/announcer foundations, an anchored-positioning engine and shared modal Dialog, keyboard reachability for toolbars/menus/radios/rename, and assistive-tech feedback parity across selection, drag, menus, and arrival.

    Добавлено

    Link — Clickable links with a hover card in both edit and read-only modes (with enter/leave animation), an edit mode featuring a title field and remove-link action, refined hover-card chrome, blocking of unsafe-scheme navigation, and a consistent same-page/anchor-link rule that opens such links in the same window across all link-creation paths.

    Добавлено

    Blocks — Structural parentId nesting: any block can now be nested inside any list (flat per-block indent), with list keyboard nesting and drag/serialization migrated onto the structural block tree.

    Добавлено

    Keyboard — Cmd+Left/Cmd+Right navigate between blocks at block edges; Backspace at the start of a nested block removes one indent level; mixed-list Tab indents both kinds; and numerous Notion-parity Tab/arrow/Delete/Backspace fixes.

    Добавлено

    Paste — Paste-without-formatting (Cmd/Ctrl+Shift+V); recovery of buildin/Notion toggles and soft breaks from lossy GFM HTML fallback.

    Добавлено

    Inline — Link-markdown auto-format and a link-paste menu; shortcut-triggered Link/Equation/Marker now open a standalone menu positioned right under the selection.

    Добавлено

    Popover — Custom cross-platform scrollbar that hides the classic OS bar while keeping a stable gutter; reel-like edge distortion replacing the scroll haze.

    Добавлено

    Convert — Shared buildConvertMenuEntries with titleKey resolution, used by both block settings and the inline "Turn into" menu (which now lists the full text family), guarded by parity E2E.

    Добавлено

    Image — Configurable auto-retry on image load failure (default 5).

    Исправлено

    CRDT/Yjs — Undo/redo no longer yanks the caret to the top of the document; the caret restores to the correct position, split() inherits full tool data (correct heading undo caret), redo moves the caret to the new block on an Enter split, and five further Yjs sync gaps in tools and modules were closed.

    Исправлено

    List — Closed dozens of Notion-parity divergences across convert, keyboard, drag, selection, and copy/paste; source ordered lists renumber when an item is dragged away; bullet glyphs refresh on depth change.

    Исправлено

    Text/Header — Fixed 30+ Notion-parity bugs by root cause (slash+space, duplicate pulse, indent toolbar, caret offset preservation on turn-into, and more).

    Исправлено

    Table — Preserve merged cells and lists when pasting external tables, and keep list markup when copying cells out to external apps.

    Исправлено

    Paste — Preserve lists and quote-ness in pasted blockquotes; pasted links use the default link color; the link menu shows on non-empty blocks without erasing content; closed remaining sanitizer/merge data-loss gaps found by an audit.

    Исправлено

    Blocks — Re-parent a merged block's children onto the survivor instead of orphaning them; release toggle children as siblings when turning a toggle into text; fire the tool moved() hook on setBlockParent; never write split text into a mutation-free decoration.

    Исправлено

    Columns — Match Notion's inter-column gutter spacing; restore DOM order when undoing column creation.

    Исправлено

    Drag — List-item drop line tucks under the text with a marker lead-in; depth changes apply on same-slot drops; non-list blocks stop previewing nested drops they can't reach.

    Исправлено

    Selection — Fake highlight matches the native selection color and stays visible while a menu input is focused; Cmd+A container-scoped staging.

    Исправлено

    Marker — Reset <mark> background so colored text never shows the browser's yellow highlight.

    Исправлено

    Toggle — Arrow container stays a constant 28px square and pins to the first line for multi-line toggle/heading.

    Исправлено

    Styles — Reserve a scrollbar gutter on all scrollable components and keep it in nested inline-toolbar menus; auto-hide scrollbars system-style while keeping the gutter.

    Изменено

    Paste — Mechanically enforce the paste attribute law and the paste stamp law via architecture tests.

    Изменено

    Tests — Repaired all CI-matrix E2E shards; added regression coverage across list keyboard shortcuts, columns undo order, popover scrollbar spec, and adapter integration/e2e.

    Изменено

    Lint — Resolved all 69 root ESLint problems at the root cause.

  40. v0.23.5Патч25 июн. 2026 г.
    Добавлено

    Core — The link config ({ target, rel, transformHref }) now also applies on the render and paste paths, not just the interactive link tool. Anchors coming from stored block HTML (rendered via blocks.render()) and <a> arriving through the clipboard now get the configured target/rel forced and transformHref applied to their href — so consumers no longer need to post-process the rendered or pasted DOM. Because the render path rewrites live anchors whose href round-trips into saved data, transformHref must be idempotent.

    Добавлено

    Core — New onBeforeRender(blocks) => blocks config transforms the blocks array before every render (the initial render and each blocks.render()), letting you run app-specific data migrations inside Blok instead of pre-processing the data yourself. It runs on the raw saved blocks before format analysis, so it can also inject blocks into an empty document.

    Добавлено

    Core — New onAfterRender(api) config fires after a render completes and the blocks are in the DOM (initial render and every blocks.render()), for post-render side effects such as scroll restoration — distinct from the once-only onReady.

    Добавлено

    Core — A stable data-blok-rendered attribute (exposed as DATA_ATTR.rendered) is now set on the editor wrapper when a render batch finishes inserting blocks, and removed while a re-render is in flight — a DOM-level render-readiness gate that complements the existing blocks:rendered event.

    Добавлено

    Block Tunes — A custom tune's render(context) now receives an optional BlockTuneRenderContext whose getPopoverElement() returns the host tune popover element ([data-blok-popover]), so tunes can anchor sub-menus or portals inside Blok's popover without reaching into the DOM via closest(...). The element resolves once the popover mounts (it is null synchronously during render()).

    Добавлено

    React — <BlokEditor>/useBlok now accept onBeforeRender and onAfterRender. Both are attached only when provided and are ref-stable, so updating the callbacks never recreates the editor.

  41. v0.23.4Патч25 июн. 2026 г.
    Добавлено

    Core — New onSave(data, api) config delivers the full serialized OutputData (debounced via the existing change-batch window) whenever content changes — the "output half" of a controlled editor. Pair it with the data config to mirror editor state into your own store with a single callback instead of calling saver.save() by hand. Only user-driven changes trigger it; programmatic render() does not (the change observer is disabled during render), so a controlled round-trip won't recurse. Available to all consumers, not just React.

    Добавлено

    React — <BlokEditor>/useBlok now accept onSave, making <BlokEditor data={data} onSave={setData} /> a true controlled component to pair with the reactive data prop from 0.23.3. The callback is ref-stable (never recreates the editor) and attached only when provided. Echoing the payload straight back via onSave={setData} is caret-stable: the adapter records the editor's own emitted output as the content baseline, so the round-trip deep-equal–dedupes to a no-op (no re-render, no caret reset) while genuine external data changes still render in place.

  42. v0.23.3Патч25 июн. 2026 г.
    Добавлено

    React — The <BlokEditor>/useBlok data prop is now reactive: passing new content re-renders the editor in place via editor.render() instead of being read only once at creation. Identical content is de-duplicated (deep-equality) so the caret is never clobbered, rapid changes are serialized, and a freshly-seeded editor is not double-rendered.

    Добавлено

    Core — New typed render events: blocks:rendered (payload { count }) fires when a batch finishes rendering, and block:rendered (payload { blockId }) fires per block. The runtime event-name constants BlocksRendered/BlockRendered are exported, so consumers can react to rendering instead of polling the DOM. The public Events API is now typed against an event/payload map while still accepting arbitrary string events.

    Добавлено

    Core — New link config ({ target, rel, transformHref }) lets consumers configure the anchors the link tool creates instead of post-processing the DOM. Defaults (_blank/nofollow) are preserved, configured values now survive save, and URL validation/allowlisting is unchanged.

    Добавлено

    Paste — New onBeforePaste(html) => string | null config hook transforms (or drops) raw clipboard HTML before Blok preprocessing; returning null falls back to plain-text paste.

    Добавлено

    API — New editor.tools.update(name, config) shallow-merges a tool's config in place — e.g. swap an uploader — without recreating the editor.

    Изменено

    Tests — Exported stable TEST_ID constants (plus button, settings toggler, block wrapper) wired into the editor chrome via data-blok-testid, so consumers no longer query internal selectors.

  43. v0.23.2Патч25 июн. 2026 г.
    Изменено

    Docs — Documented two React-adapter caveats. <BlokEditor> must not be wrapped in styled() or any HOC that reserves the theme prop: styled-components claims theme for its own ThemeProvider, so it never reaches the editor and theme sync silently breaks — render it directly and style the container via className. And deps values must be referentially stable (each value compared individually, not the array wrapper), otherwise the editor is recreated on every render. Both caveats now appear in the README, the docs site, and the BlokEditor/useBlok JSDoc and published type declarations.

  44. v0.23.1Патч25 июн. 2026 г.
    Добавлено

    Core — A new editor.placeholder runtime API (get/set) lets consumers read and change the empty-paragraph placeholder on a live editor, mirroring the existing width API. Updates apply to existing blocks and to blocks created afterwards.

    Добавлено

    React — <BlokEditor> now accepts a reactive placeholder prop (backed by the new core API) that updates the editor in place without recreating it, and forwards all standard <div> attributes — id, aria-*, data-*, and the like — to the editor container.

  45. v0.23.0Минорный24 июн. 2026 г.
    Добавлено

    React — A blessed <BlokEditor> component is now the recommended way to embed Blok in React. It forwards a typed ref to the live editor instance, takes an uncontrolled data seed, and reactively syncs readOnly, autofocus, theme, and width props without recreating the editor. Its onReady callback fires after the ref commits, so consumers can safely call ref.current from inside it. The lower-level useBlok hook plus BlokContent remain available as an escape hatch.

    Изменено

    React — useBlok now reactively syncs theme and width prop changes to the editor instance, mirroring the existing readOnly/autofocus pattern.

    Изменено

    Docs — The demo wrapper now dogfoods BlokEditor, and the README React section documents the recommended BlokEditor path, the uncontrolled data contract, reactive props, and the useBlok + BlokContent escape hatch.

    Изменено

    Tests — Added e2e coverage for save-via-ref and live prop toggles, a published-vs-source type-drift guard, and data-blok-testid-based locators.

  46. v0.22.0Минорный24 июн. 2026 г.
    Добавлено

    Paste — Content copied from buildin.ai now imports as native Blok blocks at full fidelity. buildin's clipboard carries a lossless text/next-space-blocks JSON payload beside a lossy Markdown/HTML twin; Blok previously fell back to the twin, where tables collapsed to literal |pipes|, media degraded to links, and callouts, toggles, columns, to-dos, and code language flattened away. A new handler decodes the JSON directly, reconstructing the same native blocks as a Blok→Blok paste — paragraphs, to-dos, H1–H4, tables (grid + parented cells), bulleted/numbered lists, toggles, dividers, quotes, callouts (emoji + colour), code (with language), equations, toggle-headings, column lists, and image/video/audio/file/embed-bookmark media. (Inline marks — bold/italic/link/colour — are a documented follow-up.)

    Исправлено

    Paste — Callout body and colour now survive import from both Notion and buildin.ai. Blok's callout stores its body in child blocks, so the inline title/body text the parsers emitted as data.text was silently discarded — the callout is now emitted (colours only) plus a child paragraph carrying its text. Out-of-palette callout colours (e.g. buildin's British grey, or any name outside Blok's 9-colour preset) previously produced an undefined CSS variable that dropped both the background and the border; colours now normalize through Blok's preset palette (grey→gray; unknown names clamp to null).

  47. v0.21.1Патч24 июн. 2026 г.
    Добавлено

    Media — Image, video, audio, and file blocks can now be restricted to upload-only or link-only via configuration, so consumers can offer a single source instead of always exposing both.

    Изменено

    Media — Deduped MediaSource into a single shared type across the media tools.

    Изменено

    Docs — Documented the audio block tool, and added upload-only and link-only empty states to the playground gallery.

  48. v0.21.0Минорный23 июн. 2026 г.
    Исправлено

    Paste — Rich clipboards (Notion and similar) ship both a faithful HTML payload and a lossy Markdown twin. Routing now prefers the HTML handler, so pasted images, links, and structure the Markdown twin drops are preserved.

    Исправлено

    Paste — Notion content keeps its document order: nested children no longer render above their parents (only table cells stay children-first, since the table tool resolves cell ids on insert). Internal references that previously vanished — sub-pages, linked databases / collection views, and inline page mentions — now paste as Notion bookmarks/links instead of being dropped or leaking the raw "‣" glyph, and uploaded media whose binary isn't on the clipboard becomes a Notion-link bookmark carrying the filename rather than a bare filename paragraph.

    Исправлено

    Paste — Pasted external Notion audio now shows its title (the player reads data.title, which was left blank), and a malformed inline date annotation no longer leaks the raw "‣" placeholder glyph.

    Изменено

    Tests — Added regression coverage for HTML-over-Markdown routing, document-order preservation, internal-reference rescue, pasted audio titles, and date-glyph handling.

  49. v0.20.0Минорный22 июн. 2026 г.
    Добавлено

    Paste — Content copied from Notion now migrates as native blocks with full state preserved. When Notion's lossless clipboard JSON is present it is used directly (the high-fidelity path), with an HTML fallback for sources that only expose markup. Inline equations and page mentions are mapped to their Blok equivalents.

    Добавлено

    Audio — Custom cover art. A cover picker (file upload or image URL) opens from an editable overlay button on the player; covers can be set, replaced, or removed (via a "Remove cover" block setting), with an animated picker open, a sliding Upload/Link tab transition, a themed surface that matches the player, and i18n across all locales. Audio blocks with no cover now show an inertial spinning-vinyl turntable placeholder instead of an empty panel.

    Исправлено

    Audio — Repaired the transport controls and the video-style playback-speed menu, which now stays open after picking a preset. The volume bar fill is fixed so a muted track reads differently from a full one, and the playing waveform pulses smoothly without gouging its dots. The caption toggle stays on the compositor, and the cover picker no longer jumps height on tab swap, gets an explicit width so the URL field isn't cramped, and revokes leaked cover blobs on a destroy race.

    Исправлено

    Table — Pinned the top toolbar anchor flush to the table edge.

    Изменено

    Tests — Added unit and e2e coverage for custom cover set/remove and for real Notion page-mention arity, and cleared the lint/type violations the cover-art work introduced.

  50. v0.19.2Патч20 июн. 2026 г.
    Ломающее изменение

    Types — OutputBlockData's data field is now typed Record<string, unknown> instead of any (matching BlockToolData and SavedData). Reading a property off a saved block's data — e.g. on save() output — now yields unknown rather than any, so code that indexes into block.data may need a cast or type guard. This is a type-only change with no runtime effect.

    Исправлено

    Types — Published .d.ts declarations are now self-contained and no longer re-export raw src/*.ts. A bare import { Blok } from '@jackuait/blok' previously dragged editor source into the consumer's TypeScript program (through tooltip and popover → flipper), surfacing internal type errors under strict consumer flags such as noUncheckedIndexedAccess. The tooltip and popover declarations now inline their public types, so consuming the package no longer type-checks Blok's internals. (The opt-in /markdown subpath is unchanged.)

    Исправлено

    Types — The published declarations are now internally consistent under skipLibCheck: false. Fixed an incorrect BlockToolData import path in the database/header/list tool declarations (which also produced spurious "incorrectly extends BlockTool" errors), added a missing InlineToolConstructable/InlineToolConstructorOptions import in the type entry, and removed phantom Dictionary/DictValue re-exports.

    Изменено

    Dependencies — Moved nanoid to devDependencies; it is bundled into every dist artifact and was never a runtime external.

  51. v0.19.1Патч20 июн. 2026 г.
    Добавлено

    Types — isReady now resolves with the fully-initialized Blok instance (was Promise<void>), so const editor = await blok.isReady yields a ready, fully-typed editor without a cast. New exported PendingBlok type describes the surface available synchronously after new Blok() and before isReady resolves (isReady, destroy, theme, width) — type a reference held during that window as PendingBlok instead of widening to Partial<Blok>, then await isReady to narrow it to the full API. new Blok() still returns the full Blok, so existing usage is unaffected.

  52. v0.19.0Минорный20 июн. 2026 г.
    Добавлено

    Width — New public width API on the editor instance: instance.width.get(), set('full' | 'narrow'), and toggle() switch the content layout between 'narrow' (the default, constrained to --max-width-content) and 'full' (the content max-width is removed so it fills its container). It mirrors the theme API, including buffering a set() call made before the editor is ready and replaying it once the editor is initialized.

    Исправлено

    Types — Declare the history API on the exported Blok instance type. history (clear(), undo()/redo(), canUndo()/canRedo()) was already available at runtime; consumers no longer need to cast the instance to reach it.

  53. v0.18.0Минорный19 июн. 2026 г.
    Добавлено

    Audio — New native Audio block tool. Now-playing card with cover art (lazy music-metadata extraction), a waveform canvas with click/drag seek, transport controls (play/pause, volume, playback speed, loop, keyboard shortcuts, persisted preferences), file and URL upload, paste handling routed away from the File block, read-only support, and i18n across all locales. The player card is a full-bleed redesign — a tall cover panel (music-note placeholder when there is no art), a hero waveform scrubber with rounded bars, a slim transport bar, and motion polish.

    Добавлено

    Media — Image, video, and audio blocks now accept any file of their media family (image/*, video/*, audio/*) by default. Restrict the accepted types through the existing types config, which now accepts both exact MIME types (image/png) and family wildcards (image/*).

    Исправлено

    Types — Export File, Audio, and Video (and their data/config/uploader types) and add the file/audio/video keys to defaultBlockTools from the @jackuait/blok/tools types entry. The runtime already exported these tools; consumers no longer need a local ambient type shim to import them.

    Изменено

    Playground — Audio block states in the block-states gallery (real ID3-tagged track and a "No cover art" state) plus an e2e harness for insert/upload/play/seek.

  54. v0.17.0Минорный19 июн. 2026 г.
    Добавлено

    Video — New native Video block with a custom Airbnb-style player, brought to YouTube parity: full keyboard control (j/l/k, 0–9, Home/End, frame-step, volume, speed), a scrubber with buffered range, hover frame-preview tooltip and mini progress bar, an in-player gear menu (Notion-style playback speed with glide, loop, ambient-glow intensity), and view modes — picture-in-picture, a FLIP-morphed theater/cinema mode, and a fade-in ambient glow. Player polish includes click-to-toggle play/pause, a centre play/pause burst, press-and-hold for 2× playback, arrow-key ±5s seek with side indicators, idle auto-hide, buffer spinner, time-remaining toggle, right-click menu, stats overlay and persisted preferences.

    Добавлено

    Video — Custom fullscreen surface with a top caption bar, a "Hide controls" tune for a control-free player, and GIF-style autoplay/loop tunes.

    Добавлено

    Image — Auto-convert dropped, pasted and remote-URL GIFs into a looping Video block via WebCodecs + webm-muxer, gated by the convertGifToVideo config (default on); the original GIF is kept on CORS failure, with a "Converting…" label shown during conversion.

    Добавлено

    Media — 30MB default upload limit with per-type maxSize configuration and human-readable too-large errors.

    Исправлено

    Paste — URL paste always prompts now; the previous auto-embed behaviour has been removed. Breaking: consumers relying on silent auto-embed must opt in through the paste menu.

    Исправлено

    Video — Reserve the aspect ratio before metadata loads to prevent squeeze-on-load, centre and letterbox the fullscreen player, strip editor chrome in fullscreen, and hide the bottom mini progress bar while fullscreen.

    Исправлено

    Video — Exit theater mode reliably on Escape via a capture-phase listener with a smooth deferred dismiss, and drive the scrubber fill with requestAnimationFrame for smooth playback tracking.

    Изменено

    Build — Move webm-muxer to devDependencies so it is bundled rather than treated as an external runtime dependency.

    Изменено

    README — Replace the logo with the optimized noodle mascot.

    Изменено

    Playground — Use real self-hosted videos in the block-states gallery.

  55. v0.16.0Минорный16 июн. 2026 г.
    Добавлено

    File — New File block tool. Tabbed empty state with upload (validation, progress bar, cancel), URL and drag-and-drop; per-type icon and tint; editable filename; consumer upload endpoints and download card. Rich preview modal dispatched by kind: PDF (top-layer modal with open-in-new-tab), Office (docx/xlsx/pptx via lazy renderers, xlsx parsed through JSZip), and text/code/markdown — including advanced markdown (math, footnotes, references, alerts, anchors, safe block-level raw HTML) with an animated Rendered ⇄ Raw toggle. Read-only support, i18n in every locale, and Storybook stories.

    Добавлено

    Embed — Generic embed: frame arbitrary URLs through a gated resolver, offered in the paste menu behind the linkPaste.allowGenericEmbed flag with an api.config accessor. Replace the source via an empty-state URL bar and an overlay more-menu item.

    Добавлено

    Migration — Complete Editor.js block-type coverage plus a drop-in UMD build; adapt legacy Editor.js inline tools and linkTool data.

    Добавлено

    Playground — Block-states selector as a fixed left side menu; real docx/xlsx/pptx, code and text samples for the File block; richer quarterly-budget sheet; File block wired into the editor demo.

    Исправлено

    Table — Resolve merged-cell coordinate bugs; preserve merges on load; split overlapped merges on paste so no destination data is dropped; keep empty cells editable on the read-only→edit toggle; harden input, clipboard and move-guard handling.

    Исправлено

    File — Unbreak pptx preview; vertically center the preview modal; stop wrong-colour strips and toggle flicker during preview transitions; block javascript: URLs in download hrefs.

    Исправлено

    Build — Make the published install self-contained (ship src, keep markdown and nanoid as runtime deps) so bundlephobia can build; green the self-contained-install and css-token audits.

    Изменено

    Refactor — Extract table visual-subsystem orchestration into TableSubsystems; split BlockOperations into focused worker classes; share the media uploader empty state across the image and file tools.

    Изменено

    Code — Cover every Prism token in both the light and dark themes.

    Изменено

    Lint — Resolve all lint errors by root cause and mute advisory-only rules.

    Изменено

    Docs — Refresh the README tool list and entry points; add a File block tool reference entry.

  56. v0.15.1Патч13 июн. 2026 г.
    Исправлено

    Types — Declare Embed and Bookmark (and their defaultBlockTools entries) in the published @jackuait/blok/tools types. The runtime exported them in 0.15.0 but the .d.ts did not, so import { Embed, Bookmark } failed to typecheck.

  57. v0.15.0Минорный12 июн. 2026 г.
    Добавлено

    Link Paste — Pasting a URL now offers a Notion-style menu to keep it as a link, or convert it into a Bookmark card or rich Embed block. The pasted link shows immediately with the menu anchored at its end, and menu labels name the detected link type via provider metadata.

    Добавлено

    Embed — Worldwide embed registry covering ~115 services across video, audio, social, documents, design and developer domains, including Google published docs/forms and draw.io. Per-source minimum resize widths keep each provider's iframe legible, and fixed-width providers hug their content with figure, handles and toolbar.

    Добавлено

    Bookmark — Notion-parity bookmark card with a dev unfurl endpoint; crawler-UA retry recovers metadata from bot-blocked sites.

    Добавлено

    Playground — Smooth cross-fade theme switching via View Transitions, plus an Airbnb-style neutral redesign.

    Исправлено

    Embed — Preserve the live iframe across every editor action: caption and alignment toggles now apply in place instead of reloading the player. Selection highlight hugs the figure dimensions.

    Исправлено

    Drag & Drop — FLIP-animate the column drop moment and slim the vertical drop bar to read like the horizontal line.

    Исправлено

    Security — Harden URL-scheme filtering and neutralize XSS gaps in markdown paste, the inline link tool, and the paste/render pipeline.

    Исправлено

    Tools — Implement setReadOnly on embed, bookmark and column tools so read-only toggles in place without a full re-render.

    Исправлено

    Icons — Unify the icon set on the 20×20 / 1.25 house spec; refine heading family, quote, caption, pencil, cells, toggles, and numbered-list glyphs.

    Исправлено

    CI — Pin Node 24.14.1 to dodge a Playwright install hang; share Playwright setup to stop Storybook browser install hanging; repair 6 failing CI specs (5 stale expectations, 1 real drop-indicator regression).

    Изменено

    Dependencies — Resolve all 52 open Dependabot alerts; bump brace-expansion, ws, smol-toml.

    Изменено

    Tests — Embed/bookmark/link stories with screenshot baselines, wave-2 embed visual-regression baselines, verified real sample URLs replacing fixtures, refreshed main.css golden snapshot.

    Изменено

    Docs & Playground — Embed, bookmark and link entries in tools data and the editor demo.

  58. v0.14.1Патч8 июн. 2026 г.
    Добавлено

    Tools — Register the Columns tool with a single Columns group key. Tool-group "provides" manifests expand into their underlying block tools during prepare(), so consumers add one key instead of wiring each block.

    Исправлено

    Tools — Export Columns from public types for single-key registration; keep defaultBlockTools settings-only so the group key forwards settings without re-registering.

  59. v0.14.0Минорный5 июн. 2026 г.
    Добавлено

    Columns — New side-by-side layout tool (#67). Create 2–5 column presets from the toolbox, or drag a block beside another to spawn a column. Drop anywhere left/right of a block to make a new column, or into a column body to stack inside it. Columns nest, auto-unwrap when emptied, and stack vertically on narrow viewports.

    Добавлено

    Columns — "Turn into columns" command wraps a multi-block selection into a column layout, available from the Convert-to menu.

    Добавлено

    Columns — Hover-revealed resize separators between columns: drag to resize, keyboard-resizable with ARIA slider semantics, double-click a divider to equalize widths.

    Добавлено

    Columns — Horizontal arrow keys traverse between sibling columns; new columns animate in Notion-style.

    Добавлено

    Inline Toolbar — Appears instantly on selection release, no animation delay.

    Исправлено

    Inline Toolbar — Removed entry animation that delayed appearance.

    Изменено

    i18n — Column resize aria-labels and turn-into-columns strings across all locales.

    Изменено

    CI — Repair unit tests, e2e merge, and mirror push on master; mirror push works for both branch and tag events.

    Изменено

    Tests — Exhaustive block-in-column compatibility suite, live-drag lifecycle specs for every block type, multi-select block-settings header i18n regression.

    Изменено

    Playground — Columns example in the editor demo and block-states gallery.

  60. v0.13.2Патч30 мая 2026 г.
    Исправлено

    Read-Only — Collapse the empty bottom click-to-add zone to 0px in read-only mode and restore the configured min-height when editing

  61. v0.13.1Патч29 мая 2026 г.
    Добавлено

    Image — Auto-retry failed image loads with loading overlay; distinguish upload-failed vs broken-image error states; predict loading-placeholder dimensions from URL, SVG, and cache; pipe upload progress to bar (#41)

    Добавлено

    Codemod — Default migrated images to size: 'full' and inherit the stretched flag into migrated image size

    Добавлено

    Block Link — Highlight pulse on hash-link arrival

    Добавлено

    Read-Only — Show copy-link menu on block hover

    Добавлено

    Playground — Add loading image state demo in block-states gallery

    Исправлено

    Image — Force full width and compact overlay for short images; reuse looping-arrows glyph for replace icon

    Исправлено

    Paste — Keep Google Docs images inside tables and stop double-bolding headings; prevent default page background collapsing to gray preset

    Исправлено

    Table — Recover migrated cell text detached by a pre-fix save

    Исправлено

    Toolbar — Align plus/drag handle with content lane for stretched blocks

    Исправлено

    Block Settings — Anchor popover to trigger instead of (0,0); translate popover context label

    Исправлено

    Database — Center block toolbar on the title line

    Изменено

    i18n — Translate strings identical to English across 25 locales

    Изменено

    Lint — Resolve all ESLint and tsc problems

    Изменено

    Image — Move inline upload-failed SVG to icons module

    Изменено

    Tests — Cover migrated cell content surviving load→save round-trip; fix CSS guard test failures from image loading shimmer

  62. v0.12.0Минорный22 апр. 2026 г.
    Добавлено

    Image — New image block tool (#66): drag-drop/URL/file upload, captions, alt text via inline popover, resize handles with symmetric growth, edge-pinned aspect-ratio resize, crop editor (rect/circle/oval) in modal, fullscreen lightbox with wheel/pinch zoom, drag-to-pan, rubber-band, alignment popover (left/center/right), block settings entries (size/download/copy-url), three-dots overflow menu for narrow images, empty/uploading/error states with unified card design, light-theme crop editor, legacy editor.js shape migration

    Добавлено

    Code — Migrate from Shiki to Prism.js for syntax highlighting with lazy grammar loading and class-based applier; add auto-indent and bracket expansion on Enter; add Mermaid highlighting with One Dark/Light palette; gutter line-number click focuses the line

    Добавлено

    Fonts — Bundle @fontsource fonts via generator script; new fontFamilySans/Serif/Mono/Handwriting config fields with CSS variable injection; font-display: swap for body text

    Добавлено

    Popover — Render above all elements via CSS Top Layer; nested-submenu viewport clamping on both axes; close transition via ghost clone; tighter item sizing; end-of-list padding hidden on empty search; simpler animations

    Добавлено

    Toolbar — Hide plus and dots buttons while toolbox is open; place block settings popover left of the dots button

    Добавлено

    Toolbox — Nowrap pill with tighter radius and unified plus/slash search styling

    Добавлено

    Playground — Icon gallery lightbox; block states gallery tab; settings panel shortcuts; hide header on scroll; logotype image example

    Добавлено

    CSS Variables — Tokenize radii, spacing, icon sizes, border widths, z-index ladder, duration/easing, typography; extract direct rgba literals to palette tokens; migrate @apply arbitrary hex values; split actions-icon/divider vars; add audit test and visual regression baselines

    Добавлено

    Database — Match Notion card shadow and radius on kanban cards; showcase all 10 column color variants

    Добавлено

    Block Settings — Add shortcut keys to i18n with regression tests

    Добавлено

    Icons — Migrate inline SVGs to shared icon layer

    Исправлено

    Inline Toolbar — Tighten item padding and radius; suppress toolbar inside code blocks; apply symmetric top/bottom padding

    Исправлено

    Code — Pin caret color so it does not inherit Prism token colors; restore trailing <br> after highlight so Enter works once; refresh gutter/highlight after native paste; focus line end when clicking empty strip of short lines; scope inline-code styling to not leak into code block; support contenteditable="plaintext-only" and preserve view mode on undo; correct syntax highlighting offset calculation

    Исправлено

    Toolbar — Reposition + / ⋮⋮ live while hovered block resizes; disable pointer-events on every actions descendant for left-edge blocks; keep slash search in inserted block after plus button

    Исправлено

    Popover — Distinguish synthesized hover from real hover; hide context label while searching; keep block settings menu visible and attached to dots trigger

    Исправлено

    Block Manager — Skip cross-container auto-heal inside move group

    Исправлено

    Tooltip — Anchor wrapper with position: fixed to survive page scroll; render above popover and survive UA stylesheet

    Исправлено

    Fonts — Add error handling for font load failures

    Изменено

    Styles — Split main.css into 11 concern-files

    Изменено

    License — Add fork attribution and NOTICE file

    Изменено

    Build — Replace shiki with prismjs

    Изменено

    Tests — Fix 60+ unit + E2E failures across the suite; add Prism integration test for all highlightable languages

    Изменено

    Chore — Untrack .vscode; remove stale root files; add favicon to dev playground; drop .editorconfig

  63. v0.11.1Патч16 апр. 2026 г.
    Добавлено

    Bundles — Ship CJS (require()) and IIFE (<script> tag / CDN) bundles alongside ESM; add "main", "browser", "unpkg", and "jsdelivr" fields to package.json

    Изменено

    README — Add installation section documenting ESM, CJS, and CDN usage

  64. v0.10.9Патч14 апр. 2026 г.
    Добавлено

    Toggle — Gray arrow icon when toggle body is empty

    Исправлено

    Drag — Eliminate "wrong block dropped" with multi-layer stale-block defense; block paste, undo/redo, and move shortcuts during active drag; integrate drag-reparent with undo as a single step

    Исправлено

    Hierarchy — Reject dangling parentId at universal chokepoint; reconcile remote Yjs reparents; close remaining container drift vectors; exempt Yjs remote sync from dangling parent throw

    Исправлено

    Paste — Inherit container parent on replace-insert and x-blok root paste; harden container paste ejection across all container block types

    Исправлено

    Callout — Restore plus button and drag handle; stop paste from ejecting children via stale contentIds; prevent Enter from inserting new block inside callout

    Исправлено

    Undo — Collapse multi-block paste and alt-drag duplicate into one undo group; eliminate spurious entries from metadata-only writes

    Исправлено

    Toolbar — Keep drag handle visible when editing inside table cell

    Исправлено

    Insert — Universally protect all Enter paths from nested-block leak

    Исправлено

    Table — Tighten list item spacing inside table cells

    Исправлено

    Yjs — Map 'no-capture' origin to local to prevent mid-op sync clobbering tool state

    Изменено

    Yjs — Make DocumentStore.ydoc private; enforce local origin whitelist with exhaustive mapper

    Изменено

    CI — Shard E2E tests via reusable workflow; add merge-reports job; run spec-file coverage validator on every PR; remove size-limit bundle size check

  65. v0.10.8Патч13 апр. 2026 г.
    Исправлено

    Table — Normalize flat-array table child parents at every entry point

    Исправлено

    Data Model — Recursively expand legacy nested toggleList/callout bodies

  66. v0.10.7Патч13 апр. 2026 г.
    Исправлено

    Theme — Prevent nested editor instances from overriding parent theme on prepare

  67. v0.10.6Патч12 апр. 2026 г.
    Добавлено

    Config — Replace user.name with user.id + resolveUser callback for multi-editor identity tracking

    Добавлено

    Keyboard — Del shortcut for block delete; markdown shortcuts for quote (" + space) and code (` ` ` + space) blocks

    Исправлено

    i18n — Use Blok locale for date formatting with full month names; strip trailing abbreviation suffixes for ru/uk locales

    Исправлено

    Popover — Display scroll haze instantly on open instead of fading in

    Изменено

    Deps — Add lodash-es resolution to pin ^4.18.0

  68. v0.10.5Патч11 апр. 2026 г.
    Добавлено

    Database — DatabaseView rendering layer with kanban board DOM

    Исправлено

    i18n — Localize hardcoded "Last edited" strings in block settings footer; add missing translations across 67 locales

    Исправлено

    Theme — Expose theme API before isReady to prevent dark theme race condition

    Изменено

    Lint — Resolve all 226 lint issues across source and test files

    Изменено

    CI — Enable Corepack before setup-node to resolve Yarn version mismatch; remove dead version-check job

    Изменено

    Tests — Resolve 119 failing tests across E2E, unit, and docs suites

  69. v0.10.4Патч11 апр. 2026 г.
    Добавлено

    Database — Kanban board view with drag-and-drop cards and columns, card drawer with nested editor, inline title editing, list view with collapsible sections, multi-view tabs with drag reorder, property-based data model, column controls, backend sync, and read-only mode

    Добавлено

    Copy block link — CopyLinkTune block tune with Cmd+Ctrl+L shortcut and automatic scroll-to-block on URL hash load

    Добавлено

    Block edit metadata — Track lastEditedAt/lastEditedBy on every block mutation with Yjs sync, saved output inclusion, and block settings footer display; new user config option

    Добавлено

    Popover — Scroll haze indicators on popover lists

    Добавлено

    Shortcut keys — Render shortcut keys as SVG icons with readable tooltip on hover

    Исправлено

    Inline tools — Preserve trailing nbsp through format/unformat cycles; preserve trailing spaces when applying inline formatting; extend trailing-whitespace range detection; unwrap whitespace-only bold ancestors when un-bolding partial selection

    Исправлено

    Block — Default lastEditedAt to Date.now() so footer always shows; preserve user-provided block IDs and deduplicate on render; validate block ID format in constructor

    Исправлено

    Paste — Prevent new table block when pasting into table cell with lost focus; handle hsl/hsla color formats

    Исправлено

    Scroll to block — Guard decodeURIComponent against malformed URL hash; encode block ID in URL hash

    Исправлено

    Theme — Prevent nested editor from resetting parent theme

  70. v0.10.3Патч9 апр. 2026 г.
    Исправлено

    Table — Guard addBlockToCell and setCellBlocks against writing into covered (merged) cells; resolve paste target and copy source coordinates from model attributes instead of DOM visual position; fix overlay/pill missing and wrong merge/split button after rect expansion; expand selection rect to include full spans of merged cells; use logical cell coordinates in getCellPosition; don't intercept copy/cut when user has text selected in a single cell; reindexCoordinates assigns model coordinates instead of DOM physical indices; center row grip on merged cell using getBoundingClientRect

    Исправлено

    Toolbar — Correct marginLeft for nested blocks and popover position when scrolled; restore focus to originally-typed block after plus+Escape

    Исправлено

    Toolbox — Position popover at caret when inside nested blocks (toggle/callout)

    Исправлено

    Keyboard — Prevent text-jumping by preserving focus on toolbar interactions

  71. v0.10.0Минорный8 апр. 2026 г.
    Добавлено

    Code block — New CodeTool with syntax highlighting (via Shiki), line numbers toggle, language selector popover, copy button, wrap toggle, and preview tab for KaTeX/Mermaid rendering

    Добавлено

    Inline code — New InlineCodeTool with CMD+E shortcut

    Добавлено

    Quote block — Notion-style quote block with size options submenu

    Добавлено

    Divider block — Horizontal rule block with --- markdown shortcut

    Добавлено

    Callout block — Callout block with emoji picker and skin tone persistence

    Добавлено

    Toggle list — Collapsible toggle list block with drag & drop support inside toggles ([#46](https://github.com/JackUait/blok/pull/46), [#52](https://github.com/JackUait/blok/pull/52))

    Добавлено

    Toggle headings — Toggle heading blocks with markdown shortcuts (>#, >##, >###) and body placeholder

    Добавлено

    Marker inline tool — Color text/background inline tool with color picker and dark mode support

    Добавлено

    Underline & Strikethrough — New inline tools with CMD+U and CMD+SHIFT+S shortcuts

    Добавлено

    Table enhancements — Cell color picker, cell placement picker, HTML <table> rendering, corner drag, Tab/Arrow escape from cells, and cross-table block protection ([#38](https://github.com/JackUait/blok/pull/38), [#45](https://github.com/JackUait/blok/pull/45), [#63](https://github.com/JackUait/blok/pull/63))

    Добавлено

    Markdown import — importMarkdown() API method and paste handler with GFM support including math (KaTeX) extensions

    Добавлено

    React adapter — useBlok hook and BlokContent component for React integration

    Добавлено

    Read-only toggle — Seamless in-place readonly mode toggle with scroll position preservation

    Добавлено

    Editor width API — editor.width namespace with WidthManager module and config.width options

    Добавлено

    Content alignment — config.style.contentAlign option for global block content alignment

    Добавлено

    Font family config — config.style.fontFamily option for editor and popover typography

    Добавлено

    Theme API — ThemeAPI module for programmatic dark/light theme control

    Добавлено

    Fuzzy toolbox search — Ranked fuzzy search in slash menu with animated filtering

    Добавлено

    Toolbox plus button — Opens blocks menu directly without inserting /

    Добавлено

    Link suggestion chip — URL type detection chip in inline toolbar

    Добавлено

    Google Docs paste — Expand <details> tags into toggle blocks with parent-child wiring

    Добавлено

    blok-cli package — New @jackuait/blok-cli package with convert (HTML→JSON) and convert-gdocs commands

    Добавлено

    i18n search terms — Multilingual toolbox search via searchTermKeys across all 68 locales

    Исправлено

    Drag & drop — Toggle hierarchy, ghost preview, subtree depth preservation, and spring-load auto-expand for closed toggles

    Исправлено

    Toolbar — Drag handle reachability, left-edge overflow, and actions not intercepting toggle arrow clicks

    Исправлено

    Inline toolbar — Cross-block selection positioning, background element cleanup on close

    Исправлено

    Table — Cross-table block stealing, undo/redo focus, cell selection border persistence, and arrow key navigation between blocks

    Исправлено

    Marker — Partial selection color removal, dark theme palette, and active color display on toolbar button

    Исправлено

    Toggle — Backspace/Delete boundary crossing, undo atomicity for Enter, children DOM nesting, and collapse in read-only mode

    Исправлено

    List — Tab indent for multi-selected items, depth reduction cascade on outdent, and bullet marker pinning

    Исправлено

    Paste — Table cell content appearing outside table, marker formatting preservation, and math formula detection

  72. v0.5.0Минорный23 янв. 2026 г.
    Добавлено

    CRDT-based undo/redo — The undo/redo system now uses Conflict-Free Replicated Data Type principles for better conflict resolution and history tracking

    Исправлено

    toolbar hover behavior after cross-block selection — The inline toolbar now resets its positioning state when extending selections across multiple blocks

    Исправлено

    PatternPasteEvent for internal cut/paste — Internal cut and paste operations now emit PatternPasteEvent, so external code can react to all clipboard actions

  73. v0.4.1-beta.5Патч7 дек. 2025 г.
    Исправлено

    Tailwind CSS conflicts — Fixed CSS conflicts that caused external plugins to break by isolating Tailwind's style precedence

    Добавлено

    data-blok-header-level attribute — Headers in the formatting popover now include a data-blok-header-level attribute for styling and testing hooks

  74. v0.4.1-beta.3Патч6 дек. 2025 г.
    Добавлено

    undo/redo — Added keyboard shortcuts (Ctrl/Cmd+Z and Ctrl/Cmd+Shift+Z) for editing history navigation

  75. v0.4.1-beta.0Патч16 дек. 2025 г.
    Добавлено

    RTL language support — Added translations for Hebrew, Persian, Urdu, Yiddish, Pashto, Sindhi, Uyghur, Kurdish, and Dhivehi with right-to-left layout

    Добавлено

    Eastern European languages — Added Czech, Romanian, and Hungarian translations

    Добавлено

    Southeast Asian languages — Added Thai, Ukrainian, and Greek translations

    Добавлено

    South Asian languages — Added Hindi, Bengali, Indonesian, and Vietnamese translations

    Добавлено

    Turkic languages — Added Turkish and Azerbaijani translations

    Добавлено

    Arabic — Added Arabic translation with RTL support

    Добавлено

    Northern European languages — Added Dutch, Polish, and Swedish translations

    Добавлено

    Korean, Japanese, Italian, Portuguese, German, French, Spanish — Added translations

    Добавлено

    Armenian, Chinese, Russian — Added translations

    Добавлено

    rename checklist to to-do list — Changed terminology from "checklist" to "to-do list"

    Добавлено

    drag & drop — Rewrote the drag and drop system for smoother interactions

    Добавлено

    flat data model — Changed from nested to flat structure using parentId and contentIds references

    Добавлено

    lists: flat data model — List items now use the flat data structure

    Добавлено

    keyboard navigation — Added keyboard shortcuts for editing without the mouse

    Добавлено

    list tools — Added numbered lists, ordered (nested) lists, and to-do lists with checkboxes

    Добавлено

    paragraph tool: custom configuration — The paragraph tool supports custom configuration for placeholder text and styling

    Добавлено

    header tool: custom configuration — The header tool supports custom configuration for levels and placeholder text

    Добавлено

    navigation mode — Added arrow key navigation through blocks, separate from text editing

    Добавлено

    UX improvements — Focus management, cursor positioning, and block interactions

    Исправлено

    translation keys: camelCase — Converted all translation keys to camelCase

    Исправлено

    translation key parsing — Fixed nested translation key parsing

    Исправлено

    remove redundant translation keys — Cleaned up duplicate and unused translation keys

    Исправлено

    fix Russian translation — Corrected a missing word in the Russian translation

    Исправлено

    fake selection display — Fixed how fake (visual-only) selections render

    Исправлено

    close inline toolbar on outside click — The inline toolbar now closes when clicking outside the editor

    Исправлено

    toolbar centering — Fixed toolbar positioning to stay centered regardless of content width

  76. v0.3.1-beta.0Патч3 дек. 2025 г.
    Изменено

    codemod improvements — Better pattern matching and safer transformations for the Editor.js migration

  77. v0.3.0Минорный2 дек. 2025 г.
    Добавлено

    bundle paragraph and header tools — These tools are now included by default in the core bundle

  78. v0.2.0Минорный2 дек. 2025 г.
    Добавлено

    drag & drop — Block reordering via the block handle (☰) icon

    Исправлено

    remove debug logging — Cleaned up console.log statements and resolved performance bottlenecks

    Изменено

    rebrand to Blok — Updated logos, color schemes, and documentation

  79. v0.1.0Минорный24 нояб. 2025 г.
    Изменено

    fork from Editor.js — Blok forked from Editor.js, preserving the block-based editing architecture

    Изменено

    initial feature set — Block management, inline formatting, slash toolbox, and plugin system