From ac6333031af992f596bae1fd02bd64355dd5d0bd Mon Sep 17 00:00:00 2001 From: Rim Zabarov Date: Tue, 10 Nov 2026 20:45:04 +0300 Subject: [PATCH 01/10] Let example frames take the size ladder of their own width The shell sent every page token to a frame, so a frame narrower than the page kept the page's desktop ladder (control heights, text sizes, spacing) while its own width queries read the phone side. Tokens declared under a width query, tokens built from them and measured breakout widths are now left to the frame's own stylesheets; a token the page sets on its root is sent as written. Co-Authored-By: Claude Opus 5.5 --- resources/portable/declarative-shell.js | 29 +++++++++++++---- tests/Unit/ExampleRuntimeContractTest.php | 38 +++++++++++++++++++++-- 2 files changed, 59 insertions(+), 8 deletions(-) diff --git a/resources/portable/declarative-shell.js b/resources/portable/declarative-shell.js index 491dc38d..7309fdfe 100644 --- a/resources/portable/declarative-shell.js +++ b/resources/portable/declarative-shell.js @@ -489,27 +489,44 @@ return content===null?null:portableExampleStyle(content,resolved.href,codepoints,faces); }); } - function collectExampleTokenNames(rules,names){ + /* The frame gets the page's design tokens, except those that follow the viewport width: the Framework switches its size ladder (text, control heights, spacing, containers) with width media queries, and a frame narrower than the page must take the ladder of its own width. A token declared under a width query, or declared from such a token, is left to the frame's own stylesheets; a token the page sets on its root element itself (a reader setting such as the UI radius) is sent as written, so the frame resolves it against its own ladder. */ + function collectExampleTokenNames(rules,names,declared,widthScoped,inWidth){ Array.from(rules||[]).forEach(function(rule){ + var scoped=inWidth||Boolean(rule.media&&/width/i.test(rule.media.mediaText||'')); if(rule.style){ for(var index=0;index512||/url\s*\(|@import|expression\s*\(/i.test(value))return; tokens[name]=value; }); diff --git a/tests/Unit/ExampleRuntimeContractTest.php b/tests/Unit/ExampleRuntimeContractTest.php index f994e986..cdd24fce 100644 --- a/tests/Unit/ExampleRuntimeContractTest.php +++ b/tests/Unit/ExampleRuntimeContractTest.php @@ -27,9 +27,9 @@ public function test_framework_scripts_are_propagated_into_sandboxed_examples(): self::assertStringContainsString('inlineStyles=styles', $shell); self::assertStringContainsString('simai.framework.icon_fallback_font.css', $shell); self::assertStringContainsString('function exampleDesignTokens()', $shell); - self::assertStringContainsString('function collectExampleTokenNames(rules,names)', $shell); + self::assertStringContainsString('function collectExampleTokenNames(rules,names,declared,widthScoped,inWidth)', $shell); self::assertStringContainsString("names=new Set(['--sf-text--size','--sf-text--height'])", $shell); - self::assertStringContainsString('collectExampleTokenNames(sheet.cssRules,names)', $shell); + self::assertStringContainsString('collectExampleTokenNames(sheet.cssRules,names,declared,widthScoped,', $shell); self::assertStringContainsString('designTokens:exampleDesignTokens()', $shell); self::assertStringContainsString('rootFontSize:getComputedStyle(document.documentElement).fontSize', $shell); self::assertStringContainsString('Array.isArray(data.scripts)?data.scripts:[]', $renderer); @@ -214,6 +214,40 @@ public function test_a_frame_document_starts_in_the_page_language_before_its_scr } } + public function test_a_frame_takes_the_page_tokens_but_not_the_width_ladder(): void + { + $shell = (string) file_get_contents(dirname(__DIR__, 2) . '/resources/portable/declarative-shell.js'); + self::assertSame(1, preg_match('/\n function collectExampleTokenNames\(rules,names,declared,widthScoped,inWidth\)\{\n.*?\n function exampleDesignTokens\(\)\{\n.*?\n return tokens;\n \}\n/s', $shell, $match)); + $node = (new ExecutableFinder)->find('node'); + self::assertIsString($node, 'The shell check runs the function in Node.js.'); + + // A stylesheet like the Framework's: colours for every width, a size + // ladder switched by a width query, a token built from the ladder, + // a reader setting on the root element and a measured breakout width. + $script = <<<'JS' +const style=(declarations)=>{const names=Object.keys(declarations);const s={length:names.length,getPropertyValue:(n)=>declarations[n]||''};names.forEach((n,i)=>{s[i]=n});return s}; +const computedValues={'--sf-primary':'#0a6cff','--sf-text--height-1':'1.5rem','--sf-ui-1--control-height':'calc(1.5rem + 2 * 0.5rem)','--sf-radius--ui':'0.5rem','--sf-container-breakout--page':'1440px','--sf-text--size':'1rem','--sf-text--height':'1.5'}; +const computed=style(computedValues); +const root={style:style({'--sf-radius--ui':'var(--sf-radius-1)','--sf-container-breakout--page':'1440px'})}; +globalThis.document={documentElement:root,styleSheets:[{media:{mediaText:''},cssRules:[ + {style:style({'--sf-primary':'#0a6cff','--sf-text--height-1':'1.25rem','--sf-ui-1--control-height':'calc(var(--sf-text--height-1) + 2 * 0.5rem)','--sf-text--size':'1rem','--sf-text--height':'1.5'})}, + {media:{mediaText:'(min-width: 60rem)'},cssRules:[{style:style({'--sf-text--height-1':'1.5rem'})}]} +]}]}; +globalThis.getComputedStyle=()=>computed; +JS; + $script .= $match[0] . 'process.stdout.write(JSON.stringify(exampleDesignTokens()));'; + $process = new Process([$node, '-e', $script]); + $process->mustRun(); + $tokens = json_decode($process->getOutput(), true, flags: JSON_THROW_ON_ERROR); + + self::assertSame([ + '--sf-primary' => '#0a6cff', + '--sf-radius--ui' => 'var(--sf-radius-1)', + '--sf-text--height' => '1.5', + '--sf-text--size' => '1rem', + ], $tokens); + } + public function test_example_height_measures_content_instead_of_its_current_viewport(): void { $shell = (string) file_get_contents(dirname(__DIR__, 2) . '/resources/portable/declarative-shell.js'); From b47ed8a67ec9f95ef8f6319b87e541ad475808a3 Mon Sep 17 00:00:00 2001 From: Rim Zabarov Date: Tue, 10 Nov 2026 20:54:30 +0300 Subject: [PATCH 02/10] Release 3.14.2 Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 15 + VERSION | 2 +- .../component-catalog/source-metadata.json | 430 +++++++++--------- tests/Unit/DocumentationContractTest.php | 2 +- 4 files changed, 232 insertions(+), 217 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44b2fbc6..0bcaf7f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,21 @@ All notable changes to Docara are recorded here. The format follows ## [Unreleased] +## [3.14.2] - 2026-11-10 + +### Fixed + +- **An example frame takes the size ladder of its own width.** The page + sent every one of its design tokens to the frame, so a frame narrower + than the page kept the page's desktop sizes (40 px controls, 16 px text) + while its own width queries, density among them, read the phone side. + Tokens declared under a width query, tokens built from them and the + breakout width the Framework measures are now left to the frame's own + stylesheets: a 760 px frame on a 1440 px page draws 36 px controls and + 14 px text. Colours and the other page tokens still reach the frame, and + a token the page sets on its root (the reader's UI radius) is sent as + written, so the frame resolves it against its own sizes. + ## [3.14.1] - 2026-11-10 ### Fixed diff --git a/VERSION b/VERSION index 49547fdc..95ed564f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.14.1 +3.14.2 diff --git a/resources/component-catalog/source-metadata.json b/resources/component-catalog/source-metadata.json index 1d70ca53..d6ec9f53 100644 --- a/resources/component-catalog/source-metadata.json +++ b/resources/component-catalog/source-metadata.json @@ -2,576 +2,576 @@ "schema": "docara.component_source_metadata.v1", "version": 1, "repository": "https://github.com/simai/docara", - "release": "3.14.1", + "release": "3.14.2", "entries": [ { "source_ref": "docs/site/content/ru/authoring/markdown.md", "source_sha256": "a4454e9ab09f3f08bda110fc78750541121486680184cbe4db448d6b7d17966a", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/authoring/markdown.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/authoring/markdown.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/authoring/markdown.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/authoring/markdown.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/components.md", "source_sha256": "7ffb25f0acc83eeb1f42ffea8b1623c430eb8aa54cc07d5de0c12bbedee9e66c", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/components.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/components.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/components.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/components.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/components/alert.md", "source_sha256": "1dc4dfe8919d14a639219fc65bd5658aacc317c8ab4a84110b0fce09dce73e8e", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/components/alert.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/components/alert.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/components/alert.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/components/alert.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/components/backlinks.md", "source_sha256": "b38400a0789b185d392c675c507a9f0ed4c6ff07270e3d7f6ff9f56fa980cfe9", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/components/backlinks.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/components/backlinks.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/components/backlinks.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/components/backlinks.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/components/badge.md", "source_sha256": "aa9314a42187106875c35c15c0b982b271d1486ea8771864621b5cf732a23e42", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/components/badge.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/components/badge.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/components/badge.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/components/badge.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/components/banner.md", "source_sha256": "65999c481c14ed6fbfe0cc8690265226ac95fd356fb227d2e833393e3f5f553f", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/components/banner.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/components/banner.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/components/banner.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/components/banner.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/components/button.md", "source_sha256": "cd5ff6d7791033c7b393eea354d6fb6b0fd98acd201d6486750e40d3bf95a9c1", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/components/button.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/components/button.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/components/button.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/components/button.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/components/card.md", "source_sha256": "084394ec828ece65c5b753c56290a1b91cf90ad61d94d20a14d6e70897782639", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/components/card.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/components/card.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/components/card.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/components/card.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/components/code-from-file.md", "source_sha256": "5fc794faac8d53351395aab89e73b1d22087d7b29c3ac16914edff57c6986a5d", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/components/code-from-file.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/components/code-from-file.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/components/code-from-file.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/components/code-from-file.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/components/code.md", "source_sha256": "ee23ffd10c680dbc56815440c5e1d189cda62421dd29188e2e1d6506908ef205", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/components/code.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/components/code.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/components/code.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/components/code.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/components/component-reference.md", "source_sha256": "b2f889340379b8eeb73cbd6cc745b3e2fe19a6a5944523aaa748ef376061a852", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/components/component-reference.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/components/component-reference.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/components/component-reference.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/components/component-reference.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/components/details.md", "source_sha256": "811ac863393ba599a7bd01c86ff85aac95ddd802e99136c8ca44bb76cf184c43", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/components/details.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/components/details.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/components/details.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/components/details.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/components/diagram.md", "source_sha256": "b3c41c8a95a572e552683c9c63ecc9877add7c7b710158ce2fee9a103d6eda48", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/components/diagram.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/components/diagram.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/components/diagram.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/components/diagram.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/components/download.md", "source_sha256": "c071446dc699f73f75938a57853498ec72731e6e64c95925d6f4a9c31ec2cf5f", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/components/download.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/components/download.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/components/download.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/components/download.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/components/embed.md", "source_sha256": "7cc911ee839c62b4596fa0237d5a26d309491ccde9654e3bb5e6dcb46ffafd89", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/components/embed.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/components/embed.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/components/embed.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/components/embed.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/components/example.md", "source_sha256": "b12bc5240f5a91906c333e59117e9f9a8e302d321241aced54348aff638f4d2d", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/components/example.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/components/example.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/components/example.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/components/example.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/components/figure.md", "source_sha256": "95952e8ef7f6f43f41f4cc9e44d2e92e9e242d74398b6e152596f431f4f10441", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/components/figure.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/components/figure.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/components/figure.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/components/figure.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/components/grid.md", "source_sha256": "ccbc3f462d4969f293edaaa661f42645129169654877401b62917060dbb8dfee", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/components/grid.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/components/grid.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/components/grid.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/components/grid.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/components/hero.md", "source_sha256": "80094d6b3968052da1e042d7c640a826baf8f14315eb4ad2f0a9fc1d151bae7b", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/components/hero.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/components/hero.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/components/hero.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/components/hero.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/components/html.md", "source_sha256": "b405f56feb9ad74fa7238a043c5743ab549e080474b3ef8966052681916d10e5", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/components/html.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/components/html.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/components/html.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/components/html.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/components/icon.md", "source_sha256": "537b9f4d17ee57ce01074f5102be18d69687ec853a5a553ee7dfff189444551d", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/components/icon.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/components/icon.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/components/icon.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/components/icon.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/components/kbd.md", "source_sha256": "b810ce6dcf919c3a18c94dd2e5d33d110d95650c9a8973407747f0618d14fe67", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/components/kbd.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/components/kbd.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/components/kbd.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/components/kbd.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/components/landing-blocks.md", "source_sha256": "52c0abb1155e17ccb1e388f8710d69f6052aec64e6bc61e0c2daf13df03b39ff", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/components/landing-blocks.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/components/landing-blocks.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/components/landing-blocks.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/components/landing-blocks.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/components/logos.md", "source_sha256": "41d9508f44a0a66f9243017e575f11b2ddf860d40f71908a4c87b0ab6cced9c4", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/components/logos.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/components/logos.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/components/logos.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/components/logos.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/components/math.md", "source_sha256": "87ce27cf99aa57c6ec1928ad1aae2912e847159d9186fc3603a141cab9dded1b", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/components/math.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/components/math.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/components/math.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/components/math.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/components/media.md", "source_sha256": "4787fad22f9c3c5b01cc702d8185d6b28a6ade18aa9175c05d888e7239914bae", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/components/media.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/components/media.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/components/media.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/components/media.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/components/smart-ui.md", "source_sha256": "45e699ec4f7358e1eac9a081f1ab4264ef31fdb028c42fbc17dd34eb9f2e2370", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/components/smart-ui.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/components/smart-ui.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/components/smart-ui.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/components/smart-ui.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/components/steps.md", "source_sha256": "415fe9203085092842d3bcb0be2eadda3d5618febfcabcf461d6d04b85a08e42", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/components/steps.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/components/steps.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/components/steps.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/components/steps.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/components/surface.md", "source_sha256": "064e19f026412b2d1cbf7442c67b23b16cd169d576a6d920f65f795ebfaa0616", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/components/surface.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/components/surface.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/components/surface.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/components/surface.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/components/tabs.md", "source_sha256": "e81729f385b53b47ffdc348b714a922af2d5b14ba23f9a88b288cd4de885e350", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/components/tabs.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/components/tabs.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/components/tabs.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/components/tabs.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/components/tree.md", "source_sha256": "e97687ac5d621b212f9a267e1a8162e68a209df231c7af06159ee4e1c96bb4d1", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/components/tree.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/components/tree.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/components/tree.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/components/tree.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/development/composition.md", "source_sha256": "e078736a7d45414e2390ece1fd5ac900afc2b77ffbd95a790d9e7a74b4c27285", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/development/composition.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/development/composition.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/development/composition.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/development/composition.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/reference/docara-json.md", "source_sha256": "c735ee48e172de4172fbebe791089e557c0b69b0e1b43a922ea48c8a8bae6ed4", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/reference/docara-json.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/reference/docara-json.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/reference/docara-json.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/reference/docara-json.md", "history_exact": false }, { "source_ref": "docs/site/content/ru/start/component-model.md", "source_sha256": "8eb1e2e5956f7b5199e5f7dc0a43bbac716bb4a34b9273c9ca40cc480272efc8", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/docs/site/content/ru/start/component-model.md", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/docs/site/content/ru/start/component-model.md", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/docs/site/content/ru/start/component-model.md", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/docs/site/content/ru/start/component-model.md", "history_exact": false }, { "source_ref": "resources/component-catalog/inline/docara.badge.json", "source_sha256": "c1730c22d271282282d5350838090c02fa83e05489cfd4d84bc342ec8042ea36", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/inline/docara.badge.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/inline/docara.badge.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/inline/docara.badge.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/inline/docara.badge.json", "history_exact": false }, { "source_ref": "resources/component-catalog/inline/docara.button.json", "source_sha256": "20c3d1302e79a1fcb1e47f72fd32309399186504a2799a299292f69a96fee25b", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/inline/docara.button.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/inline/docara.button.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/inline/docara.button.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/inline/docara.button.json", "history_exact": false }, { "source_ref": "resources/component-catalog/inline/docara.icon.json", "source_sha256": "073286d0b6d5c003b7c02dbdda4fdd05cd603496e3e88ec4a970a01eff5620fd", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/inline/docara.icon.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/inline/docara.icon.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/inline/docara.icon.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/inline/docara.icon.json", "history_exact": false }, { "source_ref": "resources/component-catalog/inline/docara.kbd.json", "source_sha256": "85b80371da10765ba28d153436447a1d66b319ec759710d4d0a190ef854cb756", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/inline/docara.kbd.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/inline/docara.kbd.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/inline/docara.kbd.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/inline/docara.kbd.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.alert.json", "source_sha256": "049a5cc544eaefb987623e60bce62fcb7a401581f8a0565f9d622c4eef5eb5d5", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.alert.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.alert.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.alert.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.alert.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.atlas_index.json", "source_sha256": "13ea455192e58e8e99cc334b2d6cbc0a14e41d1289c3d9753bb62d243e8bdc12", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.atlas_index.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.atlas_index.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.atlas_index.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.atlas_index.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.backlinks.json", "source_sha256": "59470c5010adefc12e4204d5e040c07396bce56646e4b6c9c937797d7eb4f35c", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.backlinks.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.backlinks.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.backlinks.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.backlinks.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.banner.json", "source_sha256": "0b4adcec2caeb363ab8f8e3b87fd4e974b3338cda8ec50fa1abcaa90d151d804", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.banner.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.banner.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.banner.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.banner.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.card.json", "source_sha256": "0b46097e94d2460c950a8f529673867cc8dd37200172bbe2ba2375374570d83d", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.card.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.card.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.card.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.card.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.code.json", "source_sha256": "f5bdef80e991d740096e4135e119f72e367684fd8d44dab3da36d228233318e7", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.code.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.code.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.code.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.code.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.columns.json", "source_sha256": "ea56620ce21eaa0505b79fff899550099ec52d01a751d75bb0f1b8d0aea4995d", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.columns.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.columns.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.columns.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.columns.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.component_index.json", "source_sha256": "73e7946c188921aa774ee3a410458935f26c774a662a2c7d0a6a1be29e6b63b2", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.component_index.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.component_index.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.component_index.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.component_index.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.component_reference.json", "source_sha256": "b3c299edafc770a6e72b897a0350104ccb26307de132849ff565d684367733ed", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.component_reference.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.component_reference.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.component_reference.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.component_reference.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.cta.json", "source_sha256": "30b8215da87ed010234b90adc9285cab47853b5889f46f8f2a9db34ff76a83a3", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.cta.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.cta.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.cta.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.cta.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.details.json", "source_sha256": "d5fc153f38d152836fb55d3a78147e0dcab190202856f3a76ca830678d46be4c", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.details.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.details.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.details.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.details.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.diagram.json", "source_sha256": "b71e38fbec1848e38dad180547f2a4fb0e775c070b1fe3f2313f2b5722b116a6", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.diagram.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.diagram.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.diagram.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.diagram.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.download.json", "source_sha256": "0306fc6abc853cfb55b12054484b0d1c91bd1620ab115544e541c411de50466e", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.download.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.download.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.download.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.download.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.embed.json", "source_sha256": "19d468e226ad90da6e1c60c8dd04b59fd94ebf2ad54b1c66d4f4ce84b1ddd1ce", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.embed.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.embed.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.embed.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.embed.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.example.json", "source_sha256": "62925257ff150b646fafd3d63bfa581e0539d62d6780b7afba6f5413527f9d3b", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.example.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.example.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.example.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.example.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.features.json", "source_sha256": "add66619291ddef970e36acde70653cfd0f2441e2542eb82c602a624c630dfa7", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.features.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.features.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.features.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.features.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.figure.json", "source_sha256": "eb20efbf7eb89921f04dde3add4f542cc2ceafbf4b7ec7e53c1bc1345638a569", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.figure.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.figure.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.figure.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.figure.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.grid.json", "source_sha256": "073c51116df037350698e5618b33140c2e748bb49f9081a1319dac43103d0338", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.grid.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.grid.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.grid.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.grid.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.hero.json", "source_sha256": "401b919a62deb57d3934200f8951c02aaa7e566ee7318e659c4a738b963573a7", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.hero.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.hero.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.hero.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.hero.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.html.json", "source_sha256": "3c2f29634e6c18f12a55dd8217ae7fd941bef0f00cdcf00294a5431f1a0afae9", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.html.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.html.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.html.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.html.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.internal_preview.json", "source_sha256": "2fe39bb4dac60cadfe7db29304875feea569beec32aca37e8c943b634719e1c4", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.internal_preview.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.internal_preview.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.internal_preview.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.internal_preview.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.logos.json", "source_sha256": "64685ef0ec7aa618c79448aa127d9efb110dcf2c71c41e80919805b2d4d7d9d7", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.logos.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.logos.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.logos.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.logos.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.math.json", "source_sha256": "ffcfe13dcd819807cf64093b9d4bcc343c9c46defc587f4a05f01f023053b104", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.math.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.math.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.math.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.math.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.media.json", "source_sha256": "8c63cd4df1980d88742170111a509851636c5b4c321c9f054358c04982a16b76", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.media.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.media.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.media.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.media.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.promo.json", "source_sha256": "dead413503002e1934519a269afd911a54c56b837f2cff4770c4b69433990f0f", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.promo.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.promo.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.promo.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.promo.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.schema_reference.json", "source_sha256": "13e57f1b747c6133e6baaf9b691bce83a190690a5d0e62a508b2f5699626a1a3", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.schema_reference.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.schema_reference.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.schema_reference.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.schema_reference.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.showcase.json", "source_sha256": "b92a3c090533976cc01a1ca77d3a4378c13b1672160627a43f685656e356ece4", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.showcase.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.showcase.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.showcase.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.showcase.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.steps.json", "source_sha256": "e597d0addf210f2cc0cd8cd5656d459c2d8f0668eedd4b99036f298e4da597b0", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.steps.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.steps.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.steps.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.steps.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.surface.json", "source_sha256": "54d6cf6b20cc4b59ed60304b1bc85c1260dd2fe0f865a6bc87451704b96faa0b", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.surface.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.surface.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.surface.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.surface.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.tabs.json", "source_sha256": "6532f01ce4d28f2f2fe44477f6ea4a04ed55515169a8cc83b59e73a27e555940", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.tabs.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.tabs.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.tabs.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.tabs.json", "history_exact": false }, { "source_ref": "resources/component-catalog/typed/docara.tree.json", "source_sha256": "59e70bc26a44d4ebfe6602a3490ca826ed41f995da0878989ddc3ea636af7915", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/component-catalog/typed/docara.tree.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/component-catalog/typed/docara.tree.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/component-catalog/typed/docara.tree.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/component-catalog/typed/docara.tree.json", "history_exact": false }, { "source_ref": "resources/framework/manifests/ui-alert.json", "source_sha256": "b3d33db0792d44111af9a9063463e24c9fe35ba2aa7ad4c130de67cf625d3389", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/framework/manifests/ui-alert.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/framework/manifests/ui-alert.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/framework/manifests/ui-alert.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/framework/manifests/ui-alert.json", "history_exact": false }, { "source_ref": "resources/framework/manifests/ui-button.json", "source_sha256": "0faae4d38be9c9df8c25596e8efc38d454c7b1bf6f25a74c2dbf9fa95b51b7fd", - "release": "3.14.1", - "source_url": "https://github.com/simai/docara/blob/v3.14.1/resources/framework/manifests/ui-button.json", - "history_url": "https://github.com/simai/docara/commits/v3.14.1/resources/framework/manifests/ui-button.json", + "release": "3.14.2", + "source_url": "https://github.com/simai/docara/blob/v3.14.2/resources/framework/manifests/ui-button.json", + "history_url": "https://github.com/simai/docara/commits/v3.14.2/resources/framework/manifests/ui-button.json", "history_exact": false } ], - "content_sha256": "e6b0cd141b1bba22df6bc1f2f55471f7e90ed470b60c3b7c9d047b7537f51618" + "content_sha256": "f21810db28747f24145673a7640d01e181bf2bb80864ea7d59c766560d74df24" } diff --git a/tests/Unit/DocumentationContractTest.php b/tests/Unit/DocumentationContractTest.php index e8a82dd3..d7d219ae 100644 --- a/tests/Unit/DocumentationContractTest.php +++ b/tests/Unit/DocumentationContractTest.php @@ -270,7 +270,7 @@ public function beginner_path_ends_with_a_verified_http_preview_contract(): void public function portable_installation_surfaces_use_the_stable_package_after_release(): void { self::assertSame( - '3.14.1', + '3.14.2', trim((string) file_get_contents($this->repositoryRoot() . '/VERSION')), ); From 7f8fafab956a79f71d318614f510f9d934355ff9 Mon Sep 17 00:00:00 2001 From: Rim Zabarov Date: Wed, 11 Nov 2026 00:41:26 +0300 Subject: [PATCH 03/10] Follow the width-aware token collector in the documentation contract test Co-Authored-By: Claude Opus 5.5 --- tests/PortableDocumentationSiteTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/PortableDocumentationSiteTest.php b/tests/PortableDocumentationSiteTest.php index 18d3d23e..f51ae61e 100644 --- a/tests/PortableDocumentationSiteTest.php +++ b/tests/PortableDocumentationSiteTest.php @@ -221,8 +221,8 @@ public function real_documentation_build_matches_the_exact_product_matrix_and_st self::assertStringContainsString('script[data-docara-framework-asset="simai.framework.preloaded"]:not([src])', $shellJs); self::assertStringNotContainsString("!=='simai.framework.core.js'", $shellJs); self::assertStringContainsString('function exampleDesignTokens()', $shellJs); - self::assertStringContainsString('function collectExampleTokenNames(rules,names)', $shellJs); - self::assertStringContainsString('collectExampleTokenNames(sheet.cssRules,names)', $shellJs); + self::assertStringContainsString('function collectExampleTokenNames(rules,names,declared,widthScoped,inWidth)', $shellJs); + self::assertStringContainsString('collectExampleTokenNames(sheet.cssRules,names,declared,widthScoped,', $shellJs); self::assertStringContainsString('designTokens:exampleDesignTokens()', $shellJs); self::assertStringContainsString('rootFontSize:getComputedStyle(document.documentElement).fontSize', $shellJs); self::assertStringContainsString("addEventListener('resize',function()", $shellJs); From 3f3b81546d7e4203c0b186afd46461eb3a722ebb Mon Sep 17 00:00:00 2001 From: Rim Zabarov Date: Wed, 11 Nov 2026 03:09:22 +0300 Subject: [PATCH 04/10] Let an example frame settle when a toast container is fixed to its bottom edge A block or popover fixed to the frame's bottom moved down as far as the frame grew, so the frame chased it (56/62 px about 40 times a second on the toast placement example) and clipped the toast's top. Such a block now counts with its own uncapped height and its gap to that edge. Co-Authored-By: Claude Opus 5.5 --- src/PortableSite/PortableMarkdownRenderer.php | 16 +++++++++++++--- tests/Unit/PortableMarkdownRendererTest.php | 12 ++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/PortableSite/PortableMarkdownRenderer.php b/src/PortableSite/PortableMarkdownRenderer.php index 46ed26ea..96df482b 100644 --- a/src/PortableSite/PortableMarkdownRenderer.php +++ b/src/PortableSite/PortableMarkdownRenderer.php @@ -1561,18 +1561,27 @@ function measure(){ }); } /* Offscreen sandboxed frames get no animation frames, so timers measure directly to size them before they scroll into view. */ +var layerPlaces=typeof WeakMap==='function'?new WeakMap():{get:function(){},set:function(){}}; +/* Typed OM tells a layer whose top is auto and bottom is set; elsewhere a layer that moves by exactly the frame's growth is taken as pinned. */ +/* A notification area is capped at the frame's height and squeezes its messages in a short frame; without the cap it shows the height it needs. The cap comes back before anything paints, and the observer drops the change. */ +function naturalBlockSize(layer){var value=layer.style.getPropertyValue('max-block-size'),priority=layer.style.getPropertyPriority('max-block-size'),size;layer.style.setProperty('max-block-size','none','important');size=Math.max(layer.getBoundingClientRect().height,layer.scrollHeight);if(value)layer.style.setProperty('max-block-size',value,priority);else layer.style.removeProperty('max-block-size');if(bodyObserver)bodyObserver.takeRecords();return size} +function bottomPinned(layer){try{var map=layer.computedStyleMap();return map.get('position').toString()==='fixed'&&map.get('top').toString()==='auto'&&map.get('bottom').toString()!=='auto'}catch(error){return false}} function measureNow(){ var style=getComputedStyle(body),rect=body.getBoundingClientRect(); var marginTop=parseFloat(style.marginTop)||0,marginBottom=parseFloat(style.marginBottom)||0; -var contentTop=rect.top-marginTop,contentBottom=rect.bottom+marginBottom; +var contentTop=rect.top-marginTop,contentBottom=rect.bottom+marginBottom,pinnedExtent=0; Array.from(body.children).forEach(function(child){ var childRect=child.getBoundingClientRect(),childStyle=getComputedStyle(child); +/* A block fixed to the frame's bottom edge, such as a toast container, moves down as far as the frame grows: it counts with its own height and its gap to that edge, and an empty one not at all. */ +if(childStyle.position==='fixed'&&bottomPinned(child)){if(childRect.height>0)pinnedExtent=Math.max(pinnedExtent,Math.max(0,innerHeight-childRect.bottom)+naturalBlockSize(child));return} contentTop=Math.min(contentTop,childRect.top-(parseFloat(childStyle.marginTop)||0)); contentBottom=Math.max(contentBottom,childRect.bottom+(parseFloat(childStyle.marginBottom)||0)); }); +contentBottom=Math.max(contentBottom,contentTop+pinnedExtent); /* An open menu or dialog sits in the top layer, which a frame clips at its own height, and a positioned menu shrinks to the room it has. The frame grows to the layer's full height, so the menu gets its natural size: the part a scrolling list hides counts too. */ var layers=[];try{layers=Array.from(document.querySelectorAll(':popover-open,dialog[open]'))}catch(error){} -layers.forEach(function(layer){var layerRect=layer.getBoundingClientRect(),hidden=Math.max(0,layer.scrollHeight-layer.clientHeight);Array.prototype.forEach.call(layer.querySelectorAll('*'),function(part){var overflow=getComputedStyle(part).overflowY;if(overflow==='auto'||overflow==='scroll')hidden=Math.max(hidden,part.scrollHeight-part.clientHeight)});contentBottom=Math.max(contentBottom,layerRect.bottom+hidden+8)}); +/* A layer pinned to the frame's bottom edge, such as a notification area, moves down as far as the frame grows: it needs its own height and its gap to that edge, not room below its bottom, or the frame would chase it. */ +layers.forEach(function(layer){var layerRect=layer.getBoundingClientRect(),hidden=Math.max(0,layer.scrollHeight-layer.clientHeight);Array.prototype.forEach.call(layer.querySelectorAll('*'),function(part){var overflow=getComputedStyle(part).overflowY;if(overflow==='auto'||overflow==='scroll')hidden=Math.max(hidden,part.scrollHeight-part.clientHeight)});var seen=layerPlaces.get(layer),viewport=innerHeight;if(!seen){seen={pinned:bottomPinned(layer)};layerPlaces.set(layer,seen)}else if(seen.viewport!==viewport&&Math.abs((layerRect.top-seen.top)-(viewport-seen.viewport))<1)seen.pinned=true;seen.viewport=viewport;seen.top=layerRect.top;contentBottom=Math.max(contentBottom,seen.pinned?contentTop+Math.max(0,viewport-layerRect.bottom)+naturalBlockSize(layer)+8:layerRect.bottom+hidden+8)}); var height=Math.ceil(Math.max(0,contentBottom-contentTop)); if(height===lastHeight)return; lastHeight=height; @@ -1617,7 +1626,8 @@ function scheduleIconReport(){if(iconScan===null)iconScan=setTimeout(reportIcons }); if(typeof ResizeObserver==='function')new ResizeObserver(measure).observe(body); if(typeof ResizeObserver==='function')new ResizeObserver(measure).observe(document.documentElement); -if(typeof MutationObserver==='function')new MutationObserver(measure).observe(body,{childList:true,subtree:true,attributes:true,characterData:true}); +var bodyObserver=null; +if(typeof MutationObserver==='function'){bodyObserver=new MutationObserver(measure);bodyObserver.observe(body,{childList:true,subtree:true,attributes:true,characterData:true})} if(document.fonts&&document.fonts.ready)document.fonts.ready.then(measureSettled); measureSettled(); /* A fresh frame document holds nothing yet; this asks the shell for the whole environment. */ diff --git a/tests/Unit/PortableMarkdownRendererTest.php b/tests/Unit/PortableMarkdownRendererTest.php index 380527a7..74194684 100644 --- a/tests/Unit/PortableMarkdownRendererTest.php +++ b/tests/Unit/PortableMarkdownRendererTest.php @@ -457,6 +457,18 @@ public function it_renders_markdown_and_multifile_examples_as_one_tabbed_surface self::assertStringContainsString('hidden=Math.max(hidden,part.scrollHeight-part.clientHeight)', $web); self::assertStringContainsString('document.addEventListener('toggle',measureSettled,true)', $web); self::assertStringContainsString('setTimeout(measureNow,100)', $web); + // A toast container fixed to the frame's bottom edge moves down as the + // frame grows: it counts with its own uncapped height and its gap to + // that edge, so the frame settles instead of chasing it. + self::assertStringContainsString('function bottomPinned(layer)', $web); + self::assertStringContainsString('map.get('top').toString()==='auto'', $web); + self::assertStringContainsString('function naturalBlockSize(layer)', $web); + self::assertStringContainsString('layer.style.setProperty('max-block-size','none','important')', $web); + self::assertStringContainsString('if(bodyObserver)bodyObserver.takeRecords()', $web); + self::assertStringContainsString('if(childStyle.position==='fixed'&&bottomPinned(child))', $web); + self::assertStringContainsString('pinnedExtent=Math.max(pinnedExtent,Math.max(0,innerHeight-childRect.bottom)+naturalBlockSize(child))', $web); + self::assertStringContainsString('contentBottom=Math.max(contentBottom,contentTop+pinnedExtent)', $web); + self::assertStringNotContainsString('new MutationObserver(measure).observe(body', $web); self::assertStringContainsString('script.setAttribute('data-docara-example-framework-boot',item.key)', $web); self::assertStringContainsString('link.setAttribute('data-docara-example-framework-style','')', $web); self::assertStringContainsString('document.documentElement.classList.add('theme-'+theme)', $web); From e79fcb25f4bd1c183c36245f9d5c109b71da4a73 Mon Sep 17 00:00:00 2001 From: Rim Zabarov Date: Wed, 11 Nov 2026 03:11:14 +0300 Subject: [PATCH 05/10] Keep the Framework preloader off in example frames, as on the page Co-Authored-By: Claude Opus 5.5 --- src/PortableSite/PortableMarkdownRenderer.php | 2 ++ tests/Unit/PortableMarkdownRendererTest.php | 3 +++ 2 files changed, 5 insertions(+) diff --git a/src/PortableSite/PortableMarkdownRenderer.php b/src/PortableSite/PortableMarkdownRenderer.php index 96df482b..62a795ec 100644 --- a/src/PortableSite/PortableMarkdownRenderer.php +++ b/src/PortableSite/PortableMarkdownRenderer.php @@ -1527,6 +1527,8 @@ function applyEnvironment(data){ document.head.appendChild(script); currentBoot.push(item.key); }); +/* The page turns the Framework preloader off in its own preference script, which a frame does not get: without it a slow load covers the finished example with the preloader. */ +window.SF_BOOT_CONFIG=window.SF_BOOT_CONFIG||{};window.SF_BOOT_CONFIG.preloader={enabled:false}; /* The page's boot state turns the Loader's theme off (Docara resolves the page theme itself); an example with its own theme keeps the Loader's theme API, which then works on this frame alone. */ if(ownTheme&&window.SF_BOOT_CONFIG&&window.SF_BOOT_CONFIG.theme===false){delete window.SF_BOOT_CONFIG.theme} var scriptsLoaded=loadFrameworkScripts(Array.isArray(data.scripts)?data.scripts:[]); diff --git a/tests/Unit/PortableMarkdownRendererTest.php b/tests/Unit/PortableMarkdownRendererTest.php index 74194684..55085e73 100644 --- a/tests/Unit/PortableMarkdownRendererTest.php +++ b/tests/Unit/PortableMarkdownRendererTest.php @@ -460,6 +460,9 @@ public function it_renders_markdown_and_multifile_examples_as_one_tabbed_surface // A toast container fixed to the frame's bottom edge moves down as the // frame grows: it counts with its own uncapped height and its gap to // that edge, so the frame settles instead of chasing it. + // The page turns the Framework preloader off; a frame does the same, + // or a slow load covers the finished example. + self::assertStringContainsString('window.SF_BOOT_CONFIG=window.SF_BOOT_CONFIG||{};window.SF_BOOT_CONFIG.preloader={enabled:false};', $web); self::assertStringContainsString('function bottomPinned(layer)', $web); self::assertStringContainsString('map.get('top').toString()==='auto'', $web); self::assertStringContainsString('function naturalBlockSize(layer)', $web); From dcf6bb230d0dab8887d4a260c7267597914b3acd Mon Sep 17 00:00:00 2001 From: Rim Zabarov Date: Wed, 11 Nov 2026 03:11:41 +0300 Subject: [PATCH 06/10] Note the toast and preloader frame fixes in 3.14.2 Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bcaf7f2..7e28f48a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ All notable changes to Docara are recorded here. The format follows ## [Unreleased] -## [3.14.2] - 2026-11-10 +## [3.14.2] - 2026-11-11 ### Fixed @@ -20,6 +20,15 @@ All notable changes to Docara are recorded here. The format follows 14 px text. Colours and the other page tokens still reach the frame, and a token the page sets on its root (the reader's UI radius) is sent as written, so the frame resolves it against its own sizes. +- **An example frame settles when a toast is fixed to its bottom edge.** A + block or popover fixed to the frame's bottom moved down as far as the + frame grew, so the frame chased it (56 and 62 px about 40 times a second + on a toast placement example) and clipped the toast's top. Such a block + now counts with its own height and its gap to that edge: the frame grows + once and shows the whole toast. +- **The Framework preloader stays off in example frames.** The page turns + it off in its preference script, which a frame does not get, so a slow + load covered a finished example with the preloader. ## [3.14.1] - 2026-11-10 From f5f59af352d2b3bfb6f6973d99edc8bdc1eabe97 Mon Sep 17 00:00:00 2001 From: Rim Zabarov Date: Wed, 11 Nov 2026 03:42:38 +0300 Subject: [PATCH 07/10] Show an example's open menu over the page instead of pushing the page down The frame reports its flow height and the boxes of its open popovers and dialogs; the shell keeps the flow height in the layout, lets the menu's room hang over what follows and clips the frame to its flow box and the menus. The menu gets 12 px to spare instead of 8. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 6 +++++ resources/portable/declarative-shell.css | 1 + resources/portable/declarative-shell.js | 22 ++++++++++++++++++- src/PortableSite/PortableMarkdownRenderer.php | 15 ++++++++----- tests/PortableDocumentationSiteTest.php | 3 ++- tests/Unit/ExampleRuntimeContractTest.php | 12 +++++++++- 6 files changed, 50 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e28f48a..0051fe38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,12 @@ All notable changes to Docara are recorded here. The format follows on a toast placement example) and clipped the toast's top. Such a block now counts with its own height and its gap to that edge: the frame grows once and shows the whole toast. +- **An open menu in an example frame no longer pushes the page down.** A + date picker, menu or dialog that needs more room than the example grew + the frame and moved everything below it (118 to 496 px on a date and time + example), then moved it back on close. The frame now keeps its own height + in the page and shows the menu's room over what follows, as a menu does + on a page, with 12 px to spare below the menu instead of 8. - **The Framework preloader stays off in example frames.** The page turns it off in its preference script, which a frame does not get, so a slow load covered a finished example with the preloader. diff --git a/resources/portable/declarative-shell.css b/resources/portable/declarative-shell.css index c78789a3..e240d819 100644 --- a/resources/portable/declarative-shell.css +++ b/resources/portable/declarative-shell.css @@ -241,6 +241,7 @@ body[data-docara-shell] sf-button:not(:where(.docara-example-inline *)){display: .docara-example-preview .docara-example-preview__action:focus:not(:focus-visible),.docara-example-preview .docara-example-preview__copy:focus:not(:focus-visible){--sf-icon-button--box-shadow:none;outline:0;box-shadow:none} .docara-example-preview__copy[data-copy-state="copied"],.docara-example-preview__copy[data-copy-state="copied"] .sf-icon{color:var(--sf-on-surface);--sf-icon--color:var(--sf-on-surface)} .docara-example-preview__panels{background:var(--sf-surface-0)} +.docara-example-preview[data-docara-example-overlay]{overflow:visible} .docara-example-preview__panel{display:none;min-inline-size:0;padding:var(--sf-space-2)} .docara-example-preview__panel>:last-child{margin-block-end:0} .docara-example-preview__panel--source{padding:0} diff --git a/resources/portable/declarative-shell.js b/resources/portable/declarative-shell.js index 7309fdfe..42be566d 100644 --- a/resources/portable/declarative-shell.js +++ b/resources/portable/declarative-shell.js @@ -655,7 +655,27 @@ var frame=docaraExampleFrames.find(function(candidate){return candidate.contentWindow===event.source})||null; var height=Number(event.data.height); if(!frame||!Number.isFinite(height))return; - frame.style.blockSize=Math.max(32,Math.ceil(height))+'px'; + var size=Math.max(32,Math.ceil(height)),flow=Number(event.data.flow); + var boxes=Array.isArray(event.data.overlays)?event.data.overlays.filter(function(box){return Array.isArray(box)&&box.length===4&&box.every(Number.isFinite)}):[]; + var extra=Number.isFinite(flow)&&boxes.length?Math.max(0,size-Math.max(32,Math.ceil(flow))):0; + var preview=frame.closest('.docara-example-preview'); + frame.style.blockSize=size+'px'; + /* An open menu's room hangs below the frame's flow height over what follows, as a menu does on a page: the page keeps its place, and only the frame's flow box and the menus stay visible and clickable. */ + if(extra>0){ + var width=frame.clientWidth,flowSize=size-extra; + var path='M0 0H'+width+'V'+flowSize+'H0Z'+boxes.map(function(box){return 'M'+box[0]+' '+box[1]+'H'+box[2]+'V'+box[3]+'H'+box[0]+'Z'}).join(''); + frame.style.marginBlockEnd=(-extra)+'px'; + frame.style.position='relative'; + frame.style.zIndex='5'; + frame.style.clipPath="path('"+path+"')"; + if(preview)preview.setAttribute('data-docara-example-overlay',''); + }else{ + frame.style.marginBlockEnd=''; + frame.style.position=''; + frame.style.zIndex=''; + frame.style.clipPath=''; + if(preview)preview.removeAttribute('data-docara-example-overlay'); + } }); docaraExampleFrames.forEach(function(frame){ frame.addEventListener('load',function(){requestExampleHeight(frame)}); diff --git a/src/PortableSite/PortableMarkdownRenderer.php b/src/PortableSite/PortableMarkdownRenderer.php index 62a795ec..ed57e35d 100644 --- a/src/PortableSite/PortableMarkdownRenderer.php +++ b/src/PortableSite/PortableMarkdownRenderer.php @@ -1573,6 +1573,8 @@ function measureNow(){ var marginTop=parseFloat(style.marginTop)||0,marginBottom=parseFloat(style.marginBottom)||0; var contentTop=rect.top-marginTop,contentBottom=rect.bottom+marginBottom,pinnedExtent=0; Array.from(body.children).forEach(function(child){ +/* An open popover or dialog is measured with the top layer below. */ +var open=false;try{open=child.matches(':popover-open,dialog[open]')}catch(error){}if(open)return; var childRect=child.getBoundingClientRect(),childStyle=getComputedStyle(child); /* A block fixed to the frame's bottom edge, such as a toast container, moves down as far as the frame grows: it counts with its own height and its gap to that edge, and an empty one not at all. */ if(childStyle.position==='fixed'&&bottomPinned(child)){if(childRect.height>0)pinnedExtent=Math.max(pinnedExtent,Math.max(0,innerHeight-childRect.bottom)+naturalBlockSize(child));return} @@ -1581,13 +1583,14 @@ function measureNow(){ }); contentBottom=Math.max(contentBottom,contentTop+pinnedExtent); /* An open menu or dialog sits in the top layer, which a frame clips at its own height, and a positioned menu shrinks to the room it has. The frame grows to the layer's full height, so the menu gets its natural size: the part a scrolling list hides counts too. */ -var layers=[];try{layers=Array.from(document.querySelectorAll(':popover-open,dialog[open]'))}catch(error){} +var layers=[],flowBottom=contentBottom,overlays=[];try{layers=Array.from(document.querySelectorAll(':popover-open,dialog[open]'))}catch(error){} /* A layer pinned to the frame's bottom edge, such as a notification area, moves down as far as the frame grows: it needs its own height and its gap to that edge, not room below its bottom, or the frame would chase it. */ -layers.forEach(function(layer){var layerRect=layer.getBoundingClientRect(),hidden=Math.max(0,layer.scrollHeight-layer.clientHeight);Array.prototype.forEach.call(layer.querySelectorAll('*'),function(part){var overflow=getComputedStyle(part).overflowY;if(overflow==='auto'||overflow==='scroll')hidden=Math.max(hidden,part.scrollHeight-part.clientHeight)});var seen=layerPlaces.get(layer),viewport=innerHeight;if(!seen){seen={pinned:bottomPinned(layer)};layerPlaces.set(layer,seen)}else if(seen.viewport!==viewport&&Math.abs((layerRect.top-seen.top)-(viewport-seen.viewport))<1)seen.pinned=true;seen.viewport=viewport;seen.top=layerRect.top;contentBottom=Math.max(contentBottom,seen.pinned?contentTop+Math.max(0,viewport-layerRect.bottom)+naturalBlockSize(layer)+8:layerRect.bottom+hidden+8)}); -var height=Math.ceil(Math.max(0,contentBottom-contentTop)); -if(height===lastHeight)return; -lastHeight=height; -parent.postMessage({type:'docara:example-height',height:height},'*'); +layers.forEach(function(layer){var layerRect=layer.getBoundingClientRect(),hidden=Math.max(0,layer.scrollHeight-layer.clientHeight);Array.prototype.forEach.call(layer.querySelectorAll('*'),function(part){var overflow=getComputedStyle(part).overflowY;if(overflow==='auto'||overflow==='scroll')hidden=Math.max(hidden,part.scrollHeight-part.clientHeight)});var seen=layerPlaces.get(layer),viewport=innerHeight;if(!seen){seen={pinned:bottomPinned(layer)};layerPlaces.set(layer,seen)}else if(seen.viewport!==viewport&&Math.abs((layerRect.top-seen.top)-(viewport-seen.viewport))<1)seen.pinned=true;seen.viewport=viewport;seen.top=layerRect.top;if(seen.pinned){contentBottom=Math.max(contentBottom,contentTop+Math.max(0,viewport-layerRect.bottom)+naturalBlockSize(layer)+12);return}var reach=layerRect.bottom+hidden+12;if(reach>contentBottom)contentBottom=reach;overlays.push([Math.floor(layerRect.left-12),Math.floor(layerRect.top-contentTop-12),Math.ceil(layerRect.right+12),Math.ceil(reach-contentTop)])}); +var height=Math.ceil(Math.max(0,contentBottom-contentTop)),flow=Math.ceil(Math.max(0,flowBottom-contentTop)),report=height+'/'+flow+'/'+overlays.join(';'); +if(report===lastHeight)return; +lastHeight=report; +/* The page lays the frame out at its flow height and shows an open menu's room over what follows, so the menu does not push the page down. */ +parent.postMessage({type:'docara:example-height',height:height,flow:flow,overlays:overlays},'*'); } function measureSettled(){ measure(); diff --git a/tests/PortableDocumentationSiteTest.php b/tests/PortableDocumentationSiteTest.php index f51ae61e..52f62762 100644 --- a/tests/PortableDocumentationSiteTest.php +++ b/tests/PortableDocumentationSiteTest.php @@ -213,7 +213,8 @@ public function real_documentation_build_matches_the_exact_product_matrix_and_st self::assertStringContainsString('localizeCodeCopy', $shellJs); self::assertStringContainsString('showCopyState(false);', $shellJs); self::assertStringContainsString("event.data.type!=='docara:example-height'", $shellJs); - self::assertStringContainsString("frame.style.blockSize=Math.max(32,Math.ceil(height))+'px'", $shellJs); + self::assertStringContainsString("frame.style.blockSize=size+'px'", $shellJs); + self::assertStringContainsString("frame.style.clipPath=\"path('\"+path+\"')\"", $shellJs); self::assertStringContainsString('link[data-docara-framework-asset][rel="stylesheet"]', $shellJs); self::assertStringContainsString('return exampleEnvironment(frame).then(function(environment)', $shellJs); self::assertStringContainsString('script[data-docara-framework-asset="simai.framework.boot"]:not([src])', $shellJs); diff --git a/tests/Unit/ExampleRuntimeContractTest.php b/tests/Unit/ExampleRuntimeContractTest.php index cdd24fce..205d82a7 100644 --- a/tests/Unit/ExampleRuntimeContractTest.php +++ b/tests/Unit/ExampleRuntimeContractTest.php @@ -262,7 +262,17 @@ public function test_example_height_measures_content_instead_of_its_current_view self::assertStringContainsString('Object.keys(tokens).sort().slice(0,4096)', $renderer); self::assertStringContainsString('contentBottom-contentTop', $renderer); self::assertStringNotContainsString('body.scrollHeight,root.scrollHeight', $renderer); - self::assertStringContainsString("frame.style.blockSize=Math.max(32,Math.ceil(height))+'px'", $shell); + self::assertStringContainsString("frame.style.blockSize=size+'px'", $shell); + // An open menu's room hangs over what follows instead of pushing the + // page down: the frame keeps its flow height in the layout, and a clip + // path shows only the flow box and the menus. + self::assertStringContainsString("var extra=Number.isFinite(flow)&&boxes.length?Math.max(0,size-Math.max(32,Math.ceil(flow))):0;", $shell); + self::assertStringContainsString("frame.style.marginBlockEnd=(-extra)+'px';", $shell); + self::assertStringContainsString("frame.style.clipPath=\"path('\"+path+\"')\"", $shell); + self::assertStringContainsString(".docara-example-preview[data-docara-example-overlay]{overflow:visible}", (string) file_get_contents(dirname(__DIR__, 2) . '/resources/portable/declarative-shell.css')); + self::assertStringContainsString("parent.postMessage({type:'docara:example-height',height:height,flow:flow,overlays:overlays},'*')", $renderer); + self::assertStringContainsString("var reach=layerRect.bottom+hidden+12;", $renderer); + self::assertStringContainsString("try{open=child.matches(':popover-open,dialog[open]')}catch(error){}if(open)return;", $renderer); self::assertStringNotContainsString('Math.min(4096', $shell); } From d15586faf4192aeee9a255d1e17bb71b375a0558 Mon Sep 17 00:00:00 2001 From: Rim Zabarov Date: Wed, 11 Nov 2026 06:24:59 +0300 Subject: [PATCH 08/10] Count an open menu in an example frame by its drawn box, not its scrolled rows A list capped to the frame's height grew with the frame, so the frame chased it (a country input reached 9815 px). Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 5 +++++ src/PortableSite/PortableMarkdownRenderer.php | 2 +- tests/Unit/ExampleRuntimeContractTest.php | 2 +- tests/Unit/PortableMarkdownRendererTest.php | 6 ++++-- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0051fe38..32e5e349 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,11 @@ All notable changes to Docara are recorded here. The format follows example), then moved it back on close. The frame now keeps its own height in the page and shows the menu's room over what follows, as a menu does on a page, with 12 px to spare below the menu instead of 8. +- **An open list no longer stretches its example frame without end.** The + frame added the rows a list scrolls inside its own popup, and a list + capped to the frame's height then got taller as the frame grew: a country + input with its list open reached a 9815 px frame. The frame now reaches + the menu's drawn box only. - **The Framework preloader stays off in example frames.** The page turns it off in its preference script, which a frame does not get, so a slow load covered a finished example with the preloader. diff --git a/src/PortableSite/PortableMarkdownRenderer.php b/src/PortableSite/PortableMarkdownRenderer.php index ed57e35d..478a2ed6 100644 --- a/src/PortableSite/PortableMarkdownRenderer.php +++ b/src/PortableSite/PortableMarkdownRenderer.php @@ -1585,7 +1585,7 @@ function measureNow(){ /* An open menu or dialog sits in the top layer, which a frame clips at its own height, and a positioned menu shrinks to the room it has. The frame grows to the layer's full height, so the menu gets its natural size: the part a scrolling list hides counts too. */ var layers=[],flowBottom=contentBottom,overlays=[];try{layers=Array.from(document.querySelectorAll(':popover-open,dialog[open]'))}catch(error){} /* A layer pinned to the frame's bottom edge, such as a notification area, moves down as far as the frame grows: it needs its own height and its gap to that edge, not room below its bottom, or the frame would chase it. */ -layers.forEach(function(layer){var layerRect=layer.getBoundingClientRect(),hidden=Math.max(0,layer.scrollHeight-layer.clientHeight);Array.prototype.forEach.call(layer.querySelectorAll('*'),function(part){var overflow=getComputedStyle(part).overflowY;if(overflow==='auto'||overflow==='scroll')hidden=Math.max(hidden,part.scrollHeight-part.clientHeight)});var seen=layerPlaces.get(layer),viewport=innerHeight;if(!seen){seen={pinned:bottomPinned(layer)};layerPlaces.set(layer,seen)}else if(seen.viewport!==viewport&&Math.abs((layerRect.top-seen.top)-(viewport-seen.viewport))<1)seen.pinned=true;seen.viewport=viewport;seen.top=layerRect.top;if(seen.pinned){contentBottom=Math.max(contentBottom,contentTop+Math.max(0,viewport-layerRect.bottom)+naturalBlockSize(layer)+12);return}var reach=layerRect.bottom+hidden+12;if(reach>contentBottom)contentBottom=reach;overlays.push([Math.floor(layerRect.left-12),Math.floor(layerRect.top-contentTop-12),Math.ceil(layerRect.right+12),Math.ceil(reach-contentTop)])}); +layers.forEach(function(layer){var layerRect=layer.getBoundingClientRect();var seen=layerPlaces.get(layer),viewport=innerHeight;if(!seen){seen={pinned:bottomPinned(layer)};layerPlaces.set(layer,seen)}else if(seen.viewport!==viewport&&Math.abs((layerRect.top-seen.top)-(viewport-seen.viewport))<1)seen.pinned=true;seen.viewport=viewport;seen.top=layerRect.top;if(seen.pinned){contentBottom=Math.max(contentBottom,contentTop+Math.max(0,viewport-layerRect.bottom)+naturalBlockSize(layer)+12);return}var reach=layerRect.bottom+12;if(reach>contentBottom)contentBottom=reach;overlays.push([Math.floor(layerRect.left-12),Math.floor(layerRect.top-contentTop-12),Math.ceil(layerRect.right+12),Math.ceil(reach-contentTop)])}); var height=Math.ceil(Math.max(0,contentBottom-contentTop)),flow=Math.ceil(Math.max(0,flowBottom-contentTop)),report=height+'/'+flow+'/'+overlays.join(';'); if(report===lastHeight)return; lastHeight=report; diff --git a/tests/Unit/ExampleRuntimeContractTest.php b/tests/Unit/ExampleRuntimeContractTest.php index 205d82a7..6ebdd175 100644 --- a/tests/Unit/ExampleRuntimeContractTest.php +++ b/tests/Unit/ExampleRuntimeContractTest.php @@ -271,7 +271,7 @@ public function test_example_height_measures_content_instead_of_its_current_view self::assertStringContainsString("frame.style.clipPath=\"path('\"+path+\"')\"", $shell); self::assertStringContainsString(".docara-example-preview[data-docara-example-overlay]{overflow:visible}", (string) file_get_contents(dirname(__DIR__, 2) . '/resources/portable/declarative-shell.css')); self::assertStringContainsString("parent.postMessage({type:'docara:example-height',height:height,flow:flow,overlays:overlays},'*')", $renderer); - self::assertStringContainsString("var reach=layerRect.bottom+hidden+12;", $renderer); + self::assertStringContainsString("var reach=layerRect.bottom+12;", $renderer); self::assertStringContainsString("try{open=child.matches(':popover-open,dialog[open]')}catch(error){}if(open)return;", $renderer); self::assertStringNotContainsString('Math.min(4096', $shell); } diff --git a/tests/Unit/PortableMarkdownRendererTest.php b/tests/Unit/PortableMarkdownRendererTest.php index 55085e73..e116285f 100644 --- a/tests/Unit/PortableMarkdownRendererTest.php +++ b/tests/Unit/PortableMarkdownRendererTest.php @@ -452,9 +452,11 @@ public function it_renders_markdown_and_multifile_examples_as_one_tabbed_surface self::assertStringNotContainsString('body.scrollHeight,root.scrollHeight', $web); self::assertStringContainsString('function measureSettled()', $web); // An open menu sits in the top layer, which the frame clips; the frame - // grows to the menu's natural height, the part its list scrolls included. + // reaches the menu's drawn box. Rows the list scrolls stay out, or a + // list capped to the viewport would grow the frame without end. self::assertStringContainsString('querySelectorAll(':popover-open,dialog[open]')', $web); - self::assertStringContainsString('hidden=Math.max(hidden,part.scrollHeight-part.clientHeight)', $web); + self::assertStringContainsString('var reach=layerRect.bottom+12;', $web); + self::assertStringNotContainsString('part.scrollHeight-part.clientHeight', $web); self::assertStringContainsString('document.addEventListener('toggle',measureSettled,true)', $web); self::assertStringContainsString('setTimeout(measureNow,100)', $web); // A toast container fixed to the frame's bottom edge moves down as the From 8d5734b2a40ad83eec24cf261d027e1795e8fb06 Mon Sep 17 00:00:00 2001 From: Rim Zabarov Date: Wed, 11 Nov 2026 14:32:24 +0300 Subject: [PATCH 09/10] Use single quotes in the example runtime contract assertions Co-Authored-By: Claude Opus 5.5 --- tests/Unit/ExampleRuntimeContractTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Unit/ExampleRuntimeContractTest.php b/tests/Unit/ExampleRuntimeContractTest.php index 6ebdd175..53ab5ab4 100644 --- a/tests/Unit/ExampleRuntimeContractTest.php +++ b/tests/Unit/ExampleRuntimeContractTest.php @@ -266,12 +266,12 @@ public function test_example_height_measures_content_instead_of_its_current_view // An open menu's room hangs over what follows instead of pushing the // page down: the frame keeps its flow height in the layout, and a clip // path shows only the flow box and the menus. - self::assertStringContainsString("var extra=Number.isFinite(flow)&&boxes.length?Math.max(0,size-Math.max(32,Math.ceil(flow))):0;", $shell); + self::assertStringContainsString('var extra=Number.isFinite(flow)&&boxes.length?Math.max(0,size-Math.max(32,Math.ceil(flow))):0;', $shell); self::assertStringContainsString("frame.style.marginBlockEnd=(-extra)+'px';", $shell); self::assertStringContainsString("frame.style.clipPath=\"path('\"+path+\"')\"", $shell); - self::assertStringContainsString(".docara-example-preview[data-docara-example-overlay]{overflow:visible}", (string) file_get_contents(dirname(__DIR__, 2) . '/resources/portable/declarative-shell.css')); + self::assertStringContainsString('.docara-example-preview[data-docara-example-overlay]{overflow:visible}', (string) file_get_contents(dirname(__DIR__, 2) . '/resources/portable/declarative-shell.css')); self::assertStringContainsString("parent.postMessage({type:'docara:example-height',height:height,flow:flow,overlays:overlays},'*')", $renderer); - self::assertStringContainsString("var reach=layerRect.bottom+12;", $renderer); + self::assertStringContainsString('var reach=layerRect.bottom+12;', $renderer); self::assertStringContainsString("try{open=child.matches(':popover-open,dialog[open]')}catch(error){}if(open)return;", $renderer); self::assertStringNotContainsString('Math.min(4096', $shell); } From d8838711ce08797824c217142a61f1c2af123936 Mon Sep 17 00:00:00 2001 From: Rim Zabarov Date: Wed, 11 Nov 2026 15:34:38 +0300 Subject: [PATCH 10/10] Follow the 3.14.2 example runtime in the frozen page builder bytes The badge page embeds an example frame, so its HTML carries the frame runtime that 3.14.2 changed. Co-Authored-By: Claude Opus 5.5 --- tests/Unit/PageBuilderTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/PageBuilderTest.php b/tests/Unit/PageBuilderTest.php index b57263f7..72e9f5c9 100644 --- a/tests/Unit/PageBuilderTest.php +++ b/tests/Unit/PageBuilderTest.php @@ -126,7 +126,7 @@ public function test_badge_uses_one_pagebuilder_with_typed_ir_and_sixteen_gatewa ]))->types(), ); self::assertSame( - '7e6760d3c31396406da76c8c22566e86ab98893665309b940d965ce7bd1398fb', + '6afdf022361473db8e07be1883f8191f7849557d5f4244c1ac6b1f56787b1043', hash('sha256', $result->contentHtml), ); foreach ($result->componentArtifacts as $artifact) {