Skip to content

Commit

Permalink
Merge pull request #384 from marp-team/suppress-firefox-not-supported…
Browse files Browse the repository at this point in the history
…-error

Suppress uncaught `DOMException` error while upgrading `<marp-pre>` Web Component elements in Firefox
  • Loading branch information
yhatt authored Sep 8, 2024
2 parents 125e6ef + cf6cfa7 commit fd631a0
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 13 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@
* Upgrade dependent packages to the latest version ([#380](https://github.com/marp-team/marp-core/pull/380))
* Switch package manager from yarn to npm ([#379](https://github.com/marp-team/marp-core/pull/379))
### Fixed
- Suppress uncaught `DOMException` error while upgrading `<marp-pre>` Web Component elements in Firefox ([#370](https://github.com/marp-team/marp-core/issues/370), [#384](https://github.com/marp-team/marp-core/pull/384))
## v3.9.0 - 2023-10-15
### Added
Expand Down
9 changes: 7 additions & 2 deletions jest.config.js → jest.config.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
const { defaults: tsjPreset } = require('ts-jest/presets')
import { createDefaultPreset } from 'ts-jest'

module.exports = {
const tsjPreset = createDefaultPreset()

/** @type {import('jest').Config} */
const config = {
collectCoverageFrom: ['src/**/*.{j,t}s'],
coveragePathIgnorePatterns: ['/node_modules/', '.*\\.d\\.ts'],
coverageThreshold: { global: { lines: 95 } },
Expand All @@ -12,3 +15,5 @@ module.exports = {
},
prettierPath: null,
}

export default config
37 changes: 26 additions & 11 deletions src/custom-elements/browser/marp-custom-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export const createMarpCustomElement = <T extends Constructor<HTMLElement>>(
{ attrs = {}, style }: { attrs?: Record<string, string>; style?: string },
) =>
class MarpCustomElement extends Base {
declare shadowRoot: ShadowRoot
declare readonly shadowRoot: ShadowRoot | null

constructor(...args: any[]) {
super(...args)
Expand All @@ -14,7 +14,7 @@ export const createMarpCustomElement = <T extends Constructor<HTMLElement>>(
if (!this.hasAttribute(key)) this.setAttribute(key, value)
}

this.attachShadow({ mode: 'open' })
this._shadow()
}

static get observedAttributes() {
Expand All @@ -29,19 +29,34 @@ export const createMarpCustomElement = <T extends Constructor<HTMLElement>>(
this._update()
}

_shadow() {
if (!this.shadowRoot) {
try {
this.attachShadow({ mode: 'open' })
} catch (e) {
if (!(e instanceof Error && e.name === 'NotSupportedError')) throw e
}
}
return this.shadowRoot
}

_update() {
const styleTag = style ? `<style>:host { ${style} }</style>` : ''
let slotTag = '<slot></slot>'
const shadowRoot = this._shadow()

const { autoScaling } = this.dataset
if (shadowRoot) {
const styleTag = style ? `<style>:host { ${style} }</style>` : ''
let slotTag = '<slot></slot>'

if (autoScaling !== undefined) {
const downscale =
autoScaling === 'downscale-only' ? 'data-downscale-only' : ''
const { autoScaling } = this.dataset

slotTag = `<marp-auto-scaling exportparts="svg:auto-scaling" ${downscale}>${slotTag}</marp-auto-scaling>`
}
if (autoScaling !== undefined) {
const downscale =
autoScaling === 'downscale-only' ? 'data-downscale-only' : ''

slotTag = `<marp-auto-scaling exportparts="svg:auto-scaling" ${downscale}>${slotTag}</marp-auto-scaling>`
}

this.shadowRoot.innerHTML = styleTag + slotTag
shadowRoot.innerHTML = styleTag + slotTag
}
}
}
28 changes: 28 additions & 0 deletions test/custom-elements/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,34 @@ describe('The hydration script for custom elements', () => {
)
})

it('does not throw known DOMException error while upgrading <pre is="marp-pre"> to <marp-pre> (for Firefox)', () => {
document.body.innerHTML = '<pre is="marp-pre">1</pre>'

jest
.spyOn(HTMLElement.prototype, 'attachShadow')
.mockImplementationOnce(() => {
throw new DOMException(
'Element.attachShadow: Unable to attach ShadowDOM',
'NotSupportedError',
)
})

expect(() => browser.applyCustomElements()).not.toThrow()
})

it.skip('throws error if unknown error occured while upgrading <pre is="marp-pre"> to <marp-pre>', () => {
document.body.innerHTML = '<pre is="marp-pre">1</pre>'

jest.spyOn(console, 'error').mockImplementation(() => {})
jest
.spyOn(HTMLElement.prototype, 'attachShadow')
.mockImplementationOnce(() => {
throw new Error('Unknown error while attaching shadow')
})

expect(() => browser.applyCustomElements()).toThrow()
})

it('does not replace <h1 is="marp-h1"> to <marp-h1>', () => {
const html = '<h1 is="marp-h1">test</h1>'
document.body.innerHTML = html
Expand Down

0 comments on commit fd631a0

Please sign in to comment.