Skip to content

Commit

Permalink
Merge pull request #28 from marp-team/target-option
Browse files Browse the repository at this point in the history
Allow to change the target of observer
  • Loading branch information
yhatt authored Aug 16, 2020
2 parents e11277f + dc2932b commit 58d253e
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 12 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## [Unreleased]

### Changed

- Allow to change the target of observer ([#28](https://github.com/marp-team/marpit-svg-polyfill/pull/28))

## v1.5.0 - 2020-07-16

### Changed
Expand Down
8 changes: 7 additions & 1 deletion src/entry.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
/* istanbul ignore file */
export { observe as default, observe, polyfills, webkit } from './polyfill'
export {
PolyfillOption,
observe as default,
observe,
polyfills,
webkit,
} from './polyfill'
34 changes: 24 additions & 10 deletions src/polyfill.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,39 @@
const msgPrefix = 'marpitSVGPolyfill:setZoomFactor,'

export type PolyfillOption = { target?: ParentNode }

export const observerSymbol = Symbol()
export const zoomFactorRecieverSymbol = Symbol()

export function observe() {
if (window[observerSymbol]) return
export function observe(target: ParentNode = document): () => void {
if (target[observerSymbol]) return target[observerSymbol]

let enableObserver = true

const cleanup = () => {
enableObserver = false
delete target[observerSymbol]
}

Object.defineProperty(window, observerSymbol, {
Object.defineProperty(target, observerSymbol, {
configurable: true,
value: true,
value: cleanup,
})

const observedPolyfills = polyfills()

if (observedPolyfills.length > 0) {
const observer = () => {
for (const polyfill of observedPolyfills) polyfill()
window.requestAnimationFrame(observer)
for (const polyfill of observedPolyfills) polyfill({ target })
if (enableObserver) window.requestAnimationFrame(observer)
}
observer()
}

return cleanup
}

export const polyfills = () =>
export const polyfills = (): Array<(opts: PolyfillOption) => void> =>
navigator.vendor === 'Apple Computer, Inc.' ? [webkit] : []

let previousZoomFactor: number
Expand All @@ -35,7 +46,10 @@ export const _resetCachedZoomFactor = () => {

_resetCachedZoomFactor()

export function webkit(zoom?: number) {
export function webkit(opts?: number | (PolyfillOption & { zoom?: number })) {
const target = (typeof opts === 'object' && opts.target) || document
const zoom = typeof opts === 'object' ? opts.zoom : opts

if (!window[zoomFactorRecieverSymbol]) {
Object.defineProperty(window, zoomFactorRecieverSymbol, {
configurable: true,
Expand All @@ -61,7 +75,7 @@ export function webkit(zoom?: number) {
let changedZoomFactor: false | number = false

Array.from(
document.querySelectorAll<SVGSVGElement>('svg[data-marpit-svg]'),
target.querySelectorAll<SVGSVGElement>('svg[data-marpit-svg]'),
(svg) => {
const { children, clientHeight, clientWidth, viewBox } = svg
if (!svg.style.transform) svg.style.transform = 'translateZ(0)'
Expand Down Expand Up @@ -93,7 +107,7 @@ export function webkit(zoom?: number) {

if (changedZoomFactor !== false) {
Array.from(
document.querySelectorAll<HTMLIFrameElement>('iframe'),
target.querySelectorAll<HTMLIFrameElement>('iframe'),
({ contentWindow }) => {
contentWindow?.postMessage(
`${msgPrefix}${changedZoomFactor}`,
Expand Down
33 changes: 32 additions & 1 deletion test/polyfill.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
let vendor: jest.SpyInstance

beforeEach(() => {
window[observerSymbol] = false
delete document[observerSymbol]
vendor = jest.spyOn(navigator, 'vendor', 'get').mockImplementation(() => '')
_resetCachedZoomFactor()
})
Expand Down Expand Up @@ -37,6 +37,37 @@ describe('Marpit SVG polyfill', () => {
observe()
expect(spy).toHaveBeenCalledTimes(1)
})

describe('Clean-up function', () => {
it('returns function for clean-up', () => {
vendor.mockImplementation(() => 'Apple Computer, Inc.')

const cleanup = observe()
expect(cleanup).toStrictEqual(expect.any(Function))

// Observer can enable again after cleaning up
cleanup()
observe()
expect(spy).toHaveBeenCalledTimes(2)
})
})

describe('Different target', () => {
it('availables observation for different target', () => {
vendor.mockImplementation(() => 'Apple Computer, Inc.')

const element = document.createElement('div')
const querySpy = jest.spyOn(element, 'querySelectorAll')
const cleanup = observe(element)

expect(element[observerSymbol]).toStrictEqual(cleanup)
expect(querySpy).toHaveBeenCalled()

// Returns always same clean-up function even if observing some times
expect(observe(element)).toStrictEqual(cleanup)
expect(spy).toHaveBeenCalledTimes(1)
})
})
})

describe('#webkit', () => {
Expand Down

0 comments on commit 58d253e

Please sign in to comment.