@marp-team/marpit-svg-polyfill

Polyfill for inline SVG slides rendered by Marpit

Usage no npm install needed!

<script type="module">
  import marpTeamMarpitSvgPolyfill from 'https://cdn.skypack.dev/@marp-team/marpit-svg-polyfill';
</script>

README

@marp-team/marpit-svg-polyfill

CircleCI Codecov npm LICENSE

The polyfill for the inline SVG slide rendered by Marpit.

Supported browser

  • WebKit based browser: Safari and iOS browsers (included Chrome and Firefox)

Usage

<!-- Generated HTML by Marpit's inline SVG mode -->
<div class="marpit">
  <svg viewBox="0 0 1280 720" data-marpit-svg="">
    <foreignObject width="1280" height="720">
      <section>...</section>
    </foreignObject>
  </svg>
</div>

<!-- After than, use polyfill through jsDelivr CDN -->
<script src="https://cdn.jsdelivr.net/npm/@marp-team/marpit-svg-polyfill/lib/polyfill.browser.js"></script>

Why need?

WebKit

Marpit's inline SVG slide has a lot of advantages: No requires JavaScript, gives better performance for scaling, and has predicatable DOM structure.

But unfortunately, WebKit browser has not scaled the wrapped HTML correctly. It is caused from a long standing bug 23113, and it does not resolved in the last 10 years.

Through inspector, we have not confirmed that there is a wrong layout in SVG itself and around. Thus, the problem has in a rendering of the parent SVG.

Actually, the nested SVG seems to be scaled correctly (e.g. <!--fit--> keyword in Marp Core).

Solutions

For Webkit

Scaling

We try to simulate scaling and centering by applying transform / transform-origin style to Marpit <section> elements.

<svg viewBox="0 0 1280 960">
  <foreignObject width="1280" height="960">
    <section
      style="transform-origin:0 0;transform:translate(123px,456px) scale(0.36666);"
    >
      ...
    </section>
  </foreignObject>
</svg>

We have to get the computed size of SVG element, so the polyfill would make a sacrifice of zero-JS feature.

Repainting

WebKit browser would not trigger repainting even if modified the contents of slide. It becomes a problem when supporting the live preview feature in Marp Web.

Fortunately, a genius already resolved this problem only in CSS! transform:translateZ(0) would trigger re-painting immidiately when modified contents.

Advanced

Apply polyfill manually

You may pick out the logic of polyfill if you required. When called a picked function, it applies polyfill forcibly without browser detection.

import { webkit } from '@marp-team/marpit-svg-polyfill'

const observer = () => {
  // Apply polyfill for webkit forcibly
  webkit()

  window.requestAnimationFrame(observer)
}

document.addEventListener('DOMContentLoaded', observer)

Use case in Blink browsers

We have confirmed a similar rendering bug to WebKit in a few Blink based browsers. (e.g. Chrome 66, Electron 3.x. refs: marp-team/marpit#35, marp-team/marp-cli#15)

We are not applied polyfill for Blink browsers because they are working toward to resolve this. But you may apply webkit() manually if you required.

Contributing

We are following the contributing guideline of marp-team projects. Please read these guidelines this before starting work in this repository.

Author

Managed by @marp-team.

License

This module releases under the MIT License.