update reveal.js

This commit is contained in:
2025-07-07 20:42:39 +02:00
parent 91d4509dac
commit e5beded4a5
119 changed files with 11231 additions and 13895 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3 -3
View File
@@ -19,7 +19,7 @@ const Plugin = {
hljs,
/**
* Highlights code blocks withing the given deck.
* Highlights code blocks within the given deck.
*
* Note that this can be called multiple times if
* there are multiple presentations on one page.
@@ -52,7 +52,7 @@ const Plugin = {
block.innerHTML = betterTrim( block );
}
// Escape HTML tags unless the "data-noescape" attrbute is present
// Escape HTML tags unless the "data-noescape" attribute is present
if( config.escapeHTML && !block.hasAttribute( 'data-noescape' )) {
block.innerHTML = block.innerHTML.replace( /</g,"&lt;").replace(/>/g, '&gt;' );
}
@@ -138,7 +138,7 @@ const Plugin = {
// Scroll highlights into view as we step through them
fragmentBlock.addEventListener( 'visible', Plugin.scrollHighlightedLineIntoView.bind( Plugin, fragmentBlock, scrollState ) );
fragmentBlock.addEventListener( 'hidden', Plugin.scrollHighlightedLineIntoView.bind( Plugin, fragmentBlock.previousSibling, scrollState ) );
fragmentBlock.addEventListener( 'hidden', Plugin.scrollHighlightedLineIntoView.bind( Plugin, fragmentBlock.previousElementSibling, scrollState ) );
} );
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+64 -48
View File
@@ -7,13 +7,16 @@
import { marked } from 'marked';
const DEFAULT_SLIDE_SEPARATOR = '\r?\n---\r?\n',
DEFAULT_NOTES_SEPARATOR = 'notes?:',
DEFAULT_VERTICAL_SEPARATOR = null,
DEFAULT_NOTES_SEPARATOR = '^\s*notes?:',
DEFAULT_ELEMENT_ATTRIBUTES_SEPARATOR = '\\\.element\\\s*?(.+?)$',
DEFAULT_SLIDE_ATTRIBUTES_SEPARATOR = '\\\.slide:\\\s*?(\\\S.+?)$';
const SCRIPT_END_PLACEHOLDER = '__SCRIPT_END__';
const CODE_LINE_NUMBER_REGEX = /\[([\s\d,|-]*)\]/;
// match an optional line number offset and highlight line numbers
// [<line numbers>] or [<offset>: <line numbers>]
const CODE_LINE_NUMBER_REGEX = /\[\s*((\d*):)?\s*([\s\d,|-]*)\]/;
const HTML_ESCAPE_MAP = {
'&': '&amp;',
@@ -35,22 +38,22 @@ const Plugin = () => {
function getMarkdownFromSlide( section ) {
// look for a <script> or <textarea data-template> wrapper
var template = section.querySelector( '[data-template]' ) || section.querySelector( 'script' );
const template = section.querySelector( '[data-template]' ) || section.querySelector( 'script' );
// strip leading whitespace so it isn't evaluated as code
var text = ( template || section ).textContent;
let text = ( template || section ).textContent;
// restore script end tags
text = text.replace( new RegExp( SCRIPT_END_PLACEHOLDER, 'g' ), '</script>' );
var leadingWs = text.match( /^\n?(\s*)/ )[1].length,
const leadingWs = text.match( /^\n?(\s*)/ )[1].length,
leadingTabs = text.match( /^\n?(\t*)/ )[1].length;
if( leadingTabs > 0 ) {
text = text.replace( new RegExp('\\n?\\t{' + leadingTabs + '}','g'), '\n' );
text = text.replace( new RegExp('\\n?\\t{' + leadingTabs + '}(.*)','g'), function(m, p1) { return '\n' + p1 ; } );
}
else if( leadingWs > 1 ) {
text = text.replace( new RegExp('\\n? {' + leadingWs + '}', 'g'), '\n' );
text = text.replace( new RegExp('\\n? {' + leadingWs + '}(.*)', 'g'), function(m, p1) { return '\n' + p1 ; } );
}
return text;
@@ -65,11 +68,11 @@ const Plugin = () => {
*/
function getForwardedAttributes( section ) {
var attributes = section.attributes;
var result = [];
const attributes = section.attributes;
const result = [];
for( var i = 0, len = attributes.length; i < len; i++ ) {
var name = attributes[i].name,
for( let i = 0, len = attributes.length; i < len; i++ ) {
const name = attributes[i].name,
value = attributes[i].value;
// disregard attributes that are used for markdown loading/parsing
@@ -92,10 +95,12 @@ const Plugin = () => {
* values for what's not defined.
*/
function getSlidifyOptions( options ) {
const markdownConfig = deck?.getConfig?.().markdown;
options = options || {};
options.separator = options.separator || DEFAULT_SLIDE_SEPARATOR;
options.notesSeparator = options.notesSeparator || DEFAULT_NOTES_SEPARATOR;
options.separator = options.separator || markdownConfig?.separator || DEFAULT_SLIDE_SEPARATOR;
options.verticalSeparator = options.verticalSeparator || markdownConfig?.verticalSeparator || DEFAULT_VERTICAL_SEPARATOR;
options.notesSeparator = options.notesSeparator || markdownConfig?.notesSeparator || DEFAULT_NOTES_SEPARATOR;
options.attributes = options.attributes || '';
return options;
@@ -109,7 +114,7 @@ const Plugin = () => {
options = getSlidifyOptions( options );
var notesMatch = content.split( new RegExp( options.notesSeparator, 'mgi' ) );
const notesMatch = content.split( new RegExp( options.notesSeparator, 'mgi' ) );
if( notesMatch.length === 2 ) {
content = notesMatch[0] + '<aside class="notes">' + marked(notesMatch[1].trim()) + '</aside>';
@@ -131,10 +136,10 @@ const Plugin = () => {
options = getSlidifyOptions( options );
var separatorRegex = new RegExp( options.separator + ( options.verticalSeparator ? '|' + options.verticalSeparator : '' ), 'mg' ),
const separatorRegex = new RegExp( options.separator + ( options.verticalSeparator ? '|' + options.verticalSeparator : '' ), 'mg' ),
horizontalSeparatorRegex = new RegExp( options.separator );
var matches,
let matches,
lastIndex = 0,
isHorizontal,
wasHorizontal = true,
@@ -143,7 +148,7 @@ const Plugin = () => {
// iterate until all blocks between separators are stacked up
while( matches = separatorRegex.exec( markdown ) ) {
var notes = null;
const notes = null;
// determine direction (horizontal by default)
isHorizontal = horizontalSeparatorRegex.test( matches[0] );
@@ -172,10 +177,10 @@ const Plugin = () => {
// add the remaining slide
( wasHorizontal ? sectionStack : sectionStack[sectionStack.length-1] ).push( markdown.substring( lastIndex ) );
var markdownSections = '';
let markdownSections = '';
// flatten the hierarchical stack, and insert <section data-markdown> tags
for( var i = 0, len = sectionStack.length; i < len; i++ ) {
for( let i = 0, len = sectionStack.length; i < len; i++ ) {
// vertical
if( sectionStack[i] instanceof Array ) {
markdownSections += '<section '+ options.attributes +'>';
@@ -204,7 +209,7 @@ const Plugin = () => {
return new Promise( function( resolve ) {
var externalPromises = [];
const externalPromises = [];
[].slice.call( scope.querySelectorAll( 'section[data-markdown]:not([data-markdown-parsed])') ).forEach( function( section, i ) {
@@ -257,13 +262,13 @@ const Plugin = () => {
return new Promise( function( resolve, reject ) {
var xhr = new XMLHttpRequest(),
const xhr = new XMLHttpRequest(),
url = section.getAttribute( 'data-markdown' );
var datacharset = section.getAttribute( 'data-charset' );
const datacharset = section.getAttribute( 'data-charset' );
// see https://developer.mozilla.org/en-US/docs/Web/API/element.getAttribute#Notes
if( datacharset != null && datacharset != '' ) {
if( datacharset !== null && datacharset !== '' ) {
xhr.overrideMimeType( 'text/html; charset=' + datacharset );
}
@@ -308,17 +313,17 @@ const Plugin = () => {
*/
function addAttributeInElement( node, elementTarget, separator ) {
var mardownClassesInElementsRegex = new RegExp( separator, 'mg' );
var mardownClassRegex = new RegExp( "([^\"= ]+?)=\"([^\"]+?)\"|(data-[^\"= ]+?)(?=[\" ])", 'mg' );
var nodeValue = node.nodeValue;
var matches,
const markdownClassesInElementsRegex = new RegExp( separator, 'mg' );
const markdownClassRegex = new RegExp( "([^\"= ]+?)=\"([^\"]+?)\"|(data-[^\"= ]+?)(?=[\" ])", 'mg' );
let nodeValue = node.nodeValue;
let matches,
matchesClass;
if( matches = mardownClassesInElementsRegex.exec( nodeValue ) ) {
if( matches = markdownClassesInElementsRegex.exec( nodeValue ) ) {
var classes = matches[1];
nodeValue = nodeValue.substring( 0, matches.index ) + nodeValue.substring( mardownClassesInElementsRegex.lastIndex );
const classes = matches[1];
nodeValue = nodeValue.substring( 0, matches.index ) + nodeValue.substring( markdownClassesInElementsRegex.lastIndex );
node.nodeValue = nodeValue;
while( matchesClass = mardownClassRegex.exec( classes ) ) {
while( matchesClass = markdownClassRegex.exec( classes ) ) {
if( matchesClass[2] ) {
elementTarget.setAttribute( matchesClass[1], matchesClass[2] );
} else {
@@ -336,34 +341,34 @@ const Plugin = () => {
*/
function addAttributes( section, element, previousElement, separatorElementAttributes, separatorSectionAttributes ) {
if ( element != null && element.childNodes != undefined && element.childNodes.length > 0 ) {
var previousParentElement = element;
for( var i = 0; i < element.childNodes.length; i++ ) {
var childElement = element.childNodes[i];
if ( element !== null && element.childNodes !== undefined && element.childNodes.length > 0 ) {
let previousParentElement = element;
for( let i = 0; i < element.childNodes.length; i++ ) {
const childElement = element.childNodes[i];
if ( i > 0 ) {
var j = i - 1;
let j = i - 1;
while ( j >= 0 ) {
var aPreviousChildElement = element.childNodes[j];
if ( typeof aPreviousChildElement.setAttribute == 'function' && aPreviousChildElement.tagName != "BR" ) {
const aPreviousChildElement = element.childNodes[j];
if ( typeof aPreviousChildElement.setAttribute === 'function' && aPreviousChildElement.tagName !== "BR" ) {
previousParentElement = aPreviousChildElement;
break;
}
j = j - 1;
}
}
var parentSection = section;
if( childElement.nodeName == "section" ) {
let parentSection = section;
if( childElement.nodeName === "section" ) {
parentSection = childElement ;
previousParentElement = childElement ;
}
if ( typeof childElement.setAttribute == 'function' || childElement.nodeType == Node.COMMENT_NODE ) {
if ( typeof childElement.setAttribute === 'function' || childElement.nodeType === Node.COMMENT_NODE ) {
addAttributes( parentSection, childElement, previousParentElement, separatorElementAttributes, separatorSectionAttributes );
}
}
}
if ( element.nodeType == Node.COMMENT_NODE ) {
if ( addAttributeInElement( element, previousElement, separatorElementAttributes ) == false ) {
if ( element.nodeType === Node.COMMENT_NODE ) {
if ( addAttributeInElement( element, previousElement, separatorElementAttributes ) === false ) {
addAttributeInElement( element, section, separatorSectionAttributes );
}
}
@@ -375,14 +380,14 @@ const Plugin = () => {
*/
function convertSlides() {
var sections = deck.getRevealElement().querySelectorAll( '[data-markdown]:not([data-markdown-parsed])');
const sections = deck.getRevealElement().querySelectorAll( '[data-markdown]:not([data-markdown-parsed])');
[].slice.call( sections ).forEach( function( section ) {
section.setAttribute( 'data-markdown-parsed', true )
var notes = section.querySelector( 'aside.notes' );
var markdown = getMarkdownFromSlide( section );
const notes = section.querySelector( 'aside.notes' );
const markdown = getMarkdownFromSlide( section );
section.innerHTML = marked( markdown );
addAttributes( section, section, null, section.getAttribute( 'data-element-attributes' ) ||
@@ -429,14 +434,23 @@ const Plugin = () => {
renderer.code = ( code, language ) => {
// Off by default
let lineNumberOffset = '';
let lineNumbers = '';
// Users can opt in to show line numbers and highlight
// specific lines.
// ```javascript [] show line numbers
// ```javascript [1,4-8] highlights lines 1 and 4-8
// optional line number offset:
// ```javascript [25: 1,4-8] start line numbering at 25,
// highlights lines 1 (numbered as 25) and 4-8 (numbered as 28-32)
if( CODE_LINE_NUMBER_REGEX.test( language ) ) {
lineNumbers = language.match( CODE_LINE_NUMBER_REGEX )[1].trim();
let lineNumberOffsetMatch = language.match( CODE_LINE_NUMBER_REGEX )[2];
if (lineNumberOffsetMatch){
lineNumberOffset = `data-ln-start-from="${lineNumberOffsetMatch.trim()}"`;
}
lineNumbers = language.match( CODE_LINE_NUMBER_REGEX )[3].trim();
lineNumbers = `data-line-numbers="${lineNumbers}"`;
language = language.replace( CODE_LINE_NUMBER_REGEX, '' ).trim();
}
@@ -446,7 +460,9 @@ const Plugin = () => {
// highlight.js is able to read it
code = escapeForHTML( code );
return `<pre><code ${lineNumbers} class="${language}">${code}</code></pre>`;
// return `<pre><code ${lineNumbers} class="${language}">${code}</code></pre>`;
return `<pre><code ${lineNumbers} ${lineNumberOffset} class="${language}">${code}</code></pre>`;
};
}
+1 -1
View File
@@ -16,7 +16,7 @@ export const KaTeX = () => {
{left: '\\(', right: '\\)', display: false},
{left: '\\[', right: '\\]', display: true}
],
ignoredTags: ['script', 'noscript', 'style', 'textarea', 'pre']
ignoredTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
}
const loadCss = src => {
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -13,7 +13,7 @@ export const MathJax2 = () => {
messageStyle: 'none',
tex2jax: {
inlineMath: [ [ '$', '$' ], [ '\\(', '\\)' ] ],
skipTags: [ 'script', 'noscript', 'style', 'textarea', 'pre' ]
skipTags: [ 'script', 'noscript', 'style', 'textarea', 'pre', 'code' ]
},
skipStartupTypeset: true
};
+3 -3
View File
@@ -15,13 +15,13 @@ export const MathJax3 = () => {
inlineMath: [ [ '$', '$' ], [ '\\(', '\\)' ] ]
},
options: {
skipHtmlTags: [ 'script', 'noscript', 'style', 'textarea', 'pre' ]
skipHtmlTags: [ 'script', 'noscript', 'style', 'textarea', 'pre', 'code' ]
},
startup: {
ready: () => {
MathJax.startup.defaultReady();
MathJax.startup.promise.then(() => {
Reveal.layout();
deck.layout();
});
}
}
@@ -66,7 +66,7 @@ export const MathJax3 = () => {
loadScript( url, function() {
// Reprocess equations in slides when they turn visible
Reveal.addEventListener( 'slidechanged', function( event ) {
deck.addEventListener( 'slidechanged', function( event ) {
MathJax.typeset();
} );
} );
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+50 -15
View File
@@ -1,4 +1,4 @@
import speakerViewHTML from './speaker-view.html';
import speakerViewHTML from './speaker-view.html'
import { marked } from 'marked';
@@ -108,7 +108,7 @@ const Plugin = () => {
function post( event ) {
let slideElement = deck.getCurrentSlide(),
notesElement = slideElement.querySelector( 'aside.notes' ),
notesElements = slideElement.querySelectorAll( 'aside.notes' ),
fragmentElement = slideElement.querySelector( '.current-fragment' );
let messageData = {
@@ -130,36 +130,67 @@ const Plugin = () => {
if( fragmentElement ) {
let fragmentNotes = fragmentElement.querySelector( 'aside.notes' );
if( fragmentNotes ) {
notesElement = fragmentNotes;
messageData.notes = fragmentNotes.innerHTML;
messageData.markdown = typeof fragmentNotes.getAttribute( 'data-markdown' ) === 'string';
// Ignore other slide notes
notesElements = null;
}
else if( fragmentElement.hasAttribute( 'data-notes' ) ) {
messageData.notes = fragmentElement.getAttribute( 'data-notes' );
messageData.whitespace = 'pre-wrap';
// In case there are slide notes
notesElement = null;
notesElements = null;
}
}
// Look for notes defined in an aside element
if( notesElement ) {
messageData.notes = notesElement.innerHTML;
messageData.markdown = typeof notesElement.getAttribute( 'data-markdown' ) === 'string';
if( notesElements && notesElements.length ) {
// Ignore notes inside of fragments since those are shown
// individually when stepping through fragments
notesElements = Array.from( notesElements ).filter( notesElement => notesElement.closest( '.fragment' ) === null );
messageData.notes = notesElements.map( notesElement => notesElement.innerHTML ).join( '\n' );
messageData.markdown = notesElements[0] && typeof notesElements[0].getAttribute( 'data-markdown' ) === 'string';
}
speakerWindow.postMessage( JSON.stringify( messageData ), '*' );
}
/**
* Check if the given event is from the same origin as the
* current window.
*/
function isSameOriginEvent( event ) {
try {
return window.location.origin === event.source.location.origin;
}
catch ( error ) {
return false;
}
}
function onPostMessage( event ) {
let data = JSON.parse( event.data );
if( data && data.namespace === 'reveal-notes' && data.type === 'connected' ) {
clearInterval( connectInterval );
onConnected();
}
else if( data && data.namespace === 'reveal-notes' && data.type === 'call' ) {
callRevealApi( data.methodName, data.arguments, data.callId );
// Only allow same-origin messages
// (added 12/5/22 as a XSS safeguard)
if( isSameOriginEvent( event ) ) {
try {
let data = JSON.parse( event.data );
if( data && data.namespace === 'reveal-notes' && data.type === 'connected' ) {
clearInterval( connectInterval );
onConnected();
}
else if( data && data.namespace === 'reveal-notes' && data.type === 'call' ) {
callRevealApi( data.methodName, data.arguments, data.callId );
}
} catch (e) {}
}
}
@@ -178,6 +209,10 @@ const Plugin = () => {
deck.on( 'overviewshown', post );
deck.on( 'paused', post );
deck.on( 'resumed', post );
deck.on( 'previewiframe', post );
deck.on( 'previewimage', post );
deck.on( 'previewvideo', post );
deck.on( 'closeoverlay', post );
// Post the initial state
post();
@@ -198,7 +233,7 @@ const Plugin = () => {
openSpeakerWindow();
}
else {
// Keep listening for speaker view hearbeats. If we receive a
// Keep listening for speaker view heartbeats. If we receive a
// heartbeat from an orphaned window, reconnect it. This ensures
// that we remain connected to the notes even if the presentation
// is reloaded.
@@ -350,8 +350,9 @@
layoutDropdown,
pendingCalls = {},
lastRevealApiCallId = 0,
connected = false,
whitelistedWindows = [window.opener];
connected = false
var connectionStatus = document.querySelector( '#connection-status' );
var SPEAKER_LAYOUTS = {
'default': 'Default',
@@ -362,16 +363,31 @@
setupLayout();
var connectionStatus = document.querySelector( '#connection-status' );
let openerOrigin;
try {
openerOrigin = window.opener.location.origin;
}
catch ( error ) { console.warn( error ) }
// In order to prevent XSS, the speaker view will only run if its
// opener has the same origin as itself
if( window.location.origin !== openerOrigin ) {
connectionStatus.innerHTML = 'Cross origin error.<br>The speaker window can only be opened from the same origin.';
return;
}
var connectionTimeout = setTimeout( function() {
connectionStatus.innerHTML = 'Error connecting to main window.<br>Please try closing and reopening the speaker view.';
}, 5000 );
;
window.addEventListener( 'message', function( event ) {
// Validate the origin of this message to prevent XSS
if( window.location.origin !== event.origin && whitelistedWindows.indexOf( event.source ) === -1 ) {
return;
// Validate the origin of all messages to avoid parsing messages
// that aren't meant for us. Ignore when running off file:// so
// that the speaker view continues to work without a web server.
if( window.location.origin !== event.origin && window.location.origin !== 'file://' ) {
return
}
clearTimeout( connectionTimeout );
@@ -398,14 +414,24 @@
}
// Messages sent by the reveal.js inside of the current slide preview
else if( data && data.namespace === 'reveal' ) {
const supportedEvents = [
'slidechanged',
'fragmentshown',
'fragmenthidden',
'paused',
'resumed',
'previewiframe',
'previewimage',
'previewvideo',
'closeoverlay'
];
if( /ready/.test( data.eventName ) ) {
// Send a message back to notify that the handshake is complete
window.opener.postMessage( JSON.stringify({ namespace: 'reveal-notes', type: 'connected'} ), '*' );
}
else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) && currentState !== JSON.stringify( data.state ) ) {
else if( supportedEvents.includes( data.eventName ) && currentState !== JSON.stringify( data.state ) ) {
dispatchStateToMainWindow( data.state );
}
}
@@ -478,9 +504,12 @@
notes.classList.add( 'hidden' );
}
// Don't show lightboxes in the upcoming slide
const { previewVideo, previewImage, previewIframe, ...upcomingState } = data.state;
// Update the note slides
currentSlide.contentWindow.postMessage( JSON.stringify({ method: 'setState', args: [ data.state ] }), '*' );
upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: 'setState', args: [ data.state ] }), '*' );
upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: 'setState', args: [ upcomingState ] }), '*' );
upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: 'next' }), '*' );
}
@@ -524,8 +553,8 @@
var urlSeparator = /\?/.test(data.url) ? '&' : '?';
var hash = '#/' + data.state.indexh + '/' + data.state.indexv;
var currentURL = data.url + urlSeparator + params + '&postMessageEvents=true' + hash;
var upcomingURL = data.url + urlSeparator + params + '&controls=false' + hash;
var currentURL = data.url + urlSeparator + params + '&scrollActivationWidth=false&postMessageEvents=true' + hash;
var upcomingURL = data.url + urlSeparator + params + '&scrollActivationWidth=false&controls=false' + hash;
currentSlide = document.createElement( 'iframe' );
currentSlide.setAttribute( 'width', 1280 );
@@ -539,8 +568,6 @@
upcomingSlide.setAttribute( 'src', upcomingURL );
document.querySelector( '#upcoming-slide' ).appendChild( upcomingSlide );
whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );
}
/**
+4 -2
View File
@@ -137,7 +137,7 @@ const Plugin = () => {
this.setRegex = function(input)
{
input = input.replace(/^[^\w]+|[^\w]+$/g, "").replace(/[^\w'-]+/g, "|");
input = input.trim();
matchRegex = new RegExp("(" + input + ")","i");
}
@@ -235,7 +235,9 @@ const Plugin = () => {
},
open: openSearch
open: openSearch,
close: closeSearch,
toggle: toggleSearch
}
};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -147,7 +147,7 @@ var zoom = (function(){
}
/**
* Pan the document when the mosue cursor approaches the edges
* Pan the document when the mouse cursor approaches the edges
* of the window.
*/
function pan() {
+8 -1
View File
@@ -1,4 +1,11 @@
/*!
* reveal.js Zoom plugin
*/
var e={id:"zoom",init:function(e){e.getRevealElement().addEventListener("mousedown",(function(n){var o=/Linux/.test(window.navigator.platform)?"ctrl":"alt",i=(e.getConfig().zoomKey?e.getConfig().zoomKey:o)+"Key",d=e.getConfig().zoomLevel?e.getConfig().zoomLevel:2;n[i]&&!e.isOverview()&&(n.preventDefault(),t.to({x:n.clientX,y:n.clientY,scale:d,pan:!1}))}))},destroy:function(){t.reset()}},t=function(){var e=1,n=0,o=0,i=-1,d=-1,l="transform"in document.body.style;function s(t,n){var o=r();if(t.width=t.width||1,t.height=t.height||1,t.x-=(window.innerWidth-t.width*n)/2,t.y-=(window.innerHeight-t.height*n)/2,l)if(1===n)document.body.style.transform="";else{var i=o.x+"px "+o.y+"px",d="translate("+-t.x+"px,"+-t.y+"px) scale("+n+")";document.body.style.transformOrigin=i,document.body.style.transform=d}else 1===n?(document.body.style.position="",document.body.style.left="",document.body.style.top="",document.body.style.width="",document.body.style.height="",document.body.style.zoom=""):(document.body.style.position="relative",document.body.style.left=-(o.x+t.x)/n+"px",document.body.style.top=-(o.y+t.y)/n+"px",document.body.style.width=100*n+"%",document.body.style.height=100*n+"%",document.body.style.zoom=n);e=n,document.documentElement.classList&&(1!==e?document.documentElement.classList.add("zoomed"):document.documentElement.classList.remove("zoomed"))}function c(){var t=.12*window.innerWidth,i=.12*window.innerHeight,d=r();o<i?window.scroll(d.x,d.y-14/e*(1-o/i)):o>window.innerHeight-i&&window.scroll(d.x,d.y+(1-(window.innerHeight-o)/i)*(14/e)),n<t?window.scroll(d.x-14/e*(1-n/t),d.y):n>window.innerWidth-t&&window.scroll(d.x+(1-(window.innerWidth-n)/t)*(14/e),d.y)}function r(){return{x:void 0!==window.scrollX?window.scrollX:window.pageXOffset,y:void 0!==window.scrollY?window.scrollY:window.pageYOffset}}return l&&(document.body.style.transition="transform 0.8s ease"),document.addEventListener("keyup",(function(n){1!==e&&27===n.keyCode&&t.out()})),document.addEventListener("mousemove",(function(t){1!==e&&(n=t.clientX,o=t.clientY)})),{to:function(n){if(1!==e)t.out();else{if(n.x=n.x||0,n.y=n.y||0,n.element){var o=n.element.getBoundingClientRect();n.x=o.left-20,n.y=o.top-20,n.width=o.width+40,n.height=o.height+40}void 0!==n.width&&void 0!==n.height&&(n.scale=Math.max(Math.min(window.innerWidth/n.width,window.innerHeight/n.height),1)),n.scale>1&&(n.x*=n.scale,n.y*=n.scale,s(n,n.scale),!1!==n.pan&&(i=setTimeout((function(){d=setInterval(c,1e3/60)}),800)))}},out:function(){clearTimeout(i),clearInterval(d),s({x:0,y:0},1),e=1},magnify:function(e){this.to(e)},reset:function(){this.out()},zoomLevel:function(){return e}}}();export default function(){return e}
const e={id:"zoom",init:function(e){e.getRevealElement().addEventListener("mousedown",(function(t){var n=/Linux/.test(window.navigator.platform)?"ctrl":"alt",i=(e.getConfig().zoomKey?e.getConfig().zoomKey:n)+"Key",d=e.getConfig().zoomLevel?e.getConfig().zoomLevel:2;t[i]&&!e.isOverview()&&(t.preventDefault(),o.to({x:t.clientX,y:t.clientY,scale:d,pan:!1}))}))},destroy:()=>{o.reset()}};var t=()=>e,o=function(){var e=1,t=0,n=0,i=-1,d=-1,l="transform"in document.body.style;function s(t,o){var n=r();if(t.width=t.width||1,t.height=t.height||1,t.x-=(window.innerWidth-t.width*o)/2,t.y-=(window.innerHeight-t.height*o)/2,l)if(1===o)document.body.style.transform="";else{var i=n.x+"px "+n.y+"px",d="translate("+-t.x+"px,"+-t.y+"px) scale("+o+")";document.body.style.transformOrigin=i,document.body.style.transform=d}else 1===o?(document.body.style.position="",document.body.style.left="",document.body.style.top="",document.body.style.width="",document.body.style.height="",document.body.style.zoom=""):(document.body.style.position="relative",document.body.style.left=-(n.x+t.x)/o+"px",document.body.style.top=-(n.y+t.y)/o+"px",document.body.style.width=100*o+"%",document.body.style.height=100*o+"%",document.body.style.zoom=o);e=o,document.documentElement.classList&&(1!==e?document.documentElement.classList.add("zoomed"):document.documentElement.classList.remove("zoomed"))}function c(){var o=.12*window.innerWidth,i=.12*window.innerHeight,d=r();n<i?window.scroll(d.x,d.y-14/e*(1-n/i)):n>window.innerHeight-i&&window.scroll(d.x,d.y+(1-(window.innerHeight-n)/i)*(14/e)),t<o?window.scroll(d.x-14/e*(1-t/o),d.y):t>window.innerWidth-o&&window.scroll(d.x+(1-(window.innerWidth-t)/o)*(14/e),d.y)}function r(){return{x:void 0!==window.scrollX?window.scrollX:window.pageXOffset,y:void 0!==window.scrollY?window.scrollY:window.pageYOffset}}return l&&(document.body.style.transition="transform 0.8s ease"),document.addEventListener("keyup",(function(t){1!==e&&27===t.keyCode&&o.out()})),document.addEventListener("mousemove",(function(o){1!==e&&(t=o.clientX,n=o.clientY)})),{to:function(t){if(1!==e)o.out();else{if(t.x=t.x||0,t.y=t.y||0,t.element){var n=t.element.getBoundingClientRect();t.x=n.left-20,t.y=n.top-20,t.width=n.width+40,t.height=n.height+40}void 0!==t.width&&void 0!==t.height&&(t.scale=Math.max(Math.min(window.innerWidth/t.width,window.innerHeight/t.height),1)),t.scale>1&&(t.x*=t.scale,t.y*=t.scale,s(t,t.scale),!1!==t.pan&&(i=setTimeout((function(){d=setInterval(c,1e3/60)}),800)))}},out:function(){clearTimeout(i),clearInterval(d),s({x:0,y:0},1),e=1},magnify:function(e){this.to(e)},reset:function(){this.out()},zoomLevel:function(){return e}}}();
/*!
* zoom.js 0.3 (modified for use with reveal.js)
* http://lab.hakim.se/zoom-js
* MIT licensed
*
* Copyright (C) 2011-2014 Hakim El Hattab, http://hakim.se
*/export{t as default};
+8 -1
View File
@@ -1,4 +1,11 @@
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).RevealZoom=t()}(this,(function(){"use strict";
/*!
* reveal.js Zoom plugin
*/var e={id:"zoom",init:function(e){e.getRevealElement().addEventListener("mousedown",(function(o){var n=/Linux/.test(window.navigator.platform)?"ctrl":"alt",i=(e.getConfig().zoomKey?e.getConfig().zoomKey:n)+"Key",d=e.getConfig().zoomLevel?e.getConfig().zoomLevel:2;o[i]&&!e.isOverview()&&(o.preventDefault(),t.to({x:o.clientX,y:o.clientY,scale:d,pan:!1}))}))},destroy:function(){t.reset()}},t=function(){var e=1,o=0,n=0,i=-1,d=-1,l="transform"in document.body.style;function s(t,o){var n=r();if(t.width=t.width||1,t.height=t.height||1,t.x-=(window.innerWidth-t.width*o)/2,t.y-=(window.innerHeight-t.height*o)/2,l)if(1===o)document.body.style.transform="";else{var i=n.x+"px "+n.y+"px",d="translate("+-t.x+"px,"+-t.y+"px) scale("+o+")";document.body.style.transformOrigin=i,document.body.style.transform=d}else 1===o?(document.body.style.position="",document.body.style.left="",document.body.style.top="",document.body.style.width="",document.body.style.height="",document.body.style.zoom=""):(document.body.style.position="relative",document.body.style.left=-(n.x+t.x)/o+"px",document.body.style.top=-(n.y+t.y)/o+"px",document.body.style.width=100*o+"%",document.body.style.height=100*o+"%",document.body.style.zoom=o);e=o,document.documentElement.classList&&(1!==e?document.documentElement.classList.add("zoomed"):document.documentElement.classList.remove("zoomed"))}function c(){var t=.12*window.innerWidth,i=.12*window.innerHeight,d=r();n<i?window.scroll(d.x,d.y-14/e*(1-n/i)):n>window.innerHeight-i&&window.scroll(d.x,d.y+(1-(window.innerHeight-n)/i)*(14/e)),o<t?window.scroll(d.x-14/e*(1-o/t),d.y):o>window.innerWidth-t&&window.scroll(d.x+(1-(window.innerWidth-o)/t)*(14/e),d.y)}function r(){return{x:void 0!==window.scrollX?window.scrollX:window.pageXOffset,y:void 0!==window.scrollY?window.scrollY:window.pageYOffset}}return l&&(document.body.style.transition="transform 0.8s ease"),document.addEventListener("keyup",(function(o){1!==e&&27===o.keyCode&&t.out()})),document.addEventListener("mousemove",(function(t){1!==e&&(o=t.clientX,n=t.clientY)})),{to:function(o){if(1!==e)t.out();else{if(o.x=o.x||0,o.y=o.y||0,o.element){var n=o.element.getBoundingClientRect();o.x=n.left-20,o.y=n.top-20,o.width=n.width+40,o.height=n.height+40}void 0!==o.width&&void 0!==o.height&&(o.scale=Math.max(Math.min(window.innerWidth/o.width,window.innerHeight/o.height),1)),o.scale>1&&(o.x*=o.scale,o.y*=o.scale,s(o,o.scale),!1!==o.pan&&(i=setTimeout((function(){d=setInterval(c,1e3/60)}),800)))}},out:function(){clearTimeout(i),clearInterval(d),s({x:0,y:0},1),e=1},magnify:function(e){this.to(e)},reset:function(){this.out()},zoomLevel:function(){return e}}}();return function(){return e}}));
*/const e={id:"zoom",init:function(e){e.getRevealElement().addEventListener("mousedown",(function(o){var n=/Linux/.test(window.navigator.platform)?"ctrl":"alt",i=(e.getConfig().zoomKey?e.getConfig().zoomKey:n)+"Key",d=e.getConfig().zoomLevel?e.getConfig().zoomLevel:2;o[i]&&!e.isOverview()&&(o.preventDefault(),t.to({x:o.clientX,y:o.clientY,scale:d,pan:!1}))}))},destroy:()=>{t.reset()}};var t=function(){var e=1,o=0,n=0,i=-1,d=-1,l="transform"in document.body.style;function s(t,o){var n=r();if(t.width=t.width||1,t.height=t.height||1,t.x-=(window.innerWidth-t.width*o)/2,t.y-=(window.innerHeight-t.height*o)/2,l)if(1===o)document.body.style.transform="";else{var i=n.x+"px "+n.y+"px",d="translate("+-t.x+"px,"+-t.y+"px) scale("+o+")";document.body.style.transformOrigin=i,document.body.style.transform=d}else 1===o?(document.body.style.position="",document.body.style.left="",document.body.style.top="",document.body.style.width="",document.body.style.height="",document.body.style.zoom=""):(document.body.style.position="relative",document.body.style.left=-(n.x+t.x)/o+"px",document.body.style.top=-(n.y+t.y)/o+"px",document.body.style.width=100*o+"%",document.body.style.height=100*o+"%",document.body.style.zoom=o);e=o,document.documentElement.classList&&(1!==e?document.documentElement.classList.add("zoomed"):document.documentElement.classList.remove("zoomed"))}function c(){var t=.12*window.innerWidth,i=.12*window.innerHeight,d=r();n<i?window.scroll(d.x,d.y-14/e*(1-n/i)):n>window.innerHeight-i&&window.scroll(d.x,d.y+(1-(window.innerHeight-n)/i)*(14/e)),o<t?window.scroll(d.x-14/e*(1-o/t),d.y):o>window.innerWidth-t&&window.scroll(d.x+(1-(window.innerWidth-o)/t)*(14/e),d.y)}function r(){return{x:void 0!==window.scrollX?window.scrollX:window.pageXOffset,y:void 0!==window.scrollY?window.scrollY:window.pageYOffset}}return l&&(document.body.style.transition="transform 0.8s ease"),document.addEventListener("keyup",(function(o){1!==e&&27===o.keyCode&&t.out()})),document.addEventListener("mousemove",(function(t){1!==e&&(o=t.clientX,n=t.clientY)})),{to:function(o){if(1!==e)t.out();else{if(o.x=o.x||0,o.y=o.y||0,o.element){var n=o.element.getBoundingClientRect();o.x=n.left-20,o.y=n.top-20,o.width=n.width+40,o.height=n.height+40}void 0!==o.width&&void 0!==o.height&&(o.scale=Math.max(Math.min(window.innerWidth/o.width,window.innerHeight/o.height),1)),o.scale>1&&(o.x*=o.scale,o.y*=o.scale,s(o,o.scale),!1!==o.pan&&(i=setTimeout((function(){d=setInterval(c,1e3/60)}),800)))}},out:function(){clearTimeout(i),clearInterval(d),s({x:0,y:0},1),e=1},magnify:function(e){this.to(e)},reset:function(){this.out()},zoomLevel:function(){return e}}}();
/*!
* zoom.js 0.3 (modified for use with reveal.js)
* http://lab.hakim.se/zoom-js
* MIT licensed
*
* Copyright (C) 2011-2014 Hakim El Hattab, http://hakim.se
*/return()=>e}));