update packages and add valign
This commit is contained in:
@@ -1,333 +0,0 @@
|
||||
/**
|
||||
* The default reveal.js config object.
|
||||
*/
|
||||
export default {
|
||||
|
||||
// The "normal" size of the presentation, aspect ratio will be preserved
|
||||
// when the presentation is scaled to fit different resolutions
|
||||
width: 960,
|
||||
height: 700,
|
||||
|
||||
// Factor of the display size that should remain empty around the content
|
||||
margin: 0.04,
|
||||
|
||||
// Bounds for smallest/largest possible scale to apply to content
|
||||
minScale: 0.2,
|
||||
maxScale: 2.0,
|
||||
|
||||
// Display presentation control arrows.
|
||||
// - true: Display controls on all screens
|
||||
// - false: Hide controls on all screens
|
||||
// - "speaker-only": Only display controls in the speaker view
|
||||
controls: true,
|
||||
|
||||
// Help the user learn the controls by providing hints, for example by
|
||||
// bouncing the down arrow when they first encounter a vertical slide
|
||||
controlsTutorial: true,
|
||||
|
||||
// Determines where controls appear, "edges" or "bottom-right"
|
||||
controlsLayout: 'bottom-right',
|
||||
|
||||
// Visibility rule for backwards navigation arrows; "faded", "hidden"
|
||||
// or "visible"
|
||||
controlsBackArrows: 'faded',
|
||||
|
||||
// Display a presentation progress bar
|
||||
progress: true,
|
||||
|
||||
// Display the page number of the current slide
|
||||
// - true: Show slide number
|
||||
// - false: Hide slide number
|
||||
//
|
||||
// Can optionally be set as a string that specifies the number formatting:
|
||||
// - "h.v": Horizontal . vertical slide number (default)
|
||||
// - "h/v": Horizontal / vertical slide number
|
||||
// - "c": Flattened slide number
|
||||
// - "c/t": Flattened slide number / total slides
|
||||
//
|
||||
// Alternatively, you can provide a function that returns the slide
|
||||
// number for the current slide. The function should take in a slide
|
||||
// object and return an array with one string [slideNumber] or
|
||||
// three strings [n1,delimiter,n2]. See #formatSlideNumber().
|
||||
slideNumber: false,
|
||||
|
||||
// Can be used to limit the contexts in which the slide number appears
|
||||
// - "all": Always show the slide number
|
||||
// - "print": Only when printing to PDF
|
||||
// - "speaker": Only in the speaker view
|
||||
showSlideNumber: 'all',
|
||||
|
||||
// Use 1 based indexing for # links to match slide number (default is zero
|
||||
// based)
|
||||
hashOneBasedIndex: false,
|
||||
|
||||
// Add the current slide number to the URL hash so that reloading the
|
||||
// page/copying the URL will return you to the same slide
|
||||
hash: false,
|
||||
|
||||
// Flags if we should monitor the hash and change slides accordingly
|
||||
respondToHashChanges: true,
|
||||
|
||||
// Enable support for jump-to-slide navigation shortcuts
|
||||
jumpToSlide: true,
|
||||
|
||||
// Push each slide change to the browser history. Implies `hash: true`
|
||||
history: false,
|
||||
|
||||
// Enable keyboard shortcuts for navigation
|
||||
keyboard: true,
|
||||
|
||||
// Optional function that blocks keyboard events when returning false
|
||||
//
|
||||
// If you set this to 'focused', we will only capture keyboard events
|
||||
// for embedded decks when they are in focus
|
||||
keyboardCondition: null,
|
||||
|
||||
// Disables the default reveal.js slide layout (scaling and centering)
|
||||
// so that you can use custom CSS layout
|
||||
disableLayout: false,
|
||||
|
||||
// Enable the slide overview mode
|
||||
overview: true,
|
||||
|
||||
// Vertical centering of slides
|
||||
center: true,
|
||||
|
||||
// Enables touch navigation on devices with touch input
|
||||
touch: true,
|
||||
|
||||
// Loop the presentation
|
||||
loop: false,
|
||||
|
||||
// Change the presentation direction to be RTL
|
||||
rtl: false,
|
||||
|
||||
// Changes the behavior of our navigation directions.
|
||||
//
|
||||
// "default"
|
||||
// Left/right arrow keys step between horizontal slides, up/down
|
||||
// arrow keys step between vertical slides. Space key steps through
|
||||
// all slides (both horizontal and vertical).
|
||||
//
|
||||
// "linear"
|
||||
// Removes the up/down arrows. Left/right arrows step through all
|
||||
// slides (both horizontal and vertical).
|
||||
//
|
||||
// "grid"
|
||||
// When this is enabled, stepping left/right from a vertical stack
|
||||
// to an adjacent vertical stack will land you at the same vertical
|
||||
// index.
|
||||
//
|
||||
// Consider a deck with six slides ordered in two vertical stacks:
|
||||
// 1.1 2.1
|
||||
// 1.2 2.2
|
||||
// 1.3 2.3
|
||||
//
|
||||
// If you're on slide 1.3 and navigate right, you will normally move
|
||||
// from 1.3 -> 2.1. If "grid" is used, the same navigation takes you
|
||||
// from 1.3 -> 2.3.
|
||||
navigationMode: 'default',
|
||||
|
||||
// Randomizes the order of slides each time the presentation loads
|
||||
shuffle: false,
|
||||
|
||||
// Turns fragments on and off globally
|
||||
fragments: true,
|
||||
|
||||
// Flags whether to include the current fragment in the URL,
|
||||
// so that reloading brings you to the same fragment position
|
||||
fragmentInURL: true,
|
||||
|
||||
// Flags if the presentation is running in an embedded mode,
|
||||
// i.e. contained within a limited portion of the screen
|
||||
embedded: false,
|
||||
|
||||
// Flags if we should show a help overlay when the question-mark
|
||||
// key is pressed
|
||||
help: true,
|
||||
|
||||
// Flags if it should be possible to pause the presentation (blackout)
|
||||
pause: true,
|
||||
|
||||
// Flags if speaker notes should be visible to all viewers
|
||||
showNotes: false,
|
||||
|
||||
// Flags if slides with data-visibility="hidden" should be kep visible
|
||||
showHiddenSlides: false,
|
||||
|
||||
// Global override for autoplaying embedded media (video/audio/iframe)
|
||||
// - null: Media will only autoplay if data-autoplay is present
|
||||
// - true: All media will autoplay, regardless of individual setting
|
||||
// - false: No media will autoplay, regardless of individual setting
|
||||
autoPlayMedia: null,
|
||||
|
||||
// Global override for preloading lazy-loaded iframes
|
||||
// - null: Iframes with data-src AND data-preload will be loaded when within
|
||||
// the viewDistance, iframes with only data-src will be loaded when visible
|
||||
// - true: All iframes with data-src will be loaded when within the viewDistance
|
||||
// - false: All iframes with data-src will be loaded only when visible
|
||||
preloadIframes: null,
|
||||
|
||||
// Can be used to globally disable auto-animation
|
||||
autoAnimate: true,
|
||||
|
||||
// Optionally provide a custom element matcher that will be
|
||||
// used to dictate which elements we can animate between.
|
||||
autoAnimateMatcher: null,
|
||||
|
||||
// Default settings for our auto-animate transitions, can be
|
||||
// overridden per-slide or per-element via data arguments
|
||||
autoAnimateEasing: 'ease',
|
||||
autoAnimateDuration: 1.0,
|
||||
autoAnimateUnmatched: true,
|
||||
|
||||
// CSS properties that can be auto-animated. Position & scale
|
||||
// is matched separately so there's no need to include styles
|
||||
// like top/right/bottom/left, width/height or margin.
|
||||
autoAnimateStyles: [
|
||||
'opacity',
|
||||
'color',
|
||||
'background-color',
|
||||
'padding',
|
||||
'font-size',
|
||||
'line-height',
|
||||
'letter-spacing',
|
||||
'border-width',
|
||||
'border-color',
|
||||
'border-radius',
|
||||
'outline',
|
||||
'outline-offset'
|
||||
],
|
||||
|
||||
// Controls automatic progression to the next slide
|
||||
// - 0: Auto-sliding only happens if the data-autoslide HTML attribute
|
||||
// is present on the current slide or fragment
|
||||
// - 1+: All slides will progress automatically at the given interval
|
||||
// - false: No auto-sliding, even if data-autoslide is present
|
||||
autoSlide: 0,
|
||||
|
||||
// Stop auto-sliding after user input
|
||||
autoSlideStoppable: true,
|
||||
|
||||
// Use this method for navigation when auto-sliding (defaults to navigateNext)
|
||||
autoSlideMethod: null,
|
||||
|
||||
// Specify the average time in seconds that you think you will spend
|
||||
// presenting each slide. This is used to show a pacing timer in the
|
||||
// speaker view
|
||||
defaultTiming: null,
|
||||
|
||||
// Enable slide navigation via mouse wheel
|
||||
mouseWheel: false,
|
||||
|
||||
// Opens links in an iframe preview overlay
|
||||
// Add `data-preview-link` and `data-preview-link="false"` to customise each link
|
||||
// individually
|
||||
previewLinks: false,
|
||||
|
||||
// Exposes the reveal.js API through window.postMessage
|
||||
postMessage: true,
|
||||
|
||||
// Dispatches all reveal.js events to the parent window through postMessage
|
||||
postMessageEvents: false,
|
||||
|
||||
// Focuses body when page changes visibility to ensure keyboard shortcuts work
|
||||
focusBodyOnPageVisibilityChange: true,
|
||||
|
||||
// Transition style
|
||||
transition: 'slide', // none/fade/slide/convex/concave/zoom
|
||||
|
||||
// Transition speed
|
||||
transitionSpeed: 'default', // default/fast/slow
|
||||
|
||||
// Transition style for full page slide backgrounds
|
||||
backgroundTransition: 'fade', // none/fade/slide/convex/concave/zoom
|
||||
|
||||
// Parallax background image
|
||||
parallaxBackgroundImage: '', // CSS syntax, e.g. "a.jpg"
|
||||
|
||||
// Parallax background size
|
||||
parallaxBackgroundSize: '', // CSS syntax, e.g. "3000px 2000px"
|
||||
|
||||
// Parallax background repeat
|
||||
parallaxBackgroundRepeat: '', // repeat/repeat-x/repeat-y/no-repeat/initial/inherit
|
||||
|
||||
// Parallax background position
|
||||
parallaxBackgroundPosition: '', // CSS syntax, e.g. "top left"
|
||||
|
||||
// Amount of pixels to move the parallax background per slide step
|
||||
parallaxBackgroundHorizontal: null,
|
||||
parallaxBackgroundVertical: null,
|
||||
|
||||
// Can be used to initialize reveal.js in one of the following views:
|
||||
// - print: Render the presentation so that it can be printed to PDF
|
||||
// - scroll: Show the presentation as a tall scrollable page with scroll
|
||||
// triggered animations
|
||||
view: null,
|
||||
|
||||
// Adjusts the height of each slide in the scroll view.
|
||||
// - full: Each slide is as tall as the viewport
|
||||
// - compact: Slides are as small as possible, allowing multiple slides
|
||||
// to be visible in parallel on tall devices
|
||||
scrollLayout: 'full',
|
||||
|
||||
// Control how scroll snapping works in the scroll view.
|
||||
// - false: No snapping, scrolling is continuous
|
||||
// - proximity: Snap when close to a slide
|
||||
// - mandatory: Always snap to the closest slide
|
||||
//
|
||||
// Only applies to presentations in scroll view.
|
||||
scrollSnap: 'mandatory',
|
||||
|
||||
// Enables and configure the scroll view progress bar.
|
||||
// - 'auto': Show the scrollbar while scrolling, hide while idle
|
||||
// - true: Always show the scrollbar
|
||||
// - false: Never show the scrollbar
|
||||
scrollProgress: 'auto',
|
||||
|
||||
// Automatically activate the scroll view when we the viewport falls
|
||||
// below the given width.
|
||||
scrollActivationWidth: 435,
|
||||
|
||||
// The maximum number of pages a single slide can expand onto when printing
|
||||
// to PDF, unlimited by default
|
||||
pdfMaxPagesPerSlide: Number.POSITIVE_INFINITY,
|
||||
|
||||
// Prints each fragment on a separate slide
|
||||
pdfSeparateFragments: true,
|
||||
|
||||
// Offset used to reduce the height of content within exported PDF pages.
|
||||
// This exists to account for environment differences based on how you
|
||||
// print to PDF. CLI printing options, like phantomjs and wkpdf, can end
|
||||
// on precisely the total height of the document whereas in-browser
|
||||
// printing has to end one pixel before.
|
||||
pdfPageHeightOffset: -1,
|
||||
|
||||
// Number of slides away from the current that are visible
|
||||
viewDistance: 3,
|
||||
|
||||
// Number of slides away from the current that are visible on mobile
|
||||
// devices. It is advisable to set this to a lower number than
|
||||
// viewDistance in order to save resources.
|
||||
mobileViewDistance: 2,
|
||||
|
||||
// The display mode that will be used to show slides
|
||||
display: 'block',
|
||||
|
||||
// Hide cursor if inactive
|
||||
hideInactiveCursor: true,
|
||||
|
||||
// Time before the cursor is hidden (in ms)
|
||||
hideCursorTime: 5000,
|
||||
|
||||
// Should we automatically sort and set indices for fragments
|
||||
// at each sync? (See Reveal.sync)
|
||||
sortFragmentsOnSync: true,
|
||||
|
||||
// Script dependencies to load
|
||||
dependencies: [],
|
||||
|
||||
// Plugin objects to register and use for this presentation
|
||||
plugins: []
|
||||
|
||||
}
|
||||
973
scripts/reveal.js/js/config.ts
Normal file
973
scripts/reveal.js/js/config.ts
Normal file
@@ -0,0 +1,973 @@
|
||||
/**
|
||||
* Slide transition styles.
|
||||
*
|
||||
* @see {@link https://revealjs.com/transitions/}
|
||||
*/
|
||||
type TransitionStyle = 'none' | 'fade' | 'slide' | 'convex' | 'concave' | 'zoom';
|
||||
|
||||
/**
|
||||
* Slide transition speeds.
|
||||
*
|
||||
* @see {@link https://revealjs.com/transitions/}
|
||||
*/
|
||||
type TransitionSpeed = 'default' | 'fast' | 'slow';
|
||||
|
||||
/**
|
||||
* Fragment animation classes.
|
||||
*
|
||||
* @see {@link https://revealjs.com/fragments/}
|
||||
*/
|
||||
type FragmentAnimation =
|
||||
| 'fade-out'
|
||||
| 'fade-up'
|
||||
| 'fade-down'
|
||||
| 'fade-left'
|
||||
| 'fade-right'
|
||||
| 'fade-in-then-out'
|
||||
| 'fade-in-then-semi-out'
|
||||
| 'grow'
|
||||
| 'shrink'
|
||||
| 'strike'
|
||||
| 'highlight-red'
|
||||
| 'highlight-blue'
|
||||
| 'highlight-green'
|
||||
| 'highlight-current-red'
|
||||
| 'highlight-current-blue'
|
||||
| 'highlight-current-green'
|
||||
| (string & {});
|
||||
|
||||
/**
|
||||
* katex - Math Plugin configuration
|
||||
*
|
||||
* @see {@link https://github.com/reveal/revealjs.com/blob/master/src/math.md}
|
||||
* @see {@link https://github.com/hakimel/reveal.js/blob/master/plugin/math/katex.js}
|
||||
*/
|
||||
interface KatexConfig {
|
||||
local?: string;
|
||||
version?: string;
|
||||
delimiters?: Array<{ left: string; right: string; display: boolean }>;
|
||||
ignoredTags?: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* mathjax2 - Math Plugin configuration
|
||||
*
|
||||
* @see {@link https://github.com/reveal/revealjs.com/blob/master/src/math.md}
|
||||
* @see {@link https://github.com/hakimel/reveal.js/blob/master/plugin/math/mathjax2.js}
|
||||
*/
|
||||
interface Mathjax2Config {
|
||||
mathjax?: string;
|
||||
config?: string;
|
||||
tex2jax?: {
|
||||
inlineMath?: any;
|
||||
skipTags?: string[];
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* mathjax3 - Math Plugin configuration
|
||||
*
|
||||
* @see {@link https://github.com/reveal/revealjs.com/blob/master/src/math.md}
|
||||
* @see {@link https://github.com/hakimel/reveal.js/blob/master/plugin/math/mathjax3.js}
|
||||
*/
|
||||
interface Mathjax3Config {
|
||||
mathjax?: string;
|
||||
tex?: { inlineMath?: any };
|
||||
options?: { skipHtmlTags: string[] };
|
||||
}
|
||||
|
||||
/**
|
||||
* mathjax4 - Math Plugin configuration
|
||||
*
|
||||
* @see {@link https://github.com/reveal/revealjs.com/blob/master/src/math.md}
|
||||
* @see {@link https://github.com/hakimel/reveal.js/blob/master/plugin/math/mathjax4.js}
|
||||
*/
|
||||
interface Mathjax4Config {
|
||||
mathjax?: string;
|
||||
tex?: {
|
||||
inlineMath?: Array<[string, string]>;
|
||||
displayMath?: Array<[string, string]>;
|
||||
macros?: Record<string, string | [string, number]>;
|
||||
};
|
||||
options?: {
|
||||
skipHtmlTags?: string[];
|
||||
};
|
||||
startup?: {
|
||||
ready?: () => void;
|
||||
};
|
||||
output?: {
|
||||
font?: string;
|
||||
displayOverflow?: string;
|
||||
linebreaks?: {
|
||||
inline?: boolean;
|
||||
width?: string;
|
||||
lineleading?: number;
|
||||
LinebreakVisitor?: unknown;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Highlight Plugin configuration
|
||||
*
|
||||
* @see {@link https://github.com/hakimel/reveal.js/blob/master/plugin/highlight/plugin.js}
|
||||
*/
|
||||
interface HighlightConfig {
|
||||
highlightOnLoad?: boolean;
|
||||
escapeHTML?: boolean;
|
||||
beforeHighlight?: (...args: any) => any;
|
||||
}
|
||||
|
||||
/**
|
||||
* Markdown Plugin configuration
|
||||
*
|
||||
* @see {@link https://github.com/reveal/revealjs.com/blob/master/src/markdown.md}
|
||||
* @see {@link https://marked.js.org/using_advanced}
|
||||
*/
|
||||
interface MarkdownConfig {
|
||||
async?: boolean;
|
||||
baseUrl?: string;
|
||||
breaks?: boolean;
|
||||
gfm?: boolean;
|
||||
headerIds?: boolean;
|
||||
headerPrefix?: string;
|
||||
highlight?: (...args: any) => any;
|
||||
langPrefix?: string;
|
||||
mangle?: boolean;
|
||||
pedantic?: boolean;
|
||||
renderer?: object;
|
||||
sanitize?: boolean;
|
||||
sanitizer?: (...args: any) => any;
|
||||
silent?: boolean;
|
||||
smartLists?: boolean;
|
||||
smartypants?: boolean;
|
||||
tokenizer?: object;
|
||||
walkTokens?: (...args: any) => any;
|
||||
xhtml?: boolean;
|
||||
separator?: string;
|
||||
verticalSeparator?: string;
|
||||
notesSeparator?: string;
|
||||
attributes?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration object for reveal.js.
|
||||
*
|
||||
* @see {@link https://revealjs.com/config/}
|
||||
*/
|
||||
interface RevealConfig {
|
||||
/**
|
||||
* The "normal" size of the presentation, aspect ratio will be preserved
|
||||
* when the presentation is scaled to fit different resolutions
|
||||
*
|
||||
* @see {@link https://revealjs.com/presentation-size/}
|
||||
*
|
||||
* @defaultValue 960
|
||||
*/
|
||||
width?: number | string;
|
||||
|
||||
/**
|
||||
* The "normal" size of the presentation, aspect ratio will be preserved
|
||||
* when the presentation is scaled to fit different resolutions
|
||||
*
|
||||
* @see {@link https://revealjs.com/presentation-size/}
|
||||
*
|
||||
* @defaultValue 700
|
||||
*/
|
||||
height?: number | string;
|
||||
|
||||
/**
|
||||
* Factor of the display size that should remain empty around the content
|
||||
*
|
||||
* @see {@link https://revealjs.com/presentation-size/}
|
||||
*
|
||||
* @defaultValue 0.04
|
||||
*/
|
||||
margin?: number;
|
||||
|
||||
/**
|
||||
* The smallest possible factor to scale content down by in order to fit
|
||||
* the available viewport.
|
||||
*
|
||||
* @see {@link https://revealjs.com/presentation-size/}
|
||||
*
|
||||
* @defaultValue 0.2
|
||||
*/
|
||||
minScale?: number;
|
||||
|
||||
/**
|
||||
* The largest possible factor to scale content up by in order to cover
|
||||
* the available viewport.
|
||||
*
|
||||
* @see {@link https://revealjs.com/presentation-size/}
|
||||
*
|
||||
* @defaultValue 2.0
|
||||
*/
|
||||
maxScale?: number;
|
||||
|
||||
/**
|
||||
* Display presentation control arrows
|
||||
* - true: Display controls in all views
|
||||
* - false: Hide controls in all views
|
||||
* - 'speaker': Display controls only in the speaker view
|
||||
*
|
||||
* @defaultValue true
|
||||
*/
|
||||
controls?: boolean | 'speaker' | 'speaker-only';
|
||||
|
||||
/**
|
||||
* Help the user learn the controls by providing hints, for example by
|
||||
* bouncing the down arrow when they first encounter a vertical slide
|
||||
*
|
||||
* @defaultValue true
|
||||
*/
|
||||
controlsTutorial?: boolean;
|
||||
|
||||
/**
|
||||
* Determines where controls appear, "edges" or "bottom-right"
|
||||
*
|
||||
* @defaultValue 'bottom-right'
|
||||
*/
|
||||
controlsLayout?: 'edges' | 'bottom-right';
|
||||
|
||||
/**
|
||||
* Visibility rule for backwards navigation arrows; "faded", "hidden"
|
||||
* or "visible"
|
||||
*
|
||||
* @defaultValue 'faded'
|
||||
*/
|
||||
controlsBackArrows?: 'faded' | 'hidden' | 'visible';
|
||||
|
||||
/**
|
||||
* Display a presentation progress bar
|
||||
*
|
||||
* @defaultValue true
|
||||
*/
|
||||
progress?: boolean;
|
||||
|
||||
/**
|
||||
* Display the page number of the current slide
|
||||
* - true: Show slide number
|
||||
* - false: Hide slide number
|
||||
*
|
||||
* Can optionally be set as a string that specifies the number formatting:
|
||||
* - "h.v": Horizontal . vertical slide number (default)
|
||||
* - "h/v": Horizontal / vertical slide number
|
||||
* - "c": Flattened slide number
|
||||
* - "c/t": Flattened slide number / total slides
|
||||
*
|
||||
* Alternatively, you can provide a function that returns the slide
|
||||
* number for the current slide. The function should take in a slide
|
||||
* object and return an array with one string [slideNumber] or
|
||||
* three strings [n1,delimiter,n2]. See #formatSlideNumber().
|
||||
*
|
||||
* @defaultValue false
|
||||
*/
|
||||
slideNumber?:
|
||||
| boolean
|
||||
| 'h.v'
|
||||
| 'h/v'
|
||||
| 'c'
|
||||
| 'c/t'
|
||||
| ((slide: any) => string | [string, string, string]);
|
||||
|
||||
/**
|
||||
* Can be used to limit the contexts in which the slide number appears
|
||||
* - "all": Always show the slide number
|
||||
* - "print": Only when printing to PDF
|
||||
* - "speaker": Only in the speaker view
|
||||
*
|
||||
* @defaultValue 'all'
|
||||
*/
|
||||
showSlideNumber?: 'all' | 'print' | 'speaker';
|
||||
|
||||
/**
|
||||
* Use 1 based indexing for # links to match slide number (default is zero
|
||||
* based)
|
||||
*
|
||||
* @defaultValue false
|
||||
*/
|
||||
hashOneBasedIndex?: boolean;
|
||||
|
||||
/**
|
||||
* Add the current slide number to the URL hash so that reloading the
|
||||
* page/copying the URL will return you to the same slide
|
||||
*
|
||||
* @defaultValue false
|
||||
*/
|
||||
hash?: boolean;
|
||||
|
||||
/**
|
||||
* Flags if we should monitor the hash and change slides accordingly
|
||||
*
|
||||
* @defaultValue true
|
||||
*/
|
||||
respondToHashChanges?: boolean;
|
||||
|
||||
/**
|
||||
* Enable support for jump-to-slide navigation shortcuts
|
||||
*
|
||||
* @defaultValue true
|
||||
*/
|
||||
jumpToSlide?: boolean;
|
||||
|
||||
/**
|
||||
* Push each slide change to the browser history. Implies `hash: true`
|
||||
*
|
||||
* @defaultValue false
|
||||
*/
|
||||
history?: boolean;
|
||||
|
||||
/**
|
||||
* Enable keyboard shortcuts for navigation
|
||||
*
|
||||
* @defaultValue true
|
||||
*/
|
||||
keyboard?: boolean | { [keyCode: number]: string | ((event: KeyboardEvent) => void) };
|
||||
|
||||
/**
|
||||
* Optional function that blocks keyboard events when returning false
|
||||
*
|
||||
* If you set this to 'focused', we will only capture keyboard events
|
||||
* for embedded decks when they are in focus
|
||||
*
|
||||
* @defaultValue null
|
||||
*/
|
||||
keyboardCondition?: null | 'focused' | ((event: KeyboardEvent) => boolean);
|
||||
|
||||
/**
|
||||
* Disables the default reveal.js slide layout (scaling and centering)
|
||||
* so that you can use custom CSS layout
|
||||
*
|
||||
* @defaultValue false
|
||||
*/
|
||||
disableLayout?: boolean;
|
||||
|
||||
/**
|
||||
* Enable the slide overview mode
|
||||
*
|
||||
* @see {@link https://revealjs.com/overview/}
|
||||
*
|
||||
* @defaultValue true
|
||||
*/
|
||||
overview?: boolean;
|
||||
|
||||
/**
|
||||
* Vertical centering of slides
|
||||
*
|
||||
* @defaultValue true
|
||||
*/
|
||||
center?: boolean;
|
||||
|
||||
/**
|
||||
* Enables touch navigation on devices with touch input
|
||||
*
|
||||
* @defaultValue true
|
||||
*/
|
||||
touch?: boolean;
|
||||
|
||||
/**
|
||||
* Loop the presentation
|
||||
*
|
||||
* @defaultValue false
|
||||
*/
|
||||
loop?: boolean;
|
||||
|
||||
/**
|
||||
* Change the presentation direction to be RTL
|
||||
*
|
||||
* @defaultValue false
|
||||
*/
|
||||
rtl?: boolean;
|
||||
|
||||
/**
|
||||
* Changes the behavior of our navigation directions.
|
||||
*
|
||||
* "default"
|
||||
* Left/right arrow keys step between horizontal slides, up/down
|
||||
* arrow keys step between vertical slides. Space key steps through
|
||||
* all slides (both horizontal and vertical).
|
||||
*
|
||||
* "linear"
|
||||
* Removes the up/down arrows. Left/right arrows step through all
|
||||
* slides (both horizontal and vertical).
|
||||
*
|
||||
* "grid"
|
||||
* When this is enabled, stepping left/right from a vertical stack
|
||||
* to an adjacent vertical stack will land you at the same vertical
|
||||
* index.
|
||||
*
|
||||
* Consider a deck with six slides ordered in two vertical stacks:
|
||||
* 1.1 2.1
|
||||
* 1.2 2.2
|
||||
* 1.3 2.3
|
||||
*
|
||||
* If you're on slide 1.3 and navigate right, you will normally move
|
||||
* from 1.3 -> 2.1. If "grid" is used, the same navigation takes you
|
||||
* from 1.3 -> 2.3.
|
||||
*
|
||||
* @defaultValue 'default'
|
||||
*/
|
||||
navigationMode?: 'default' | 'linear' | 'grid';
|
||||
|
||||
/**
|
||||
* Randomizes the order of slides each time the presentation loads
|
||||
*
|
||||
* @defaultValue false
|
||||
*/
|
||||
shuffle?: boolean;
|
||||
|
||||
/**
|
||||
* Turns fragments on and off globally
|
||||
*
|
||||
* @see {@link https://revealjs.com/fragments/}
|
||||
*
|
||||
* @defaultValue true
|
||||
*/
|
||||
fragments?: boolean;
|
||||
|
||||
/**
|
||||
* Flags whether to include the current fragment in the URL,
|
||||
* so that reloading brings you to the same fragment position
|
||||
*
|
||||
* @defaultValue true
|
||||
*/
|
||||
fragmentInURL?: boolean;
|
||||
|
||||
/**
|
||||
* Flags if the presentation is running in an embedded mode,
|
||||
* i.e. contained within a limited portion of the screen
|
||||
*
|
||||
* @defaultValue false
|
||||
*/
|
||||
embedded?: boolean;
|
||||
|
||||
/**
|
||||
* Flags if we should show a help overlay when the question-mark
|
||||
* key is pressed
|
||||
*
|
||||
* @defaultValue true
|
||||
*/
|
||||
help?: boolean;
|
||||
|
||||
/**
|
||||
* Flags if it should be possible to pause the presentation (blackout)
|
||||
*
|
||||
* @defaultValue true
|
||||
*/
|
||||
pause?: boolean;
|
||||
|
||||
/**
|
||||
* Flags if speaker notes should be visible to all viewers
|
||||
*
|
||||
* @defaultValue false
|
||||
*/
|
||||
showNotes?: boolean;
|
||||
|
||||
/**
|
||||
* Flags if slides with data-visibility="hidden" should be kept visible
|
||||
*
|
||||
* @defaultValue false
|
||||
*/
|
||||
showHiddenSlides?: boolean;
|
||||
|
||||
/**
|
||||
* Global override for autoplaying embedded media (video/audio/iframe)
|
||||
* - null: Media will only autoplay if data-autoplay is present
|
||||
* - true: All media will autoplay, regardless of individual setting
|
||||
* - false: No media will autoplay, regardless of individual setting
|
||||
*
|
||||
* @defaultValue null
|
||||
*/
|
||||
autoPlayMedia?: null | boolean;
|
||||
|
||||
/**
|
||||
* Global override for preloading lazy-loaded iframes
|
||||
* - null: Iframes with data-src AND data-preload will be loaded when within
|
||||
* the viewDistance, iframes with only data-src will be loaded when visible
|
||||
* - true: All iframes with data-src will be loaded when within the viewDistance
|
||||
* - false: All iframes with data-src will be loaded only when visible
|
||||
*
|
||||
* @defaultValue null
|
||||
*/
|
||||
preloadIframes?: null | boolean;
|
||||
|
||||
/**
|
||||
* Prevent embedded iframes from automatically focusing on themselves
|
||||
*
|
||||
* @defaultValue false
|
||||
*/
|
||||
preventIframeAutoFocus?: boolean;
|
||||
|
||||
/**
|
||||
* Can be used to globally disable auto-animation
|
||||
*
|
||||
* @see {@link https://revealjs.com/auto-animate/}
|
||||
*
|
||||
* @defaultValue true
|
||||
*/
|
||||
autoAnimate?: boolean;
|
||||
|
||||
/**
|
||||
* Optionally provide a custom element matcher that will be
|
||||
* used to dictate which elements we can animate between.
|
||||
*
|
||||
* @defaultValue null
|
||||
*/
|
||||
autoAnimateMatcher?: null | Function;
|
||||
|
||||
/**
|
||||
* Default settings for our auto-animate transitions, can be
|
||||
* overridden per-slide or per-element via data arguments
|
||||
*
|
||||
* @defaultValue 'ease'
|
||||
*/
|
||||
autoAnimateEasing?: 'ease' | string;
|
||||
|
||||
/**
|
||||
* Number of seconds to animate each element.
|
||||
*
|
||||
* @defaultValue 1.0
|
||||
*/
|
||||
autoAnimateDuration?: number;
|
||||
|
||||
/**
|
||||
* Should unmatched elements be faded in?
|
||||
*
|
||||
* @defaultValue true
|
||||
*/
|
||||
autoAnimateUnmatched?: boolean;
|
||||
|
||||
/**
|
||||
* CSS properties that can be auto-animated. Position & scale
|
||||
* is matched separately so there's no need to include styles
|
||||
* like top/right/bottom/left, width/height or margin.
|
||||
*
|
||||
* @defaultValue ['opacity', 'color', 'background-color', 'padding', 'font-size', 'line-height', 'letter-spacing', 'border-width', 'border-color', 'border-radius', 'outline', 'outline-offset']
|
||||
*/
|
||||
autoAnimateStyles?: string[];
|
||||
|
||||
/**
|
||||
* Controls automatic progression to the next slide
|
||||
* - 0: Auto-sliding only happens if the data-autoslide HTML attribute
|
||||
* is present on the current slide or fragment
|
||||
* - 1+: All slides will progress automatically at the given interval
|
||||
* - false: No auto-sliding, even if data-autoslide is present
|
||||
*
|
||||
* @defaultValue 0
|
||||
*/
|
||||
autoSlide?: number | false;
|
||||
|
||||
/**
|
||||
* Stop auto-sliding after user input
|
||||
*
|
||||
* @defaultValue true
|
||||
*/
|
||||
autoSlideStoppable?: boolean;
|
||||
|
||||
/**
|
||||
* Use this method for navigation when auto-sliding (defaults to navigateNext)
|
||||
*
|
||||
* @defaultValue null
|
||||
*/
|
||||
autoSlideMethod?: null | Function;
|
||||
|
||||
/**
|
||||
* Specify the average time in seconds that you think you will spend
|
||||
* presenting each slide. This is used to show a pacing timer in the
|
||||
* speaker view
|
||||
*
|
||||
* @defaultValue null
|
||||
*/
|
||||
defaultTiming?: null;
|
||||
|
||||
/**
|
||||
* Enable slide navigation via mouse wheel
|
||||
*
|
||||
* @defaultValue false
|
||||
*/
|
||||
mouseWheel?: boolean;
|
||||
|
||||
/**
|
||||
* Opens links in an iframe preview overlay
|
||||
* Add `data-preview-link` and `data-preview-link="false"` to customize each link
|
||||
* individually
|
||||
*
|
||||
* @defaultValue false
|
||||
*/
|
||||
previewLinks?: boolean;
|
||||
|
||||
/**
|
||||
* Exposes the reveal.js API through window.postMessage
|
||||
*
|
||||
* @defaultValue true
|
||||
*/
|
||||
postMessage?: boolean;
|
||||
|
||||
/**
|
||||
* Dispatches all reveal.js events to the parent window through postMessage
|
||||
*
|
||||
* @defaultValue false
|
||||
*/
|
||||
postMessageEvents?: boolean;
|
||||
|
||||
/**
|
||||
* Focuses body when page changes visibility to ensure keyboard shortcuts work
|
||||
*
|
||||
* @defaultValue true
|
||||
*/
|
||||
focusBodyOnPageVisibilityChange?: boolean;
|
||||
|
||||
/**
|
||||
* Transition style
|
||||
*
|
||||
* @see {@link https://revealjs.com/transitions/}
|
||||
*
|
||||
* @defaultValue 'slide'
|
||||
*/
|
||||
transition?: TransitionStyle;
|
||||
|
||||
/**
|
||||
* Transition speed
|
||||
*
|
||||
* @defaultValue 'default'
|
||||
*/
|
||||
transitionSpeed?: TransitionSpeed;
|
||||
|
||||
/**
|
||||
* Transition style for full page slide backgrounds
|
||||
*
|
||||
* @defaultValue 'fade'
|
||||
*/
|
||||
backgroundTransition?: TransitionStyle;
|
||||
|
||||
/**
|
||||
* Parallax background image
|
||||
*
|
||||
* @defaultValue ''
|
||||
*/
|
||||
parallaxBackgroundImage?: null | string; // CSS syntax, e.g. "a.jpg"
|
||||
|
||||
/**
|
||||
* Parallax background size
|
||||
*
|
||||
* @defaultValue ''
|
||||
*/
|
||||
parallaxBackgroundSize?: null | string; // CSS syntax, e.g. "3000px 2000px"
|
||||
|
||||
/**
|
||||
* Parallax background repeat
|
||||
*
|
||||
* @defaultValue ''
|
||||
*/
|
||||
parallaxBackgroundRepeat?: null | string; // repeat/repeat-x/repeat-y/no-repeat/initial/inherit
|
||||
|
||||
/**
|
||||
* Parallax background position
|
||||
*
|
||||
* @defaultValue ''
|
||||
*/
|
||||
parallaxBackgroundPosition?: null | string; // CSS syntax, e.g. "top left"
|
||||
|
||||
/**
|
||||
* Amount of pixels to move the parallax background per slide step
|
||||
*
|
||||
* @defaultValue null
|
||||
*/
|
||||
parallaxBackgroundHorizontal?: null | number;
|
||||
/**
|
||||
*
|
||||
* @defaultValue null
|
||||
*/
|
||||
parallaxBackgroundVertical?: null | number;
|
||||
|
||||
/**
|
||||
* Can be used to initialize reveal.js in one of the following views:
|
||||
* - print: Render the presentation so that it can be printed to PDF
|
||||
* - scroll: Show the presentation as a tall scrollable page with scroll
|
||||
* triggered animations
|
||||
*
|
||||
* @see {@link https://revealjs.com/scroll-view/}
|
||||
*
|
||||
* @defaultValue null
|
||||
*/
|
||||
view?: null | 'print' | 'scroll';
|
||||
|
||||
/**
|
||||
* Adjusts the height of each slide in the scroll view.
|
||||
* - full: Each slide is as tall as the viewport
|
||||
* - compact: Slides are as small as possible, allowing multiple slides
|
||||
* to be visible in parallel on tall devices
|
||||
*
|
||||
* @defaultValue 'full'
|
||||
*/
|
||||
scrollLayout?: 'full' | 'compact';
|
||||
|
||||
/**
|
||||
* Control how scroll snapping works in the scroll view.
|
||||
* - false: No snapping, scrolling is continuous
|
||||
* - proximity: Snap when close to a slide
|
||||
* - mandatory: Always snap to the closest slide
|
||||
*
|
||||
* Only applies to presentations in scroll view.
|
||||
*
|
||||
* @defaultValue 'mandatory'
|
||||
*/
|
||||
scrollSnap?: false | 'proximity' | 'mandatory';
|
||||
|
||||
/**
|
||||
* Enables and configures the scroll view progress bar.
|
||||
* - 'auto': Show the scrollbar while scrolling, hide while idle
|
||||
* - true: Always show the scrollbar
|
||||
* - false: Never show the scrollbar
|
||||
*
|
||||
* @defaultValue 'auto'
|
||||
*/
|
||||
scrollProgress?: 'auto' | boolean;
|
||||
|
||||
/**
|
||||
* Automatically activate the scroll view when we the viewport falls
|
||||
* below the given width.
|
||||
*
|
||||
* @defaultValue 435
|
||||
*/
|
||||
scrollActivationWidth?: number;
|
||||
|
||||
/**
|
||||
* The maximum number of pages a single slide can expand onto when printing
|
||||
* to PDF, unlimited by default
|
||||
*
|
||||
* @defaultValue Number.POSITIVE_INFINITY
|
||||
*/
|
||||
pdfMaxPagesPerSlide?: number;
|
||||
|
||||
/**
|
||||
* Prints each fragment on a separate slide
|
||||
*
|
||||
* @defaultValue true
|
||||
*/
|
||||
pdfSeparateFragments?: boolean;
|
||||
|
||||
/**
|
||||
* Offset used to reduce the height of content within exported PDF pages.
|
||||
* This exists to account for environment differences based on how you
|
||||
* print to PDF. CLI printing options, like phantomjs and wkpdf, can end
|
||||
* on precisely the total height of the document whereas in-browser
|
||||
* printing has to end one pixel before.
|
||||
*
|
||||
* @defaultValue -1
|
||||
*/
|
||||
pdfPageHeightOffset?: number;
|
||||
|
||||
/**
|
||||
* Number of slides away from the current that are visible
|
||||
*
|
||||
* @defaultValue 3
|
||||
*/
|
||||
viewDistance?: number;
|
||||
|
||||
/**
|
||||
* Number of slides away from the current that are visible on mobile
|
||||
* devices. It is advisable to set this to a lower number than
|
||||
* viewDistance in order to save resources.
|
||||
*
|
||||
* @defaultValue 2
|
||||
*/
|
||||
mobileViewDistance?: number;
|
||||
|
||||
/**
|
||||
* The display mode that will be used to show slides
|
||||
*
|
||||
* @defaultValue 'block'
|
||||
*/
|
||||
display?: string;
|
||||
|
||||
/**
|
||||
* Hide cursor if inactive
|
||||
*
|
||||
* @defaultValue true
|
||||
*/
|
||||
hideInactiveCursor?: boolean;
|
||||
|
||||
/**
|
||||
* Time before the cursor is hidden (in ms)
|
||||
*
|
||||
* @defaultValue 5000
|
||||
*/
|
||||
hideCursorTime?: number;
|
||||
|
||||
/**
|
||||
* Should we automatically sort and set indices for fragments
|
||||
* at each sync? (See Reveal.sync)
|
||||
*
|
||||
* @defaultValue true
|
||||
*/
|
||||
sortFragmentsOnSync?: boolean;
|
||||
|
||||
/**
|
||||
* Highlight plugin configuration
|
||||
*/
|
||||
highlight?: HighlightConfig;
|
||||
|
||||
/**
|
||||
* Markdown plugin configuration
|
||||
*/
|
||||
markdown?: MarkdownConfig;
|
||||
|
||||
/**
|
||||
* KaTeX math plugin configuration
|
||||
*/
|
||||
katex?: KatexConfig;
|
||||
|
||||
/**
|
||||
* MathJax 2 plugin configuration
|
||||
*/
|
||||
mathjax2?: Mathjax2Config;
|
||||
|
||||
/**
|
||||
* MathJax 3 plugin configuration
|
||||
*/
|
||||
mathjax3?: Mathjax3Config;
|
||||
|
||||
/**
|
||||
* MathJax 4 plugin configuration
|
||||
*/
|
||||
mathjax4?: Mathjax4Config;
|
||||
|
||||
/**
|
||||
* Script dependencies to load
|
||||
*
|
||||
* @defaultValue []
|
||||
*/
|
||||
dependencies?: any[];
|
||||
|
||||
/**
|
||||
* Plugin objects to register and use for this presentation
|
||||
*
|
||||
* @defaultValue []
|
||||
*/
|
||||
plugins?: any[];
|
||||
}
|
||||
|
||||
/**
|
||||
* The default reveal.js config object.
|
||||
*/
|
||||
const defaultConfig: RevealConfig = {
|
||||
width: 960,
|
||||
height: 700,
|
||||
margin: 0.04,
|
||||
minScale: 0.2,
|
||||
maxScale: 2.0,
|
||||
|
||||
controls: true,
|
||||
controlsTutorial: true,
|
||||
controlsLayout: 'bottom-right',
|
||||
controlsBackArrows: 'faded',
|
||||
progress: true,
|
||||
|
||||
slideNumber: false,
|
||||
showSlideNumber: 'all',
|
||||
hashOneBasedIndex: false,
|
||||
hash: false,
|
||||
respondToHashChanges: true,
|
||||
jumpToSlide: true,
|
||||
history: false,
|
||||
keyboard: true,
|
||||
keyboardCondition: null,
|
||||
disableLayout: false,
|
||||
overview: true,
|
||||
center: true,
|
||||
touch: true,
|
||||
loop: false,
|
||||
rtl: false,
|
||||
navigationMode: 'default',
|
||||
shuffle: false,
|
||||
fragments: true,
|
||||
fragmentInURL: true,
|
||||
embedded: false,
|
||||
help: true,
|
||||
pause: true,
|
||||
showNotes: false,
|
||||
showHiddenSlides: false,
|
||||
autoPlayMedia: null,
|
||||
preloadIframes: null,
|
||||
mouseWheel: false,
|
||||
previewLinks: false,
|
||||
viewDistance: 3,
|
||||
mobileViewDistance: 2,
|
||||
display: 'block',
|
||||
hideInactiveCursor: true,
|
||||
hideCursorTime: 5000,
|
||||
sortFragmentsOnSync: true,
|
||||
|
||||
autoAnimate: true,
|
||||
autoAnimateMatcher: null,
|
||||
autoAnimateEasing: 'ease',
|
||||
autoAnimateDuration: 1.0,
|
||||
autoAnimateUnmatched: true,
|
||||
|
||||
autoAnimateStyles: [
|
||||
'opacity',
|
||||
'color',
|
||||
'background-color',
|
||||
'padding',
|
||||
'font-size',
|
||||
'line-height',
|
||||
'letter-spacing',
|
||||
'border-width',
|
||||
'border-color',
|
||||
'border-radius',
|
||||
'outline',
|
||||
'outline-offset',
|
||||
],
|
||||
|
||||
autoSlide: 0,
|
||||
autoSlideStoppable: true,
|
||||
autoSlideMethod: null,
|
||||
defaultTiming: null,
|
||||
|
||||
postMessage: true,
|
||||
postMessageEvents: false,
|
||||
|
||||
focusBodyOnPageVisibilityChange: true,
|
||||
|
||||
transition: 'slide',
|
||||
transitionSpeed: 'default',
|
||||
backgroundTransition: 'fade',
|
||||
|
||||
parallaxBackgroundImage: '',
|
||||
parallaxBackgroundSize: '',
|
||||
parallaxBackgroundRepeat: '',
|
||||
parallaxBackgroundPosition: '',
|
||||
parallaxBackgroundHorizontal: null,
|
||||
parallaxBackgroundVertical: null,
|
||||
|
||||
view: null,
|
||||
|
||||
scrollLayout: 'full',
|
||||
scrollSnap: 'mandatory',
|
||||
scrollProgress: 'auto',
|
||||
scrollActivationWidth: 435,
|
||||
|
||||
pdfMaxPagesPerSlide: Number.POSITIVE_INFINITY,
|
||||
pdfSeparateFragments: true,
|
||||
pdfPageHeightOffset: -1,
|
||||
|
||||
dependencies: [],
|
||||
plugins: [],
|
||||
};
|
||||
|
||||
export type {
|
||||
RevealConfig,
|
||||
TransitionStyle,
|
||||
TransitionSpeed,
|
||||
FragmentAnimation,
|
||||
KatexConfig,
|
||||
Mathjax2Config,
|
||||
Mathjax3Config,
|
||||
Mathjax4Config,
|
||||
HighlightConfig,
|
||||
MarkdownConfig,
|
||||
};
|
||||
|
||||
export { defaultConfig };
|
||||
@@ -1,5 +1,4 @@
|
||||
import { queryAll, extend, createStyleSheet, matches, closest } from '../utils/util.js'
|
||||
import { FRAGMENT_STYLE_REGEX } from '../utils/constants.js'
|
||||
import { queryAll, extend, createStyleSheet, matches, closest } from '../utils/util'
|
||||
|
||||
// Counter used to generate unique IDs for auto-animated elements
|
||||
let autoAnimateCounter = 0;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { queryAll } from '../utils/util.js'
|
||||
import { colorToRgb, colorBrightness } from '../utils/color.js'
|
||||
import { queryAll } from '../utils/util'
|
||||
import { colorToRgb, colorBrightness } from '../utils/color'
|
||||
|
||||
/**
|
||||
* Creates and updates slide backgrounds.
|
||||
|
||||
15
scripts/reveal.js/js/controllers/controls.js
vendored
15
scripts/reveal.js/js/controllers/controls.js
vendored
@@ -1,5 +1,5 @@
|
||||
import { queryAll, enterFullscreen } from '../utils/util.js'
|
||||
import { isAndroid } from '../utils/device.js'
|
||||
import { queryAll, enterFullscreen } from '../utils/util'
|
||||
import { isAndroid } from '../utils/device'
|
||||
|
||||
/**
|
||||
* Manages our presentation controls. This includes both
|
||||
@@ -66,9 +66,11 @@ export default class Controls {
|
||||
*/
|
||||
configure( config, oldConfig ) {
|
||||
|
||||
const speakerOnly = config.controls === 'speaker' || config.controls === 'speaker-only';
|
||||
|
||||
this.element.style.display = (
|
||||
config.controls &&
|
||||
(config.controls !== 'speaker-only' || this.Reveal.isSpeakerNotes())
|
||||
(!speakerOnly || this.Reveal.isSpeakerNotes())
|
||||
) ? 'block' : 'none';
|
||||
|
||||
this.element.setAttribute( 'data-controls-layout', config.controlsLayout );
|
||||
@@ -83,9 +85,10 @@ export default class Controls {
|
||||
let pointerEvents = [ 'touchstart', 'click' ];
|
||||
|
||||
// Only support touch for Android, fixes double navigations in
|
||||
// stock browser
|
||||
// stock browser. Use touchend for it to be considered a valid
|
||||
// user interaction (so we're allowed to autoplay media).
|
||||
if( isAndroid ) {
|
||||
pointerEvents = [ 'touchstart' ];
|
||||
pointerEvents = [ 'touchend' ];
|
||||
}
|
||||
|
||||
pointerEvents.forEach( eventName => {
|
||||
@@ -102,7 +105,7 @@ export default class Controls {
|
||||
|
||||
unbind() {
|
||||
|
||||
[ 'touchstart', 'click' ].forEach( eventName => {
|
||||
[ 'touchstart', 'touchend', 'click' ].forEach( eventName => {
|
||||
this.controlsLeft.forEach( el => el.removeEventListener( eventName, this.onNavigateLeftClicked, false ) );
|
||||
this.controlsRight.forEach( el => el.removeEventListener( eventName, this.onNavigateRightClicked, false ) );
|
||||
this.controlsUp.forEach( el => el.removeEventListener( eventName, this.onNavigateUpClicked, false ) );
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { closest } from '../utils/util.js'
|
||||
import { closest } from '../utils/util'
|
||||
|
||||
/**
|
||||
* Manages focus when a presentation is embedded. This
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { extend, queryAll } from '../utils/util.js'
|
||||
import { extend, queryAll } from '../utils/util'
|
||||
|
||||
/**
|
||||
* Handles sorting and navigation of slide fragments.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { enterFullscreen } from '../utils/util.js'
|
||||
import { enterFullscreen } from '../utils/util'
|
||||
|
||||
/**
|
||||
* Handles all reveal.js keyboard interactions.
|
||||
@@ -398,6 +398,12 @@ export default class Keyboard {
|
||||
|
||||
event.preventDefault && event.preventDefault();
|
||||
}
|
||||
|
||||
// Enter to exit overview mode
|
||||
else if (keyCode === 13 && this.Reveal.overview.isActive()) {
|
||||
this.Reveal.overview.deactivate();
|
||||
event.preventDefault && event.preventDefault();
|
||||
}
|
||||
|
||||
// If auto-sliding is enabled we need to cue up
|
||||
// another timeout
|
||||
|
||||
@@ -60,11 +60,13 @@ export default class Location {
|
||||
name = name.split( '/' ).shift();
|
||||
}
|
||||
|
||||
// Ensure the named link is a valid HTML ID attribute
|
||||
// Ensure the named link is a valid HTML id or data-id attribute
|
||||
try {
|
||||
slide = document
|
||||
.getElementById( decodeURIComponent( name ) )
|
||||
.closest('.slides section');
|
||||
const decodedName = decodeURIComponent( name );
|
||||
slide = (
|
||||
document.getElementById( decodedName ) ||
|
||||
document.querySelector( `[data-id="${decodedName}"]` )
|
||||
).closest('.slides section');
|
||||
}
|
||||
catch ( error ) { }
|
||||
|
||||
|
||||
@@ -72,8 +72,8 @@ export default class Overlay {
|
||||
|
||||
this.viewport.innerHTML =
|
||||
`<header class="r-overlay-header">
|
||||
<a class="r-overlay-button r-overlay-external" href="${url}" target="_blank"><span class="icon"></span></a>
|
||||
<button class="r-overlay-button r-overlay-close"><span class="icon"></span></button>
|
||||
<a class="r-overlay-header-button r-overlay-external" href="${url}" target="_blank"><span class="icon"></span></a>
|
||||
<button class="r-overlay-header-button r-overlay-close"><span class="icon"></span></button>
|
||||
</header>
|
||||
<div class="r-overlay-spinner"></div>
|
||||
<div class="r-overlay-content">
|
||||
@@ -125,7 +125,7 @@ export default class Overlay {
|
||||
|
||||
this.viewport.innerHTML =
|
||||
`<header class="r-overlay-header">
|
||||
<button class="r-overlay-button r-overlay-close">Esc <span class="icon"></span></button>
|
||||
<button class="r-overlay-header-button r-overlay-close">Esc <span class="icon"></span></button>
|
||||
</header>
|
||||
<div class="r-overlay-spinner"></div>
|
||||
<div class="r-overlay-content"></div>`;
|
||||
@@ -262,7 +262,7 @@ export default class Overlay {
|
||||
|
||||
this.viewport.innerHTML = `
|
||||
<header class="r-overlay-header">
|
||||
<button class="r-overlay-button r-overlay-close">Esc <span class="icon"></span></button>
|
||||
<button class="r-overlay-header-button r-overlay-close">Esc <span class="icon"></span></button>
|
||||
</header>
|
||||
<div class="r-overlay-content">
|
||||
<div class="r-overlay-help-content">${html}</div>
|
||||
@@ -348,7 +348,9 @@ export default class Overlay {
|
||||
// Let the browser handle meta keys naturally so users can cmd+click
|
||||
return;
|
||||
}
|
||||
let url = linkTarget.getAttribute( 'href' ) || linkTarget.getAttribute( 'data-preview-link' );
|
||||
const dataPreviewLink = linkTarget.getAttribute( 'data-preview-link' );
|
||||
const dataPreviewLinkIsUrl = typeof dataPreviewLink === 'string' && dataPreviewLink.startsWith( 'http' );
|
||||
let url = dataPreviewLinkIsUrl ? dataPreviewLink : linkTarget.getAttribute( 'href' );
|
||||
if( url ) {
|
||||
this.previewIframe( url );
|
||||
event.preventDefault();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { SLIDES_SELECTOR } from '../utils/constants.js'
|
||||
import { extend, queryAll, transformElement } from '../utils/util.js'
|
||||
import { SLIDES_SELECTOR } from '../utils/constants'
|
||||
import { extend, queryAll, transformElement } from '../utils/util'
|
||||
|
||||
/**
|
||||
* Handles all logic related to the overview mode
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { loadScript } from '../utils/loader.js'
|
||||
import { loadScript } from '../utils/loader'
|
||||
|
||||
/**
|
||||
* Manages loading and registering of reveal.js plugins.
|
||||
@@ -206,7 +206,6 @@ export default class Plugins {
|
||||
else {
|
||||
console.warn( 'reveal.js: "'+ id +'" plugin has already been registered' );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { SLIDES_SELECTOR } from '../utils/constants.js'
|
||||
import { queryAll, createStyleSheet } from '../utils/util.js'
|
||||
import { SLIDES_SELECTOR } from '../utils/constants'
|
||||
import { queryAll, createStyleSheet } from '../utils/util'
|
||||
|
||||
/**
|
||||
* Setups up our presentation for printing/exporting to PDF.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { HORIZONTAL_SLIDES_SELECTOR, HORIZONTAL_BACKGROUNDS_SELECTOR } from '../utils/constants.js'
|
||||
import { queryAll } from '../utils/util.js'
|
||||
import { HORIZONTAL_SLIDES_SELECTOR, HORIZONTAL_BACKGROUNDS_SELECTOR } from '../utils/constants'
|
||||
import { queryAll } from '../utils/util'
|
||||
|
||||
const HIDE_SCROLLBAR_TIMEOUT = 500;
|
||||
const MAX_PROGRESS_SPACING = 4;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { extend, queryAll, closest, getMimeTypeFromFile, encodeRFC3986URI } from '../utils/util.js'
|
||||
import { isMobile } from '../utils/device.js'
|
||||
import { extend, queryAll, closest, getMimeTypeFromFile, encodeRFC3986URI } from '../utils/util'
|
||||
import { isMobile } from '../utils/device'
|
||||
|
||||
import fitty from 'fitty';
|
||||
|
||||
@@ -9,11 +9,44 @@ import fitty from 'fitty';
|
||||
*/
|
||||
export default class SlideContent {
|
||||
|
||||
allowedToPlayAudio = null;
|
||||
|
||||
constructor( Reveal ) {
|
||||
|
||||
this.Reveal = Reveal;
|
||||
|
||||
this.startEmbeddedMedia = this.startEmbeddedMedia.bind( this );
|
||||
this.startEmbeddedIframe = this.startEmbeddedIframe.bind( this );
|
||||
this.preventIframeAutoFocus = this.preventIframeAutoFocus.bind( this );
|
||||
this.ensureMobileMediaPlaying = this.ensureMobileMediaPlaying.bind( this );
|
||||
|
||||
this.failedAudioPlaybackTargets = new Set();
|
||||
this.failedVideoPlaybackTargets = new Set();
|
||||
this.failedMutedVideoPlaybackTargets = new Set();
|
||||
|
||||
this.renderMediaPlayButton();
|
||||
|
||||
}
|
||||
|
||||
renderMediaPlayButton() {
|
||||
|
||||
this.mediaPlayButton = document.createElement( 'button' );
|
||||
this.mediaPlayButton.className = 'r-overlay-button r-media-play-button';
|
||||
this.mediaPlayButton.addEventListener( 'click', () => {
|
||||
this.resetTemporarilyMutedMedia();
|
||||
|
||||
const failedTargets = new Set( [
|
||||
...this.failedAudioPlaybackTargets,
|
||||
...this.failedVideoPlaybackTargets,
|
||||
...this.failedMutedVideoPlaybackTargets
|
||||
] );
|
||||
|
||||
failedTargets.forEach( target => {
|
||||
this.startEmbeddedMedia( { target: target } );
|
||||
} );
|
||||
|
||||
this.clearMediaPlaybackErrors();
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
@@ -51,14 +84,25 @@ export default class SlideContent {
|
||||
load( slide, options = {} ) {
|
||||
|
||||
// Show the slide element
|
||||
slide.style.display = this.Reveal.getConfig().display;
|
||||
const displayValue = this.Reveal.getConfig().display;
|
||||
if( displayValue.includes('!important') ) {
|
||||
const value = displayValue.replace(/\s*!important\s*$/, '').trim();
|
||||
slide.style.setProperty('display', value, 'important');
|
||||
} else {
|
||||
slide.style.display = displayValue;
|
||||
}
|
||||
|
||||
// Media elements with data-src attributes
|
||||
// Media and iframe elements with data-src attributes
|
||||
queryAll( slide, 'img[data-src], video[data-src], audio[data-src], iframe[data-src]' ).forEach( element => {
|
||||
if( element.tagName !== 'IFRAME' || this.shouldPreload( element ) ) {
|
||||
const isIframe = element.tagName === 'IFRAME';
|
||||
if( !isIframe || this.shouldPreload( element ) ) {
|
||||
element.setAttribute( 'src', element.getAttribute( 'data-src' ) );
|
||||
element.setAttribute( 'data-lazy-loaded', '' );
|
||||
element.removeAttribute( 'data-src' );
|
||||
|
||||
if( isIframe ) {
|
||||
element.addEventListener( 'load', this.preventIframeAutoFocus );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
@@ -131,12 +175,7 @@ export default class SlideContent {
|
||||
}
|
||||
|
||||
// Enable inline playback in mobile Safari
|
||||
//
|
||||
// Mute is required for video to play when using
|
||||
// swipe gestures to navigate since they don't
|
||||
// count as direct user actions :'(
|
||||
if( isMobile ) {
|
||||
video.muted = true;
|
||||
video.setAttribute( 'playsinline', '' );
|
||||
}
|
||||
|
||||
@@ -318,20 +357,9 @@ export default class SlideContent {
|
||||
// Mobile devices never fire a loaded event so instead
|
||||
// of waiting, we initiate playback
|
||||
else if( isMobile ) {
|
||||
let promise = el.play();
|
||||
el.addEventListener( 'canplay', this.ensureMobileMediaPlaying );
|
||||
|
||||
// If autoplay does not work, ensure that the controls are visible so
|
||||
// that the viewer can start the media on their own
|
||||
if( promise && typeof promise.catch === 'function' && el.controls === false ) {
|
||||
promise.catch( () => {
|
||||
el.controls = true;
|
||||
|
||||
// Once the video does start playing, hide the controls again
|
||||
el.addEventListener( 'play', () => {
|
||||
el.controls = false;
|
||||
} );
|
||||
} );
|
||||
}
|
||||
this.playMediaElement( el );
|
||||
}
|
||||
// If the media isn't loaded, wait before playing
|
||||
else {
|
||||
@@ -374,6 +402,40 @@ export default class SlideContent {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that an HTMLMediaElement is playing on mobile devices.
|
||||
*
|
||||
* This is a workaround for a bug in mobile Safari where
|
||||
* the media fails to display if many videos are started
|
||||
* at the same moment. When this happens, Mobile Safari
|
||||
* reports the video is playing, and the current time
|
||||
* advances, but nothing is visible.
|
||||
*
|
||||
* @param {Event} event
|
||||
*/
|
||||
ensureMobileMediaPlaying( event ) {
|
||||
|
||||
const el = event.target;
|
||||
|
||||
// Ignore this check incompatible browsers
|
||||
if( typeof el.getVideoPlaybackQuality !== 'function' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
setTimeout( () => {
|
||||
|
||||
const playing = el.paused === false;
|
||||
const totalFrames = el.getVideoPlaybackQuality().totalVideoFrames;
|
||||
|
||||
if( playing && totalFrames === 0 ) {
|
||||
el.load();
|
||||
el.play();
|
||||
}
|
||||
|
||||
}, 1000 );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts playing an embedded video/audio element after
|
||||
* it has finished loading.
|
||||
@@ -389,7 +451,7 @@ export default class SlideContent {
|
||||
// Don't restart if media is already playing
|
||||
if( event.target.paused || event.target.ended ) {
|
||||
event.target.currentTime = 0;
|
||||
event.target.play();
|
||||
this.playMediaElement( event.target );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,6 +459,55 @@ export default class SlideContent {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays the given HTMLMediaElement and handles any playback
|
||||
* errors, such as the browser not allowing audio to play without
|
||||
* user action.
|
||||
*
|
||||
* @param {HTMLElement} mediaElement
|
||||
*/
|
||||
playMediaElement( mediaElement ) {
|
||||
|
||||
const promise = mediaElement.play();
|
||||
|
||||
if( promise && typeof promise.catch === 'function' ) {
|
||||
promise
|
||||
.then( () => {
|
||||
if( !mediaElement.muted ) {
|
||||
this.allowedToPlayAudio = true;
|
||||
}
|
||||
} )
|
||||
.catch( ( error ) => {
|
||||
if( error.name === 'NotAllowedError' ) {
|
||||
this.allowedToPlayAudio = false;
|
||||
|
||||
// If this is a video, we record the error and try to play it
|
||||
// muted as a fallback. The user will be presented with an unmute
|
||||
// button.
|
||||
if( mediaElement.tagName === 'VIDEO' ) {
|
||||
this.onVideoPlaybackNotAllowed( mediaElement );
|
||||
|
||||
let isAttachedToDOM = !!closest( mediaElement, 'html' ),
|
||||
isVisible = !!closest( mediaElement, '.present' ),
|
||||
isMuted = mediaElement.muted;
|
||||
|
||||
if( isAttachedToDOM && isVisible && !isMuted ) {
|
||||
mediaElement.setAttribute( 'data-muted-by-reveal', 'true' );
|
||||
mediaElement.muted = true;
|
||||
mediaElement.play().catch(() => {
|
||||
this.onMutedVideoPlaybackNotAllowed( mediaElement );
|
||||
});
|
||||
}
|
||||
}
|
||||
else if( mediaElement.tagName === 'AUDIO' ) {
|
||||
this.onAudioPlaybackNotAllowed( mediaElement );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* "Starts" the content of an embedded iframe using the
|
||||
* postMessage API.
|
||||
@@ -407,6 +518,8 @@ export default class SlideContent {
|
||||
|
||||
let iframe = event.target;
|
||||
|
||||
this.preventIframeAutoFocus( event );
|
||||
|
||||
if( iframe && iframe.contentWindow ) {
|
||||
|
||||
let isAttachedToDOM = !!closest( event.target, 'html' ),
|
||||
@@ -461,12 +574,17 @@ export default class SlideContent {
|
||||
if( !el.hasAttribute( 'data-ignore' ) && typeof el.pause === 'function' ) {
|
||||
el.setAttribute('data-paused-by-reveal', '');
|
||||
el.pause();
|
||||
|
||||
if( isMobile ) {
|
||||
el.removeEventListener( 'canplay', this.ensureMobileMediaPlaying );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
// Generic postMessage API for non-lazy loaded iframes
|
||||
queryAll( element, 'iframe' ).forEach( el => {
|
||||
if( el.contentWindow ) el.contentWindow.postMessage( 'slide:stop', '*' );
|
||||
el.removeEventListener( 'load', this.preventIframeAutoFocus );
|
||||
el.removeEventListener( 'load', this.startEmbeddedIframe );
|
||||
});
|
||||
|
||||
@@ -497,4 +615,132 @@ export default class SlideContent {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether media playback is blocked by the browser. This
|
||||
* typically happens when media playback is initiated without a
|
||||
* direct user interaction.
|
||||
*/
|
||||
isAllowedToPlayAudio() {
|
||||
|
||||
return this.allowedToPlayAudio;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a manual button in situations where autoamtic media playback
|
||||
* is not allowed by the browser.
|
||||
*/
|
||||
showPlayOrUnmuteButton() {
|
||||
|
||||
const audioTargets = this.failedAudioPlaybackTargets.size;
|
||||
const videoTargets = this.failedVideoPlaybackTargets.size;
|
||||
const mutedVideoTargets = this.failedMutedVideoPlaybackTargets.size;
|
||||
|
||||
let label = 'Play media';
|
||||
|
||||
if( mutedVideoTargets > 0 ) {
|
||||
label = 'Play video';
|
||||
}
|
||||
else if( videoTargets > 0 ) {
|
||||
label = 'Unmute video';
|
||||
}
|
||||
else if( audioTargets > 0 ) {
|
||||
label = 'Play audio';
|
||||
}
|
||||
|
||||
this.mediaPlayButton.textContent = label;
|
||||
|
||||
this.Reveal.getRevealElement().appendChild( this.mediaPlayButton );
|
||||
|
||||
}
|
||||
|
||||
onAudioPlaybackNotAllowed( target ) {
|
||||
|
||||
this.failedAudioPlaybackTargets.add( target );
|
||||
this.showPlayOrUnmuteButton( target );
|
||||
|
||||
}
|
||||
|
||||
onVideoPlaybackNotAllowed( target ) {
|
||||
|
||||
this.failedVideoPlaybackTargets.add( target );
|
||||
this.showPlayOrUnmuteButton();
|
||||
|
||||
}
|
||||
|
||||
onMutedVideoPlaybackNotAllowed( target ) {
|
||||
|
||||
this.failedMutedVideoPlaybackTargets.add( target );
|
||||
this.showPlayOrUnmuteButton();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Videos may be temporarily muted by us to get around browser
|
||||
* restrictions on automatic playback. This method rolls back
|
||||
* all such temporary audio changes.
|
||||
*/
|
||||
resetTemporarilyMutedMedia() {
|
||||
|
||||
const failedTargets = new Set( [
|
||||
...this.failedAudioPlaybackTargets,
|
||||
...this.failedVideoPlaybackTargets,
|
||||
...this.failedMutedVideoPlaybackTargets
|
||||
] );
|
||||
|
||||
failedTargets.forEach( target => {
|
||||
if( target.hasAttribute( 'data-muted-by-reveal' ) ) {
|
||||
target.muted = false;
|
||||
target.removeAttribute( 'data-muted-by-reveal' );
|
||||
}
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
clearMediaPlaybackErrors() {
|
||||
|
||||
this.resetTemporarilyMutedMedia();
|
||||
|
||||
this.failedAudioPlaybackTargets.clear();
|
||||
this.failedVideoPlaybackTargets.clear();
|
||||
this.failedMutedVideoPlaybackTargets.clear();
|
||||
this.mediaPlayButton.remove();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents iframes from automatically focusing themselves.
|
||||
*
|
||||
* @param {Event} event
|
||||
*/
|
||||
preventIframeAutoFocus( event ) {
|
||||
|
||||
const iframe = event.target;
|
||||
|
||||
if( iframe && this.Reveal.getConfig().preventIframeAutoFocus ) {
|
||||
|
||||
let elapsed = 0;
|
||||
const interval = 100;
|
||||
const maxTime = 1000;
|
||||
const checkFocus = () => {
|
||||
if( document.activeElement === iframe ) {
|
||||
document.activeElement.blur();
|
||||
} else if( elapsed < maxTime ) {
|
||||
elapsed += interval;
|
||||
setTimeout( checkFocus, interval );
|
||||
}
|
||||
};
|
||||
|
||||
setTimeout( checkFocus, interval );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
afterSlideChanged() {
|
||||
|
||||
this.clearMediaPlaybackErrors();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { isAndroid } from '../utils/device.js'
|
||||
import { matches } from '../utils/util.js'
|
||||
import { isAndroid } from '../utils/device'
|
||||
import { matches } from '../utils/util'
|
||||
|
||||
const SWIPE_THRESHOLD = 40;
|
||||
|
||||
@@ -216,6 +216,14 @@ export default class Touch {
|
||||
*/
|
||||
onTouchEnd( event ) {
|
||||
|
||||
// Media playback is only allowed as a direct result of a
|
||||
// user interaction. Some mobile devices do not consider a
|
||||
// 'touchmove' to be a direct user action. If this is the
|
||||
// case, we fall back to starting playback here instead.
|
||||
if( this.touchCaptured && !this.Reveal.slideContent.isAllowedToPlayAudio() ) {
|
||||
this.Reveal.startEmbeddedContent( this.Reveal.getCurrentSlide() );
|
||||
}
|
||||
|
||||
this.touchCaptured = false;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
import Deck, { VERSION } from './reveal.js'
|
||||
|
||||
/**
|
||||
* Expose the Reveal class to the window. To create a
|
||||
* new instance:
|
||||
* let deck = new Reveal( document.querySelector( '.reveal' ), {
|
||||
* controls: false
|
||||
* } );
|
||||
* deck.initialize().then(() => {
|
||||
* // reveal.js is ready
|
||||
* });
|
||||
*/
|
||||
let Reveal = Deck;
|
||||
|
||||
|
||||
/**
|
||||
* The below is a thin shell that mimics the pre 4.0
|
||||
* reveal.js API and ensures backwards compatibility.
|
||||
* This API only allows for one Reveal instance per
|
||||
* page, whereas the new API above lets you run many
|
||||
* presentations on the same page.
|
||||
*
|
||||
* Reveal.initialize( { controls: false } ).then(() => {
|
||||
* // reveal.js is ready
|
||||
* });
|
||||
*/
|
||||
|
||||
let enqueuedAPICalls = [];
|
||||
|
||||
Reveal.initialize = options => {
|
||||
|
||||
// Create our singleton reveal.js instance
|
||||
Object.assign( Reveal, new Deck( document.querySelector( '.reveal' ), options ) );
|
||||
|
||||
// Invoke any enqueued API calls
|
||||
enqueuedAPICalls.map( method => method( Reveal ) );
|
||||
|
||||
return Reveal.initialize();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The pre 4.0 API let you add event listener before
|
||||
* initializing. We maintain the same behavior by
|
||||
* queuing up premature API calls and invoking all
|
||||
* of them when Reveal.initialize is called.
|
||||
*/
|
||||
[ 'configure', 'on', 'off', 'addEventListener', 'removeEventListener', 'registerPlugin' ].forEach( method => {
|
||||
Reveal[method] = ( ...args ) => {
|
||||
enqueuedAPICalls.push( deck => deck[method].call( null, ...args ) );
|
||||
}
|
||||
} );
|
||||
|
||||
Reveal.isReady = () => false;
|
||||
|
||||
Reveal.VERSION = VERSION;
|
||||
|
||||
export default Reveal;
|
||||
74
scripts/reveal.js/js/index.ts
Normal file
74
scripts/reveal.js/js/index.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
/// <reference path="./reveal.d.ts" />
|
||||
|
||||
import { RevealConfig } from './config.ts';
|
||||
import type { RevealApi } from './reveal';
|
||||
|
||||
// @ts-ignore
|
||||
import Deck, { VERSION } from './reveal.js';
|
||||
|
||||
/**
|
||||
* Expose the Reveal class to the window. To create a
|
||||
* new instance:
|
||||
* let deck = new Reveal( document.querySelector( '.reveal' ), {
|
||||
* controls: false
|
||||
* } );
|
||||
* deck.initialize().then(() => {
|
||||
* // reveal.js is ready
|
||||
* });
|
||||
*/
|
||||
const Reveal: {
|
||||
initialize: (options?: RevealConfig) => Promise<RevealApi>;
|
||||
[key: string]: any;
|
||||
} = Deck;
|
||||
|
||||
/**
|
||||
* The below is a thin shell that mimics the pre 4.0
|
||||
* reveal.js API and ensures backwards compatibility.
|
||||
* This API only allows for one Reveal instance per
|
||||
* page, whereas the new API above lets you run many
|
||||
* presentations on the same page.
|
||||
*
|
||||
* Reveal.initialize( { controls: false } ).then(() => {
|
||||
* // reveal.js is ready
|
||||
* });
|
||||
*/
|
||||
|
||||
type RevealApiFunction = (deck: RevealApi) => any;
|
||||
|
||||
const enqueuedAPICalls: RevealApiFunction[] = [];
|
||||
|
||||
Reveal.initialize = (options?: RevealConfig) => {
|
||||
const revealElement = document.querySelector('.reveal');
|
||||
|
||||
if (!(revealElement instanceof HTMLElement)) {
|
||||
throw new Error('Unable to find presentation root (<div class="reveal">).');
|
||||
}
|
||||
|
||||
// Create our singleton reveal.js instance
|
||||
Object.assign(Reveal, new Deck(revealElement, options));
|
||||
|
||||
// Invoke any enqueued API calls
|
||||
enqueuedAPICalls.map((method) => method(Reveal as RevealApi));
|
||||
|
||||
return Reveal.initialize();
|
||||
};
|
||||
|
||||
/**
|
||||
* The pre 4.0 API let you add event listener before
|
||||
* initializing. We maintain the same behavior by
|
||||
* queuing up premature API calls and invoking all
|
||||
* of them when Reveal.initialize is called.
|
||||
*/
|
||||
(
|
||||
['configure', 'on', 'off', 'addEventListener', 'removeEventListener', 'registerPlugin'] as const
|
||||
).forEach((method) => {
|
||||
Reveal[method] = (...args: any) => {
|
||||
enqueuedAPICalls.push((deck) => (deck[method] as any).call(null, ...args));
|
||||
};
|
||||
});
|
||||
|
||||
Reveal.isReady = () => false;
|
||||
|
||||
Reveal.VERSION = VERSION;
|
||||
|
||||
export default Reveal;
|
||||
876
scripts/reveal.js/js/reveal.d.ts
vendored
Normal file
876
scripts/reveal.js/js/reveal.d.ts
vendored
Normal file
@@ -0,0 +1,876 @@
|
||||
import type {
|
||||
RevealConfig,
|
||||
TransitionStyle,
|
||||
TransitionSpeed,
|
||||
FragmentAnimation,
|
||||
KatexConfig,
|
||||
Mathjax2Config,
|
||||
Mathjax3Config,
|
||||
Mathjax4Config,
|
||||
HighlightConfig,
|
||||
MarkdownConfig,
|
||||
} from './config';
|
||||
|
||||
export type {
|
||||
RevealConfig,
|
||||
TransitionStyle,
|
||||
TransitionSpeed,
|
||||
FragmentAnimation,
|
||||
KatexConfig,
|
||||
Mathjax2Config,
|
||||
Mathjax3Config,
|
||||
Mathjax4Config,
|
||||
HighlightConfig,
|
||||
MarkdownConfig,
|
||||
} from './config';
|
||||
|
||||
export default Reveal;
|
||||
|
||||
// The type definitions in this file are adapted from those
|
||||
// originally created by the community on DefinitelyTyped:
|
||||
// https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/reveal.js
|
||||
|
||||
/**
|
||||
* reveal.js - MIT licensed
|
||||
*
|
||||
* Copyright (C) 2011-2026 Hakim El Hattab, https://hakim.se
|
||||
*
|
||||
* @see {@link https://revealjs.com}
|
||||
* @see {@link https://github.com/hakimel/reveal.js/blob/master/js/reveal.js}
|
||||
* @see {@link https://revealjs.com/api/}
|
||||
*/
|
||||
declare const Reveal: {
|
||||
new (options?: RevealConfig): RevealApi;
|
||||
new (revealElement: HTMLElement, options?: RevealConfig): RevealApi;
|
||||
} & RevealApi;
|
||||
|
||||
/**
|
||||
* The public reveal.js API
|
||||
*
|
||||
* @see {@link https://github.com/hakimel/reveal.js/blob/master/js/reveal.js}
|
||||
*/
|
||||
export interface RevealApi {
|
||||
/**
|
||||
* The reveal.js version
|
||||
*
|
||||
* @returns reveal.js version
|
||||
*/
|
||||
VERSION: string;
|
||||
|
||||
/**
|
||||
* Starts up the presentation.
|
||||
*
|
||||
* @param options - RevealOption see {@link Options}
|
||||
* @returns a promise
|
||||
*/
|
||||
initialize(options?: RevealConfig): Promise<RevealApi>;
|
||||
|
||||
/**
|
||||
* Applies the configuration settings from the config
|
||||
* object. May be called multiple times.
|
||||
*
|
||||
* @param options - RevealOption see {@link RevealConfig}
|
||||
*/
|
||||
configure(options?: RevealConfig): void;
|
||||
|
||||
/**
|
||||
* Uninitializes reveal.js by undoing changes made to the
|
||||
* DOM and removing all event listeners.
|
||||
*/
|
||||
destroy(): void;
|
||||
|
||||
/**
|
||||
* Syncs the presentation with the current DOM. Useful
|
||||
* when new slides or control elements are added or when
|
||||
* the configuration has changed.
|
||||
*/
|
||||
sync(): void;
|
||||
|
||||
/**
|
||||
* Updates reveal.js to keep in sync with new slide attributes. For
|
||||
* example, if you add a new `data-background-image` you can call
|
||||
* this to have reveal.js render the new background image.
|
||||
*
|
||||
* Similar to #sync() but more efficient when you only need to
|
||||
* refresh a specific slide. Dispatches a `slidesync` event
|
||||
* when syncing has completed.
|
||||
*
|
||||
* @param slide
|
||||
* @see {@link sync}
|
||||
*/
|
||||
syncSlide(slide: HTMLElement): void;
|
||||
|
||||
/**
|
||||
* Formats the fragments on the given slide so that they have
|
||||
* valid indices. Call this if fragments are changed in the DOM
|
||||
* after reveal.js has already initialized.
|
||||
*
|
||||
* @param slide
|
||||
* @returns a list of the HTML fragments that were synced
|
||||
*/
|
||||
syncFragments(slide: HTMLElement): HTMLElement[];
|
||||
|
||||
/**
|
||||
* Removes hidden slides (data-visibility="hidden") from the DOM.
|
||||
* This happens automatically when reveal.js initialized, so only
|
||||
* call this to remove hidden slides before initialization.
|
||||
*/
|
||||
removeHiddenSlides(): void;
|
||||
|
||||
/**
|
||||
* Steps from the current point in the presentation to the
|
||||
* slide which matches the specified horizontal and vertical
|
||||
* indices.
|
||||
*
|
||||
* @param horizontalIndex - Horizontal index of the target slide
|
||||
* @param verticalIndex - Vertical index of the target slide
|
||||
* @param fragmentIndex - Index of a fragment within the target slide to activate
|
||||
* @param origin - Origin for use in multimaster environments
|
||||
*/
|
||||
slide(
|
||||
horizontalIndex?: number,
|
||||
verticalIndex?: number,
|
||||
fragmentIndex?: number,
|
||||
origin?: number
|
||||
): void;
|
||||
|
||||
/**
|
||||
* Navigate one step to the left
|
||||
*
|
||||
* @param params see {@link NavigateParams}
|
||||
*/
|
||||
left: NavigationFunction;
|
||||
|
||||
/**
|
||||
* Navigate one step to the right
|
||||
*
|
||||
* @param params see {@link NavigateParams}
|
||||
*/
|
||||
right: NavigationFunction;
|
||||
|
||||
/**
|
||||
* Navigate one step up
|
||||
*
|
||||
* @param params see {@link NavigateParams}
|
||||
*/
|
||||
up: NavigationFunction;
|
||||
|
||||
/**
|
||||
* Navigate one step down
|
||||
*
|
||||
* @param params see {@link NavigateParams}
|
||||
*/
|
||||
down: NavigationFunction;
|
||||
|
||||
/**
|
||||
* Navigates backwards, prioritized in the following order:
|
||||
* 1) Previous fragment
|
||||
* 2) Previous vertical slide
|
||||
* 3) Previous horizontal slide
|
||||
*
|
||||
* @param params see {@link NavigateParams}
|
||||
*/
|
||||
prev: NavigationFunction;
|
||||
|
||||
/**
|
||||
* Navigates forwards, prioritized in the following order:
|
||||
* 1) Next fragment
|
||||
* 2) Next vertical slide
|
||||
* 3) Next horizontal slide
|
||||
*
|
||||
* @param params see {@link NavigateParams}
|
||||
*/
|
||||
next: NavigationFunction;
|
||||
|
||||
// Navigation aliases
|
||||
|
||||
/**
|
||||
* Alias for `left` see {@link left}
|
||||
*/
|
||||
navigateLeft: NavigationFunction;
|
||||
|
||||
/**
|
||||
* Alias for `right` see {@link right}
|
||||
*/
|
||||
navigateRight: NavigationFunction;
|
||||
|
||||
/**
|
||||
* Alias for `up` see {@link up}
|
||||
*/
|
||||
navigateUp: NavigationFunction;
|
||||
|
||||
/**
|
||||
* Alias for `down` see {@link down}
|
||||
*/
|
||||
navigateDown: NavigationFunction;
|
||||
|
||||
/**
|
||||
* Alias for `prev` see {@link prev}
|
||||
*/
|
||||
navigatePrev: NavigationFunction;
|
||||
|
||||
/**
|
||||
* Alias for `next` see {@link next}
|
||||
*/
|
||||
navigateNext: NavigationFunction;
|
||||
|
||||
/**
|
||||
* Navigate to the specified slide fragment.
|
||||
*
|
||||
* @param index - The index of the fragment that
|
||||
* should be shown, -1 means all are invisible
|
||||
* @param offset - Integer offset to apply to the
|
||||
* fragment index
|
||||
*
|
||||
* @returns true if a change was made in any
|
||||
* fragments visibility as part of this call
|
||||
*/
|
||||
navigateFragment(index?: number, offset?: number): boolean;
|
||||
|
||||
/**
|
||||
* Navigate to the previous slide fragment.
|
||||
*
|
||||
* @returns true if there was a previous fragment,
|
||||
* false otherwise
|
||||
*/
|
||||
prevFragment(): boolean;
|
||||
|
||||
/**
|
||||
* Navigate to the next slide fragment.
|
||||
*
|
||||
* @returns true if there was a next fragment,
|
||||
* false otherwise
|
||||
*/
|
||||
nextFragment(): boolean;
|
||||
|
||||
/**
|
||||
* Adds a listener to one of our custom reveal.js events,
|
||||
* like slidechanged and slidesync.
|
||||
*
|
||||
* @param type
|
||||
* @param listener
|
||||
* @param useCapture
|
||||
*/
|
||||
on: HTMLElement['addEventListener'];
|
||||
|
||||
/**
|
||||
* Unsubscribes from a reveal.js event.
|
||||
*
|
||||
* @param type
|
||||
* @param listener
|
||||
* @param useCapture
|
||||
*/
|
||||
off: HTMLElement['removeEventListener'];
|
||||
|
||||
/**
|
||||
* Legacy event binding methods left in for backwards compatibility
|
||||
* Adds a listener to one of our custom reveal.js events,
|
||||
* like slidechanged and slidesync.
|
||||
* See: {@link on}
|
||||
*
|
||||
* @param type
|
||||
* @param listener
|
||||
* @param useCapture
|
||||
*/
|
||||
addEventListener: HTMLElement['addEventListener'];
|
||||
|
||||
/**
|
||||
* Legacy event binding methods left in for backwards compatibility
|
||||
* Unsubscribes from a reveal.js event.
|
||||
* See: {@link off}
|
||||
*
|
||||
* @param type
|
||||
* @param listener
|
||||
* @param useCapture
|
||||
*/
|
||||
removeEventListener: HTMLElement['removeEventListener'];
|
||||
|
||||
/**
|
||||
* Applies JavaScript-controlled layout rules to the
|
||||
* presentation.
|
||||
*/
|
||||
layout(): void;
|
||||
|
||||
/**
|
||||
* Randomly shuffles all slides in the deck.
|
||||
*/
|
||||
shuffle(slides?: HTMLElement[]): void;
|
||||
|
||||
/**
|
||||
* Determine what available routes there are for navigation.
|
||||
*
|
||||
* @param params - If includeFragments is set, a route will be considered
|
||||
* available if either a slide OR a fragment is available in the given direction
|
||||
*
|
||||
* @returns Available route {left, right, up, down}
|
||||
*/
|
||||
availableRoutes(params?: { includeFragments?: boolean }): {
|
||||
down: boolean;
|
||||
left: boolean;
|
||||
right: boolean;
|
||||
up: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns an object describing the available fragment
|
||||
* directions.
|
||||
*
|
||||
* @returns Available fragments {prev, next}
|
||||
*/
|
||||
availableFragments(): { prev: boolean; next: boolean };
|
||||
|
||||
/**
|
||||
* Open or close help overlay window.
|
||||
*
|
||||
* @param override - Flag which overrides the
|
||||
* toggle logic and forcibly sets the desired state. True means
|
||||
* help is open, false means it's closed.
|
||||
*/
|
||||
toggleHelp(override?: boolean): void;
|
||||
|
||||
/**
|
||||
* Toggles the slide overview mode on and off.
|
||||
*
|
||||
* @param override - Flag which overrides the
|
||||
* toggle logic and forcibly sets the desired state. True means
|
||||
* overview is open, false means it's closed.
|
||||
*/
|
||||
toggleOverview(override?: boolean): void;
|
||||
|
||||
/**
|
||||
* Toggles the paused mode on and off.
|
||||
*
|
||||
* @param override - Flag which overrides the
|
||||
* toggle logic and forcibly sets the desired state.
|
||||
*/
|
||||
togglePause(override?: boolean): void;
|
||||
|
||||
/**
|
||||
* Toggles the auto slide mode on and off.
|
||||
*
|
||||
* @param override - Flag which sets the desired state.
|
||||
* True means autoplay starts, false means it stops.
|
||||
*/
|
||||
toggleAutoSlide(override?: boolean): void;
|
||||
|
||||
/**
|
||||
* @returns true if we're currently on the first slide in
|
||||
* the presentation.
|
||||
*/
|
||||
isFirstSlide(): boolean;
|
||||
|
||||
/**
|
||||
* @returns Returns true if we're currently on the last slide in
|
||||
* the presentation. If the last slide is a stack, we only
|
||||
* consider this the last slide if it's at the end of the
|
||||
* stack.
|
||||
*/
|
||||
isLastSlide(): boolean;
|
||||
|
||||
/**
|
||||
* @returns true if we're on the last slide in the current
|
||||
* vertical stack.
|
||||
*/
|
||||
isLastVerticalSlide(): boolean;
|
||||
|
||||
/**
|
||||
* Checks if the current or specified slide is vertical
|
||||
* (nested within another slide).
|
||||
*
|
||||
* @param slide - the slide to check orientation of. Defaults to the current slide.
|
||||
* @return true if the current or specified slide is vertical
|
||||
*/
|
||||
isVerticalSlide(slide?: HTMLElement): boolean;
|
||||
|
||||
/**
|
||||
* @returns true if we are currently in the paused mode.
|
||||
*/
|
||||
isPaused(): boolean;
|
||||
|
||||
/**
|
||||
* @returns true if the auto slide mode is currently on.
|
||||
*/
|
||||
isAutoSliding(): boolean;
|
||||
|
||||
/**
|
||||
* @returns true if this presentation is running inside of
|
||||
* the speaker notes window.
|
||||
*/
|
||||
isSpeakerNotes(): boolean;
|
||||
|
||||
/**
|
||||
* @returns true if the overview is active, false otherwise
|
||||
*/
|
||||
isOverview(): boolean;
|
||||
|
||||
/**
|
||||
* Checks if the presentation is focused
|
||||
*
|
||||
* @returns true if the it is focused, false otherwise
|
||||
*/
|
||||
isFocused(): boolean;
|
||||
|
||||
/**
|
||||
* Checks if this reveal.js instance is being used to print a PDF.
|
||||
*
|
||||
* @returns true if being used to print a PDF, false otherwise
|
||||
*/
|
||||
isPrintingPDF(): boolean;
|
||||
|
||||
/**
|
||||
* Checks if reveal.js has been loaded and is ready for use
|
||||
*
|
||||
* @returns true if reveal.js is ready for use, false otherwise
|
||||
*/
|
||||
isReady(): boolean;
|
||||
|
||||
/**
|
||||
* Called when the given slide is within the configured view
|
||||
* distance. Shows the slide element and loads any content
|
||||
* that is set to load lazily (data-src).
|
||||
*
|
||||
* @param slide - Slide to show
|
||||
*/
|
||||
loadSlide(slide: HTMLElement, options?: { excludeIframes?: boolean }): void;
|
||||
|
||||
/**
|
||||
* Unloads and hides the given slide. This is called when the
|
||||
* slide is moved outside of the configured view distance.
|
||||
*
|
||||
* @param slide
|
||||
*/
|
||||
unloadSlide(slide: HTMLElement): void;
|
||||
|
||||
/**
|
||||
* Opens a preview window for the target URL.
|
||||
*
|
||||
* @param url - url for preview iframe src
|
||||
*/
|
||||
showPreview(url: string): void;
|
||||
|
||||
/**
|
||||
* Closes any currently open overlay.
|
||||
*/
|
||||
hidePreview(): void;
|
||||
|
||||
/**
|
||||
* Binds all internal event listeners.
|
||||
*/
|
||||
addEventListeners(): void;
|
||||
|
||||
/**
|
||||
* Unbinds all internal event listeners.
|
||||
*/
|
||||
removeEventListeners(): void;
|
||||
|
||||
/**
|
||||
* Dispatches an event of the specified type from the
|
||||
* reveal DOM element.
|
||||
*/
|
||||
dispatchEvent({
|
||||
target,
|
||||
type,
|
||||
data,
|
||||
bubbles,
|
||||
}: {
|
||||
/** `revealElement` by default */
|
||||
target?: HTMLElement;
|
||||
type: string;
|
||||
data?: unknown;
|
||||
bubbles?: boolean;
|
||||
}): Event;
|
||||
|
||||
/**
|
||||
* Retrieves the current state of the presentation as
|
||||
* an object. This state can then be restored at any
|
||||
* time.
|
||||
*
|
||||
* @returns The current state - {indexh, indexv, indexf, paused, overview}
|
||||
*/
|
||||
getState(): RevealState;
|
||||
|
||||
/**
|
||||
* Restores the presentation to the given state.
|
||||
*
|
||||
* @param object - state as generated by getState()
|
||||
* @see {@link getState} generates the parameter `state`
|
||||
*/
|
||||
setState(object: RevealState): void;
|
||||
|
||||
/**
|
||||
* Returns a value ranging from 0-1 that represents
|
||||
* how far into the presentation we have navigated.
|
||||
*
|
||||
* @returns a value ranging from 0-1 that represents
|
||||
* how far into the presentation we have navigated.
|
||||
*/
|
||||
getProgress(): number;
|
||||
|
||||
/**
|
||||
* Retrieves the h/v location and fragment of the current,
|
||||
* or specified, slide.
|
||||
*
|
||||
* @param slide - if specified, the returned index will
|
||||
* be for this slide rather than the currently active one
|
||||
*
|
||||
* @return h/v location and fragment of the current,
|
||||
* or specified, slide. {h, v, f}
|
||||
*/
|
||||
getIndices(slide?: HTMLElement): { h: number; v: number; f: number };
|
||||
|
||||
/**
|
||||
* Returns an array of objects where each object represents the
|
||||
* attributes on its respective slide.
|
||||
*
|
||||
* @returns an array of objects where each object represents the
|
||||
* attributes on its respective slide.
|
||||
*/
|
||||
getSlidesAttributes(): Record<string, string>[];
|
||||
|
||||
/**
|
||||
* Returns the number of past slides. This can be used as a global
|
||||
* flattened index for slides.
|
||||
*
|
||||
* @param [slide] - The slide we're counting before, defaults to current slide
|
||||
*
|
||||
* @returns Past slide count
|
||||
*/
|
||||
getSlidePastCount(slide?: HTMLElement): number;
|
||||
|
||||
/**
|
||||
* Retrieves the total number of slides in this presentation.
|
||||
*
|
||||
* @returns the total number of slides in this presentation.
|
||||
*/
|
||||
getTotalSlides(): number;
|
||||
|
||||
/**
|
||||
* Returns the slide element matching the specified index.
|
||||
*
|
||||
* @param x - slide index
|
||||
* @param [y] - slide index
|
||||
*
|
||||
* @returns the slide element matching the specified index
|
||||
*/
|
||||
getSlide(x: number, y?: number): HTMLElement | undefined;
|
||||
|
||||
/**
|
||||
* Returns the previous slide element, may be null
|
||||
*
|
||||
* @returns the previous slide element, may be null
|
||||
*/
|
||||
getPreviousSlide(): HTMLElement | null;
|
||||
|
||||
/**
|
||||
* Returns the current slide element
|
||||
*
|
||||
* @returns the current slide element
|
||||
*/
|
||||
getCurrentSlide(): HTMLElement;
|
||||
|
||||
/**
|
||||
* Returns the background element for the given slide.
|
||||
* All slides, even the ones with no background properties
|
||||
* defined, have a background element so as long as the
|
||||
* index is valid an element will be returned.
|
||||
*
|
||||
* @param element A slide
|
||||
* @returns the background element for the given slide
|
||||
*/
|
||||
getSlideBackground(element: HTMLElement): HTMLElement | undefined;
|
||||
|
||||
/**
|
||||
* Returns the background element for the given slide.
|
||||
* All slides, even the ones with no background properties
|
||||
* defined, have a background element so as long as the
|
||||
* index is valid an element will be returned.
|
||||
*
|
||||
* @param x - Horizontal background index OR a slide
|
||||
* HTML element
|
||||
* @param [y] - Vertical background index
|
||||
* @returns the background element for the given slide
|
||||
*/
|
||||
getSlideBackground(x: number, y?: number): HTMLElement | undefined;
|
||||
|
||||
/**
|
||||
* Retrieves the speaker notes from a slide. Notes can be
|
||||
* defined in two ways:
|
||||
* 1. As a data-notes attribute on the slide <section>
|
||||
* 2. As an <aside class="notes"> inside of the slide
|
||||
*
|
||||
* @param [slide] - defaults to current slide
|
||||
* @returns the speaker notes from a slide
|
||||
*/
|
||||
getSlideNotes(slide?: HTMLElement): string | null;
|
||||
|
||||
/**
|
||||
* Retrieves all slides in this presentation.
|
||||
*
|
||||
* @returns all slides in this presentation
|
||||
*/
|
||||
getSlides(): HTMLElement[];
|
||||
|
||||
/**
|
||||
* Returns a list of all horizontal slides in the deck. Each
|
||||
* vertical stack is included as one horizontal slide in the
|
||||
* resulting array.
|
||||
*
|
||||
* @returns a list of all horizontal slides in the deck
|
||||
*/
|
||||
getHorizontalSlides(): HTMLElement[];
|
||||
|
||||
/**
|
||||
* Returns all vertical slides that exist within this deck.
|
||||
*
|
||||
* @returns all vertical slides that exist within this deck
|
||||
*/
|
||||
getVerticalSlides(): HTMLElement[];
|
||||
|
||||
/**
|
||||
* Returns true if there are at least two horizontal slides.
|
||||
*
|
||||
* @returns true if there are at least two horizontal slides
|
||||
*/
|
||||
hasHorizontalSlides(): boolean;
|
||||
|
||||
/**
|
||||
* Returns true if there are at least two vertical slides.
|
||||
*
|
||||
* @returns true if there are at least two vertical slides
|
||||
*/
|
||||
hasVerticalSlides(): boolean;
|
||||
|
||||
/**
|
||||
* Checks if the deck has navigated on either axis at least once
|
||||
*
|
||||
* @returns true if the deck has navigated on either horizontal axis
|
||||
* at least once
|
||||
*/
|
||||
hasNavigatedHorizontally(): boolean;
|
||||
|
||||
/**
|
||||
* Checks if the deck has navigated on either axis at least once
|
||||
*
|
||||
* @returns true if the deck has navigated on either vertically axis
|
||||
* at least once
|
||||
*/
|
||||
hasNavigatedVertically(): boolean;
|
||||
|
||||
/**
|
||||
* Add a custom key binding with optional description to
|
||||
* be added to the help screen.
|
||||
*
|
||||
* @param binding
|
||||
* @param callback
|
||||
*/
|
||||
addKeyBinding(
|
||||
keyCode: number | { keyCode: number; key: string; description: string },
|
||||
callback: string | ((event: KeyboardEvent) => void)
|
||||
): void;
|
||||
|
||||
/**
|
||||
* Removes the specified custom key binding.
|
||||
*
|
||||
* @param keyCode
|
||||
*/
|
||||
removeKeyBinding(keyCode: number): void;
|
||||
|
||||
/**
|
||||
* Programmatically triggers a keyboard event
|
||||
*
|
||||
* @param keyCode
|
||||
*/
|
||||
triggerKey(keyCode: number): void;
|
||||
|
||||
/**
|
||||
* Registers a new shortcut to include in the help overlay
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
registerKeyboardShortcut(key: string, value: string): void;
|
||||
|
||||
/**
|
||||
* Calculates the computed pixel size of our slides. These
|
||||
* values are based on the width and height configuration
|
||||
* options.
|
||||
*
|
||||
* @param [presentationWidth=dom.wrapper.offsetWidth]
|
||||
* @param [presentationHeight=dom.wrapper.offsetHeight]
|
||||
* @returns the computed pixel size of the slides
|
||||
*/
|
||||
getComputedSlideSize(
|
||||
presentationWidth?: number,
|
||||
presentationHeight?: number
|
||||
): ComputedSlideSize;
|
||||
|
||||
/**
|
||||
* Returns the current scale of the presentation content
|
||||
*
|
||||
* @returns the current scale of the presentation content
|
||||
*/
|
||||
getScale(): number;
|
||||
|
||||
/**
|
||||
* Returns the current configuration object
|
||||
*
|
||||
* @returns the current configuration object
|
||||
*/
|
||||
getConfig(): RevealConfig;
|
||||
|
||||
/**
|
||||
* Returns a key:value hash of all query params.
|
||||
*
|
||||
* @returns a key:value hash of all query params
|
||||
*/
|
||||
getQueryHash(): Record<string, string>;
|
||||
|
||||
/**
|
||||
* Return a hash URL that will resolve to the given slide location.
|
||||
*
|
||||
* @param slide - the slide to link to
|
||||
* @returns a hash URL that will resolve to the given slide location
|
||||
*/
|
||||
getSlidePath(slide?: HTMLElement): string;
|
||||
|
||||
/**
|
||||
* @returns reveal.js DOM element
|
||||
*/
|
||||
getRevealElement(): HTMLElement | null;
|
||||
|
||||
/**
|
||||
* @returns reveal.js DOM element
|
||||
*/
|
||||
getSlidesElement(): HTMLElement | null;
|
||||
|
||||
/**
|
||||
* @returns reveal.js DOM element
|
||||
*/
|
||||
getViewportElement(): HTMLElement | null;
|
||||
|
||||
/**
|
||||
* @returns reveal.js DOM element
|
||||
*/
|
||||
getBackgroundsElement(): HTMLDivElement | undefined;
|
||||
|
||||
/**
|
||||
* Registers a new plugin with this reveal.js instance.
|
||||
*
|
||||
* reveal.js waits for all registered plugins to initialize
|
||||
* before considering itself ready, as long as the plugin
|
||||
* is registered before calling `Reveal.initialize()`.
|
||||
*
|
||||
* @param plugin
|
||||
*/
|
||||
registerPlugin(plugin: RevealPlugin): void;
|
||||
|
||||
/**
|
||||
* Checks if a specific plugin has been registered.
|
||||
*
|
||||
* @param id - unique plugin identifier
|
||||
* @returns true if a specific plugin has been registered.
|
||||
*/
|
||||
hasPlugin(id: string): boolean;
|
||||
|
||||
/**
|
||||
* Returns the specific plugin instance, if a plugin
|
||||
* with the given ID has been registered.
|
||||
*
|
||||
* @param id - unique plugin identifier
|
||||
* @returns plugin instance
|
||||
*/
|
||||
getPlugin(id: string): RevealPlugin | undefined;
|
||||
|
||||
/**
|
||||
* @returns id:plugin hash of all plugins
|
||||
*/
|
||||
getPlugins(): Record<string, RevealPlugin>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for navigation
|
||||
*/
|
||||
export interface NavigateParams {
|
||||
skipFragments?: boolean;
|
||||
}
|
||||
|
||||
export type NavigationFunction = (params?: NavigateParams) => void;
|
||||
|
||||
/**
|
||||
* Multiplex configuration
|
||||
*
|
||||
* @see {@link https://github.com/reveal/multiplex}
|
||||
*/
|
||||
export interface MultiplexConfig {
|
||||
// Obtained from the socket.io server. Gives this (the master) control of the presentation
|
||||
secret: string | null;
|
||||
// Obtained from the socket.io server
|
||||
id: string;
|
||||
// Location of socket.io server
|
||||
url: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reveal Dependency
|
||||
*
|
||||
* @see {@link https://revealjs.com/plugins/#dependencies}
|
||||
*/
|
||||
export interface RevealDependency {
|
||||
src: string;
|
||||
async?: boolean;
|
||||
callback?: () => void;
|
||||
condition?: () => boolean;
|
||||
}
|
||||
|
||||
export interface ComputedSlideSize {
|
||||
width: number;
|
||||
height: number;
|
||||
presentationWidth: number;
|
||||
presentationHeight: number;
|
||||
}
|
||||
|
||||
export interface RevealState {
|
||||
indexh: number;
|
||||
indexv: number;
|
||||
indexf: number;
|
||||
paused: boolean;
|
||||
overview: boolean;
|
||||
|
||||
/**
|
||||
* URL of an iframe being previewed
|
||||
*/
|
||||
previewIframe?: string;
|
||||
|
||||
/**
|
||||
* URL of an image being previewed
|
||||
*/
|
||||
previewImage?: string;
|
||||
|
||||
/**
|
||||
* URL of a video being previewed
|
||||
*/
|
||||
previewVideo?: string;
|
||||
|
||||
/**
|
||||
* Fit mode of the previewed media
|
||||
*/
|
||||
previewFit?: 'none' | 'scale-down' | 'contain' | 'cover';
|
||||
}
|
||||
|
||||
export interface SlideSyncEvent extends Event {
|
||||
slide: HTMLElement;
|
||||
}
|
||||
|
||||
// NOTE: it is possible to extend type definitions depend on the plugin
|
||||
/**
|
||||
* Reveal Plugin
|
||||
*
|
||||
* @see {@link https://revealjs.com/creating-plugins/}
|
||||
*/
|
||||
export interface RevealPlugin {
|
||||
id: string;
|
||||
init?(reveal: RevealApi): void | Promise<void>;
|
||||
destroy?(): void;
|
||||
}
|
||||
|
||||
export type RevealPluginFactory = () => RevealPlugin;
|
||||
@@ -1,42 +1,41 @@
|
||||
import SlideContent from './controllers/slidecontent.js'
|
||||
import SlideNumber from './controllers/slidenumber.js'
|
||||
import JumpToSlide from './controllers/jumptoslide.js'
|
||||
import Backgrounds from './controllers/backgrounds.js'
|
||||
import AutoAnimate from './controllers/autoanimate.js'
|
||||
import ScrollView from './controllers/scrollview.js'
|
||||
import PrintView from './controllers/printview.js'
|
||||
import Fragments from './controllers/fragments.js'
|
||||
import Overview from './controllers/overview.js'
|
||||
import Keyboard from './controllers/keyboard.js'
|
||||
import Location from './controllers/location.js'
|
||||
import Controls from './controllers/controls.js'
|
||||
import Progress from './controllers/progress.js'
|
||||
import Pointer from './controllers/pointer.js'
|
||||
import Plugins from './controllers/plugins.js'
|
||||
import Overlay from './controllers/overlay.js'
|
||||
import Touch from './controllers/touch.js'
|
||||
import Focus from './controllers/focus.js'
|
||||
import Notes from './controllers/notes.js'
|
||||
import Playback from './components/playback.js'
|
||||
import defaultConfig from './config.js'
|
||||
import * as Util from './utils/util.js'
|
||||
import * as Device from './utils/device.js'
|
||||
import SlideContent from './controllers/slidecontent'
|
||||
import SlideNumber from './controllers/slidenumber'
|
||||
import JumpToSlide from './controllers/jumptoslide'
|
||||
import Backgrounds from './controllers/backgrounds'
|
||||
import AutoAnimate from './controllers/autoanimate'
|
||||
import ScrollView from './controllers/scrollview'
|
||||
import PrintView from './controllers/printview'
|
||||
import Fragments from './controllers/fragments'
|
||||
import Overview from './controllers/overview'
|
||||
import Keyboard from './controllers/keyboard'
|
||||
import Location from './controllers/location'
|
||||
import Controls from './controllers/controls'
|
||||
import Progress from './controllers/progress'
|
||||
import Pointer from './controllers/pointer'
|
||||
import Plugins from './controllers/plugins'
|
||||
import Overlay from './controllers/overlay'
|
||||
import Touch from './controllers/touch'
|
||||
import Focus from './controllers/focus'
|
||||
import Notes from './controllers/notes'
|
||||
import Playback from './components/playback'
|
||||
import { defaultConfig } from './config.ts'
|
||||
import * as Util from './utils/util'
|
||||
import * as Device from './utils/device'
|
||||
import {
|
||||
SLIDES_SELECTOR,
|
||||
HORIZONTAL_SLIDES_SELECTOR,
|
||||
VERTICAL_SLIDES_SELECTOR,
|
||||
POST_MESSAGE_METHOD_BLACKLIST
|
||||
} from './utils/constants.js'
|
||||
|
||||
// The reveal.js version
|
||||
export const VERSION = '5.2.1';
|
||||
} from './utils/constants'
|
||||
import { version as VERSION } from '../package.json';
|
||||
export { VERSION };
|
||||
|
||||
/**
|
||||
* reveal.js
|
||||
* https://revealjs.com
|
||||
* MIT licensed
|
||||
*
|
||||
* Copyright (C) 2011-2022 Hakim El Hattab, https://hakim.se
|
||||
* Copyright (C) 2011-2026 Hakim El Hattab, https://hakim.se
|
||||
*/
|
||||
export default function( revealElement, options ) {
|
||||
|
||||
@@ -394,7 +393,7 @@ export default function( revealElement, options ) {
|
||||
|
||||
// Text node
|
||||
if( node.nodeType === 3 ) {
|
||||
text += node.textContent;
|
||||
text += node.textContent.trim();
|
||||
}
|
||||
// Element node
|
||||
else if( node.nodeType === 1 ) {
|
||||
@@ -403,10 +402,25 @@ export default function( revealElement, options ) {
|
||||
let isDisplayHidden = window.getComputedStyle( node )['display'] === 'none';
|
||||
if( isAriaHidden !== 'true' && !isDisplayHidden ) {
|
||||
|
||||
// Capture alt text from img and video elements
|
||||
if( node.tagName === 'IMG' || node.tagName === 'VIDEO' ) {
|
||||
let altText = node.getAttribute( 'alt' );
|
||||
if( altText ) {
|
||||
text += ensurePunctuation( altText );
|
||||
}
|
||||
}
|
||||
|
||||
Array.from( node.childNodes ).forEach( child => {
|
||||
text += getStatusText( child );
|
||||
} );
|
||||
|
||||
// Add period after block-level text elements to improve
|
||||
// screen reader experience
|
||||
const textElements = ['P', 'DIV', 'UL', 'OL', 'LI', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'BLOCKQUOTE'];
|
||||
if( textElements.includes( node.tagName ) && text.trim() !== '' ) {
|
||||
text = ensurePunctuation( text );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -417,6 +431,22 @@ export default function( revealElement, options ) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures text ends with proper punctuation by adding a period
|
||||
* if it doesn't already end with punctuation.
|
||||
*/
|
||||
function ensurePunctuation( text ) {
|
||||
|
||||
const trimmedText = text.trim();
|
||||
|
||||
if( trimmedText === '' ) {
|
||||
return text;
|
||||
}
|
||||
|
||||
return !/[.!?]$/.test(trimmedText) ? trimmedText + '.' : trimmedText;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This is an unfortunate necessity. Some actions – such as
|
||||
* an input field being focused in an iframe or using the
|
||||
@@ -1377,6 +1407,7 @@ export default function( revealElement, options ) {
|
||||
}
|
||||
|
||||
if( slideChanged ) {
|
||||
slideContent.afterSlideChanged();
|
||||
dispatchSlideChanged( origin );
|
||||
}
|
||||
|
||||
@@ -1470,6 +1501,8 @@ export default function( revealElement, options ) {
|
||||
|
||||
// Start or stop embedded content like videos and iframes
|
||||
if( slideChanged ) {
|
||||
slideContent.afterSlideChanged();
|
||||
|
||||
if( previousSlide ) {
|
||||
slideContent.stopEmbeddedContent( previousSlide );
|
||||
slideContent.stopEmbeddedContent( previousSlide.slideBackgroundElement );
|
||||
@@ -1517,6 +1550,14 @@ export default function( revealElement, options ) {
|
||||
fragments.sortAll();
|
||||
}
|
||||
|
||||
// Re-apply slide state classes for the current indices.
|
||||
// This ensures dynamically inserted/removed slides receive
|
||||
// proper past/present/future classes on sync.
|
||||
if( typeof indexh !== 'undefined' ) {
|
||||
indexh = updateSlides( HORIZONTAL_SLIDES_SELECTOR, indexh );
|
||||
indexv = updateSlides( VERTICAL_SLIDES_SELECTOR, indexv );
|
||||
}
|
||||
|
||||
controls.update();
|
||||
progress.update();
|
||||
|
||||
@@ -1541,6 +1582,8 @@ export default function( revealElement, options ) {
|
||||
overview.layout();
|
||||
}
|
||||
|
||||
dispatchEvent({ type: 'sync' });
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1563,6 +1606,13 @@ export default function( revealElement, options ) {
|
||||
backgrounds.update();
|
||||
notes.update();
|
||||
|
||||
dispatchEvent({
|
||||
type: 'slidesync',
|
||||
data: {
|
||||
slide
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1782,14 +1832,16 @@ export default function( revealElement, options ) {
|
||||
|
||||
if( horizontalSlidesLength && typeof indexh !== 'undefined' ) {
|
||||
|
||||
const isOverview = overview.isActive();
|
||||
|
||||
// The number of steps away from the present slide that will
|
||||
// be visible
|
||||
let viewDistance = overview.isActive() ? 10 : config.viewDistance;
|
||||
let viewDistance = isOverview ? 10 : config.viewDistance;
|
||||
|
||||
// Shorten the view distance on devices that typically have
|
||||
// less resources
|
||||
if( Device.isMobile ) {
|
||||
viewDistance = overview.isActive() ? 6 : config.mobileViewDistance;
|
||||
viewDistance = isOverview ? 6 : config.mobileViewDistance;
|
||||
}
|
||||
|
||||
// All slides need to be visible when exporting to PDF
|
||||
@@ -1822,7 +1874,7 @@ export default function( revealElement, options ) {
|
||||
|
||||
if( verticalSlidesLength ) {
|
||||
|
||||
let oy = getPreviousVerticalIndex( horizontalSlide );
|
||||
let oy = isOverview ? 0 : getPreviousVerticalIndex( horizontalSlide );
|
||||
|
||||
for( let y = 0; y < verticalSlidesLength; y++ ) {
|
||||
let verticalSlide = verticalSlides[y];
|
||||
@@ -2845,6 +2897,9 @@ export default function( revealElement, options ) {
|
||||
getComputedSlideSize,
|
||||
setCurrentScrollPage,
|
||||
|
||||
// Allows for manually removing slides prior to reveal.js initialization
|
||||
removeHiddenSlides,
|
||||
|
||||
// Returns the current scale of the presentation content
|
||||
getScale: () => scale,
|
||||
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
/**
|
||||
* Converts various color input formats to an {r:0,g:0,b:0} object.
|
||||
*
|
||||
* @param {string} color The string representation of a color
|
||||
* @example
|
||||
* colorToRgb('#000');
|
||||
* @example
|
||||
* colorToRgb('#000000');
|
||||
* @example
|
||||
* colorToRgb('rgb(0,0,0)');
|
||||
* @example
|
||||
* colorToRgb('rgba(0,0,0)');
|
||||
*
|
||||
* @return {{r: number, g: number, b: number, [a]: number}|null}
|
||||
*/
|
||||
export const colorToRgb = ( color ) => {
|
||||
|
||||
let hex3 = color.match( /^#([0-9a-f]{3})$/i );
|
||||
if( hex3 && hex3[1] ) {
|
||||
hex3 = hex3[1];
|
||||
return {
|
||||
r: parseInt( hex3.charAt( 0 ), 16 ) * 0x11,
|
||||
g: parseInt( hex3.charAt( 1 ), 16 ) * 0x11,
|
||||
b: parseInt( hex3.charAt( 2 ), 16 ) * 0x11
|
||||
};
|
||||
}
|
||||
|
||||
let hex6 = color.match( /^#([0-9a-f]{6})$/i );
|
||||
if( hex6 && hex6[1] ) {
|
||||
hex6 = hex6[1];
|
||||
return {
|
||||
r: parseInt( hex6.slice( 0, 2 ), 16 ),
|
||||
g: parseInt( hex6.slice( 2, 4 ), 16 ),
|
||||
b: parseInt( hex6.slice( 4, 6 ), 16 )
|
||||
};
|
||||
}
|
||||
|
||||
let rgb = color.match( /^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i );
|
||||
if( rgb ) {
|
||||
return {
|
||||
r: parseInt( rgb[1], 10 ),
|
||||
g: parseInt( rgb[2], 10 ),
|
||||
b: parseInt( rgb[3], 10 )
|
||||
};
|
||||
}
|
||||
|
||||
let rgba = color.match( /^rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d]+|[\d]*.[\d]+)\s*\)$/i );
|
||||
if( rgba ) {
|
||||
return {
|
||||
r: parseInt( rgba[1], 10 ),
|
||||
g: parseInt( rgba[2], 10 ),
|
||||
b: parseInt( rgba[3], 10 ),
|
||||
a: parseFloat( rgba[4] )
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates brightness on a scale of 0-255.
|
||||
*
|
||||
* @param {string} color See colorToRgb for supported formats.
|
||||
* @see {@link colorToRgb}
|
||||
*/
|
||||
export const colorBrightness = ( color ) => {
|
||||
|
||||
if( typeof color === 'string' ) color = colorToRgb( color );
|
||||
|
||||
if( color ) {
|
||||
return ( color.r * 299 + color.g * 587 + color.b * 114 ) / 1000;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
75
scripts/reveal.js/js/utils/color.ts
Normal file
75
scripts/reveal.js/js/utils/color.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* Converts various color input formats to an {r:0,g:0,b:0} object.
|
||||
*
|
||||
* @param {string} color The string representation of a color
|
||||
* @example
|
||||
* colorToRgb('#000');
|
||||
* @example
|
||||
* colorToRgb('#000000');
|
||||
* @example
|
||||
* colorToRgb('rgb(0,0,0)');
|
||||
* @example
|
||||
* colorToRgb('rgba(0,0,0)');
|
||||
*
|
||||
* @return {{r: number, g: number, b: number, [a]: number}|null}
|
||||
*/
|
||||
export const colorToRgb = (color: string) => {
|
||||
let hex3 = color.match(/^#([0-9a-f]{3})$/i);
|
||||
if (hex3 && hex3[1]) {
|
||||
const hex3Value = hex3[1];
|
||||
return {
|
||||
r: parseInt(hex3Value.charAt(0), 16) * 0x11,
|
||||
g: parseInt(hex3Value.charAt(1), 16) * 0x11,
|
||||
b: parseInt(hex3Value.charAt(2), 16) * 0x11,
|
||||
};
|
||||
}
|
||||
|
||||
let hex6 = color.match(/^#([0-9a-f]{6})$/i);
|
||||
if (hex6 && hex6[1]) {
|
||||
const hex6Value = hex6[1];
|
||||
return {
|
||||
r: parseInt(hex6Value.slice(0, 2), 16),
|
||||
g: parseInt(hex6Value.slice(2, 4), 16),
|
||||
b: parseInt(hex6Value.slice(4, 6), 16),
|
||||
};
|
||||
}
|
||||
|
||||
let rgb = color.match(/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i);
|
||||
if (rgb) {
|
||||
return {
|
||||
r: parseInt(rgb[1], 10),
|
||||
g: parseInt(rgb[2], 10),
|
||||
b: parseInt(rgb[3], 10),
|
||||
};
|
||||
}
|
||||
|
||||
let rgba = color.match(
|
||||
/^rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d]+|[\d]*.[\d]+)\s*\)$/i
|
||||
);
|
||||
if (rgba) {
|
||||
return {
|
||||
r: parseInt(rgba[1], 10),
|
||||
g: parseInt(rgba[2], 10),
|
||||
b: parseInt(rgba[3], 10),
|
||||
a: parseFloat(rgba[4]),
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates brightness on a scale of 0-255.
|
||||
*
|
||||
* @param {string} color See colorToRgb for supported formats.
|
||||
* @see {@link colorToRgb}
|
||||
*/
|
||||
export const colorBrightness = (color: string | { r: number; g: number; b: number } | null) => {
|
||||
if (typeof color === 'string') color = colorToRgb(color);
|
||||
|
||||
if (color) {
|
||||
return (color.r * 299 + color.g * 587 + color.b * 114) / 1000;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
@@ -1,17 +1,18 @@
|
||||
|
||||
export const SLIDES_SELECTOR = '.slides section';
|
||||
export const HORIZONTAL_SLIDES_SELECTOR = '.slides>section';
|
||||
export const VERTICAL_SLIDES_SELECTOR = '.slides>section.present>section';
|
||||
export const HORIZONTAL_BACKGROUNDS_SELECTOR = '.backgrounds>.slide-background';
|
||||
|
||||
// Methods that may not be invoked via the postMessage API
|
||||
export const POST_MESSAGE_METHOD_BLACKLIST = /registerPlugin|registerKeyboardShortcut|addKeyBinding|addEventListener|showPreview/;
|
||||
export const POST_MESSAGE_METHOD_BLACKLIST =
|
||||
/registerPlugin|registerKeyboardShortcut|addKeyBinding|addEventListener|showPreview/;
|
||||
|
||||
// Regex for retrieving the fragment style from a class attribute
|
||||
export const FRAGMENT_STYLE_REGEX = /fade-(down|up|right|left|out|in-then-out|in-then-semi-out)|semi-fade-out|current-visible|shrink|grow/;
|
||||
export const FRAGMENT_STYLE_REGEX =
|
||||
/fade-(down|up|right|left|out|in-then-out|in-then-semi-out)|semi-fade-out|current-visible|shrink|grow/;
|
||||
|
||||
// Slide number formats
|
||||
export const SLIDE_NUMBER_FORMAT_HORIZONTAL_DOT_VERTICAL = 'h.v';
|
||||
export const SLIDE_NUMBER_FORMAT_HORIZONTAL_SLASH_VERTICAL = 'h/v';
|
||||
export const SLIDE_NUMBER_FORMAT_CURRENT = 'c';
|
||||
export const SLIDE_NUMBER_FORMAT_CURRENT_SLASH_TOTAL = 'c/t';
|
||||
export const SLIDE_NUMBER_FORMAT_CURRENT_SLASH_TOTAL = 'c/t';
|
||||
@@ -1,8 +0,0 @@
|
||||
const UA = navigator.userAgent;
|
||||
|
||||
export const isMobile = /(iphone|ipod|ipad|android)/gi.test( UA ) ||
|
||||
( navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1 ); // iPadOS
|
||||
|
||||
export const isChrome = /chrome/i.test( UA ) && !/edge/i.test( UA );
|
||||
|
||||
export const isAndroid = /android/gi.test( UA );
|
||||
9
scripts/reveal.js/js/utils/device.ts
Normal file
9
scripts/reveal.js/js/utils/device.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
const UA = navigator.userAgent;
|
||||
|
||||
export const isMobile =
|
||||
/(iphone|ipod|ipad|android)/gi.test(UA) ||
|
||||
(navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1); // iPadOS
|
||||
|
||||
export const isChrome = /chrome/i.test(UA) && !/edge/i.test(UA);
|
||||
|
||||
export const isAndroid = /android/gi.test(UA);
|
||||
@@ -1,46 +0,0 @@
|
||||
/**
|
||||
* Loads a JavaScript file from the given URL and executes it.
|
||||
*
|
||||
* @param {string} url Address of the .js file to load
|
||||
* @param {function} callback Method to invoke when the script
|
||||
* has loaded and executed
|
||||
*/
|
||||
export const loadScript = ( url, callback ) => {
|
||||
|
||||
const script = document.createElement( 'script' );
|
||||
script.type = 'text/javascript';
|
||||
script.async = false;
|
||||
script.defer = false;
|
||||
script.src = url;
|
||||
|
||||
if( typeof callback === 'function' ) {
|
||||
|
||||
// Success callback
|
||||
script.onload = script.onreadystatechange = event => {
|
||||
if( event.type === 'load' || /loaded|complete/.test( script.readyState ) ) {
|
||||
|
||||
// Kill event listeners
|
||||
script.onload = script.onreadystatechange = script.onerror = null;
|
||||
|
||||
callback();
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
// Error callback
|
||||
script.onerror = err => {
|
||||
|
||||
// Kill event listeners
|
||||
script.onload = script.onreadystatechange = script.onerror = null;
|
||||
|
||||
callback( new Error( 'Failed loading script: ' + script.src + '\n' + err ) );
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// Append the script at the end of <head>
|
||||
const head = document.querySelector( 'head' );
|
||||
head.insertBefore( script, head.lastChild );
|
||||
|
||||
}
|
||||
40
scripts/reveal.js/js/utils/loader.ts
Normal file
40
scripts/reveal.js/js/utils/loader.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Loads a JavaScript file from the given URL and executes it.
|
||||
*
|
||||
* @param {string} url Address of the .js file to load
|
||||
* @param {function} callback Method to invoke when the script
|
||||
* has loaded and executed
|
||||
*/
|
||||
export const loadScript = (url: string, callback?: (error?: Error) => void) => {
|
||||
const script = document.createElement('script');
|
||||
script.type = 'text/javascript';
|
||||
script.async = false;
|
||||
script.defer = false;
|
||||
script.src = url;
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
// Success callback
|
||||
script.onload = (event: Event) => {
|
||||
if (event.type === 'load') {
|
||||
// Kill event listeners
|
||||
script.onload = script.onerror = null;
|
||||
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
// Error callback
|
||||
script.onerror = (err: Event | string) => {
|
||||
// Kill event listeners
|
||||
script.onload = script.onerror = null;
|
||||
|
||||
callback(new Error('Failed loading script: ' + script.src + '\n' + err));
|
||||
};
|
||||
}
|
||||
|
||||
// Append the script at the end of <head>
|
||||
const head = document.querySelector('head');
|
||||
if (head) {
|
||||
head.insertBefore(script, head.lastChild);
|
||||
}
|
||||
};
|
||||
@@ -1,313 +0,0 @@
|
||||
/**
|
||||
* Extend object a with the properties of object b.
|
||||
* If there's a conflict, object b takes precedence.
|
||||
*
|
||||
* @param {object} a
|
||||
* @param {object} b
|
||||
*/
|
||||
export const extend = ( a, b ) => {
|
||||
|
||||
for( let i in b ) {
|
||||
a[ i ] = b[ i ];
|
||||
}
|
||||
|
||||
return a;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* querySelectorAll but returns an Array.
|
||||
*/
|
||||
export const queryAll = ( el, selector ) => {
|
||||
|
||||
return Array.from( el.querySelectorAll( selector ) );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* classList.toggle() with cross browser support
|
||||
*/
|
||||
export const toggleClass = ( el, className, value ) => {
|
||||
if( value ) {
|
||||
el.classList.add( className );
|
||||
}
|
||||
else {
|
||||
el.classList.remove( className );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility for deserializing a value.
|
||||
*
|
||||
* @param {*} value
|
||||
* @return {*}
|
||||
*/
|
||||
export const deserialize = ( value ) => {
|
||||
|
||||
if( typeof value === 'string' ) {
|
||||
if( value === 'null' ) return null;
|
||||
else if( value === 'true' ) return true;
|
||||
else if( value === 'false' ) return false;
|
||||
else if( value.match( /^-?[\d\.]+$/ ) ) return parseFloat( value );
|
||||
}
|
||||
|
||||
return value;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Measures the distance in pixels between point a
|
||||
* and point b.
|
||||
*
|
||||
* @param {object} a point with x/y properties
|
||||
* @param {object} b point with x/y properties
|
||||
*
|
||||
* @return {number}
|
||||
*/
|
||||
export const distanceBetween = ( a, b ) => {
|
||||
|
||||
let dx = a.x - b.x,
|
||||
dy = a.y - b.y;
|
||||
|
||||
return Math.sqrt( dx*dx + dy*dy );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a CSS transform to the target element.
|
||||
*
|
||||
* @param {HTMLElement} element
|
||||
* @param {string} transform
|
||||
*/
|
||||
export const transformElement = ( element, transform ) => {
|
||||
|
||||
element.style.transform = transform;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Element.matches with IE support.
|
||||
*
|
||||
* @param {HTMLElement} target The element to match
|
||||
* @param {String} selector The CSS selector to match
|
||||
* the element against
|
||||
*
|
||||
* @return {Boolean}
|
||||
*/
|
||||
export const matches = ( target, selector ) => {
|
||||
|
||||
let matchesMethod = target.matches || target.matchesSelector || target.msMatchesSelector;
|
||||
|
||||
return !!( matchesMethod && matchesMethod.call( target, selector ) );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the closest parent that matches the given
|
||||
* selector.
|
||||
*
|
||||
* @param {HTMLElement} target The child element
|
||||
* @param {String} selector The CSS selector to match
|
||||
* the parents against
|
||||
*
|
||||
* @return {HTMLElement} The matched parent or null
|
||||
* if no matching parent was found
|
||||
*/
|
||||
export const closest = ( target, selector ) => {
|
||||
|
||||
// Native Element.closest
|
||||
if( typeof target.closest === 'function' ) {
|
||||
return target.closest( selector );
|
||||
}
|
||||
|
||||
// Polyfill
|
||||
while( target ) {
|
||||
if( matches( target, selector ) ) {
|
||||
return target;
|
||||
}
|
||||
|
||||
// Keep searching
|
||||
target = target.parentNode;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Handling the fullscreen functionality via the fullscreen API
|
||||
*
|
||||
* @see http://fullscreen.spec.whatwg.org/
|
||||
* @see https://developer.mozilla.org/en-US/docs/DOM/Using_fullscreen_mode
|
||||
*/
|
||||
export const enterFullscreen = element => {
|
||||
|
||||
element = element || document.documentElement;
|
||||
|
||||
// Check which implementation is available
|
||||
let requestMethod = element.requestFullscreen ||
|
||||
element.webkitRequestFullscreen ||
|
||||
element.webkitRequestFullScreen ||
|
||||
element.mozRequestFullScreen ||
|
||||
element.msRequestFullscreen;
|
||||
|
||||
if( requestMethod ) {
|
||||
requestMethod.apply( element );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an HTML element and returns a reference to it.
|
||||
* If the element already exists the existing instance will
|
||||
* be returned.
|
||||
*
|
||||
* @param {HTMLElement} container
|
||||
* @param {string} tagname
|
||||
* @param {string} classname
|
||||
* @param {string} innerHTML
|
||||
*
|
||||
* @return {HTMLElement}
|
||||
*/
|
||||
export const createSingletonNode = ( container, tagname, classname, innerHTML='' ) => {
|
||||
|
||||
// Find all nodes matching the description
|
||||
let nodes = container.querySelectorAll( '.' + classname );
|
||||
|
||||
// Check all matches to find one which is a direct child of
|
||||
// the specified container
|
||||
for( let i = 0; i < nodes.length; i++ ) {
|
||||
let testNode = nodes[i];
|
||||
if( testNode.parentNode === container ) {
|
||||
return testNode;
|
||||
}
|
||||
}
|
||||
|
||||
// If no node was found, create it now
|
||||
let node = document.createElement( tagname );
|
||||
node.className = classname;
|
||||
node.innerHTML = innerHTML;
|
||||
container.appendChild( node );
|
||||
|
||||
return node;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Injects the given CSS styles into the DOM.
|
||||
*
|
||||
* @param {string} value
|
||||
*/
|
||||
export const createStyleSheet = ( value ) => {
|
||||
|
||||
let tag = document.createElement( 'style' );
|
||||
tag.type = 'text/css';
|
||||
|
||||
if( value && value.length > 0 ) {
|
||||
if( tag.styleSheet ) {
|
||||
tag.styleSheet.cssText = value;
|
||||
}
|
||||
else {
|
||||
tag.appendChild( document.createTextNode( value ) );
|
||||
}
|
||||
}
|
||||
|
||||
document.head.appendChild( tag );
|
||||
|
||||
return tag;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a key:value hash of all query params.
|
||||
*/
|
||||
export const getQueryHash = () => {
|
||||
|
||||
let query = {};
|
||||
|
||||
location.search.replace( /[A-Z0-9]+?=([\w\.%-]*)/gi, a => {
|
||||
query[ a.split( '=' ).shift() ] = a.split( '=' ).pop();
|
||||
} );
|
||||
|
||||
// Basic deserialization
|
||||
for( let i in query ) {
|
||||
let value = query[ i ];
|
||||
|
||||
query[ i ] = deserialize( unescape( value ) );
|
||||
}
|
||||
|
||||
// Do not accept new dependencies via query config to avoid
|
||||
// the potential of malicious script injection
|
||||
if( typeof query['dependencies'] !== 'undefined' ) delete query['dependencies'];
|
||||
|
||||
return query;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the remaining height within the parent of the
|
||||
* target element.
|
||||
*
|
||||
* remaining height = [ configured parent height ] - [ current parent height ]
|
||||
*
|
||||
* @param {HTMLElement} element
|
||||
* @param {number} [height]
|
||||
*/
|
||||
export const getRemainingHeight = ( element, height = 0 ) => {
|
||||
|
||||
if( element ) {
|
||||
let newHeight, oldHeight = element.style.height;
|
||||
|
||||
// Change the .stretch element height to 0 in order find the height of all
|
||||
// the other elements
|
||||
element.style.height = '0px';
|
||||
|
||||
// In Overview mode, the parent (.slide) height is set of 700px.
|
||||
// Restore it temporarily to its natural height.
|
||||
element.parentNode.style.height = 'auto';
|
||||
|
||||
newHeight = height - element.parentNode.offsetHeight;
|
||||
|
||||
// Restore the old height, just in case
|
||||
element.style.height = oldHeight + 'px';
|
||||
|
||||
// Clear the parent (.slide) height. .removeProperty works in IE9+
|
||||
element.parentNode.style.removeProperty('height');
|
||||
|
||||
return newHeight;
|
||||
}
|
||||
|
||||
return height;
|
||||
|
||||
}
|
||||
|
||||
const fileExtensionToMimeMap = {
|
||||
'mp4': 'video/mp4',
|
||||
'm4a': 'video/mp4',
|
||||
'ogv': 'video/ogg',
|
||||
'mpeg': 'video/mpeg',
|
||||
'webm': 'video/webm'
|
||||
}
|
||||
|
||||
/**
|
||||
* Guess the MIME type for common file formats.
|
||||
*/
|
||||
export const getMimeTypeFromFile = ( filename='' ) => {
|
||||
return fileExtensionToMimeMap[filename.split('.').pop()]
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a string for RFC3986-compliant URL format.
|
||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI#encoding_for_rfc3986
|
||||
*
|
||||
* @param {string} url
|
||||
*/
|
||||
export const encodeRFC3986URI = ( url='' ) => {
|
||||
return encodeURI(url)
|
||||
.replace(/%5B/g, "[")
|
||||
.replace(/%5D/g, "]")
|
||||
.replace(
|
||||
/[!'()*]/g,
|
||||
(c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`
|
||||
);
|
||||
}
|
||||
301
scripts/reveal.js/js/utils/util.ts
Normal file
301
scripts/reveal.js/js/utils/util.ts
Normal file
@@ -0,0 +1,301 @@
|
||||
/**
|
||||
* Extend object a with the properties of object b.
|
||||
* If there's a conflict, object b takes precedence.
|
||||
*
|
||||
* @param {object} a
|
||||
* @param {object} b
|
||||
*/
|
||||
export const extend = (a: Record<string, any>, b: Record<string, any>) => {
|
||||
for (let i in b) {
|
||||
a[i] = b[i];
|
||||
}
|
||||
|
||||
return a;
|
||||
};
|
||||
|
||||
/**
|
||||
* querySelectorAll but returns an Array.
|
||||
*/
|
||||
export const queryAll = (el: Element | Document, selector: string): Element[] => {
|
||||
return Array.from(el.querySelectorAll(selector));
|
||||
};
|
||||
|
||||
/**
|
||||
* classList.toggle() with cross browser support
|
||||
*/
|
||||
export const toggleClass = (el: Element, className: string, value: boolean) => {
|
||||
if (value) {
|
||||
el.classList.add(className);
|
||||
} else {
|
||||
el.classList.remove(className);
|
||||
}
|
||||
};
|
||||
|
||||
type DeserializedValue = string | number | boolean | null;
|
||||
|
||||
/**
|
||||
* Utility for deserializing a value.
|
||||
*
|
||||
* @param {*} value
|
||||
* @return {*}
|
||||
*/
|
||||
export const deserialize = (value: string): DeserializedValue => {
|
||||
if (typeof value === 'string') {
|
||||
if (value === 'null') return null;
|
||||
else if (value === 'true') return true;
|
||||
else if (value === 'false') return false;
|
||||
else if (value.match(/^-?[\d\.]+$/)) return parseFloat(value);
|
||||
}
|
||||
|
||||
return value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Measures the distance in pixels between point a
|
||||
* and point b.
|
||||
*
|
||||
* @param {object} a point with x/y properties
|
||||
* @param {object} b point with x/y properties
|
||||
*
|
||||
* @return {number}
|
||||
*/
|
||||
export const distanceBetween = (
|
||||
a: { x: number; y: number },
|
||||
b: { x: number; y: number }
|
||||
): number => {
|
||||
let dx = a.x - b.x,
|
||||
dy = a.y - b.y;
|
||||
|
||||
return Math.sqrt(dx * dx + dy * dy);
|
||||
};
|
||||
|
||||
/**
|
||||
* Applies a CSS transform to the target element.
|
||||
*
|
||||
* @param {HTMLElement} element
|
||||
* @param {string} transform
|
||||
*/
|
||||
export const transformElement = (element: HTMLElement, transform: string) => {
|
||||
element.style.transform = transform;
|
||||
};
|
||||
|
||||
/**
|
||||
* Element.matches with IE support.
|
||||
*
|
||||
* @param {HTMLElement} target The element to match
|
||||
* @param {String} selector The CSS selector to match
|
||||
* the element against
|
||||
*
|
||||
* @return {Boolean}
|
||||
*/
|
||||
export const matches = (target: any, selector: string): boolean => {
|
||||
let matchesMethod = target.matches || target.matchesSelector || target.msMatchesSelector;
|
||||
|
||||
return !!(matchesMethod && matchesMethod.call(target, selector));
|
||||
};
|
||||
|
||||
/**
|
||||
* Find the closest parent that matches the given
|
||||
* selector.
|
||||
*
|
||||
* @param {HTMLElement} target The child element
|
||||
* @param {String} selector The CSS selector to match
|
||||
* the parents against
|
||||
*
|
||||
* @return {HTMLElement} The matched parent or null
|
||||
* if no matching parent was found
|
||||
*/
|
||||
export const closest = (target: Element | null, selector: string): Element | null => {
|
||||
// Native Element.closest
|
||||
if (target && typeof target.closest === 'function') {
|
||||
return target.closest(selector);
|
||||
}
|
||||
|
||||
// Polyfill
|
||||
while (target) {
|
||||
if (matches(target, selector)) {
|
||||
return target;
|
||||
}
|
||||
|
||||
// Keep searching
|
||||
target = target.parentElement;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handling the fullscreen functionality via the fullscreen API
|
||||
*
|
||||
* @see http://fullscreen.spec.whatwg.org/
|
||||
* @see https://developer.mozilla.org/en-US/docs/DOM/Using_fullscreen_mode
|
||||
*/
|
||||
export const enterFullscreen = (element?: Element) => {
|
||||
element = element || document.documentElement;
|
||||
|
||||
// Check which implementation is available
|
||||
let requestMethod =
|
||||
(element as any).requestFullscreen ||
|
||||
(element as any).webkitRequestFullscreen ||
|
||||
(element as any).webkitRequestFullScreen ||
|
||||
(element as any).mozRequestFullScreen ||
|
||||
(element as any).msRequestFullscreen;
|
||||
|
||||
if (requestMethod) {
|
||||
requestMethod.apply(element);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an HTML element and returns a reference to it.
|
||||
* If the element already exists the existing instance will
|
||||
* be returned.
|
||||
*
|
||||
* @param {HTMLElement} container
|
||||
* @param {string} tagname
|
||||
* @param {string} classname
|
||||
* @param {string} innerHTML
|
||||
*
|
||||
* @return {HTMLElement}
|
||||
*/
|
||||
export const createSingletonNode = (
|
||||
container: Element,
|
||||
tagname: string,
|
||||
classname: string,
|
||||
innerHTML: string = ''
|
||||
): Element => {
|
||||
// Find all nodes matching the description
|
||||
let nodes = container.querySelectorAll('.' + classname);
|
||||
|
||||
// Check all matches to find one which is a direct child of
|
||||
// the specified container
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
let testNode = nodes[i];
|
||||
if (testNode.parentNode === container) {
|
||||
return testNode;
|
||||
}
|
||||
}
|
||||
|
||||
// If no node was found, create it now
|
||||
let node = document.createElement(tagname);
|
||||
node.className = classname;
|
||||
node.innerHTML = innerHTML;
|
||||
container.appendChild(node);
|
||||
|
||||
return node;
|
||||
};
|
||||
|
||||
/**
|
||||
* Injects the given CSS styles into the DOM.
|
||||
*
|
||||
* @param {string} value
|
||||
*/
|
||||
export const createStyleSheet = (value: string): HTMLStyleElement => {
|
||||
let tag = document.createElement('style');
|
||||
|
||||
if (value && value.length > 0) {
|
||||
tag.appendChild(document.createTextNode(value));
|
||||
}
|
||||
|
||||
document.head.appendChild(tag);
|
||||
|
||||
return tag;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a key:value hash of all query params.
|
||||
*/
|
||||
export const getQueryHash = (): Record<string, DeserializedValue> => {
|
||||
let query: Record<string, DeserializedValue> = {};
|
||||
|
||||
location.search.replace(/[A-Z0-9]+?=([\w\.%-]*)/gi, (a: string) => {
|
||||
const key = a.split('=').shift();
|
||||
const value = a.split('=').pop();
|
||||
if (key && value !== undefined) {
|
||||
query[key] = value;
|
||||
}
|
||||
return a;
|
||||
});
|
||||
|
||||
// Basic deserialization
|
||||
for (let i in query) {
|
||||
let value = query[i];
|
||||
|
||||
query[i] = deserialize(unescape(value as string));
|
||||
}
|
||||
|
||||
// Do not accept new dependencies via query config to avoid
|
||||
// the potential of malicious script injection
|
||||
if (typeof query['dependencies'] !== 'undefined') delete query['dependencies'];
|
||||
|
||||
return query;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the remaining height within the parent of the
|
||||
* target element.
|
||||
*
|
||||
* remaining height = [ configured parent height ] - [ current parent height ]
|
||||
*
|
||||
* @param {HTMLElement} element
|
||||
* @param {number} [height]
|
||||
*/
|
||||
export const getRemainingHeight = (element: HTMLElement | null, height: number = 0): number => {
|
||||
if (element) {
|
||||
let newHeight: number,
|
||||
oldHeight = element.style.height;
|
||||
|
||||
// Change the .stretch element height to 0 in order find the height of all
|
||||
// the other elements
|
||||
element.style.height = '0px';
|
||||
|
||||
// In Overview mode, the parent (.slide) height is set of 700px.
|
||||
// Restore it temporarily to its natural height.
|
||||
if (element.parentElement) {
|
||||
element.parentElement.style.height = 'auto';
|
||||
}
|
||||
|
||||
newHeight = height - (element.parentElement?.offsetHeight || 0);
|
||||
|
||||
// Restore the old height, just in case
|
||||
element.style.height = oldHeight + 'px';
|
||||
|
||||
// Clear the parent (.slide) height. .removeProperty works in IE9+
|
||||
if (element.parentElement) {
|
||||
element.parentElement.style.removeProperty('height');
|
||||
}
|
||||
|
||||
return newHeight;
|
||||
}
|
||||
|
||||
return height;
|
||||
};
|
||||
|
||||
const fileExtensionToMimeMap: Record<string, string> = {
|
||||
mp4: 'video/mp4',
|
||||
m4a: 'video/mp4',
|
||||
ogv: 'video/ogg',
|
||||
mpeg: 'video/mpeg',
|
||||
webm: 'video/webm',
|
||||
};
|
||||
|
||||
/**
|
||||
* Guess the MIME type for common file formats.
|
||||
*/
|
||||
export const getMimeTypeFromFile = (filename: string = ''): string | undefined => {
|
||||
const extension = filename.split('.').pop();
|
||||
return extension ? fileExtensionToMimeMap[extension] : undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encodes a string for RFC3986-compliant URL format.
|
||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI#encoding_for_rfc3986
|
||||
*
|
||||
* @param {string} url
|
||||
*/
|
||||
export const encodeRFC3986URI = (url: string = ''): string => {
|
||||
return encodeURI(url)
|
||||
.replace(/%5B/g, '[')
|
||||
.replace(/%5D/g, ']')
|
||||
.replace(/[!'()*]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`);
|
||||
};
|
||||
Reference in New Issue
Block a user