Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v3] Auto scaling custom element #263

Merged
merged 15 commits into from
Oct 30, 2021
Merged

[v3] Auto scaling custom element #263

merged 15 commits into from
Oct 30, 2021

Conversation

yhatt
Copy link
Member

@yhatt yhatt commented Oct 29, 2021

Added custom elements for auto-scaling for v3.

Markdown to HTML

Marp Core v2 had replaced tags that are enabled auto-scaling into <svg> tag for suited to auto-scaling.

# <!--fit--> Auto scaling
<h1>
  <svg data-marp-fitting="svg" preserveAspectRatio="xMinYMin meet" viewBox="0 0 257 57">
    <foreignObject width="257" height="57">
      <span data-marp-fitting-svg-content=""> Auto scaling</span>
    </foreignObject>
  </svg>
</h1>

It can reduce runtime JS size, but makes both of the output and the implementation complex. For everyone it is hard to know what happening in replace logics and the replaced code.

A new auto scaling implementation will close a gap between regular output of Markdown and Marp's output: just adds a few attributes for auto-scaling custom elements to an original tag. It keeps an original DOM structure so would not give too surprises to slide authors and theme creators.

  • <h1> -> <h1 is="marp-h1" data-auto-scaling>
  • <pre> -> <pre is="marp-pre" data-autoscaling="downscale-only">

So the first example will transform like that:

<h1 is="marp-h1" data-auto-scaling> Auto scaling</h1>

This makes theme CSS more natural styling. For example, consider the following CSS:

h1 > strong {
  color: red;
}

Markdown heading # will transform to <h1> and the emphasis ** will to <strong>, so it's natural to have red heading text in this Markdown:

# **Hello!**
<h1><strong>Hello!</strong><h1>

However, Marp Core v2 had broken this style if enabled fitting header because of implicit transformation of DOM structure.

<!-- Marp Core v2 -->
<h1>
  <svg data-marp-fitting="svg" preserveAspectRatio="xMinYMin meet" viewBox="0 0 257 57">
    <foreignObject width="257" height="57">
      <span data-marp-fitting-svg-content="">
        <strong>Hello!</strong>
      </span>
    </foreignObject>
  </svg>
</h1>

In v3, <svg> tags will be trapped in shadow DOM created by the custom element, so regular CSS selectors will keep matching to the original DOM structure. The following heading still has a red text.

<!-- Marp Core v3: will keep to match an original selector -->
<h1 is="marp-h1" data-auto-scaling><strong>Hello!</strong></h1>

Custom built-in elements

We have defined custom built-in elements <marp-***> inherited from auto-scalable HTML elements (<h1>-<h6>, <pre>, and <span>) in a hydration script. Their shadow DOM will apply auto-scaling for children contents.

We've already replaced auto-scalable elements to use them through is attribute, so auto-scaling will have done at that time if the best case. This approach is excellent because CSS selectors defined in the theme will not break.

The replaced custom elements actually have not implemented the auto-scaling logic. We have splitted the logic of auto-scaling into an another custom element <marp-auto-scaling>, and it is used by replaced elements.

If necessary, you can use <marp-auto-scaling> component directly by turning on HTML rendering through html constructor option.

Fallback to autonomous custom elements

We will apply a fallback in either of following cases:

  • Browser has not supported custom built-in elements (Safari)
  • Attaching shadow DOM for the target element has restricted by security reason (<pre>)

Marp Core detects <*** is="marp-***"> in runtime, and replace the element to an autonomous custom element <marp-***>. Each custom elements have a default style as same as user agent style, to prevent broken theme design.

Post-processing to the output CSS

Some CSS selectors in the theme CSS will become not to match if triggered a fallback for replacing built-in element to the autonomous custom element.

We have never want to press the responsibility for taking care of both of inherited built-in element and autonomous custom element to the author of theme CSS.

So we have applied the postprocess to the output CSS for replacing auto-scalable element in the selector to :is(xxx, marp-xxx). For example, h1.test > strong will replace into :is(h1, marp-xxx).test > strong to match both of custom elements.

Styling

The custom element also provides easy-to-recognize styling.

Previously it's hard to recognize how to work styling for auto-scaled elements from CSS.

svg[data-marp-fitting='svg'] {
  max-height: 580px; /* Slide height - padding * 2 */
}

It means to set the max height for auto-scaling element for headings, but who can expect that from this definition?

A new auto-scaling component provides a way to access the scaling element (<svg>) from CSS through ::part().

h1::part(auto-scaling) {
  max-height: 580px;
}

It makes the definition easy to read!

Please note that setting the default max-height for auto-scaling elements through *::part(auto-scaling) will work in Chrome and Safari, but NOT in Firefox. The workaround is covering all auto-scalable elements by :is() selector.

:is(h1, h2, h3, h4, h5, h6, pre, span)::part(auto-scaling) {
  max-height: 563px; /* Slide height - padding * 2 */
}

Auto scaling for code block in uncover theme

By this update, uncover theme can provide the auto-scaling for code block. It means the all of built-in themes have full support of Marp Core's auto-scaling.

@yhatt yhatt merged commit 50f288b into v3 Oct 30, 2021
@yhatt yhatt deleted the auto-scaling-custom-element branch October 30, 2021 14:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
1 participant