[META] Real-time preview: supporting back-end infrastructure
>>> [!note] Migrated issue
<!-- Drupal.org comment -->
<!-- Migrated from issue #3453690. -->
Reported by: [jessebaker](https://www.drupal.org/user/3546546)
>>>
<h3 id="summary-problem-motivation">Problem/Motivation</h3>
<p>We want to replace the mocked call to render a realtime preview with a real endpoint that renders the page and returns the markup to be displayed. In this first step, performance is a low priority goal. At this early stage it is more important to have this foundation in place on which to build and optimise in the future.</p>
<h3 id="summary-proposed-resolution">Proposed resolution</h3>
<ol>
<li>✅ PRECURSOR to <strong>Real-time preview of rendered components WITHOUT in-place editing (i.e. sidebar prop editing only)</strong>:<br>
use the exact same mechanism the UI is currently using, meaning it won't need to change <em>at all</em>: <span class="drupalorg-gitlab-issue-link project-issue-status-info project-issue-status-7"><a href="https://www.drupal.org/project/experience_builder/issues/3455898" title="Status: Closed (fixed)">#3455898: Connect client & server, with zero changes to client (UI): rough working endpoints that mimic the UI's mocks</a></span>
</li>
<li>
<ul>
<li>✅<strong>A</strong> <span class="drupalorg-gitlab-issue-link project-issue-status-info project-issue-status-7"><a href="https://www.drupal.org/project/experience_builder/issues/3462441" title="Status: Closed (fixed)">#3462441: Contextual form values need to be integrated with Redux: start with single-property field types</a></span> <strong>Real-time preview of rendered components WITHOUT in-place editing (i.e. sidebar prop editing only)</strong>: ONLY able to click a component and have a form for it appear in the right sidebar, NO ability to in-place edit e.g. the title of a hero component.
</li><li>❌ <strong>B</strong> Convert the above to use HTML comments instead of a wrapping <code><div></code> like <code>\Drupal\experience_builder\Controller\SdcController::wrapComponentsForPreview()</code> is currently doing:<br>
<pre><div class="sortable-item" data-xb-uuid="%s" data-xb-type="%s"><br> <!-- actually rendered component here --><br></div></pre><p>There are relatively few annotation comments required from the backend to enable hooking up the hover/select/drag and drop. The following mocked up markup + some throwaway code were used to verify this can work:</p>
<div class="codeblock">
<pre><span style="color: #000000"><span style="color: #0000BB"><?php<br> </span><span style="color: #007700"><</span><span style="color: #0000BB">body</span><span style="color: #007700">><br> <!-- </span><span style="color: #0000BB">xb</span><span style="color: #007700">-</span><span style="color: #0000BB">slot</span><span style="color: #007700">-</span><span style="color: #0000BB">root </span><span style="color: #007700">--><br> <!-- </span><span style="color: #0000BB">xb</span><span style="color: #007700">-</span><span style="color: #0000BB">start</span><span style="color: #007700">-</span><span style="color: #0000BB">43cd7aa4</span><span style="color: #007700">-</span><span style="color: #0000BB">0160</span><span style="color: #007700">-</span><span style="color: #0000BB">4787</span><span style="color: #007700">-</span><span style="color: #0000BB">a3af</span><span style="color: #007700">-</span><span style="color: #0000BB">baf44ff17a88 </span><span style="color: #007700">--><br> <</span><span style="color: #0000BB">div</span><span style="color: #007700">><br> <</span><span style="color: #0000BB">h1</span><span style="color: #007700">></span><span style="color: #0000BB">Hello world</span><span style="color: #007700">.</</span><span style="color: #0000BB">h1</span><span style="color: #007700">><br> </</span><span style="color: #0000BB">div</span><span style="color: #007700">><br> <!-- </span><span style="color: #0000BB">xb</span><span style="color: #007700">-</span><span style="color: #0000BB">end</span><span style="color: #007700">-</span><span style="color: #0000BB">43cd7aa4</span><span style="color: #007700">-</span><span style="color: #0000BB">0160</span><span style="color: #007700">-</span><span style="color: #0000BB">4787</span><span style="color: #007700">-</span><span style="color: #0000BB">a3af</span><span style="color: #007700">-</span><span style="color: #0000BB">baf44ff17a88 </span><span style="color: #007700">--><br><br> <!-- </span><span style="color: #0000BB">xb</span><span style="color: #007700">-</span><span style="color: #0000BB">start</span><span style="color: #007700">-</span><span style="color: #0000BB">fcd2490d</span><span style="color: #007700">-</span><span style="color: #0000BB">1124</span><span style="color: #007700">-</span><span style="color: #0000BB">4146</span><span style="color: #007700">-</span><span style="color: #0000BB">82b6</span><span style="color: #007700">-</span><span style="color: #0000BB">b1e049ed8026 </span><span style="color: #007700">--><br> <</span><span style="color: #0000BB">h1</span><span style="color: #007700">></span><span style="color: #0000BB">Another component</span><span style="color: #007700">.</</span><span style="color: #0000BB">h1</span><span style="color: #007700">><br> <</span><span style="color: #0000BB">p</span><span style="color: #007700">></span><span style="color: #0000BB">Ooo 2 elements with no wrapper</span><span style="color: #007700">! </span><span style="color: #0000BB">Other components should not be able to get inserted above this P </span><span style="color: #007700">and </span><span style="color: #0000BB">below the H1 </span><span style="color: #007700">^</</span><span style="color: #0000BB">p</span><span style="color: #007700">><br> <!-- </span><span style="color: #0000BB">xb</span><span style="color: #007700">-</span><span style="color: #0000BB">end</span><span style="color: #007700">-</span><span style="color: #0000BB">fcd2490d</span><span style="color: #007700">-</span><span style="color: #0000BB">1124</span><span style="color: #007700">-</span><span style="color: #0000BB">4146</span><span style="color: #007700">-</span><span style="color: #0000BB">82b6</span><span style="color: #007700">-</span><span style="color: #0000BB">b1e049ed8026 </span><span style="color: #007700">--><br><br> <!-- </span><span style="color: #0000BB">xb</span><span style="color: #007700">-</span><span style="color: #0000BB">start</span><span style="color: #007700">-</span><span style="color: #0000BB">05fa13be</span><span style="color: #007700">-</span><span style="color: #0000BB">8291</span><span style="color: #007700">-</span><span style="color: #0000BB">4955</span><span style="color: #007700">-</span><span style="color: #0000BB">aa89</span><span style="color: #007700">-</span><span style="color: #0000BB">32351f68e776 </span><span style="color: #007700">--><br> <</span><span style="color: #0000BB">img src</span><span style="color: #007700">=</span><span style="color: #DD0000">"https://placehold.co/600x400" </span><span style="color: #0000BB">alt</span><span style="color: #007700">=</span><span style="color: #DD0000">"A placceholder image" </span><span style="color: #0000BB">width</span><span style="color: #007700">=</span><span style="color: #DD0000">"600" </span><span style="color: #0000BB">height</span><span style="color: #007700">=</span><span style="color: #DD0000">"400" </span><span style="color: #007700">/><br> <!-- </span><span style="color: #0000BB">xb</span><span style="color: #007700">-</span><span style="color: #0000BB">end</span><span style="color: #007700">-</span><span style="color: #0000BB">05fa13be</span><span style="color: #007700">-</span><span style="color: #0000BB">8291</span><span style="color: #007700">-</span><span style="color: #0000BB">4955</span><span style="color: #007700">-</span><span style="color: #0000BB">aa89</span><span style="color: #007700">-</span><span style="color: #0000BB">32351f68e776 </span><span style="color: #007700">--><br><br> <!-- </span><span style="color: #0000BB">xb</span><span style="color: #007700">-</span><span style="color: #0000BB">start</span><span style="color: #007700">-</span><span style="color: #0000BB">1941ffae</span><span style="color: #007700">-</span><span style="color: #0000BB">f9ed</span><span style="color: #007700">-</span><span style="color: #0000BB">4ce3</span><span style="color: #007700">-</span><span style="color: #0000BB">8145</span><span style="color: #007700">-</span><span style="color: #0000BB">a2c3977ac65b </span><span style="color: #007700">--><br> <</span><span style="color: #0000BB">div </span><span style="color: #007700">class=</span><span style="color: #DD0000">"row" </span><span style="color: #0000BB">style</span><span style="color: #007700">=</span><span style="color: #DD0000">"display: flex;"</span><span style="color: #007700">><br> <</span><span style="color: #0000BB">div </span><span style="color: #007700">class=</span><span style="color: #DD0000">"column" </span><span style="color: #0000BB">style</span><span style="color: #007700">=</span><span style="color: #DD0000">"width: 60%; background: #c0ffee;"</span><span style="color: #007700">><br> <!-- </span><span style="color: #0000BB">xb</span><span style="color: #007700">-</span><span style="color: #0000BB">slot</span><span style="color: #007700">-</span><span style="color: #0000BB">68cafa3e</span><span style="color: #007700">-</span><span style="color: #0000BB">bfd8</span><span style="color: #007700">-</span><span style="color: #0000BB">4767</span><span style="color: #007700">-</span><span style="color: #0000BB">a5cc</span><span style="color: #007700">-</span><span style="color: #0000BB">c18cce97c236 </span><span style="color: #007700">--><br> <!-- </span><span style="color: #0000BB">xb</span><span style="color: #007700">-</span><span style="color: #0000BB">start</span><span style="color: #007700">-</span><span style="color: #0000BB">bdfce52f</span><span style="color: #007700">-</span><span style="color: #0000BB">e666</span><span style="color: #007700">-</span><span style="color: #0000BB">49f0</span><span style="color: #007700">-</span><span style="color: #0000BB">a57f</span><span style="color: #007700">-</span><span style="color: #0000BB">dfb8c5c0c75b </span><span style="color: #007700">--><br> <</span><span style="color: #0000BB">div</span><span style="color: #007700">><br> <</span><span style="color: #0000BB">h1</span><span style="color: #007700">></span><span style="color: #0000BB">In a slot</span><span style="color: #007700">!</</span><span style="color: #0000BB">h1</span><span style="color: #007700">><br> </</span><span style="color: #0000BB">div</span><span style="color: #007700">><br> <!-- </span><span style="color: #0000BB">xb</span><span style="color: #007700">-</span><span style="color: #0000BB">end</span><span style="color: #007700">-</span><span style="color: #0000BB">bdfce52f</span><span style="color: #007700">-</span><span style="color: #0000BB">e666</span><span style="color: #007700">-</span><span style="color: #0000BB">49f0</span><span style="color: #007700">-</span><span style="color: #0000BB">a57f</span><span style="color: #007700">-</span><span style="color: #0000BB">dfb8c5c0c75b </span><span style="color: #007700">--><br> </</span><span style="color: #0000BB">div</span><span style="color: #007700">><br> <</span><span style="color: #0000BB">div </span><span style="color: #007700">class=</span><span style="color: #DD0000">"column" </span><span style="color: #0000BB">style</span><span style="color: #007700">=</span><span style="color: #DD0000">"width: 60%; background: #decade;"</span><span style="color: #007700">><br> <!-- </span><span style="color: #0000BB">xb</span><span style="color: #007700">-</span><span style="color: #0000BB">slot</span><span style="color: #007700">-</span><span style="color: #0000BB">fe01d628</span><span style="color: #007700">-</span><span style="color: #0000BB">55ab</span><span style="color: #007700">-</span><span style="color: #0000BB">4146</span><span style="color: #007700">-</span><span style="color: #0000BB">9d04</span><span style="color: #007700">-</span><span style="color: #0000BB">71e5a01ad233 </span><span style="color: #007700">--><br> </</span><span style="color: #0000BB">div</span><span style="color: #007700">><br> </</span><span style="color: #0000BB">div</span><span style="color: #007700">><br> <!-- </span><span style="color: #0000BB">xb</span><span style="color: #007700">-</span><span style="color: #0000BB">end</span><span style="color: #007700">-</span><span style="color: #0000BB">1941ffae</span><span style="color: #007700">-</span><span style="color: #0000BB">f9ed</span><span style="color: #007700">-</span><span style="color: #0000BB">4ce3</span><span style="color: #007700">-</span><span style="color: #0000BB">8145</span><span style="color: #007700">-</span><span style="color: #0000BB">a2c3977ac65b </span><span style="color: #007700">--><br> </</span><span style="color: #0000BB">body</span><span style="color: #007700">><br></span><span style="color: #0000BB">?></span></span></pre></div>
<ol>
<li><code><!-- xb-slot-* --></code> used directly inside a slot to indicate that the parent element is a drop target for sorting. The very top level should be xb-slot-root other instances should be a UUID e.g. <code><!-- xb-slot-fe01d628-55ab-4146-9d04-71e5a01ad233 --></code></li>
<li><code><!-- xb-start-UUID --></code> should be immediately before the first element of a component.</li>
<li><code><!-- xb-end-UUID --></code> should be immediately after the last element of a component.</li>
</ol>
<p><img src="https://www.drupal.org/files/issues/2024-06-10/image%20%282%29.png" alt="">
</p></li></ul>
</li>
<li>🛑 <strong>Real-time preview of rendered components WITH AFFORDANCES for in-place editing</strong>: ONLY able to click a component and have a form for it appear in the right sidebar, with PARTIAL ability to in-place edit: upon hovering component markup marked up for in-place editing we'd be able to highlight in the right sidebar which part of the form corresponds to it.
<p>Proposal by @jessebaker: <a href="https://www.drupal.org#comment-15635301">#4</a>.
</p></li>
<li>🛑 <strong>Real-time preview of rendered components WITH ACTUAL in-place editing</strong>: on top of the above, we'd need to use <em>some</em> input widgets, presumably only text initially (think <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/contenteditable"><code>contenteditable</code></a> but with restrictions).
<p>Proposal by @jessebaker: <a href="https://www.drupal.org#comment-15635301">#4</a>.
</p></li>
</ol>
<p>⚠️ Steps 2–4 would be a <em>lot</em> simpler/more productive if we could leverage @larowlan's AST work (see <a href="https://www.drupal.org#comment-15637840">#13</a>). We're waiting on @larowlan for an update on that front before proceeding further here.</p>
> Related issue: [Issue #3452497](https://www.drupal.org/node/3452497)
> Related issue: [Issue #3445566](https://www.drupal.org/node/3445566)
> Related issue: [Issue #3448927](https://www.drupal.org/node/3448927)
> Related issue: [Issue #3455898](https://www.drupal.org/node/3455898)
> Related issue: [Issue #3462441](https://www.drupal.org/node/3462441)
> Related issue: [Issue #3450586](https://www.drupal.org/node/3450586)
issue