From d2dff6a821a6da55bfbd21155f91cae915a0e4c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Lechtenb=C3=B6rger?= Date: Sun, 8 Nov 2020 17:39:04 +0100 Subject: [PATCH 01/30] Fix target for click on progress bar The progress bar shows how many slides have been passed in total. However, when clicking on the progress bar, the target slide is computed among the subset of /horizontal/ slides. Thus, when the new slide is displayed, the progress bar has usually changed to a point that is unrelated to the clicked one, which I find surprising. With this change, the target slide is computed from the number of total slides. Thus, after a click on the progress bar, the resulting progress is close to the clicked point, which seems more natural to me. --- js/controllers/progress.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/js/controllers/progress.js b/js/controllers/progress.js index e806e38a..82a370a0 100644 --- a/js/controllers/progress.js +++ b/js/controllers/progress.js @@ -88,14 +88,16 @@ export default class Progress { event.preventDefault(); - let slidesTotal = this.Reveal.getHorizontalSlides().length; + let slides = this.Reveal.getSlides(); + let slidesTotal = slides.length; let slideIndex = Math.floor( ( event.clientX / this.getMaxWidth() ) * slidesTotal ); if( this.Reveal.getConfig().rtl ) { slideIndex = slidesTotal - slideIndex; } - this.Reveal.slide( slideIndex ); + let targetIndices = this.Reveal.getIndices(slides[slideIndex]); + this.Reveal.slide( targetIndices.h, targetIndices.v ); } From 75480b5bf43cb3fd542a535aec7f34d295179b71 Mon Sep 17 00:00:00 2001 From: Jeroen Hermans Date: Sun, 15 Nov 2020 21:46:33 +0100 Subject: [PATCH 02/30] Remove unused argument --- js/reveal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/reveal.js b/js/reveal.js index 67ad0b8b..727cc8e9 100644 --- a/js/reveal.js +++ b/js/reveal.js @@ -2290,7 +2290,7 @@ export default function( revealElement, options ) { // When looping is enabled `routes.down` is always available // so we need a separate check for when we've reached the // end of a stack and should move horizontally - if( routes.down && routes.right && config.loop && isLastVerticalSlide( currentSlide ) ) { + if( routes.down && routes.right && config.loop && isLastVerticalSlide() ) { routes.down = false; } From aaa7c02b5c7cc6a1697d90c786268cb72d0649be Mon Sep 17 00:00:00 2001 From: Jeroen Hermans Date: Sun, 15 Nov 2020 21:54:05 +0100 Subject: [PATCH 03/30] Prevent layout thrashing by status text --- js/reveal.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/js/reveal.js b/js/reveal.js index 727cc8e9..b3f81a16 100644 --- a/js/reveal.js +++ b/js/reveal.js @@ -1335,7 +1335,11 @@ export default function( revealElement, options ) { } // Announce the current slide contents to screen readers - announceStatus( getStatusText( currentSlide ) ); + // Use animation frame to prevent getComputedStyle in getStatusText + // from triggering layout mid-frame + requestAnimationFrame( function() { + announceStatus( getStatusText( currentSlide ) ); + }); progress.update(); controls.update(); From 3d701edc71145e42e361b6b7898406c4d300f762 Mon Sep 17 00:00:00 2001 From: Jeroen Hermans Date: Sun, 15 Nov 2020 22:01:50 +0100 Subject: [PATCH 04/30] Limit slide number DOM mutations --- js/controllers/print.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/js/controllers/print.js b/js/controllers/print.js index ed7da73e..84651a4f 100644 --- a/js/controllers/print.js +++ b/js/controllers/print.js @@ -43,14 +43,13 @@ export default class Print { // Make sure stretch elements fit on slide this.Reveal.layoutSlideContents( slideWidth, slideHeight ); + const slides = queryAll( this.Reveal.getRevealElement(), SLIDES_SELECTOR ) + // Compute slide numbers now, before we start duplicating slides let doingSlideNumbers = config.slideNumber && /all|print/i.test( config.showSlideNumber ); - queryAll( this.Reveal.getRevealElement(), SLIDES_SELECTOR ).forEach( function( slide ) { - slide.setAttribute( 'data-slide-number', this.Reveal.slideNumber.getSlideNumber( slide ) ); - }, this ); // Slide and slide background layout - queryAll( this.Reveal.getRevealElement(), SLIDES_SELECTOR ).forEach( function( slide ) { + slides.forEach( function( slide, index ) { // Vertical stacks are not centred since their section // children will be @@ -118,10 +117,11 @@ export default class Print { // Inject slide numbers if `slideNumbers` are enabled if( doingSlideNumbers ) { - let numberElement = document.createElement( 'div' ); + const slideNumber = index + 1; + const numberElement = document.createElement( 'div' ); numberElement.classList.add( 'slide-number' ); numberElement.classList.add( 'slide-number-pdf' ); - numberElement.innerHTML = slide.getAttribute( 'data-slide-number' ); + numberElement.innerHTML = slideNumber; page.appendChild( numberElement ); } From 957f928c707b230a35afe8c9e27de1b129cfaedc Mon Sep 17 00:00:00 2001 From: Jeroen Hermans Date: Sun, 15 Nov 2020 22:03:39 +0100 Subject: [PATCH 05/30] Prevent layout thrashing by scroll height --- js/controllers/print.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/js/controllers/print.js b/js/controllers/print.js index 84651a4f..7d89f626 100644 --- a/js/controllers/print.js +++ b/js/controllers/print.js @@ -16,7 +16,7 @@ export default class Print { * Configures the presentation for printing to a static * PDF. */ - setupPDF() { + async setupPDF() { let config = this.Reveal.getConfig(); @@ -48,6 +48,13 @@ export default class Print { // Compute slide numbers now, before we start duplicating slides let doingSlideNumbers = config.slideNumber && /all|print/i.test( config.showSlideNumber ); + // Batch scrollHeight access to prevent layout thrashing + await new Promise(requestAnimationFrame); + const slideScrollHeights = [] + slides.forEach( function( slide ) { + slideScrollHeights.push( slide.scrollHeight ); + }); + // Slide and slide background layout slides.forEach( function( slide, index ) { @@ -58,7 +65,7 @@ export default class Print { let left = ( pageWidth - slideWidth ) / 2, top = ( pageHeight - slideHeight ) / 2; - let contentHeight = slide.scrollHeight; + const contentHeight = slideScrollHeights[ index ]; let numberOfPages = Math.max( Math.ceil( contentHeight / pageHeight ), 1 ); // Adhere to configured pages per slide limit From 49f78535d11d92c669630f3a7045ce6fb780d807 Mon Sep 17 00:00:00 2001 From: Jeroen Hermans Date: Sun, 15 Nov 2020 22:06:48 +0100 Subject: [PATCH 06/30] Use const in print controller --- js/controllers/print.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/js/controllers/print.js b/js/controllers/print.js index 7d89f626..c895654f 100644 --- a/js/controllers/print.js +++ b/js/controllers/print.js @@ -62,8 +62,8 @@ export default class Print { // children will be if( slide.classList.contains( 'stack' ) === false ) { // Center the slide inside of the page, giving the slide some margin - let left = ( pageWidth - slideWidth ) / 2, - top = ( pageHeight - slideHeight ) / 2; + const left = ( pageWidth - slideWidth ) / 2; + let top = ( pageHeight - slideHeight ) / 2; const contentHeight = slideScrollHeights[ index ]; let numberOfPages = Math.max( Math.ceil( contentHeight / pageHeight ), 1 ); @@ -78,7 +78,7 @@ export default class Print { // Wrap the slide in a page element and hide its overflow // so that no page ever flows onto another - let page = document.createElement( 'div' ); + const page = document.createElement( 'div' ); page.className = 'pdf-page'; page.style.height = ( ( pageHeight + config.pdfPageHeightOffset ) * numberOfPages ) + 'px'; slide.parentNode.insertBefore( page, slide ); @@ -97,12 +97,12 @@ export default class Print { if( config.showNotes ) { // Are there notes for this slide? - let notes = this.Reveal.getSlideNotes( slide ); + const notes = this.Reveal.getSlideNotes( slide ); if( notes ) { - let notesSpacing = 8; - let notesLayout = typeof config.showNotes === 'string' ? config.showNotes : 'inline'; - let notesElement = document.createElement( 'div' ); + const notesSpacing = 8; + const notesLayout = typeof config.showNotes === 'string' ? config.showNotes : 'inline'; + const notesElement = document.createElement( 'div' ); notesElement.classList.add( 'speaker-notes' ); notesElement.classList.add( 'speaker-notes-pdf' ); notesElement.setAttribute( 'data-layout', notesLayout ); @@ -138,7 +138,7 @@ export default class Print { // Each fragment 'group' is an array containing one or more // fragments. Multiple fragments that appear at the same time // are part of the same group. - let fragmentGroups = this.Reveal.fragments.sort( page.querySelectorAll( '.fragment' ), true ); + const fragmentGroups = this.Reveal.fragments.sort( page.querySelectorAll( '.fragment' ), true ); let previousFragmentStep; let previousPage; From 33c4c1c5d2bd19abda159c4b507b93ee1745f15a Mon Sep 17 00:00:00 2001 From: Jeroen Hermans Date: Sun, 15 Nov 2020 22:08:13 +0100 Subject: [PATCH 07/30] Batch print DOM updates --- js/controllers/print.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/js/controllers/print.js b/js/controllers/print.js index c895654f..2ceda1ce 100644 --- a/js/controllers/print.js +++ b/js/controllers/print.js @@ -55,6 +55,9 @@ export default class Print { slideScrollHeights.push( slide.scrollHeight ); }); + const pages = []; + const pageContainer = slides[0].parentNode; + // Slide and slide background layout slides.forEach( function( slide, index ) { @@ -79,9 +82,10 @@ export default class Print { // Wrap the slide in a page element and hide its overflow // so that no page ever flows onto another const page = document.createElement( 'div' ); + pages.push( page ); + page.className = 'pdf-page'; page.style.height = ( ( pageHeight + config.pdfPageHeightOffset ) * numberOfPages ) + 'px'; - slide.parentNode.insertBefore( page, slide ); page.appendChild( slide ); // Position the slide inside of the page @@ -109,7 +113,7 @@ export default class Print { notesElement.innerHTML = notes; if( notesLayout === 'separate-page' ) { - page.parentNode.insertBefore( notesElement, page.nextSibling ); + pages.push( notesElement ); } else { notesElement.style.left = notesSpacing + 'px'; @@ -141,7 +145,6 @@ export default class Print { const fragmentGroups = this.Reveal.fragments.sort( page.querySelectorAll( '.fragment' ), true ); let previousFragmentStep; - let previousPage; fragmentGroups.forEach( function( fragments ) { @@ -159,10 +162,9 @@ export default class Print { // Create a separate page for the current fragment state let clonedPage = page.cloneNode( true ); - page.parentNode.insertBefore( clonedPage, ( previousPage || page ).nextSibling ); + pages.push( clonedPage ); previousFragmentStep = fragments; - previousPage = clonedPage; }, this ); @@ -185,6 +187,11 @@ export default class Print { }, this ); + await new Promise(requestAnimationFrame); + pages.forEach( function( page ) { + pageContainer.appendChild( page ); + }) + // Notify subscribers that the PDF layout is good to go this.Reveal.dispatchEvent({ type: 'pdf-ready' }); @@ -199,4 +206,4 @@ export default class Print { } -} \ No newline at end of file +} From 10f02ece9942d8bb067091615591b1c1d2d2f515 Mon Sep 17 00:00:00 2001 From: Jeroen Hermans Date: Mon, 16 Nov 2020 09:47:19 +0100 Subject: [PATCH 08/30] Group pdf setup reads and writes --- js/controllers/print.js | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/js/controllers/print.js b/js/controllers/print.js index 2ceda1ce..5a6bfa88 100644 --- a/js/controllers/print.js +++ b/js/controllers/print.js @@ -18,18 +18,24 @@ export default class Print { */ async setupPDF() { - let config = this.Reveal.getConfig(); + const config = this.Reveal.getConfig(); + const slides = queryAll( this.Reveal.getRevealElement(), SLIDES_SELECTOR ) - let slideSize = this.Reveal.getComputedSlideSize( window.innerWidth, window.innerHeight ); + // Compute slide numbers now, before we start duplicating slides + const doingSlideNumbers = config.slideNumber && /all|print/i.test( config.showSlideNumber ); + + const slideSize = this.Reveal.getComputedSlideSize( window.innerWidth, window.innerHeight ); // Dimensions of the PDF pages - let pageWidth = Math.floor( slideSize.width * ( 1 + config.margin ) ), + const pageWidth = Math.floor( slideSize.width * ( 1 + config.margin ) ), pageHeight = Math.floor( slideSize.height * ( 1 + config.margin ) ); // Dimensions of slides within the pages - let slideWidth = slideSize.width, + const slideWidth = slideSize.width, slideHeight = slideSize.height; + await new Promise(requestAnimationFrame); + // Let the browser know what page size we want to print createStyleSheet( '@page{size:'+ pageWidth +'px '+ pageHeight +'px; margin: 0px;}' ); @@ -41,13 +47,9 @@ export default class Print { document.body.style.height = pageHeight + 'px'; // Make sure stretch elements fit on slide + await new Promise(requestAnimationFrame); this.Reveal.layoutSlideContents( slideWidth, slideHeight ); - const slides = queryAll( this.Reveal.getRevealElement(), SLIDES_SELECTOR ) - - // Compute slide numbers now, before we start duplicating slides - let doingSlideNumbers = config.slideNumber && /all|print/i.test( config.showSlideNumber ); - // Batch scrollHeight access to prevent layout thrashing await new Promise(requestAnimationFrame); const slideScrollHeights = [] @@ -161,7 +163,7 @@ export default class Print { }, this ); // Create a separate page for the current fragment state - let clonedPage = page.cloneNode( true ); + const clonedPage = page.cloneNode( true ); pages.push( clonedPage ); previousFragmentStep = fragments; From e57ff233a4830de7729a7235b2ec120179feb581 Mon Sep 17 00:00:00 2001 From: Jeroen Hermans Date: Mon, 16 Nov 2020 09:47:58 +0100 Subject: [PATCH 09/30] Group background reads and writes --- js/controllers/backgrounds.js | 40 +++++++++++++++++------------------ 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/js/controllers/backgrounds.js b/js/controllers/backgrounds.js index e8cc9960..1327b9f8 100644 --- a/js/controllers/backgrounds.js +++ b/js/controllers/backgrounds.js @@ -27,8 +27,6 @@ export default class Backgrounds { */ create() { - let printMode = this.Reveal.isPrintingPDF(); - // Clear prior backgrounds this.element.innerHTML = ''; this.element.classList.add( 'no-transition' ); @@ -114,9 +112,24 @@ export default class Backgrounds { */ sync( slide ) { - let element = slide.slideBackgroundElement, + const element = slide.slideBackgroundElement, contentElement = slide.slideBackgroundContentElement; + const data = { + background: slide.getAttribute( 'data-background' ), + backgroundSize: slide.getAttribute( 'data-background-size' ), + backgroundImage: slide.getAttribute( 'data-background-image' ), + backgroundVideo: slide.getAttribute( 'data-background-video' ), + backgroundIframe: slide.getAttribute( 'data-background-iframe' ), + backgroundColor: slide.getAttribute( 'data-background-color' ), + backgroundRepeat: slide.getAttribute( 'data-background-repeat' ), + backgroundPosition: slide.getAttribute( 'data-background-position' ), + backgroundTransition: slide.getAttribute( 'data-background-transition' ), + backgroundOpacity: slide.getAttribute( 'data-background-opacity' ), + }; + + const dataPreload = slide.hasAttribute( 'data-preload' ); + // Reset the prior background state in case this is not the // initial sync slide.classList.remove( 'has-dark-background' ); @@ -135,19 +148,6 @@ export default class Backgrounds { contentElement.style.opacity = ''; contentElement.innerHTML = ''; - let data = { - background: slide.getAttribute( 'data-background' ), - backgroundSize: slide.getAttribute( 'data-background-size' ), - backgroundImage: slide.getAttribute( 'data-background-image' ), - backgroundVideo: slide.getAttribute( 'data-background-video' ), - backgroundIframe: slide.getAttribute( 'data-background-iframe' ), - backgroundColor: slide.getAttribute( 'data-background-color' ), - backgroundRepeat: slide.getAttribute( 'data-background-repeat' ), - backgroundPosition: slide.getAttribute( 'data-background-position' ), - backgroundTransition: slide.getAttribute( 'data-background-transition' ), - backgroundOpacity: slide.getAttribute( 'data-background-opacity' ) - }; - if( data.background ) { // Auto-wrap image urls in url(...) if( /^(http|file|\/\/)/gi.test( data.background ) || /\.(svg|png|jpg|jpeg|gif|bmp)([?#\s]|$)/gi.test( data.background ) ) { @@ -179,7 +179,7 @@ export default class Backgrounds { if( data.backgroundColor ) element.style.backgroundColor = data.backgroundColor; if( data.backgroundTransition ) element.setAttribute( 'data-background-transition', data.backgroundTransition ); - if( slide.hasAttribute( 'data-preload' ) ) element.setAttribute( 'data-preload', '' ); + if( dataPreload ) element.setAttribute( 'data-preload', '' ); // Background image options are set on the content wrapper if( data.backgroundSize ) contentElement.style.backgroundSize = data.backgroundSize; @@ -194,14 +194,14 @@ export default class Backgrounds { // If no bg color was found, check the computed background if( !contrastColor ) { - let computedBackgroundStyle = window.getComputedStyle( element ); + const computedBackgroundStyle = window.getComputedStyle( element ); if( computedBackgroundStyle && computedBackgroundStyle.backgroundColor ) { contrastColor = computedBackgroundStyle.backgroundColor; } } if( contrastColor ) { - let rgb = colorToRgb( contrastColor ); + const rgb = colorToRgb( contrastColor ); // Ignore fully transparent backgrounds. Some browsers return // rgba(0,0,0,0) when reading the computed background color of @@ -394,4 +394,4 @@ export default class Backgrounds { } -} \ No newline at end of file +} From 1e70d9fe46d1e58a8e30703ff920278e8ad44480 Mon Sep 17 00:00:00 2001 From: Hakim El Hattab Date: Wed, 25 Nov 2020 15:06:14 +0100 Subject: [PATCH 10/30] upgrade to node-sass 5.0 (adds support for node 15.x) #2841 --- dist/reveal.css | 2 +- dist/reveal.esm.js | 4 +- dist/reveal.js | 4 +- gulpfile.js | 2 + package-lock.json | 15192 +++++++++++++++++++++++----- package.json | 3 +- plugin/highlight/highlight.esm.js | 4 +- plugin/highlight/highlight.js | 4 +- plugin/markdown/markdown.esm.js | 2 +- plugin/markdown/markdown.js | 2 +- plugin/notes/notes.esm.js | 2 +- plugin/notes/notes.js | 2 +- plugin/search/search.esm.js | 2 +- plugin/search/search.js | 2 +- 14 files changed, 12794 insertions(+), 2433 deletions(-) diff --git a/dist/reveal.css b/dist/reveal.css index b09c3b69..3d598c41 100644 --- a/dist/reveal.css +++ b/dist/reveal.css @@ -1,5 +1,5 @@ /*! -* reveal.js 4.0.2 +* reveal.js 4.1.0 * https://revealjs.com * MIT licensed * diff --git a/dist/reveal.esm.js b/dist/reveal.esm.js index c6a6b95e..c6332258 100644 --- a/dist/reveal.esm.js +++ b/dist/reveal.esm.js @@ -1,9 +1,9 @@ /*! -* reveal.js 4.0.2 +* reveal.js 4.1.0 * https://revealjs.com * MIT licensed * * Copyright (C) 2020 Hakim El Hattab, https://hakim.se */ -var e="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function t(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}function i(e,t,i){return e(i={path:t,exports:{},require:function(e,t){return function(){throw new Error("Dynamic requires are not currently supported by @rollup/plugin-commonjs")}(null==t&&i.path)}},i.exports),i.exports}var n,a=function(e){return e&&e.Math==Math&&e},s=a("object"==typeof globalThis&&globalThis)||a("object"==typeof window&&window)||a("object"==typeof self&&self)||a("object"==typeof e&&e)||Function("return this")(),r={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0},o=function(e){try{return!!e()}catch(e){return!0}},l={}.toString,d=function(e){return l.call(e).slice(8,-1)},c="".split,u=o((function(){return!Object("z").propertyIsEnumerable(0)}))?function(e){return"String"==d(e)?c.call(e,""):Object(e)}:Object,h=function(e){if(null==e)throw TypeError("Can't call method on "+e);return e},g=function(e){return u(h(e))},v=!o((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]})),p=function(e){return"object"==typeof e?null!==e:"function"==typeof e},f=s.document,m=p(f)&&p(f.createElement),b=function(e){return m?f.createElement(e):{}},y=!v&&!o((function(){return 7!=Object.defineProperty(b("div"),"a",{get:function(){return 7}}).a})),w=function(e){if(!p(e))throw TypeError(String(e)+" is not an object");return e},S=function(e,t){if(!p(e))return e;var i,n;if(t&&"function"==typeof(i=e.toString)&&!p(n=i.call(e)))return n;if("function"==typeof(i=e.valueOf)&&!p(n=i.call(e)))return n;if(!t&&"function"==typeof(i=e.toString)&&!p(n=i.call(e)))return n;throw TypeError("Can't convert object to primitive value")},E=Object.defineProperty,R={f:v?E:function(e,t,i){if(w(e),t=S(t,!0),w(i),y)try{return E(e,t,i)}catch(e){}if("get"in i||"set"in i)throw TypeError("Accessors not supported");return"value"in i&&(e[t]=i.value),e}},A=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}},k=v?function(e,t,i){return R.f(e,t,A(1,i))}:function(e,t,i){return e[t]=i,e},L=function(e,t){try{k(s,e,t)}catch(i){s[e]=t}return t},x=s["__core-js_shared__"]||L("__core-js_shared__",{}),C=i((function(e){(e.exports=function(e,t){return x[e]||(x[e]=void 0!==t?t:{})})("versions",[]).push({version:"3.6.5",mode:"global",copyright:"© 2020 Denis Pushkarev (zloirock.ru)"})})),P={}.hasOwnProperty,N=function(e,t){return P.call(e,t)},M=0,I=Math.random(),T=function(e){return"Symbol("+String(void 0===e?"":e)+")_"+(++M+I).toString(36)},D=!!Object.getOwnPropertySymbols&&!o((function(){return!String(Symbol())})),O=D&&!Symbol.sham&&"symbol"==typeof Symbol.iterator,z=C("wks"),H=s.Symbol,B=O?H:H&&H.withoutSetter||T,U=function(e){return N(z,e)||(D&&N(H,e)?z[e]=H[e]:z[e]=B("Symbol."+e)),z[e]},j=Math.ceil,F=Math.floor,q=function(e){return isNaN(e=+e)?0:(e>0?F:j)(e)},W=Math.min,_=function(e){return e>0?W(q(e),9007199254740991):0},V=Math.max,K=Math.min,X=function(e){return function(t,i,n){var a,s=g(t),r=_(s.length),o=function(e,t){var i=q(e);return i<0?V(i+t,0):K(i,t)}(n,r);if(e&&i!=i){for(;r>o;)if((a=s[o++])!=a)return!0}else for(;r>o;o++)if((e||o in s)&&s[o]===i)return e||o||0;return!e&&-1}},$={includes:X(!0),indexOf:X(!1)},Y={},G=$.indexOf,J=function(e,t){var i,n=g(e),a=0,s=[];for(i in n)!N(Y,i)&&N(n,i)&&s.push(i);for(;t.length>a;)N(n,i=t[a++])&&(~G(s,i)||s.push(i));return s},Q=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"],Z=Object.keys||function(e){return J(e,Q)},ee=v?Object.defineProperties:function(e,t){w(e);for(var i,n=Z(t),a=n.length,s=0;a>s;)R.f(e,i=n[s++],t[i]);return e},te=s,ie=function(e){return"function"==typeof e?e:void 0},ne=function(e,t){return arguments.length<2?ie(te[e])||ie(s[e]):te[e]&&te[e][t]||s[e]&&s[e][t]},ae=ne("document","documentElement"),se=C("keys"),re=function(e){return se[e]||(se[e]=T(e))},oe=re("IE_PROTO"),le=function(){},de=function(e){return"