observablehq / framework

A static site generator for data apps, dashboards, reports, and more. Observable Framework combines JavaScript on the front-end for interactive graphics with any language on the back-end for data analysis.
https://observablehq.com/framework/
ISC License
2.13k stars 85 forks source link

no wrapper span #1416

Closed mbostock closed 3 weeks ago

mbostock commented 1 month ago

Rather than producing an inline span,

<span id="cell-6212702c"></span>

inline expressions now produce a special comment:

<!--:6212702c:-->

This comment does not serve as a container for any rendered content but rather serves as a marker: rendered content (calls to display) are inserted before the comment. The rendered contents are tracked in the _nodes array and removed as needed (rather than clearing the container via innerHTML).

This eliminates the need for a wrapper span for inline expressions, which means things like this now work:

<div class="grid grid-cols-4">
  ${d3.range(10).map((i) => html`<div class="card">${i}</div>`)}
</div>

This also fixes rendering inline expressions into SVG and some edge cases with incremental update during preview.

Fixes #11. Fixes #1414. Fixes #1415.

Adding in #1425: Fixes https://github.com/observablehq/framework/issues/375. Fixes https://github.com/observablehq/framework/issues/396. Fixes https://github.com/observablehq/framework/pull/597. Fixes https://github.com/observablehq/framework/issues/636.

mbostock commented 1 month ago

I don’t have a great way of automating tests for this functionality, but here are some of the new things you can do:

<div class="flexy">
  ${d3.range(10).map((i) => html`<div>${i}</div>`)}
</div>

<style type="text/css">

.flexy {
  display: flex;
}

.flexy > * {
  flex-grow: 1;
}

</style>
<table>
  <thead>
    <tr>
      <td>i</td>
      <td>one</td>
      <td>two</td>
    </tr>
  </thead>
  <tbody>
    ${d3.range(10).map((i) => html`<tr>
      <td>${i}</td>
      <td>one</td>
      <td>two</td>
    </tr>`)}
  </tbody>
</table>
<h2>hello</h2> editme
<svg width=640 height=120 fill=red>
  <text x=20 y=20>${now}</text>
</svg>
<svg width=640 height=120>
  ${d3.range(10).map((i) => svg`<text x=${20 + i * 10} y=20 fill=${d3.interpolateTurbo(i / 10)}>${i}</text>`)}
</svg>
Fil commented 1 month ago

(erroneous comment deleted)

Nice! I wonder if this could help fix #375: now a comment with inline code <!-- ${1 + 2} --> shows -->, which is (slightly) worse than before.

mbostock commented 4 weeks ago

Fixing that requires fundamental changes to our parser as described in #597. I don’t think we should tie these two things together. Interpolating within comments is broken and will remain broken in this PR.