Add framework for creating reveal.js presentations.
This commit is contained in:
parent
08053c05d8
commit
80850677e1
19
Gruntfile.js
19
Gruntfile.js
|
@ -9,14 +9,23 @@ module.exports = function (grunt) {
|
|||
options: { destPrefix: '_sass/vendor' },
|
||||
files: {
|
||||
'bulma/sass': 'bulma/sass',
|
||||
'bulma/bulma.sass': 'bulma/bulma.sass'
|
||||
'bulma/bulma.sass': 'bulma/bulma.sass',
|
||||
'reveal': 'reveal.js/css',
|
||||
}
|
||||
},
|
||||
js: {
|
||||
options: { destPrefix: 'assets/vendor/js' },
|
||||
jquery: {
|
||||
options: { destPrefix: 'assets/vendor/jquery' },
|
||||
files: {
|
||||
'jquery/jquery.min.js': 'jquery/dist/jquery.min.js',
|
||||
'jquery/jquery.min.map': 'jquery/dist/jquery.min.map'
|
||||
'jquery.min.js': 'jquery/dist/jquery.min.js',
|
||||
'jquery.min.map': 'jquery/dist/jquery.min.map',
|
||||
}
|
||||
},
|
||||
reveal: {
|
||||
options: { destPrefix: 'assets/vendor/reveal' },
|
||||
files: {
|
||||
'reveal.js': 'reveal.js/dist/reveal.js',
|
||||
'reveal.css': 'reveal.js/dist/reveal.css',
|
||||
'plugin': 'reveal.js/plugin',
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -23,5 +23,11 @@ exclude:
|
|||
- Gruntfile.js
|
||||
- .eslintrc.json
|
||||
|
||||
defaults:
|
||||
- scope:
|
||||
path: "presentations"
|
||||
values:
|
||||
layout: "presentation"
|
||||
|
||||
kramdown:
|
||||
hard_wrap: false
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
<!DOCTYPE HTML>
|
||||
{% capture reveal_home %}{{ site.baseurl }}/assets/vendor/reveal{% endcapture %}
|
||||
{% assign theme = page.theme %}
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>{{ page.title }}</title>
|
||||
|
||||
<meta name="description" content=" {{ page.description }} "/>
|
||||
<meta name="author" content="{{ page.author }}">
|
||||
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui">
|
||||
|
||||
<link rel="stylesheet" href="{{ reveal_home }}/reveal.css">
|
||||
<link rel="stylesheet" href="{{ site.baseurl }}/assets/{{ theme }}" id="theme"/>
|
||||
|
||||
<!-- Printing and PDF exports -->
|
||||
<script type="text/javascript">
|
||||
var link = document.createElement( 'link' );
|
||||
link.rel = 'stylesheet';
|
||||
link.type = 'text/css';
|
||||
link.href = window.location.search.match( /print-pdf/gi ) ? '{{ site.baseurl }}/assets/pdf.css' : '{{ site.baseurl }}/assets/paper.css';
|
||||
document.getElementsByTagName( 'head' )[0].appendChild( link );
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script type="text/javascript" src="{{ reveal_home }}/reveal.js"></script>
|
||||
<script type="text/javascript" src="{{ reveal_home }}/plugin/markdown/markdown.js"></script>
|
||||
<script type="text/javascript" src="{{ reveal_home }}/plugin/notes/notes.js"></script>
|
||||
|
||||
<div class="reveal">
|
||||
<div class="slides">
|
||||
{{ content }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
// Full list of configuration options available at:
|
||||
// https://github.com/hakimel/reveal.js#configuration
|
||||
Reveal.initialize({
|
||||
controls: true,
|
||||
progress: true,
|
||||
history: true,
|
||||
center: true,
|
||||
width: 1600,
|
||||
height: 900,
|
||||
transition: 'slide', // none/fade/slide/convex/concave/zoom
|
||||
plugins: [ RevealMarkdown, RevealNotes ]
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
A SCSS style-sheet for Pygments using the Solarized color-scheme
|
||||
|
||||
Information on Solarized is at http://ethanschoonover.com/solarized
|
||||
|
||||
Two mixins, solarized-dark and solarized-light are provided for convenience
|
||||
and if you wish to use your own primary and secondary colors, you may call the
|
||||
solarized mixin and provide parameters for the primary and secondary values.
|
||||
|
||||
The CSS class names are derived from the CSS classes that Pygments uses when
|
||||
you generate a CSS file based on a style. E.g. pygmentize -S vim -f html
|
||||
|
||||
An explanation of the Pygments token types is at http://pygments.org/docs/tokens/
|
||||
*/
|
||||
|
||||
$solarized-yellow: #b58900;
|
||||
$solarized-orange: #cb4b16;
|
||||
$solarized-red: #dc322f;
|
||||
$solarized-magenta: #d33682;
|
||||
$solarized-violet: #6c71c4;
|
||||
$solarized-blue: #268bd2;
|
||||
$solarized-cyan: #2aa198;
|
||||
$solarized-green: #859900;
|
||||
|
||||
$solarized-base03: #002b36;
|
||||
$solarized-base02: #073642;
|
||||
$solarized-base01: #586e75;
|
||||
$solarized-base00: #657b83;
|
||||
$solarized-base0: #839496;
|
||||
$solarized-base1: #93a1a1;
|
||||
$solarized-base2: #eee8d5;
|
||||
$solarized-base3: #fdf6e3;
|
||||
|
||||
$solarized-dark-primary: $solarized-base0;
|
||||
$solarized-dark-secondary: $solarized-base01;
|
||||
$solarized-dark-bg: $solarized-base03;
|
||||
|
||||
$solarized-light-primary: $solarized-base00;
|
||||
$solarized-light-secondary: $solarized-base1;
|
||||
$solarized-light-bg: $solarized-base3;
|
||||
|
||||
@mixin solarized($solarized-primary, $solarized-secondary) {
|
||||
// Cyan
|
||||
.m, // Literal.Number
|
||||
.s, // Literal.String
|
||||
.mf, // Literal.Number.Float
|
||||
.mh, // Literal.Number.Hex
|
||||
.mi, // Literal.Number.Integer
|
||||
.mo, // Literal.Number.Oct
|
||||
.sc, // Literal.String.Char
|
||||
.s2, // Literal.String.Double
|
||||
.si, // Literal.String.Interpol
|
||||
.sx, // Literal.String.Other
|
||||
.s1, // Literal.String.Single
|
||||
.ss, // Literal.String.Symbol
|
||||
.il, // Literal.Number.Integer.Long
|
||||
.gd // Generic.Deleted
|
||||
{ color: $solarized-cyan; }
|
||||
|
||||
// Green
|
||||
.k, // Keyword
|
||||
.o, // Operator
|
||||
.ow, // Operator.Word
|
||||
.cp, // Comment.Preproc
|
||||
.cs, // Comment.Special
|
||||
.gi, // Generic.Inserted
|
||||
.kn, // Keyword.Namespace
|
||||
.kp // Keyword.Pseudo
|
||||
{ color: $solarized-green; }
|
||||
|
||||
// Orange
|
||||
.x, // Other
|
||||
.gh, // Generic.Heading
|
||||
.gu, // Generic.Subheading
|
||||
.kc, // Keyword.Constant
|
||||
.no, // Name.Constant
|
||||
.ni, // Name.Entity
|
||||
.ne, // Name.Exception
|
||||
.se // Literal.String.Escape
|
||||
{ color: $solarized-orange; }
|
||||
|
||||
// Blue
|
||||
.kd, // Keyword.Declaration
|
||||
.kr, // Keyword.Reserved
|
||||
.nc, // Name.Class
|
||||
.nd, // Name.Decorator
|
||||
.nf, // Name.Function
|
||||
.nt, // Name.Tag
|
||||
.nv, // Name.Variable
|
||||
.bp, // Name.Builtin.Pseudo
|
||||
.vc, // Name.Variable.Class
|
||||
.vg, // Name.Variable.Global
|
||||
.vi // Name.Variable.Instance
|
||||
{ color: $solarized-blue; }
|
||||
|
||||
// Red
|
||||
.gr, // Generic.Error
|
||||
.kt, // Keyword.Type
|
||||
.sr, // Literal.String.Regex
|
||||
.err // Error
|
||||
{ color: $solarized-red; }
|
||||
|
||||
// Yellow
|
||||
.nb // Name.Builtin
|
||||
{ color: $solarized-yellow; }
|
||||
|
||||
// Comments
|
||||
.c, // Comment
|
||||
.cm, // Comment.Multiline
|
||||
.c1, // Comment.Single
|
||||
.sb // Literal.String.Backtick
|
||||
{ color: $solarized-secondary; }
|
||||
|
||||
// Default
|
||||
.g, // Generic
|
||||
.l, // Literal
|
||||
.n, // Name
|
||||
.p, // Punctuation
|
||||
.w, // Text.Whitespace
|
||||
.go, // Generic.Output
|
||||
.gp, // Generic.Prompt
|
||||
.gt, // Generic.Traceback
|
||||
.na, // Name.Attribute
|
||||
.nl, // Name.Label
|
||||
.nn, // Name.Namespace
|
||||
.nx, // Name.Other
|
||||
.py, // Name.Property
|
||||
.ld, // Literal.Date
|
||||
.sd // Literal.String.Doc
|
||||
{ color: $solarized-primary; }
|
||||
|
||||
.ge // Generic.Emph
|
||||
{ color: $solarized-primary; font-style: italic; }
|
||||
|
||||
.gs // Generic.Strong
|
||||
{ color: $solarized-primary; font-weight: bold; }
|
||||
}
|
||||
|
||||
.solarized-dark {
|
||||
@include solarized($solarized-dark-primary, $solarized-dark-secondary);
|
||||
background-color: $solarized-dark-bg;
|
||||
color: $solarized-dark-primary;
|
||||
}
|
||||
|
||||
.solarized-light {
|
||||
@include solarized($solarized-light-primary, $solarized-light-secondary);
|
||||
background-color: $solarized-light-bg;
|
||||
color: $solarized-light-primary;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* Layout helpers.
|
||||
*/
|
||||
|
||||
// Stretch an element vertically based on available space
|
||||
.reveal .stretch,
|
||||
.reveal .r-stretch {
|
||||
max-width: none;
|
||||
max-height: none;
|
||||
}
|
||||
|
||||
.reveal pre.stretch code,
|
||||
.reveal pre.r-stretch code {
|
||||
height: 100%;
|
||||
max-height: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
// Stack multiple elements on top of each other
|
||||
.reveal .r-stack {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
.reveal .r-stack > * {
|
||||
grid-area: 1/1;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
// Horizontal and vertical stacks
|
||||
.reveal .r-vstack,
|
||||
.reveal .r-hstack {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.reveal .r-vstack {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.reveal .r-hstack {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
// Naming based on tailwindcss
|
||||
.reveal .items-stretch { align-items: stretch; }
|
||||
.reveal .items-start { align-items: flex-start; }
|
||||
.reveal .items-center { align-items: center; }
|
||||
.reveal .items-end { align-items: flex-end; }
|
||||
|
||||
.reveal .justify-between { justify-content: space-between; }
|
||||
.reveal .justify-around { justify-content: space-around; }
|
||||
.reveal .justify-start { justify-content: flex-start; }
|
||||
.reveal .justify-center { justify-content: center; }
|
||||
.reveal .justify-end { justify-content: flex-end; }
|
|
@ -0,0 +1,173 @@
|
|||
/* Default Print Stylesheet Template
|
||||
by Rob Glazebrook of CSSnewbie.com
|
||||
Last Updated: June 4, 2008
|
||||
|
||||
Feel free (nay, compelled) to edit, append, and
|
||||
manipulate this file as you see fit. */
|
||||
|
||||
@media print {
|
||||
html:not(.print-pdf) {
|
||||
|
||||
background: #fff;
|
||||
width: auto;
|
||||
height: auto;
|
||||
overflow: visible;
|
||||
|
||||
body {
|
||||
background: #fff;
|
||||
font-size: 20pt;
|
||||
width: auto;
|
||||
height: auto;
|
||||
border: 0;
|
||||
margin: 0 5%;
|
||||
padding: 0;
|
||||
overflow: visible;
|
||||
float: none !important;
|
||||
}
|
||||
|
||||
.nestedarrow,
|
||||
.controls,
|
||||
.fork-reveal,
|
||||
.share-reveal,
|
||||
.state-background,
|
||||
.reveal .progress,
|
||||
.reveal .backgrounds,
|
||||
.reveal .slide-number {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
body, p, td, li {
|
||||
font-size: 20pt!important;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
h1,h2,h3,h4,h5,h6 {
|
||||
color: #000!important;
|
||||
height: auto;
|
||||
line-height: normal;
|
||||
text-align: left;
|
||||
letter-spacing: normal;
|
||||
}
|
||||
|
||||
/* Need to reduce the size of the fonts for printing */
|
||||
h1 { font-size: 28pt !important; }
|
||||
h2 { font-size: 24pt !important; }
|
||||
h3 { font-size: 22pt !important; }
|
||||
h4 { font-size: 22pt !important; font-variant: small-caps; }
|
||||
h5 { font-size: 21pt !important; }
|
||||
h6 { font-size: 20pt !important; font-style: italic; }
|
||||
|
||||
a:link,
|
||||
a:visited {
|
||||
color: #000 !important;
|
||||
font-weight: bold;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
ul, ol, div, p {
|
||||
visibility: visible;
|
||||
position: static;
|
||||
width: auto;
|
||||
height: auto;
|
||||
display: block;
|
||||
overflow: visible;
|
||||
margin: 0;
|
||||
text-align: left !important;
|
||||
}
|
||||
.reveal pre,
|
||||
.reveal table {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
.reveal pre code {
|
||||
padding: 20px;
|
||||
}
|
||||
.reveal blockquote {
|
||||
margin: 20px 0;
|
||||
}
|
||||
.reveal .slides {
|
||||
position: static !important;
|
||||
width: auto !important;
|
||||
height: auto !important;
|
||||
|
||||
left: 0 !important;
|
||||
top: 0 !important;
|
||||
margin-left: 0 !important;
|
||||
margin-top: 0 !important;
|
||||
padding: 0 !important;
|
||||
zoom: 1 !important;
|
||||
transform: none !important;
|
||||
|
||||
overflow: visible !important;
|
||||
display: block !important;
|
||||
|
||||
text-align: left !important;
|
||||
perspective: none;
|
||||
|
||||
perspective-origin: 50% 50%;
|
||||
}
|
||||
.reveal .slides section {
|
||||
visibility: visible !important;
|
||||
position: static !important;
|
||||
width: auto !important;
|
||||
height: auto !important;
|
||||
display: block !important;
|
||||
overflow: visible !important;
|
||||
|
||||
left: 0 !important;
|
||||
top: 0 !important;
|
||||
margin-left: 0 !important;
|
||||
margin-top: 0 !important;
|
||||
padding: 60px 20px !important;
|
||||
z-index: auto !important;
|
||||
|
||||
opacity: 1 !important;
|
||||
|
||||
page-break-after: always !important;
|
||||
|
||||
transform-style: flat !important;
|
||||
transform: none !important;
|
||||
transition: none !important;
|
||||
}
|
||||
.reveal .slides section.stack {
|
||||
padding: 0 !important;
|
||||
}
|
||||
.reveal section:last-of-type {
|
||||
page-break-after: avoid !important;
|
||||
}
|
||||
.reveal section .fragment {
|
||||
opacity: 1 !important;
|
||||
visibility: visible !important;
|
||||
|
||||
transform: none !important;
|
||||
}
|
||||
.reveal section img {
|
||||
display: block;
|
||||
margin: 15px 0px;
|
||||
background: rgba(255,255,255,1);
|
||||
border: 1px solid #666;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.reveal section small {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.reveal .hljs {
|
||||
max-height: 100%;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
word-break: break-word;
|
||||
font-size: 15pt;
|
||||
}
|
||||
|
||||
.reveal .hljs .hljs-ln-numbers {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.reveal .hljs td {
|
||||
font-size: inherit !important;
|
||||
color: inherit !important;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
/**
|
||||
* This stylesheet is used to print reveal.js
|
||||
* presentations to PDF.
|
||||
*
|
||||
* https://revealjs.revealjs.com/pdf-export/
|
||||
*/
|
||||
|
||||
html.print-pdf {
|
||||
* {
|
||||
-webkit-print-color-adjust: exact;
|
||||
}
|
||||
|
||||
& {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0 auto !important;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
float: none !important;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/* Remove any elements not needed in print. */
|
||||
.nestedarrow,
|
||||
.reveal .controls,
|
||||
.reveal .progress,
|
||||
.reveal .playback,
|
||||
.reveal.overview,
|
||||
.state-background {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.reveal pre code {
|
||||
overflow: hidden !important;
|
||||
font-family: Courier, 'Courier New', monospace !important;
|
||||
}
|
||||
|
||||
.reveal {
|
||||
width: auto !important;
|
||||
height: auto !important;
|
||||
overflow: hidden !important;
|
||||
}
|
||||
.reveal .slides {
|
||||
position: static;
|
||||
width: 100% !important;
|
||||
height: auto !important;
|
||||
zoom: 1 !important;
|
||||
pointer-events: initial;
|
||||
|
||||
left: auto;
|
||||
top: auto;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
|
||||
overflow: visible;
|
||||
display: block;
|
||||
|
||||
perspective: none;
|
||||
perspective-origin: 50% 50%;
|
||||
}
|
||||
|
||||
.reveal .slides .pdf-page {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
z-index: 1;
|
||||
|
||||
page-break-after: always;
|
||||
}
|
||||
|
||||
.reveal .slides section {
|
||||
visibility: visible !important;
|
||||
display: block !important;
|
||||
position: absolute !important;
|
||||
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
box-sizing: border-box !important;
|
||||
min-height: 1px;
|
||||
|
||||
opacity: 1 !important;
|
||||
|
||||
transform-style: flat !important;
|
||||
transform: none !important;
|
||||
}
|
||||
|
||||
.reveal section.stack {
|
||||
position: relative !important;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
page-break-after: avoid !important;
|
||||
height: auto !important;
|
||||
min-height: auto !important;
|
||||
}
|
||||
|
||||
.reveal img {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
|
||||
/* Slide backgrounds are placed inside of their slide when exporting to PDF */
|
||||
.reveal .backgrounds {
|
||||
display: none;
|
||||
}
|
||||
.reveal .slide-background {
|
||||
display: block !important;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: auto !important;
|
||||
}
|
||||
|
||||
/* Display slide speaker notes when 'showNotes' is enabled */
|
||||
.reveal.show-notes {
|
||||
max-width: none;
|
||||
max-height: none;
|
||||
}
|
||||
.reveal .speaker-notes-pdf {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
max-height: none;
|
||||
top: auto;
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
left: auto;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
/* Layout option which makes notes appear on a separate page */
|
||||
.reveal .speaker-notes-pdf[data-layout="separate-page"] {
|
||||
position: relative;
|
||||
color: inherit;
|
||||
background-color: transparent;
|
||||
padding: 20px;
|
||||
page-break-after: always;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/* Display slide numbers when 'slideNumber' is enabled */
|
||||
.reveal .slide-number-pdf {
|
||||
display: block;
|
||||
position: absolute;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* This accessibility tool is not useful in PDF and breaks it visually */
|
||||
.aria-status {
|
||||
display: none;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,21 @@
|
|||
## Dependencies
|
||||
|
||||
Themes are written using Sass to keep things modular and reduce the need for repeated selectors across files. Make sure that you have the reveal.js development environment installed before proceeding: https://revealjs.revealjs.com/installation/#full-setup
|
||||
|
||||
## Creating a Theme
|
||||
|
||||
To create your own theme, start by duplicating a ```.scss``` file in [/css/theme/source](https://github.com/hakimel/reveal.js/blob/master/css/theme/source). It will be automatically compiled from Sass to CSS (see the [gulpfile](https://github.com/hakimel/reveal.js/blob/master/gulpfile.js)) when you run `npm run build -- css-themes`.
|
||||
|
||||
Each theme file does four things in the following order:
|
||||
|
||||
1. **Include [/css/theme/template/mixins.scss](https://github.com/hakimel/reveal.js/blob/master/css/theme/template/mixins.scss)**
|
||||
Shared utility functions.
|
||||
|
||||
2. **Include [/css/theme/template/settings.scss](https://github.com/hakimel/reveal.js/blob/master/css/theme/template/settings.scss)**
|
||||
Declares a set of custom variables that the template file (step 4) expects. Can be overridden in step 3.
|
||||
|
||||
3. **Override**
|
||||
This is where you override the default theme. Either by specifying variables (see [settings.scss](https://github.com/hakimel/reveal.js/blob/master/css/theme/template/settings.scss) for reference) or by adding any selectors and styles you please.
|
||||
|
||||
4. **Include [/css/theme/template/theme.scss](https://github.com/hakimel/reveal.js/blob/master/css/theme/template/theme.scss)**
|
||||
The template theme file which will generate final CSS output based on the currently defined variables.
|
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
* Beige theme for reveal.js.
|
||||
*
|
||||
* Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se
|
||||
*/
|
||||
|
||||
|
||||
// Default mixins and settings -----------------
|
||||
@import "../template/mixins";
|
||||
@import "../template/settings";
|
||||
// ---------------------------------------------
|
||||
|
||||
|
||||
|
||||
// Include theme-specific fonts
|
||||
@import url(fonts/league-gothic/league-gothic.css);
|
||||
@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic);
|
||||
|
||||
|
||||
// Override theme settings (see ../template/settings.scss)
|
||||
$mainColor: #333;
|
||||
$headingColor: #333;
|
||||
$headingTextShadow: none;
|
||||
$backgroundColor: #f7f3de;
|
||||
$linkColor: #8b743d;
|
||||
$linkColorHover: lighten( $linkColor, 20% );
|
||||
$selectionBackgroundColor: rgba(79, 64, 28, 0.99);
|
||||
$heading1TextShadow: 0 1px 0 #ccc, 0 2px 0 #c9c9c9, 0 3px 0 #bbb, 0 4px 0 #b9b9b9, 0 5px 0 #aaa, 0 6px 1px rgba(0,0,0,.1), 0 0 5px rgba(0,0,0,.1), 0 1px 3px rgba(0,0,0,.3), 0 3px 5px rgba(0,0,0,.2), 0 5px 10px rgba(0,0,0,.25), 0 20px 20px rgba(0,0,0,.15);
|
||||
|
||||
// Background generator
|
||||
@mixin bodyBackground() {
|
||||
@include radial-gradient( rgba(247,242,211,1), rgba(255,255,255,1) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Theme template ------------------------------
|
||||
@import "../template/theme";
|
||||
// ---------------------------------------------
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* Black theme for reveal.js. This is the opposite of the 'white' theme.
|
||||
*
|
||||
* By Hakim El Hattab, http://hakim.se
|
||||
*/
|
||||
|
||||
|
||||
// Default mixins and settings -----------------
|
||||
@import "../template/mixins";
|
||||
@import "../template/settings";
|
||||
// ---------------------------------------------
|
||||
|
||||
|
||||
// Include theme-specific fonts
|
||||
@import url(fonts/source-sans-pro/source-sans-pro.css);
|
||||
|
||||
|
||||
// Override theme settings (see ../template/settings.scss)
|
||||
$backgroundColor: #191919;
|
||||
|
||||
$mainColor: #fff;
|
||||
$headingColor: #fff;
|
||||
|
||||
$mainFontSize: 42px;
|
||||
$mainFont: 'Source Sans Pro', Helvetica, sans-serif;
|
||||
$headingFont: 'Source Sans Pro', Helvetica, sans-serif;
|
||||
$headingTextShadow: none;
|
||||
$headingLetterSpacing: normal;
|
||||
$headingTextTransform: uppercase;
|
||||
$headingFontWeight: 600;
|
||||
$linkColor: #42affa;
|
||||
$linkColorHover: lighten( $linkColor, 15% );
|
||||
$selectionBackgroundColor: lighten( $linkColor, 25% );
|
||||
|
||||
$heading1Size: 2.5em;
|
||||
$heading2Size: 1.6em;
|
||||
$heading3Size: 1.3em;
|
||||
$heading4Size: 1.0em;
|
||||
|
||||
section.has-light-background {
|
||||
&, h1, h2, h3, h4, h5, h6 {
|
||||
color: #222;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Theme template ------------------------------
|
||||
@import "../template/theme";
|
||||
// ---------------------------------------------
|
|
@ -0,0 +1,78 @@
|
|||
/**
|
||||
* Blood theme for reveal.js
|
||||
* Author: Walther http://github.com/Walther
|
||||
*
|
||||
* Designed to be used with highlight.js theme
|
||||
* "monokai_sublime.css" available from
|
||||
* https://github.com/isagalaev/highlight.js/
|
||||
*
|
||||
* For other themes, change $codeBackground accordingly.
|
||||
*
|
||||
*/
|
||||
|
||||
// Default mixins and settings -----------------
|
||||
@import "../template/mixins";
|
||||
@import "../template/settings";
|
||||
// ---------------------------------------------
|
||||
|
||||
// Include theme-specific fonts
|
||||
|
||||
@import url(https://fonts.googleapis.com/css?family=Ubuntu:300,700,300italic,700italic);
|
||||
|
||||
// Colors used in the theme
|
||||
$blood: #a23;
|
||||
$coal: #222;
|
||||
$codeBackground: #23241f;
|
||||
|
||||
$backgroundColor: $coal;
|
||||
|
||||
// Main text
|
||||
$mainFont: Ubuntu, 'sans-serif';
|
||||
$mainColor: #eee;
|
||||
|
||||
// Headings
|
||||
$headingFont: Ubuntu, 'sans-serif';
|
||||
$headingTextShadow: 2px 2px 2px $coal;
|
||||
|
||||
// h1 shadow, borrowed humbly from
|
||||
// (c) Default theme by Hakim El Hattab
|
||||
$heading1TextShadow: 0 1px 0 #ccc, 0 2px 0 #c9c9c9, 0 3px 0 #bbb, 0 4px 0 #b9b9b9, 0 5px 0 #aaa, 0 6px 1px rgba(0,0,0,.1), 0 0 5px rgba(0,0,0,.1), 0 1px 3px rgba(0,0,0,.3), 0 3px 5px rgba(0,0,0,.2), 0 5px 10px rgba(0,0,0,.25), 0 20px 20px rgba(0,0,0,.15);
|
||||
|
||||
// Links
|
||||
$linkColor: $blood;
|
||||
$linkColorHover: lighten( $linkColor, 20% );
|
||||
|
||||
// Text selection
|
||||
$selectionBackgroundColor: $blood;
|
||||
$selectionColor: #fff;
|
||||
|
||||
|
||||
// Theme template ------------------------------
|
||||
@import "../template/theme";
|
||||
// ---------------------------------------------
|
||||
|
||||
// some overrides after theme template import
|
||||
|
||||
.reveal p {
|
||||
font-weight: 300;
|
||||
text-shadow: 1px 1px $coal;
|
||||
}
|
||||
|
||||
.reveal h1,
|
||||
.reveal h2,
|
||||
.reveal h3,
|
||||
.reveal h4,
|
||||
.reveal h5,
|
||||
.reveal h6 {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.reveal p code {
|
||||
background-color: $codeBackground;
|
||||
display: inline-block;
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
.reveal small code {
|
||||
vertical-align: baseline;
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
* League theme for reveal.js.
|
||||
*
|
||||
* This was the default theme pre-3.0.0.
|
||||
*
|
||||
* Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se
|
||||
*/
|
||||
|
||||
|
||||
// Default mixins and settings -----------------
|
||||
@import "../template/mixins";
|
||||
@import "../template/settings";
|
||||
// ---------------------------------------------
|
||||
|
||||
|
||||
|
||||
// Include theme-specific fonts
|
||||
@import url(fonts/league-gothic/league-gothic.css);
|
||||
@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic);
|
||||
|
||||
// Override theme settings (see ../template/settings.scss)
|
||||
$headingTextShadow: 0px 0px 6px rgba(0,0,0,0.2);
|
||||
$heading1TextShadow: 0 1px 0 #ccc, 0 2px 0 #c9c9c9, 0 3px 0 #bbb, 0 4px 0 #b9b9b9, 0 5px 0 #aaa, 0 6px 1px rgba(0,0,0,.1), 0 0 5px rgba(0,0,0,.1), 0 1px 3px rgba(0,0,0,.3), 0 3px 5px rgba(0,0,0,.2), 0 5px 10px rgba(0,0,0,.25), 0 20px 20px rgba(0,0,0,.15);
|
||||
|
||||
// Background generator
|
||||
@mixin bodyBackground() {
|
||||
@include radial-gradient( rgba(28,30,32,1), rgba(85,90,95,1) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Theme template ------------------------------
|
||||
@import "../template/theme";
|
||||
// ---------------------------------------------
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* Solarized Dark theme for reveal.js.
|
||||
* Author: Achim Staebler
|
||||
*/
|
||||
|
||||
|
||||
// Default mixins and settings -----------------
|
||||
@import "../template/mixins";
|
||||
@import "../template/settings";
|
||||
// ---------------------------------------------
|
||||
|
||||
|
||||
|
||||
// Include theme-specific fonts
|
||||
@import url(fonts/league-gothic/league-gothic.css);
|
||||
@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic);
|
||||
|
||||
/**
|
||||
* Solarized colors by Ethan Schoonover
|
||||
*/
|
||||
html * {
|
||||
color-profile: sRGB;
|
||||
rendering-intent: auto;
|
||||
}
|
||||
|
||||
// Solarized colors
|
||||
$base03: #002b36;
|
||||
$base02: #073642;
|
||||
$base01: #586e75;
|
||||
$base00: #657b83;
|
||||
$base0: #839496;
|
||||
$base1: #93a1a1;
|
||||
$base2: #eee8d5;
|
||||
$base3: #fdf6e3;
|
||||
$yellow: #b58900;
|
||||
$orange: #cb4b16;
|
||||
$red: #dc322f;
|
||||
$magenta: #d33682;
|
||||
$violet: #6c71c4;
|
||||
$blue: #268bd2;
|
||||
$cyan: #2aa198;
|
||||
$green: #859900;
|
||||
|
||||
// Override theme settings (see ../template/settings.scss)
|
||||
$mainColor: $base1;
|
||||
$headingColor: $base2;
|
||||
$headingTextShadow: none;
|
||||
$backgroundColor: $base03;
|
||||
$linkColor: $blue;
|
||||
$linkColorHover: lighten( $linkColor, 20% );
|
||||
$selectionBackgroundColor: $magenta;
|
||||
|
||||
|
||||
|
||||
// Theme template ------------------------------
|
||||
@import "../template/theme";
|
||||
// ---------------------------------------------
|
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
* Black theme for reveal.js.
|
||||
*
|
||||
* Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se
|
||||
*/
|
||||
|
||||
|
||||
// Default mixins and settings -----------------
|
||||
@import "../template/mixins";
|
||||
@import "../template/settings";
|
||||
// ---------------------------------------------
|
||||
|
||||
|
||||
// Include theme-specific fonts
|
||||
@import url(https://fonts.googleapis.com/css?family=Montserrat:700);
|
||||
@import url(https://fonts.googleapis.com/css?family=Open+Sans:400,700,400italic,700italic);
|
||||
|
||||
|
||||
// Override theme settings (see ../template/settings.scss)
|
||||
$backgroundColor: #111;
|
||||
|
||||
$mainFont: 'Open Sans', sans-serif;
|
||||
$linkColor: #e7ad52;
|
||||
$linkColorHover: lighten( $linkColor, 20% );
|
||||
$headingFont: 'Montserrat', Impact, sans-serif;
|
||||
$headingTextShadow: none;
|
||||
$headingLetterSpacing: -0.03em;
|
||||
$headingTextTransform: none;
|
||||
$selectionBackgroundColor: #e7ad52;
|
||||
|
||||
|
||||
// Theme template ------------------------------
|
||||
@import "../template/theme";
|
||||
// ---------------------------------------------
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* A simple theme for reveal.js presentations, similar
|
||||
* to the default theme. The accent color is brown.
|
||||
*
|
||||
* This theme is Copyright (C) 2012-2013 Owen Versteeg, http://owenversteeg.com - it is MIT licensed.
|
||||
*/
|
||||
|
||||
|
||||
// Default mixins and settings -----------------
|
||||
@import "../template/mixins";
|
||||
@import "../template/settings";
|
||||
// ---------------------------------------------
|
||||
|
||||
|
||||
|
||||
// Override theme settings (see ../template/settings.scss)
|
||||
$mainFont: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif;
|
||||
$mainColor: #000;
|
||||
$headingFont: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif;
|
||||
$headingColor: #383D3D;
|
||||
$headingTextShadow: none;
|
||||
$headingTextTransform: none;
|
||||
$backgroundColor: #F0F1EB;
|
||||
$linkColor: #51483D;
|
||||
$linkColorHover: lighten( $linkColor, 20% );
|
||||
$selectionBackgroundColor: #26351C;
|
||||
|
||||
.reveal a {
|
||||
line-height: 1.3em;
|
||||
}
|
||||
|
||||
|
||||
// Theme template ------------------------------
|
||||
@import "../template/theme";
|
||||
// ---------------------------------------------
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* A simple theme for reveal.js presentations, similar
|
||||
* to the default theme. The accent color is darkblue.
|
||||
*
|
||||
* This theme is Copyright (C) 2012 Owen Versteeg, https://github.com/StereotypicalApps. It is MIT licensed.
|
||||
* reveal.js is Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se
|
||||
*/
|
||||
|
||||
|
||||
// Default mixins and settings -----------------
|
||||
@import "../template/mixins";
|
||||
@import "../template/settings";
|
||||
// ---------------------------------------------
|
||||
|
||||
|
||||
|
||||
// Include theme-specific fonts
|
||||
@import url(https://fonts.googleapis.com/css?family=News+Cycle:400,700);
|
||||
@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic);
|
||||
|
||||
|
||||
// Override theme settings (see ../template/settings.scss)
|
||||
$mainFont: 'Lato', sans-serif;
|
||||
$mainColor: #000;
|
||||
$headingFont: 'News Cycle', Impact, sans-serif;
|
||||
$headingColor: #000;
|
||||
$headingTextShadow: none;
|
||||
$headingTextTransform: none;
|
||||
$backgroundColor: #fff;
|
||||
$linkColor: #00008B;
|
||||
$linkColorHover: lighten( $linkColor, 20% );
|
||||
$selectionBackgroundColor: rgba(0, 0, 0, 0.99);
|
||||
|
||||
section.has-dark-background {
|
||||
&, h1, h2, h3, h4, h5, h6 {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Theme template ------------------------------
|
||||
@import "../template/theme";
|
||||
// ---------------------------------------------
|
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
* Sky theme for reveal.js.
|
||||
*
|
||||
* Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se
|
||||
*/
|
||||
|
||||
|
||||
// Default mixins and settings -----------------
|
||||
@import "../template/mixins";
|
||||
@import "../template/settings";
|
||||
// ---------------------------------------------
|
||||
|
||||
|
||||
|
||||
// Include theme-specific fonts
|
||||
@import url(https://fonts.googleapis.com/css?family=Quicksand:400,700,400italic,700italic);
|
||||
@import url(https://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700);
|
||||
|
||||
|
||||
// Override theme settings (see ../template/settings.scss)
|
||||
$mainFont: 'Open Sans', sans-serif;
|
||||
$mainColor: #333;
|
||||
$headingFont: 'Quicksand', sans-serif;
|
||||
$headingColor: #333;
|
||||
$headingLetterSpacing: -0.08em;
|
||||
$headingTextShadow: none;
|
||||
$backgroundColor: #f7fbfc;
|
||||
$linkColor: #3b759e;
|
||||
$linkColorHover: lighten( $linkColor, 20% );
|
||||
$selectionBackgroundColor: #134674;
|
||||
|
||||
// Fix links so they are not cut off
|
||||
.reveal a {
|
||||
line-height: 1.3em;
|
||||
}
|
||||
|
||||
// Background generator
|
||||
@mixin bodyBackground() {
|
||||
@include radial-gradient( #add9e4, #f7fbfc );
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Theme template ------------------------------
|
||||
@import "../template/theme";
|
||||
// ---------------------------------------------
|
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* Solarized Light theme for reveal.js.
|
||||
* Author: Achim Staebler
|
||||
*/
|
||||
|
||||
|
||||
// Default mixins and settings -----------------
|
||||
@import "../template/mixins";
|
||||
@import "../template/settings";
|
||||
// ---------------------------------------------
|
||||
|
||||
|
||||
|
||||
// Include theme-specific fonts
|
||||
@import url(fonts/league-gothic/league-gothic.css);
|
||||
@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic);
|
||||
|
||||
|
||||
/**
|
||||
* Solarized colors by Ethan Schoonover
|
||||
*/
|
||||
html * {
|
||||
color-profile: sRGB;
|
||||
rendering-intent: auto;
|
||||
}
|
||||
|
||||
// Solarized colors
|
||||
$base03: #002b36;
|
||||
$base02: #073642;
|
||||
$base01: #586e75;
|
||||
$base00: #657b83;
|
||||
$base0: #839496;
|
||||
$base1: #93a1a1;
|
||||
$base2: #eee8d5;
|
||||
$base3: #fdf6e3;
|
||||
$yellow: #b58900;
|
||||
$orange: #cb4b16;
|
||||
$red: #dc322f;
|
||||
$magenta: #d33682;
|
||||
$violet: #6c71c4;
|
||||
$blue: #268bd2;
|
||||
$cyan: #2aa198;
|
||||
$green: #859900;
|
||||
|
||||
// Override theme settings (see ../template/settings.scss)
|
||||
$mainColor: $base00;
|
||||
$headingColor: $base01;
|
||||
$headingTextShadow: none;
|
||||
$backgroundColor: $base3;
|
||||
$linkColor: $blue;
|
||||
$linkColorHover: lighten( $linkColor, 20% );
|
||||
$selectionBackgroundColor: $magenta;
|
||||
|
||||
// Background generator
|
||||
// @mixin bodyBackground() {
|
||||
// @include radial-gradient( rgba($base3,1), rgba(lighten($base3, 20%),1) );
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// Theme template ------------------------------
|
||||
@import "../template/theme";
|
||||
// ---------------------------------------------
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* White theme for reveal.js. This is the opposite of the 'black' theme.
|
||||
*
|
||||
* By Hakim El Hattab, http://hakim.se
|
||||
*/
|
||||
|
||||
|
||||
// Default mixins and settings -----------------
|
||||
@import "../template/mixins";
|
||||
@import "../template/settings";
|
||||
// ---------------------------------------------
|
||||
|
||||
|
||||
// Include theme-specific fonts
|
||||
@import url(fonts/source-sans-pro/source-sans-pro.css);
|
||||
|
||||
|
||||
// Override theme settings (see ../template/settings.scss)
|
||||
$backgroundColor: #fff;
|
||||
|
||||
$mainColor: #222;
|
||||
$headingColor: #222;
|
||||
|
||||
$mainFontSize: 42px;
|
||||
$mainFont: 'Source Sans Pro', Helvetica, sans-serif;
|
||||
$headingFont: 'Source Sans Pro', Helvetica, sans-serif;
|
||||
$headingTextShadow: none;
|
||||
$headingLetterSpacing: normal;
|
||||
$headingTextTransform: uppercase;
|
||||
$headingFontWeight: 600;
|
||||
$linkColor: #2a76dd;
|
||||
$linkColorHover: lighten( $linkColor, 15% );
|
||||
$selectionBackgroundColor: lighten( $linkColor, 25% );
|
||||
|
||||
$heading1Size: 2.5em;
|
||||
$heading2Size: 1.6em;
|
||||
$heading3Size: 1.3em;
|
||||
$heading4Size: 1.0em;
|
||||
|
||||
section.has-dark-background {
|
||||
&, h1, h2, h3, h4, h5, h6 {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Theme template ------------------------------
|
||||
@import "../template/theme";
|
||||
// ---------------------------------------------
|
|
@ -0,0 +1,27 @@
|
|||
// Exposes theme's variables for easy re-use in CSS for plugin authors
|
||||
|
||||
:root {
|
||||
--background-color: #{$backgroundColor};
|
||||
--main-font: #{$mainFont};
|
||||
--main-font-size: #{$mainFontSize};
|
||||
--main-color: #{$mainColor};
|
||||
--block-margin: #{$blockMargin};
|
||||
--heading-margin: #{$headingMargin};
|
||||
--heading-font: #{$headingFont};
|
||||
--heading-color: #{$headingColor};
|
||||
--heading-line-height: #{$headingLineHeight};
|
||||
--heading-letter-spacing: #{$headingLetterSpacing};
|
||||
--heading-text-transform: #{$headingTextTransform};
|
||||
--heading-text-shadow: #{$headingTextShadow};
|
||||
--heading-font-weight: #{$headingFontWeight};
|
||||
--heading1-text-shadow: #{$heading1TextShadow};
|
||||
--heading1-size: #{$heading1Size};
|
||||
--heading2-size: #{$heading2Size};
|
||||
--heading3-size: #{$heading3Size};
|
||||
--heading4-size: #{$heading4Size};
|
||||
--code-font: #{$codeFont};
|
||||
--link-color: #{$linkColor};
|
||||
--link-color-hover: #{$linkColorHover};
|
||||
--selection-background-color: #{$selectionBackgroundColor};
|
||||
--selection-color: #{$selectionColor};
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
@mixin vertical-gradient( $top, $bottom ) {
|
||||
background: $top;
|
||||
background: -moz-linear-gradient( top, $top 0%, $bottom 100% );
|
||||
background: -webkit-gradient( linear, left top, left bottom, color-stop(0%,$top), color-stop(100%,$bottom) );
|
||||
background: -webkit-linear-gradient( top, $top 0%, $bottom 100% );
|
||||
background: -o-linear-gradient( top, $top 0%, $bottom 100% );
|
||||
background: -ms-linear-gradient( top, $top 0%, $bottom 100% );
|
||||
background: linear-gradient( top, $top 0%, $bottom 100% );
|
||||
}
|
||||
|
||||
@mixin horizontal-gradient( $top, $bottom ) {
|
||||
background: $top;
|
||||
background: -moz-linear-gradient( left, $top 0%, $bottom 100% );
|
||||
background: -webkit-gradient( linear, left top, right top, color-stop(0%,$top), color-stop(100%,$bottom) );
|
||||
background: -webkit-linear-gradient( left, $top 0%, $bottom 100% );
|
||||
background: -o-linear-gradient( left, $top 0%, $bottom 100% );
|
||||
background: -ms-linear-gradient( left, $top 0%, $bottom 100% );
|
||||
background: linear-gradient( left, $top 0%, $bottom 100% );
|
||||
}
|
||||
|
||||
@mixin radial-gradient( $outer, $inner, $type: circle ) {
|
||||
background: $outer;
|
||||
background: -moz-radial-gradient( center, $type cover, $inner 0%, $outer 100% );
|
||||
background: -webkit-gradient( radial, center center, 0px, center center, 100%, color-stop(0%,$inner), color-stop(100%,$outer) );
|
||||
background: -webkit-radial-gradient( center, $type cover, $inner 0%, $outer 100% );
|
||||
background: -o-radial-gradient( center, $type cover, $inner 0%, $outer 100% );
|
||||
background: -ms-radial-gradient( center, $type cover, $inner 0%, $outer 100% );
|
||||
background: radial-gradient( center, $type cover, $inner 0%, $outer 100% );
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
// Base settings for all themes that can optionally be
|
||||
// overridden by the super-theme
|
||||
|
||||
// Background of the presentation
|
||||
$backgroundColor: #2b2b2b;
|
||||
|
||||
// Primary/body text
|
||||
$mainFont: 'Lato', sans-serif;
|
||||
$mainFontSize: 40px;
|
||||
$mainColor: #eee;
|
||||
|
||||
// Vertical spacing between blocks of text
|
||||
$blockMargin: 20px;
|
||||
|
||||
// Headings
|
||||
$headingMargin: 0 0 $blockMargin 0;
|
||||
$headingFont: 'League Gothic', Impact, sans-serif;
|
||||
$headingColor: #eee;
|
||||
$headingLineHeight: 1.2;
|
||||
$headingLetterSpacing: normal;
|
||||
$headingTextTransform: uppercase;
|
||||
$headingTextShadow: none;
|
||||
$headingFontWeight: normal;
|
||||
$heading1TextShadow: $headingTextShadow;
|
||||
|
||||
$heading1Size: 3.77em;
|
||||
$heading2Size: 2.11em;
|
||||
$heading3Size: 1.55em;
|
||||
$heading4Size: 1.00em;
|
||||
|
||||
$codeFont: monospace;
|
||||
|
||||
// Links and actions
|
||||
$linkColor: #13DAEC;
|
||||
$linkColorHover: lighten( $linkColor, 20% );
|
||||
|
||||
// Text selection
|
||||
$selectionBackgroundColor: #FF5E99;
|
||||
$selectionColor: #fff;
|
||||
|
||||
// Generates the presentation background, can be overridden
|
||||
// to return a background image or gradient
|
||||
@mixin bodyBackground() {
|
||||
background: $backgroundColor;
|
||||
}
|
|
@ -0,0 +1,310 @@
|
|||
// Base theme template for reveal.js
|
||||
|
||||
/*********************************************
|
||||
* GLOBAL STYLES
|
||||
*********************************************/
|
||||
|
||||
@import "./exposer";
|
||||
|
||||
.reveal-viewport {
|
||||
@include bodyBackground();
|
||||
background-color: $backgroundColor;
|
||||
}
|
||||
|
||||
.reveal {
|
||||
font-family: $mainFont;
|
||||
font-size: $mainFontSize;
|
||||
font-weight: normal;
|
||||
color: $mainColor;
|
||||
}
|
||||
|
||||
.reveal ::selection {
|
||||
color: $selectionColor;
|
||||
background: $selectionBackgroundColor;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.reveal ::-moz-selection {
|
||||
color: $selectionColor;
|
||||
background: $selectionBackgroundColor;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.reveal .slides section,
|
||||
.reveal .slides section>section {
|
||||
line-height: 1.3;
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
/*********************************************
|
||||
* HEADERS
|
||||
*********************************************/
|
||||
|
||||
.reveal h1,
|
||||
.reveal h2,
|
||||
.reveal h3,
|
||||
.reveal h4,
|
||||
.reveal h5,
|
||||
.reveal h6 {
|
||||
margin: $headingMargin;
|
||||
color: $headingColor;
|
||||
|
||||
font-family: $headingFont;
|
||||
font-weight: $headingFontWeight;
|
||||
line-height: $headingLineHeight;
|
||||
letter-spacing: $headingLetterSpacing;
|
||||
|
||||
text-transform: $headingTextTransform;
|
||||
text-shadow: $headingTextShadow;
|
||||
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.reveal h1 {font-size: $heading1Size; }
|
||||
.reveal h2 {font-size: $heading2Size; }
|
||||
.reveal h3 {font-size: $heading3Size; }
|
||||
.reveal h4 {font-size: $heading4Size; }
|
||||
|
||||
.reveal h1 {
|
||||
text-shadow: $heading1TextShadow;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************
|
||||
* OTHER
|
||||
*********************************************/
|
||||
|
||||
.reveal p {
|
||||
margin: $blockMargin 0;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
/* Ensure certain elements are never larger than the slide itself */
|
||||
.reveal img,
|
||||
.reveal video,
|
||||
.reveal iframe {
|
||||
max-width: 95%;
|
||||
max-height: 95%;
|
||||
}
|
||||
.reveal strong,
|
||||
.reveal b {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.reveal em {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.reveal ol,
|
||||
.reveal dl,
|
||||
.reveal ul {
|
||||
display: inline-block;
|
||||
|
||||
text-align: left;
|
||||
margin: 0 0 0 1em;
|
||||
}
|
||||
|
||||
.reveal ol {
|
||||
list-style-type: decimal;
|
||||
}
|
||||
|
||||
.reveal ul {
|
||||
list-style-type: disc;
|
||||
}
|
||||
|
||||
.reveal ul ul {
|
||||
list-style-type: square;
|
||||
}
|
||||
|
||||
.reveal ul ul ul {
|
||||
list-style-type: circle;
|
||||
}
|
||||
|
||||
.reveal ul ul,
|
||||
.reveal ul ol,
|
||||
.reveal ol ol,
|
||||
.reveal ol ul {
|
||||
display: block;
|
||||
margin-left: 40px;
|
||||
}
|
||||
|
||||
.reveal dt {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.reveal dd {
|
||||
margin-left: 40px;
|
||||
}
|
||||
|
||||
.reveal blockquote {
|
||||
display: block;
|
||||
position: relative;
|
||||
width: 70%;
|
||||
margin: $blockMargin auto;
|
||||
padding: 5px;
|
||||
|
||||
font-style: italic;
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
box-shadow: 0px 0px 2px rgba(0,0,0,0.2);
|
||||
}
|
||||
.reveal blockquote p:first-child,
|
||||
.reveal blockquote p:last-child {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.reveal q {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.reveal pre {
|
||||
display: block;
|
||||
position: relative;
|
||||
width: 90%;
|
||||
margin: $blockMargin auto;
|
||||
|
||||
text-align: left;
|
||||
font-size: 0.55em;
|
||||
font-family: $codeFont;
|
||||
line-height: 1.2em;
|
||||
|
||||
word-wrap: break-word;
|
||||
|
||||
box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.reveal code {
|
||||
font-family: $codeFont;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
.reveal pre code {
|
||||
display: block;
|
||||
padding: 5px;
|
||||
overflow: auto;
|
||||
max-height: 400px;
|
||||
word-wrap: normal;
|
||||
}
|
||||
|
||||
.reveal table {
|
||||
margin: auto;
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
.reveal table th {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.reveal table th,
|
||||
.reveal table td {
|
||||
text-align: left;
|
||||
padding: 0.2em 0.5em 0.2em 0.5em;
|
||||
border-bottom: 1px solid;
|
||||
}
|
||||
|
||||
.reveal table th[align="center"],
|
||||
.reveal table td[align="center"] {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.reveal table th[align="right"],
|
||||
.reveal table td[align="right"] {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.reveal table tbody tr:last-child th,
|
||||
.reveal table tbody tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.reveal sup {
|
||||
vertical-align: super;
|
||||
font-size: smaller;
|
||||
}
|
||||
.reveal sub {
|
||||
vertical-align: sub;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
.reveal small {
|
||||
display: inline-block;
|
||||
font-size: 0.6em;
|
||||
line-height: 1.2em;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.reveal small * {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.reveal img {
|
||||
margin: $blockMargin 0;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************
|
||||
* LINKS
|
||||
*********************************************/
|
||||
|
||||
.reveal a {
|
||||
color: $linkColor;
|
||||
text-decoration: none;
|
||||
transition: color .15s ease;
|
||||
}
|
||||
.reveal a:hover {
|
||||
color: $linkColorHover;
|
||||
text-shadow: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.reveal .roll span:after {
|
||||
color: #fff;
|
||||
background: darken( $linkColor, 15% );
|
||||
}
|
||||
|
||||
|
||||
/*********************************************
|
||||
* Frame helper
|
||||
*********************************************/
|
||||
|
||||
.reveal .r-frame {
|
||||
border: 4px solid $mainColor;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.reveal a .r-frame {
|
||||
transition: all .15s linear;
|
||||
}
|
||||
|
||||
.reveal a:hover .r-frame {
|
||||
border-color: $linkColor;
|
||||
box-shadow: 0 0 20px rgba(0, 0, 0, 0.55);
|
||||
}
|
||||
|
||||
|
||||
/*********************************************
|
||||
* NAVIGATION CONTROLS
|
||||
*********************************************/
|
||||
|
||||
.reveal .controls {
|
||||
color: $linkColor;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************
|
||||
* PROGRESS BAR
|
||||
*********************************************/
|
||||
|
||||
.reveal .progress {
|
||||
background: rgba(0,0,0,0.2);
|
||||
color: $linkColor;
|
||||
}
|
||||
|
||||
/*********************************************
|
||||
* PRINT BACKGROUND
|
||||
*********************************************/
|
||||
@media print {
|
||||
.backgrounds {
|
||||
background-color: $backgroundColor;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
---
|
||||
@import "vendor/reveal/print/paper";
|
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
---
|
||||
@import "vendor/reveal/print/pdf";
|
|
@ -0,0 +1,223 @@
|
|||
---
|
||||
---
|
||||
@import "solarized";
|
||||
|
||||
@import "vendor/reveal/theme/template/mixins";
|
||||
@import "vendor/reveal/theme/template/settings";
|
||||
|
||||
// Override Reveal.js variables
|
||||
$mainColor: $solarized-dark-primary;
|
||||
$headingColor: $solarized-dark-secondary;
|
||||
$backgroundColor: $solarized-dark-bg;
|
||||
$selectionBackgroundColor: $solarized-magenta;
|
||||
$linkColor: $solarized-blue;
|
||||
$linkColorHover: lighten($linkColor, 20%);
|
||||
|
||||
$mainFont: sans-serif;
|
||||
$mainFontSize: 37px;
|
||||
|
||||
$headingFont: sans-serif;
|
||||
$headingTextTransform: none;
|
||||
$headingTextShadow: none;
|
||||
$heading1Size: 70px;
|
||||
$heading2Size: 60px;
|
||||
$heading3Size: 50px;
|
||||
$heading4Size: 40px;
|
||||
|
||||
html * {
|
||||
color-profile: sRGB;
|
||||
rendering-intent: auto;
|
||||
}
|
||||
|
||||
.reveal .slides {
|
||||
top: 45% !important;
|
||||
|
||||
section, section > section {
|
||||
padding-top: 5px;
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: transparentize($solarized-dark-bg, 0.6);
|
||||
}
|
||||
|
||||
& > pre {
|
||||
margin-top: 30px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
pre > code {
|
||||
max-height: 750px;
|
||||
background-color: transparentize($solarized-dark-bg, 0.3);
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
p {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
li > p {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
& > ul, & > ol {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.caption {
|
||||
display: block;
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
img {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
div.two_column {
|
||||
float: left;
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
div.left_float {
|
||||
float: left;
|
||||
margin-left: 10%;
|
||||
}
|
||||
|
||||
div.right_float {
|
||||
float: right;
|
||||
margin-right: 10%;
|
||||
}
|
||||
|
||||
div.action_block {
|
||||
margin-top: 50px;
|
||||
vertical-align: middle;
|
||||
|
||||
& > pre, & > img {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
& > img {
|
||||
display: inline;
|
||||
float: left;
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
& > pre > code {
|
||||
text-align: left;
|
||||
padding-top: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
table {
|
||||
margin-top: 30px;
|
||||
|
||||
tr {
|
||||
border-bottom: 1px solid $solarized-dark-secondary;
|
||||
background-color: $solarized-dark-bg;
|
||||
}
|
||||
|
||||
thead tr, tr:nth-child(even) {
|
||||
background-color: lighten($solarized-dark-bg, 5%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Syntax highlighting.
|
||||
// See http://highlightjs.readthedocs.org/en/latest/css-classes-reference.html
|
||||
.hljs, .hljs .none {
|
||||
padding: 10px;
|
||||
background: $solarized-dark-bg;
|
||||
color: $solarized-dark-primary;
|
||||
font-family: monospace;
|
||||
overflow-x: visible;
|
||||
}
|
||||
|
||||
.hljs :not(.none) {
|
||||
.hljs-function .hljs-params {
|
||||
color: $solarized-dark-primary;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.diff .hljs-header,
|
||||
.hljs-doctype,
|
||||
.hljs-pi,
|
||||
.hljs-javadoc {
|
||||
color: $solarized-dark-secondary;
|
||||
}
|
||||
|
||||
.hljs-addition,
|
||||
.css .hljs-tag,
|
||||
.hljs-request,
|
||||
.hljs-status {
|
||||
color: $solarized-green;
|
||||
}
|
||||
|
||||
.hljs-number,
|
||||
.hljs-string,
|
||||
.hljs-tag .hljs-value,
|
||||
.hljs-rules .hljs-value,
|
||||
.hljs-hexcolor,
|
||||
.hljs-title,
|
||||
.hljs-link_url {
|
||||
color: $solarized-cyan;
|
||||
}
|
||||
|
||||
.hljs-command,
|
||||
.hljs-localvars,
|
||||
.hljs-chunk,
|
||||
.hljs-decorator,
|
||||
.hljs-annotation,
|
||||
.hljs-variable,
|
||||
.hljs-built_in,
|
||||
.hljs-class .hljs-title,
|
||||
.hljs-parent,
|
||||
.hljs-id,
|
||||
.hljs-keyword,
|
||||
.method,
|
||||
.hljs-function {
|
||||
color: $solarized-blue;
|
||||
}
|
||||
|
||||
.hljs-preprocessor,
|
||||
.hljs-preprocessor .hljs-keyword,
|
||||
.hljs-pragma,
|
||||
.hljs-shebang,
|
||||
.hljs-symbol,
|
||||
.hljs-symbol .hljs-string,
|
||||
.diff .hljs-change,
|
||||
.hljs-special,
|
||||
.hljs-attr_selector,
|
||||
.hljs-subst,
|
||||
.hljs-cdata,
|
||||
.hljs-constant,
|
||||
.css .hljs-pseudo,
|
||||
.hljs-header {
|
||||
color: $solarized-orange;
|
||||
}
|
||||
|
||||
.hljs-deletion,
|
||||
.hljs-type,
|
||||
.hljs-regexp,
|
||||
.hljs-important {
|
||||
color: $solarized-red;
|
||||
}
|
||||
|
||||
.hljs-link_label {
|
||||
color: $solarized-violet;
|
||||
}
|
||||
|
||||
.hljs-link_reference {
|
||||
color: $solarized-yellow;
|
||||
}
|
||||
}
|
||||
|
||||
@import "vendor/reveal/theme/template/theme";
|
|
@ -0,0 +1,223 @@
|
|||
---
|
||||
---
|
||||
@import "solarized";
|
||||
|
||||
@import "vendor/reveal/theme/template/mixins";
|
||||
@import "vendor/reveal/theme/template/settings";
|
||||
|
||||
// Override Reveal.js variables
|
||||
$mainColor: $solarized-light-primary;
|
||||
$headingColor: $solarized-light-secondary;
|
||||
$backgroundColor: $solarized-light-bg;
|
||||
$selectionBackgroundColor: $solarized-magenta;
|
||||
$linkColor: $solarized-blue;
|
||||
$linkColorHover: lighten($linkColor, 20%);
|
||||
|
||||
$mainFont: sans-serif;
|
||||
$mainFontSize: 37px;
|
||||
|
||||
$headingFont: sans-serif;
|
||||
$headingTextTransform: none;
|
||||
$headingTextShadow: none;
|
||||
$heading1Size: 70px;
|
||||
$heading2Size: 60px;
|
||||
$heading3Size: 50px;
|
||||
$heading4Size: 40px;
|
||||
|
||||
html * {
|
||||
color-profile: sRGB;
|
||||
rendering-intent: auto;
|
||||
}
|
||||
|
||||
.reveal .slides {
|
||||
top: 45% !important;
|
||||
|
||||
section, section > section {
|
||||
padding-top: 5px;
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: transparentize($solarized-light-bg, 0.6);
|
||||
}
|
||||
|
||||
& > pre {
|
||||
margin-top: 30px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
pre > code {
|
||||
max-height: 750px;
|
||||
background-color: transparentize($solarized-dark-bg, 0.3);
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
p {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
li > p {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
& > ul, & > ol {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.caption {
|
||||
display: block;
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
img {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
div.two_column {
|
||||
float: left;
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
div.left_float {
|
||||
float: left;
|
||||
margin-left: 10%;
|
||||
}
|
||||
|
||||
div.right_float {
|
||||
float: right;
|
||||
margin-right: 10%;
|
||||
}
|
||||
|
||||
div.action_block {
|
||||
margin-top: 50px;
|
||||
vertical-align: middle;
|
||||
|
||||
& > pre, & > img {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
& > img {
|
||||
display: inline;
|
||||
float: left;
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
& > pre > code {
|
||||
text-align: left;
|
||||
padding-top: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
table {
|
||||
margin-top: 30px;
|
||||
|
||||
tr {
|
||||
border-bottom: 1px solid $solarized-light-secondary;
|
||||
background-color: $solarized-light-bg;
|
||||
}
|
||||
|
||||
thead tr, tr:nth-child(even) {
|
||||
background-color: lighten($solarized-light-bg, 5%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Syntax highlighting.
|
||||
// See http://highlightjs.readthedocs.org/en/latest/css-classes-reference.html
|
||||
.hljs, .hljs .none {
|
||||
padding: 10px;
|
||||
background: $solarized-light-bg;
|
||||
color: $solarized-light-primary;
|
||||
font-family: monospace;
|
||||
overflow-x: visible;
|
||||
}
|
||||
|
||||
.hljs :not(.none) {
|
||||
.hljs-function .hljs-params {
|
||||
color: $solarized-light-primary;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.diff .hljs-header,
|
||||
.hljs-doctype,
|
||||
.hljs-pi,
|
||||
.hljs-javadoc {
|
||||
color: $solarized-light-secondary;
|
||||
}
|
||||
|
||||
.hljs-addition,
|
||||
.css .hljs-tag,
|
||||
.hljs-request,
|
||||
.hljs-status {
|
||||
color: $solarized-green;
|
||||
}
|
||||
|
||||
.hljs-number,
|
||||
.hljs-string,
|
||||
.hljs-tag .hljs-value,
|
||||
.hljs-rules .hljs-value,
|
||||
.hljs-hexcolor,
|
||||
.hljs-title,
|
||||
.hljs-link_url {
|
||||
color: $solarized-cyan;
|
||||
}
|
||||
|
||||
.hljs-command,
|
||||
.hljs-localvars,
|
||||
.hljs-chunk,
|
||||
.hljs-decorator,
|
||||
.hljs-annotation,
|
||||
.hljs-variable,
|
||||
.hljs-built_in,
|
||||
.hljs-class .hljs-title,
|
||||
.hljs-parent,
|
||||
.hljs-id,
|
||||
.hljs-keyword,
|
||||
.method,
|
||||
.hljs-function {
|
||||
color: $solarized-blue;
|
||||
}
|
||||
|
||||
.hljs-preprocessor,
|
||||
.hljs-preprocessor .hljs-keyword,
|
||||
.hljs-pragma,
|
||||
.hljs-shebang,
|
||||
.hljs-symbol,
|
||||
.hljs-symbol .hljs-string,
|
||||
.diff .hljs-change,
|
||||
.hljs-special,
|
||||
.hljs-attr_selector,
|
||||
.hljs-subst,
|
||||
.hljs-cdata,
|
||||
.hljs-constant,
|
||||
.css .hljs-pseudo,
|
||||
.hljs-header {
|
||||
color: $solarized-orange;
|
||||
}
|
||||
|
||||
.hljs-deletion,
|
||||
.hljs-type,
|
||||
.hljs-regexp,
|
||||
.hljs-important {
|
||||
color: $solarized-red;
|
||||
}
|
||||
|
||||
.hljs-link_label {
|
||||
color: $solarized-violet;
|
||||
}
|
||||
|
||||
.hljs-link_reference {
|
||||
color: $solarized-yellow;
|
||||
}
|
||||
}
|
||||
|
||||
@import "vendor/reveal/theme/template/theme";
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
Monokai style - ported by Luigi Maselli - http://grigio.org
|
||||
*/
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
background: #272822;
|
||||
color: #ddd;
|
||||
}
|
||||
|
||||
.hljs-tag,
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag,
|
||||
.hljs-literal,
|
||||
.hljs-strong,
|
||||
.hljs-name {
|
||||
color: #f92672;
|
||||
}
|
||||
|
||||
.hljs-code {
|
||||
color: #66d9ef;
|
||||
}
|
||||
|
||||
.hljs-class .hljs-title {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.hljs-attribute,
|
||||
.hljs-symbol,
|
||||
.hljs-regexp,
|
||||
.hljs-link {
|
||||
color: #bf79db;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-bullet,
|
||||
.hljs-subst,
|
||||
.hljs-title,
|
||||
.hljs-section,
|
||||
.hljs-emphasis,
|
||||
.hljs-type,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-selector-attr,
|
||||
.hljs-selector-pseudo,
|
||||
.hljs-addition,
|
||||
.hljs-variable,
|
||||
.hljs-template-tag,
|
||||
.hljs-template-variable {
|
||||
color: #a6e22e;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-quote,
|
||||
.hljs-deletion,
|
||||
.hljs-meta {
|
||||
color: #75715e;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag,
|
||||
.hljs-literal,
|
||||
.hljs-doctag,
|
||||
.hljs-title,
|
||||
.hljs-section,
|
||||
.hljs-type,
|
||||
.hljs-selector-id {
|
||||
font-weight: bold;
|
||||
}
|
|
@ -0,0 +1,419 @@
|
|||
import hljs from 'highlight.js'
|
||||
|
||||
/* highlightjs-line-numbers.js 2.6.0 | (C) 2018 Yauheni Pakala | MIT License | github.com/wcoder/highlightjs-line-numbers.js */
|
||||
/* Edited by Hakim for reveal.js; removed async timeout */
|
||||
!function(n,e){"use strict";function t(){var n=e.createElement("style");n.type="text/css",n.innerHTML=g(".{0}{border-collapse:collapse}.{0} td{padding:0}.{1}:before{content:attr({2})}",[v,L,b]),e.getElementsByTagName("head")[0].appendChild(n)}function r(t){"interactive"===e.readyState||"complete"===e.readyState?i(t):n.addEventListener("DOMContentLoaded",function(){i(t)})}function i(t){try{var r=e.querySelectorAll("code.hljs,code.nohighlight");for(var i in r)r.hasOwnProperty(i)&&l(r[i],t)}catch(o){n.console.error("LineNumbers error: ",o)}}function l(n,e){"object"==typeof n&&f(function(){n.innerHTML=s(n,e)})}function o(n,e){if("string"==typeof n){var t=document.createElement("code");return t.innerHTML=n,s(t,e)}}function s(n,e){e=e||{singleLine:!1};var t=e.singleLine?0:1;return c(n),a(n.innerHTML,t)}function a(n,e){var t=u(n);if(""===t[t.length-1].trim()&&t.pop(),t.length>e){for(var r="",i=0,l=t.length;i<l;i++)r+=g('<tr><td class="{0}"><div class="{1} {2}" {3}="{5}"></div></td><td class="{4}"><div class="{1}">{6}</div></td></tr>',[j,m,L,b,p,i+1,t[i].length>0?t[i]:" "]);return g('<table class="{0}">{1}</table>',[v,r])}return n}function c(n){var e=n.childNodes;for(var t in e)if(e.hasOwnProperty(t)){var r=e[t];h(r.textContent)>0&&(r.childNodes.length>0?c(r):d(r.parentNode))}}function d(n){var e=n.className;if(/hljs-/.test(e)){for(var t=u(n.innerHTML),r=0,i="";r<t.length;r++){var l=t[r].length>0?t[r]:" ";i+=g('<span class="{0}">{1}</span>\n',[e,l])}n.innerHTML=i.trim()}}function u(n){return 0===n.length?[]:n.split(y)}function h(n){return(n.trim().match(y)||[]).length}function f(e){e()}function g(n,e){return n.replace(/\{(\d+)\}/g,function(n,t){return e[t]?e[t]:n})}var v="hljs-ln",m="hljs-ln-line",p="hljs-ln-code",j="hljs-ln-numbers",L="hljs-ln-n",b="data-line-number",y=/\r\n|\r|\n/g;hljs?(hljs.initLineNumbersOnLoad=r,hljs.lineNumbersBlock=l,hljs.lineNumbersValue=o,t()):n.console.error("highlight.js not detected!")}(window,document);
|
||||
|
||||
/*!
|
||||
* reveal.js plugin that adds syntax highlight support.
|
||||
*/
|
||||
|
||||
const Plugin = {
|
||||
|
||||
id: 'highlight',
|
||||
|
||||
HIGHLIGHT_STEP_DELIMITER: '|',
|
||||
HIGHLIGHT_LINE_DELIMITER: ',',
|
||||
HIGHLIGHT_LINE_RANGE_DELIMITER: '-',
|
||||
|
||||
hljs: hljs,
|
||||
|
||||
/**
|
||||
* Highlights code blocks withing the given deck.
|
||||
*
|
||||
* Note that this can be called multiple times if
|
||||
* there are multiple presentations on one page.
|
||||
*
|
||||
* @param {Reveal} reveal the reveal.js instance
|
||||
*/
|
||||
init: function( reveal ) {
|
||||
|
||||
// Read the plugin config options and provide fallbacks
|
||||
var config = reveal.getConfig().highlight || {};
|
||||
config.highlightOnLoad = typeof config.highlightOnLoad === 'boolean' ? config.highlightOnLoad : true;
|
||||
config.escapeHTML = typeof config.escapeHTML === 'boolean' ? config.escapeHTML : true;
|
||||
|
||||
[].slice.call( reveal.getRevealElement().querySelectorAll( 'pre code' ) ).forEach( function( block ) {
|
||||
|
||||
// Trim whitespace if the "data-trim" attribute is present
|
||||
if( block.hasAttribute( 'data-trim' ) && typeof block.innerHTML.trim === 'function' ) {
|
||||
block.innerHTML = betterTrim( block );
|
||||
}
|
||||
|
||||
// Escape HTML tags unless the "data-noescape" attrbute is present
|
||||
if( config.escapeHTML && !block.hasAttribute( 'data-noescape' )) {
|
||||
block.innerHTML = block.innerHTML.replace( /</g,"<").replace(/>/g, '>' );
|
||||
}
|
||||
|
||||
// Re-highlight when focus is lost (for contenteditable code)
|
||||
block.addEventListener( 'focusout', function( event ) {
|
||||
hljs.highlightBlock( event.currentTarget );
|
||||
}, false );
|
||||
|
||||
if( config.highlightOnLoad ) {
|
||||
Plugin.highlightBlock( block );
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
// If we're printing to PDF, scroll the code highlights of
|
||||
// all blocks in the deck into view at once
|
||||
reveal.on( 'pdf-ready', function() {
|
||||
[].slice.call( reveal.getRevealElement().querySelectorAll( 'pre code[data-line-numbers].current-fragment' ) ).forEach( function( block ) {
|
||||
Plugin.scrollHighlightedLineIntoView( block, {}, true );
|
||||
} );
|
||||
} );
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Highlights a code block. If the <code> node has the
|
||||
* 'data-line-numbers' attribute we also generate slide
|
||||
* numbers.
|
||||
*
|
||||
* If the block contains multiple line highlight steps,
|
||||
* we clone the block and create a fragment for each step.
|
||||
*/
|
||||
highlightBlock: function( block ) {
|
||||
|
||||
hljs.highlightBlock( block );
|
||||
|
||||
// Don't generate line numbers for empty code blocks
|
||||
if( block.innerHTML.trim().length === 0 ) return;
|
||||
|
||||
if( block.hasAttribute( 'data-line-numbers' ) ) {
|
||||
hljs.lineNumbersBlock( block, { singleLine: true } );
|
||||
|
||||
var scrollState = { currentBlock: block };
|
||||
|
||||
// If there is at least one highlight step, generate
|
||||
// fragments
|
||||
var highlightSteps = Plugin.deserializeHighlightSteps( block.getAttribute( 'data-line-numbers' ) );
|
||||
if( highlightSteps.length > 1 ) {
|
||||
|
||||
// If the original code block has a fragment-index,
|
||||
// each clone should follow in an incremental sequence
|
||||
var fragmentIndex = parseInt( block.getAttribute( 'data-fragment-index' ), 10 );
|
||||
|
||||
if( typeof fragmentIndex !== 'number' || isNaN( fragmentIndex ) ) {
|
||||
fragmentIndex = null;
|
||||
}
|
||||
|
||||
// Generate fragments for all steps except the original block
|
||||
highlightSteps.slice(1).forEach( function( highlight ) {
|
||||
|
||||
var fragmentBlock = block.cloneNode( true );
|
||||
fragmentBlock.setAttribute( 'data-line-numbers', Plugin.serializeHighlightSteps( [ highlight ] ) );
|
||||
fragmentBlock.classList.add( 'fragment' );
|
||||
block.parentNode.appendChild( fragmentBlock );
|
||||
Plugin.highlightLines( fragmentBlock );
|
||||
|
||||
if( typeof fragmentIndex === 'number' ) {
|
||||
fragmentBlock.setAttribute( 'data-fragment-index', fragmentIndex );
|
||||
fragmentIndex += 1;
|
||||
}
|
||||
else {
|
||||
fragmentBlock.removeAttribute( 'data-fragment-index' );
|
||||
}
|
||||
|
||||
// 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 ) );
|
||||
|
||||
} );
|
||||
|
||||
block.removeAttribute( 'data-fragment-index' )
|
||||
block.setAttribute( 'data-line-numbers', Plugin.serializeHighlightSteps( [ highlightSteps[0] ] ) );
|
||||
|
||||
}
|
||||
|
||||
// Scroll the first highlight into view when the slide
|
||||
// becomes visible. Note supported in IE11 since it lacks
|
||||
// support for Element.closest.
|
||||
var slide = typeof block.closest === 'function' ? block.closest( 'section:not(.stack)' ) : null;
|
||||
if( slide ) {
|
||||
var scrollFirstHighlightIntoView = function() {
|
||||
Plugin.scrollHighlightedLineIntoView( block, scrollState, true );
|
||||
slide.removeEventListener( 'visible', scrollFirstHighlightIntoView );
|
||||
}
|
||||
slide.addEventListener( 'visible', scrollFirstHighlightIntoView );
|
||||
}
|
||||
|
||||
Plugin.highlightLines( block );
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Animates scrolling to the first highlighted line
|
||||
* in the given code block.
|
||||
*/
|
||||
scrollHighlightedLineIntoView: function( block, scrollState, skipAnimation ) {
|
||||
|
||||
cancelAnimationFrame( scrollState.animationFrameID );
|
||||
|
||||
// Match the scroll position of the currently visible
|
||||
// code block
|
||||
if( scrollState.currentBlock ) {
|
||||
block.scrollTop = scrollState.currentBlock.scrollTop;
|
||||
}
|
||||
|
||||
// Remember the current code block so that we can match
|
||||
// its scroll position when showing/hiding fragments
|
||||
scrollState.currentBlock = block;
|
||||
|
||||
var highlightBounds = this.getHighlightedLineBounds( block )
|
||||
var viewportHeight = block.offsetHeight;
|
||||
|
||||
// Subtract padding from the viewport height
|
||||
var blockStyles = getComputedStyle( block );
|
||||
viewportHeight -= parseInt( blockStyles.paddingTop ) + parseInt( blockStyles.paddingBottom );
|
||||
|
||||
// Scroll position which centers all highlights
|
||||
var startTop = block.scrollTop;
|
||||
var targetTop = highlightBounds.top + ( Math.min( highlightBounds.bottom - highlightBounds.top, viewportHeight ) - viewportHeight ) / 2;
|
||||
|
||||
// Account for offsets in position applied to the
|
||||
// <table> that holds our lines of code
|
||||
var lineTable = block.querySelector( '.hljs-ln' );
|
||||
if( lineTable ) targetTop += lineTable.offsetTop - parseInt( blockStyles.paddingTop );
|
||||
|
||||
// Make sure the scroll target is within bounds
|
||||
targetTop = Math.max( Math.min( targetTop, block.scrollHeight - viewportHeight ), 0 );
|
||||
|
||||
if( skipAnimation === true || startTop === targetTop ) {
|
||||
block.scrollTop = targetTop;
|
||||
}
|
||||
else {
|
||||
|
||||
// Don't attempt to scroll if there is no overflow
|
||||
if( block.scrollHeight <= viewportHeight ) return;
|
||||
|
||||
var time = 0;
|
||||
var animate = function() {
|
||||
time = Math.min( time + 0.02, 1 );
|
||||
|
||||
// Update our eased scroll position
|
||||
block.scrollTop = startTop + ( targetTop - startTop ) * Plugin.easeInOutQuart( time );
|
||||
|
||||
// Keep animating unless we've reached the end
|
||||
if( time < 1 ) {
|
||||
scrollState.animationFrameID = requestAnimationFrame( animate );
|
||||
}
|
||||
};
|
||||
|
||||
animate();
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* The easing function used when scrolling.
|
||||
*/
|
||||
easeInOutQuart: function( t ) {
|
||||
|
||||
// easeInOutQuart
|
||||
return t<.5 ? 8*t*t*t*t : 1-8*(--t)*t*t*t;
|
||||
|
||||
},
|
||||
|
||||
getHighlightedLineBounds: function( block ) {
|
||||
|
||||
var highlightedLines = block.querySelectorAll( '.highlight-line' );
|
||||
if( highlightedLines.length === 0 ) {
|
||||
return { top: 0, bottom: 0 };
|
||||
}
|
||||
else {
|
||||
var firstHighlight = highlightedLines[0];
|
||||
var lastHighlight = highlightedLines[ highlightedLines.length -1 ];
|
||||
|
||||
return {
|
||||
top: firstHighlight.offsetTop,
|
||||
bottom: lastHighlight.offsetTop + lastHighlight.offsetHeight
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Visually emphasize specific lines within a code block.
|
||||
* This only works on blocks with line numbering turned on.
|
||||
*
|
||||
* @param {HTMLElement} block a <code> block
|
||||
* @param {String} [linesToHighlight] The lines that should be
|
||||
* highlighted in this format:
|
||||
* "1" = highlights line 1
|
||||
* "2,5" = highlights lines 2 & 5
|
||||
* "2,5-7" = highlights lines 2, 5, 6 & 7
|
||||
*/
|
||||
highlightLines: function( block, linesToHighlight ) {
|
||||
|
||||
var highlightSteps = Plugin.deserializeHighlightSteps( linesToHighlight || block.getAttribute( 'data-line-numbers' ) );
|
||||
|
||||
if( highlightSteps.length ) {
|
||||
|
||||
highlightSteps[0].forEach( function( highlight ) {
|
||||
|
||||
var elementsToHighlight = [];
|
||||
|
||||
// Highlight a range
|
||||
if( typeof highlight.end === 'number' ) {
|
||||
elementsToHighlight = [].slice.call( block.querySelectorAll( 'table tr:nth-child(n+'+highlight.start+'):nth-child(-n+'+highlight.end+')' ) );
|
||||
}
|
||||
// Highlight a single line
|
||||
else if( typeof highlight.start === 'number' ) {
|
||||
elementsToHighlight = [].slice.call( block.querySelectorAll( 'table tr:nth-child('+highlight.start+')' ) );
|
||||
}
|
||||
|
||||
if( elementsToHighlight.length ) {
|
||||
elementsToHighlight.forEach( function( lineElement ) {
|
||||
lineElement.classList.add( 'highlight-line' );
|
||||
} );
|
||||
|
||||
block.classList.add( 'has-highlights' );
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Parses and formats a user-defined string of line
|
||||
* numbers to highlight.
|
||||
*
|
||||
* @example
|
||||
* Plugin.deserializeHighlightSteps( '1,2|3,5-10' )
|
||||
* // [
|
||||
* // [ { start: 1 }, { start: 2 } ],
|
||||
* // [ { start: 3 }, { start: 5, end: 10 } ]
|
||||
* // ]
|
||||
*/
|
||||
deserializeHighlightSteps: function( highlightSteps ) {
|
||||
|
||||
// Remove whitespace
|
||||
highlightSteps = highlightSteps.replace( /\s/g, '' );
|
||||
|
||||
// Divide up our line number groups
|
||||
highlightSteps = highlightSteps.split( Plugin.HIGHLIGHT_STEP_DELIMITER );
|
||||
|
||||
return highlightSteps.map( function( highlights ) {
|
||||
|
||||
return highlights.split( Plugin.HIGHLIGHT_LINE_DELIMITER ).map( function( highlight ) {
|
||||
|
||||
// Parse valid line numbers
|
||||
if( /^[\d-]+$/.test( highlight ) ) {
|
||||
|
||||
highlight = highlight.split( Plugin.HIGHLIGHT_LINE_RANGE_DELIMITER );
|
||||
|
||||
var lineStart = parseInt( highlight[0], 10 ),
|
||||
lineEnd = parseInt( highlight[1], 10 );
|
||||
|
||||
if( isNaN( lineEnd ) ) {
|
||||
return {
|
||||
start: lineStart
|
||||
};
|
||||
}
|
||||
else {
|
||||
return {
|
||||
start: lineStart,
|
||||
end: lineEnd
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
// If no line numbers are provided, no code will be highlighted
|
||||
else {
|
||||
|
||||
return {};
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Serializes parsed line number data into a string so
|
||||
* that we can store it in the DOM.
|
||||
*/
|
||||
serializeHighlightSteps: function( highlightSteps ) {
|
||||
|
||||
return highlightSteps.map( function( highlights ) {
|
||||
|
||||
return highlights.map( function( highlight ) {
|
||||
|
||||
// Line range
|
||||
if( typeof highlight.end === 'number' ) {
|
||||
return highlight.start + Plugin.HIGHLIGHT_LINE_RANGE_DELIMITER + highlight.end;
|
||||
}
|
||||
// Single line
|
||||
else if( typeof highlight.start === 'number' ) {
|
||||
return highlight.start;
|
||||
}
|
||||
// All lines
|
||||
else {
|
||||
return '';
|
||||
}
|
||||
|
||||
} ).join( Plugin.HIGHLIGHT_LINE_DELIMITER );
|
||||
|
||||
} ).join( Plugin.HIGHLIGHT_STEP_DELIMITER );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Function to perform a better "data-trim" on code snippets
|
||||
// Will slice an indentation amount on each line of the snippet (amount based on the line having the lowest indentation length)
|
||||
function betterTrim(snippetEl) {
|
||||
// Helper functions
|
||||
function trimLeft(val) {
|
||||
// Adapted from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim#Polyfill
|
||||
return val.replace(/^[\s\uFEFF\xA0]+/g, '');
|
||||
}
|
||||
function trimLineBreaks(input) {
|
||||
var lines = input.split('\n');
|
||||
|
||||
// Trim line-breaks from the beginning
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
if (lines[i].trim() === '') {
|
||||
lines.splice(i--, 1);
|
||||
} else break;
|
||||
}
|
||||
|
||||
// Trim line-breaks from the end
|
||||
for (var i = lines.length-1; i >= 0; i--) {
|
||||
if (lines[i].trim() === '') {
|
||||
lines.splice(i, 1);
|
||||
} else break;
|
||||
}
|
||||
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
// Main function for betterTrim()
|
||||
return (function(snippetEl) {
|
||||
var content = trimLineBreaks(snippetEl.innerHTML);
|
||||
var lines = content.split('\n');
|
||||
// Calculate the minimum amount to remove on each line start of the snippet (can be 0)
|
||||
var pad = lines.reduce(function(acc, line) {
|
||||
if (line.length > 0 && trimLeft(line).length > 0 && acc > line.length - trimLeft(line).length) {
|
||||
return line.length - trimLeft(line).length;
|
||||
}
|
||||
return acc;
|
||||
}, Number.POSITIVE_INFINITY);
|
||||
// Slice each line with this amount
|
||||
return lines.map(function(line, index) {
|
||||
return line.slice(pad);
|
||||
})
|
||||
.join('\n');
|
||||
})(snippetEl);
|
||||
}
|
||||
|
||||
export default () => Plugin;
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
|
||||
Zenburn style from voldmar.ru (c) Vladimir Epifanov <voldmar@voldmar.ru>
|
||||
based on dark.css by Ivan Sagalaev
|
||||
|
||||
*/
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
background: #3f3f3f;
|
||||
color: #dcdcdc;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag,
|
||||
.hljs-tag {
|
||||
color: #e3ceab;
|
||||
}
|
||||
|
||||
.hljs-template-tag {
|
||||
color: #dcdcdc;
|
||||
}
|
||||
|
||||
.hljs-number {
|
||||
color: #8cd0d3;
|
||||
}
|
||||
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-attribute {
|
||||
color: #efdcbc;
|
||||
}
|
||||
|
||||
.hljs-literal {
|
||||
color: #efefaf;
|
||||
}
|
||||
|
||||
.hljs-subst {
|
||||
color: #8f8f8f;
|
||||
}
|
||||
|
||||
.hljs-title,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class,
|
||||
.hljs-section,
|
||||
.hljs-type {
|
||||
color: #efef8f;
|
||||
}
|
||||
|
||||
.hljs-symbol,
|
||||
.hljs-bullet,
|
||||
.hljs-link {
|
||||
color: #dca3a3;
|
||||
}
|
||||
|
||||
.hljs-deletion,
|
||||
.hljs-string,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name {
|
||||
color: #cc9393;
|
||||
}
|
||||
|
||||
.hljs-addition,
|
||||
.hljs-comment,
|
||||
.hljs-quote,
|
||||
.hljs-meta {
|
||||
color: #7f9f7f;
|
||||
}
|
||||
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,451 @@
|
|||
/*!
|
||||
* The reveal.js markdown plugin. Handles parsing of
|
||||
* markdown inside of presentations as well as loading
|
||||
* of external markdown documents.
|
||||
*/
|
||||
|
||||
import marked from 'marked'
|
||||
|
||||
const DEFAULT_SLIDE_SEPARATOR = '^\r?\n---\r?\n$',
|
||||
DEFAULT_NOTES_SEPARATOR = '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,|-]*)\]/;
|
||||
|
||||
const Plugin = () => {
|
||||
|
||||
// The reveal.js instance this plugin is attached to
|
||||
let deck;
|
||||
|
||||
/**
|
||||
* Retrieves the markdown contents of a slide section
|
||||
* element. Normalizes leading tabs/whitespace.
|
||||
*/
|
||||
function getMarkdownFromSlide( section ) {
|
||||
|
||||
// look for a <script> or <textarea data-template> wrapper
|
||||
var template = section.querySelector( '[data-template]' ) || section.querySelector( 'script' );
|
||||
|
||||
// strip leading whitespace so it isn't evaluated as code
|
||||
var 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,
|
||||
leadingTabs = text.match( /^\n?(\t*)/ )[1].length;
|
||||
|
||||
if( leadingTabs > 0 ) {
|
||||
text = text.replace( new RegExp('\\n?\\t{' + leadingTabs + '}','g'), '\n' );
|
||||
}
|
||||
else if( leadingWs > 1 ) {
|
||||
text = text.replace( new RegExp('\\n? {' + leadingWs + '}', 'g'), '\n' );
|
||||
}
|
||||
|
||||
return text;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a markdown slide section element, this will
|
||||
* return all arguments that aren't related to markdown
|
||||
* parsing. Used to forward any other user-defined arguments
|
||||
* to the output markdown slide.
|
||||
*/
|
||||
function getForwardedAttributes( section ) {
|
||||
|
||||
var attributes = section.attributes;
|
||||
var result = [];
|
||||
|
||||
for( var i = 0, len = attributes.length; i < len; i++ ) {
|
||||
var name = attributes[i].name,
|
||||
value = attributes[i].value;
|
||||
|
||||
// disregard attributes that are used for markdown loading/parsing
|
||||
if( /data\-(markdown|separator|vertical|notes)/gi.test( name ) ) continue;
|
||||
|
||||
if( value ) {
|
||||
result.push( name + '="' + value + '"' );
|
||||
}
|
||||
else {
|
||||
result.push( name );
|
||||
}
|
||||
}
|
||||
|
||||
return result.join( ' ' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Inspects the given options and fills out default
|
||||
* values for what's not defined.
|
||||
*/
|
||||
function getSlidifyOptions( options ) {
|
||||
|
||||
options = options || {};
|
||||
options.separator = options.separator || DEFAULT_SLIDE_SEPARATOR;
|
||||
options.notesSeparator = options.notesSeparator || DEFAULT_NOTES_SEPARATOR;
|
||||
options.attributes = options.attributes || '';
|
||||
|
||||
return options;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for constructing a markdown slide.
|
||||
*/
|
||||
function createMarkdownSlide( content, options ) {
|
||||
|
||||
options = getSlidifyOptions( options );
|
||||
|
||||
var notesMatch = content.split( new RegExp( options.notesSeparator, 'mgi' ) );
|
||||
|
||||
if( notesMatch.length === 2 ) {
|
||||
content = notesMatch[0] + '<aside class="notes">' + marked(notesMatch[1].trim()) + '</aside>';
|
||||
}
|
||||
|
||||
// prevent script end tags in the content from interfering
|
||||
// with parsing
|
||||
content = content.replace( /<\/script>/g, SCRIPT_END_PLACEHOLDER );
|
||||
|
||||
return '<script type="text/template">' + content + '</script>';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a data string into multiple slides based
|
||||
* on the passed in separator arguments.
|
||||
*/
|
||||
function slidify( markdown, options ) {
|
||||
|
||||
options = getSlidifyOptions( options );
|
||||
|
||||
var separatorRegex = new RegExp( options.separator + ( options.verticalSeparator ? '|' + options.verticalSeparator : '' ), 'mg' ),
|
||||
horizontalSeparatorRegex = new RegExp( options.separator );
|
||||
|
||||
var matches,
|
||||
lastIndex = 0,
|
||||
isHorizontal,
|
||||
wasHorizontal = true,
|
||||
content,
|
||||
sectionStack = [];
|
||||
|
||||
// iterate until all blocks between separators are stacked up
|
||||
while( matches = separatorRegex.exec( markdown ) ) {
|
||||
var notes = null;
|
||||
|
||||
// determine direction (horizontal by default)
|
||||
isHorizontal = horizontalSeparatorRegex.test( matches[0] );
|
||||
|
||||
if( !isHorizontal && wasHorizontal ) {
|
||||
// create vertical stack
|
||||
sectionStack.push( [] );
|
||||
}
|
||||
|
||||
// pluck slide content from markdown input
|
||||
content = markdown.substring( lastIndex, matches.index );
|
||||
|
||||
if( isHorizontal && wasHorizontal ) {
|
||||
// add to horizontal stack
|
||||
sectionStack.push( content );
|
||||
}
|
||||
else {
|
||||
// add to vertical stack
|
||||
sectionStack[sectionStack.length-1].push( content );
|
||||
}
|
||||
|
||||
lastIndex = separatorRegex.lastIndex;
|
||||
wasHorizontal = isHorizontal;
|
||||
}
|
||||
|
||||
// add the remaining slide
|
||||
( wasHorizontal ? sectionStack : sectionStack[sectionStack.length-1] ).push( markdown.substring( lastIndex ) );
|
||||
|
||||
var markdownSections = '';
|
||||
|
||||
// flatten the hierarchical stack, and insert <section data-markdown> tags
|
||||
for( var i = 0, len = sectionStack.length; i < len; i++ ) {
|
||||
// vertical
|
||||
if( sectionStack[i] instanceof Array ) {
|
||||
markdownSections += '<section '+ options.attributes +'>';
|
||||
|
||||
sectionStack[i].forEach( function( child ) {
|
||||
markdownSections += '<section data-markdown>' + createMarkdownSlide( child, options ) + '</section>';
|
||||
} );
|
||||
|
||||
markdownSections += '</section>';
|
||||
}
|
||||
else {
|
||||
markdownSections += '<section '+ options.attributes +' data-markdown>' + createMarkdownSlide( sectionStack[i], options ) + '</section>';
|
||||
}
|
||||
}
|
||||
|
||||
return markdownSections;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses any current data-markdown slides, splits
|
||||
* multi-slide markdown into separate sections and
|
||||
* handles loading of external markdown.
|
||||
*/
|
||||
function processSlides( scope ) {
|
||||
|
||||
return new Promise( function( resolve ) {
|
||||
|
||||
var externalPromises = [];
|
||||
|
||||
[].slice.call( scope.querySelectorAll( '[data-markdown]:not([data-markdown-parsed])') ).forEach( function( section, i ) {
|
||||
|
||||
if( section.getAttribute( 'data-markdown' ).length ) {
|
||||
|
||||
externalPromises.push( loadExternalMarkdown( section ).then(
|
||||
|
||||
// Finished loading external file
|
||||
function( xhr, url ) {
|
||||
section.outerHTML = slidify( xhr.responseText, {
|
||||
separator: section.getAttribute( 'data-separator' ),
|
||||
verticalSeparator: section.getAttribute( 'data-separator-vertical' ),
|
||||
notesSeparator: section.getAttribute( 'data-separator-notes' ),
|
||||
attributes: getForwardedAttributes( section )
|
||||
});
|
||||
},
|
||||
|
||||
// Failed to load markdown
|
||||
function( xhr, url ) {
|
||||
section.outerHTML = '<section data-state="alert">' +
|
||||
'ERROR: The attempt to fetch ' + url + ' failed with HTTP status ' + xhr.status + '.' +
|
||||
'Check your browser\'s JavaScript console for more details.' +
|
||||
'<p>Remember that you need to serve the presentation HTML from a HTTP server.</p>' +
|
||||
'</section>';
|
||||
}
|
||||
|
||||
) );
|
||||
|
||||
}
|
||||
else if( section.getAttribute( 'data-separator' ) || section.getAttribute( 'data-separator-vertical' ) || section.getAttribute( 'data-separator-notes' ) ) {
|
||||
|
||||
section.outerHTML = slidify( getMarkdownFromSlide( section ), {
|
||||
separator: section.getAttribute( 'data-separator' ),
|
||||
verticalSeparator: section.getAttribute( 'data-separator-vertical' ),
|
||||
notesSeparator: section.getAttribute( 'data-separator-notes' ),
|
||||
attributes: getForwardedAttributes( section )
|
||||
});
|
||||
|
||||
}
|
||||
else {
|
||||
section.innerHTML = createMarkdownSlide( getMarkdownFromSlide( section ) );
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Promise.all( externalPromises ).then( resolve );
|
||||
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
function loadExternalMarkdown( section ) {
|
||||
|
||||
return new Promise( function( resolve, reject ) {
|
||||
|
||||
var xhr = new XMLHttpRequest(),
|
||||
url = section.getAttribute( 'data-markdown' );
|
||||
|
||||
var datacharset = section.getAttribute( 'data-charset' );
|
||||
|
||||
// see https://developer.mozilla.org/en-US/docs/Web/API/element.getAttribute#Notes
|
||||
if( datacharset != null && datacharset != '' ) {
|
||||
xhr.overrideMimeType( 'text/html; charset=' + datacharset );
|
||||
}
|
||||
|
||||
xhr.onreadystatechange = function( section, xhr ) {
|
||||
if( xhr.readyState === 4 ) {
|
||||
// file protocol yields status code 0 (useful for local debug, mobile applications etc.)
|
||||
if ( ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status === 0 ) {
|
||||
|
||||
resolve( xhr, url );
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
reject( xhr, url );
|
||||
|
||||
}
|
||||
}
|
||||
}.bind( this, section, xhr );
|
||||
|
||||
xhr.open( 'GET', url, true );
|
||||
|
||||
try {
|
||||
xhr.send();
|
||||
}
|
||||
catch ( e ) {
|
||||
console.warn( 'Failed to get the Markdown file ' + url + '. Make sure that the presentation and the file are served by a HTTP server and the file can be found there. ' + e );
|
||||
resolve( xhr, url );
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a node value has the attributes pattern.
|
||||
* If yes, extract it and add that value as one or several attributes
|
||||
* to the target element.
|
||||
*
|
||||
* You need Cache Killer on Chrome to see the effect on any FOM transformation
|
||||
* directly on refresh (F5)
|
||||
* http://stackoverflow.com/questions/5690269/disabling-chrome-cache-for-website-development/7000899#answer-11786277
|
||||
*/
|
||||
function addAttributeInElement( node, elementTarget, separator ) {
|
||||
|
||||
var mardownClassesInElementsRegex = new RegExp( separator, 'mg' );
|
||||
var mardownClassRegex = new RegExp( "([^\"= ]+?)=\"([^\"]+?)\"|(data-[^\"= ]+?)(?=[\" ])", 'mg' );
|
||||
var nodeValue = node.nodeValue;
|
||||
var matches,
|
||||
matchesClass;
|
||||
if( matches = mardownClassesInElementsRegex.exec( nodeValue ) ) {
|
||||
|
||||
var classes = matches[1];
|
||||
nodeValue = nodeValue.substring( 0, matches.index ) + nodeValue.substring( mardownClassesInElementsRegex.lastIndex );
|
||||
node.nodeValue = nodeValue;
|
||||
while( matchesClass = mardownClassRegex.exec( classes ) ) {
|
||||
if( matchesClass[2] ) {
|
||||
elementTarget.setAttribute( matchesClass[1], matchesClass[2] );
|
||||
} else {
|
||||
elementTarget.setAttribute( matchesClass[3], "" );
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add attributes to the parent element of a text node,
|
||||
* or the element of an attribute node.
|
||||
*/
|
||||
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 ( i > 0 ) {
|
||||
var j = i - 1;
|
||||
while ( j >= 0 ) {
|
||||
var 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" ) {
|
||||
parentSection = childElement ;
|
||||
previousParentElement = childElement ;
|
||||
}
|
||||
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 ) {
|
||||
addAttributeInElement( element, section, separatorSectionAttributes );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts any current data-markdown slides in the
|
||||
* DOM to HTML.
|
||||
*/
|
||||
function convertSlides() {
|
||||
|
||||
var 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 );
|
||||
|
||||
section.innerHTML = marked( markdown );
|
||||
addAttributes( section, section, null, section.getAttribute( 'data-element-attributes' ) ||
|
||||
section.parentNode.getAttribute( 'data-element-attributes' ) ||
|
||||
DEFAULT_ELEMENT_ATTRIBUTES_SEPARATOR,
|
||||
section.getAttribute( 'data-attributes' ) ||
|
||||
section.parentNode.getAttribute( 'data-attributes' ) ||
|
||||
DEFAULT_SLIDE_ATTRIBUTES_SEPARATOR);
|
||||
|
||||
// If there were notes, we need to re-add them after
|
||||
// having overwritten the section's HTML
|
||||
if( notes ) {
|
||||
section.appendChild( notes );
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
return Promise.resolve();
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
id: 'markdown',
|
||||
|
||||
/**
|
||||
* Starts processing and converting Markdown within the
|
||||
* current reveal.js deck.
|
||||
*/
|
||||
init: function( reveal ) {
|
||||
|
||||
deck = reveal;
|
||||
|
||||
let renderer = new marked.Renderer();
|
||||
|
||||
renderer.code = ( code, language ) => {
|
||||
|
||||
// Off by default
|
||||
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
|
||||
if( CODE_LINE_NUMBER_REGEX.test( language ) ) {
|
||||
lineNumbers = language.match( CODE_LINE_NUMBER_REGEX )[1].trim();
|
||||
lineNumbers = `data-line-numbers="${lineNumbers}"`;
|
||||
language = language.replace( CODE_LINE_NUMBER_REGEX, '' ).trim();
|
||||
}
|
||||
|
||||
return `<pre><code ${lineNumbers} class="${language}">${code}</code></pre>`;
|
||||
};
|
||||
|
||||
marked.setOptions( {
|
||||
renderer,
|
||||
...deck.getConfig().markdown
|
||||
} );
|
||||
|
||||
return processSlides( deck.getRevealElement() ).then( convertSlides );
|
||||
|
||||
},
|
||||
|
||||
// TODO: Do these belong in the API?
|
||||
processSlides: processSlides,
|
||||
convertSlides: convertSlides,
|
||||
slidify: slidify,
|
||||
marked: marked
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
export default Plugin;
|
|
@ -0,0 +1 @@
|
|||
function e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function t(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function n(n){for(var r=1;r<arguments.length;r++){var a=null!=arguments[r]?arguments[r]:{};r%2?t(Object(a),!0).forEach((function(t){e(n,t,a[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(n,Object.getOwnPropertyDescriptors(a)):t(Object(a)).forEach((function(e){Object.defineProperty(n,e,Object.getOwnPropertyDescriptor(a,e))}))}return n}export default function(){var e,t={messageStyle:"none",tex2jax:{inlineMath:[["$","$"],["\\(","\\)"]],skipTags:["script","noscript","style","textarea","pre"]},skipStartupTypeset:!0};return{id:"math",init:function(r){var a=(e=r).getConfig().math||{},o=n(n({},t),a),c=(o.mathjax||"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js")+"?config="+(o.config||"TeX-AMS_HTML-full");o.tex2jax=n(n({},t.tex2jax),a.tex2jax),o.mathjax=o.config=null,function(e,t){var n=this,r=document.querySelector("head"),a=document.createElement("script");a.type="text/javascript",a.src=e;var o=function(){"function"==typeof t&&(t.call(),t=null)};a.onload=o,a.onreadystatechange=function(){"loaded"===n.readyState&&o()},r.appendChild(a)}(c,(function(){MathJax.Hub.Config(o),MathJax.Hub.Queue(["Typeset",MathJax.Hub,e.getRevealElement()]),MathJax.Hub.Queue(e.layout),e.on("slidechanged",(function(e){MathJax.Hub.Queue(["Typeset",MathJax.Hub,e.currentSlide])}))}))}}}
|
|
@ -0,0 +1 @@
|
|||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).RevealMath=t()}(this,(function(){"use strict";function e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function t(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function n(n){for(var r=1;r<arguments.length;r++){var a=null!=arguments[r]?arguments[r]:{};r%2?t(Object(a),!0).forEach((function(t){e(n,t,a[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(n,Object.getOwnPropertyDescriptors(a)):t(Object(a)).forEach((function(e){Object.defineProperty(n,e,Object.getOwnPropertyDescriptor(a,e))}))}return n}return function(){var e,t={messageStyle:"none",tex2jax:{inlineMath:[["$","$"],["\\(","\\)"]],skipTags:["script","noscript","style","textarea","pre"]},skipStartupTypeset:!0};return{id:"math",init:function(r){var a=(e=r).getConfig().math||{},o=n(n({},t),a),c=(o.mathjax||"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js")+"?config="+(o.config||"TeX-AMS_HTML-full");o.tex2jax=n(n({},t.tex2jax),a.tex2jax),o.mathjax=o.config=null,function(e,t){var n=this,r=document.querySelector("head"),a=document.createElement("script");a.type="text/javascript",a.src=e;var o=function(){"function"==typeof t&&(t.call(),t=null)};a.onload=o,a.onreadystatechange=function(){"loaded"===n.readyState&&o()},r.appendChild(a)}(c,(function(){MathJax.Hub.Config(o),MathJax.Hub.Queue(["Typeset",MathJax.Hub,e.getRevealElement()]),MathJax.Hub.Queue(e.layout),e.on("slidechanged",(function(e){MathJax.Hub.Queue(["Typeset",MathJax.Hub,e.currentSlide])}))}))}}}}));
|
|
@ -0,0 +1,91 @@
|
|||
/**
|
||||
* A plugin which enables rendering of math equations inside
|
||||
* of reveal.js slides. Essentially a thin wrapper for MathJax.
|
||||
*
|
||||
* @author Hakim El Hattab
|
||||
*/
|
||||
const Plugin = () => {
|
||||
|
||||
// The reveal.js instance this plugin is attached to
|
||||
let deck;
|
||||
|
||||
let defaultOptions = {
|
||||
messageStyle: 'none',
|
||||
tex2jax: {
|
||||
inlineMath: [ [ '$', '$' ], [ '\\(', '\\)' ] ],
|
||||
skipTags: [ 'script', 'noscript', 'style', 'textarea', 'pre' ]
|
||||
},
|
||||
skipStartupTypeset: true
|
||||
};
|
||||
|
||||
function loadScript( url, callback ) {
|
||||
|
||||
let head = document.querySelector( 'head' );
|
||||
let script = document.createElement( 'script' );
|
||||
script.type = 'text/javascript';
|
||||
script.src = url;
|
||||
|
||||
// Wrapper for callback to make sure it only fires once
|
||||
let finish = () => {
|
||||
if( typeof callback === 'function' ) {
|
||||
callback.call();
|
||||
callback = null;
|
||||
}
|
||||
}
|
||||
|
||||
script.onload = finish;
|
||||
|
||||
// IE
|
||||
script.onreadystatechange = () => {
|
||||
if ( this.readyState === 'loaded' ) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
// Normal browsers
|
||||
head.appendChild( script );
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
id: 'math',
|
||||
|
||||
init: function( reveal ) {
|
||||
|
||||
deck = reveal;
|
||||
|
||||
let revealOptions = deck.getConfig().math || {};
|
||||
|
||||
let options = { ...defaultOptions, ...revealOptions };
|
||||
let mathjax = options.mathjax || 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js';
|
||||
let config = options.config || 'TeX-AMS_HTML-full';
|
||||
let url = mathjax + '?config=' + config;
|
||||
|
||||
options.tex2jax = { ...defaultOptions.tex2jax, ...revealOptions.tex2jax };
|
||||
|
||||
options.mathjax = options.config = null;
|
||||
|
||||
loadScript( url, function() {
|
||||
|
||||
MathJax.Hub.Config( options );
|
||||
|
||||
// Typeset followed by an immediate reveal.js layout since
|
||||
// the typesetting process could affect slide height
|
||||
MathJax.Hub.Queue( [ 'Typeset', MathJax.Hub, deck.getRevealElement() ] );
|
||||
MathJax.Hub.Queue( deck.layout );
|
||||
|
||||
// Reprocess equations in slides when they turn visible
|
||||
deck.on( 'slidechanged', function( event ) {
|
||||
|
||||
MathJax.Hub.Queue( [ 'Typeset', MathJax.Hub, event.currentSlide ] );
|
||||
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
export default Plugin;
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,184 @@
|
|||
import speakerViewHTML from './speaker-view.html';
|
||||
|
||||
import marked from 'marked';
|
||||
|
||||
/**
|
||||
* Handles opening of and synchronization with the reveal.js
|
||||
* notes window.
|
||||
*
|
||||
* Handshake process:
|
||||
* 1. This window posts 'connect' to notes window
|
||||
* - Includes URL of presentation to show
|
||||
* 2. Notes window responds with 'connected' when it is available
|
||||
* 3. This window proceeds to send the current presentation state
|
||||
* to the notes window
|
||||
*/
|
||||
const Plugin = () => {
|
||||
|
||||
let popup = null;
|
||||
|
||||
let deck;
|
||||
|
||||
function openNotes() {
|
||||
|
||||
if (popup && !popup.closed) {
|
||||
popup.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
popup = window.open( 'about:blank', 'reveal.js - Notes', 'width=1100,height=700' );
|
||||
popup.marked = marked;
|
||||
popup.document.write( speakerViewHTML );
|
||||
|
||||
if( !popup ) {
|
||||
alert( 'Speaker view popup failed to open. Please make sure popups are allowed and reopen the speaker view.' );
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to the notes window through a postmessage handshake.
|
||||
* Using postmessage enables us to work in situations where the
|
||||
* origins differ, such as a presentation being opened from the
|
||||
* file system.
|
||||
*/
|
||||
function connect() {
|
||||
// Keep trying to connect until we get a 'connected' message back
|
||||
let connectInterval = setInterval( function() {
|
||||
popup.postMessage( JSON.stringify( {
|
||||
namespace: 'reveal-notes',
|
||||
type: 'connect',
|
||||
url: window.location.protocol + '//' + window.location.host + window.location.pathname + window.location.search,
|
||||
state: deck.getState()
|
||||
} ), '*' );
|
||||
}, 500 );
|
||||
|
||||
window.addEventListener( 'message', function( event ) {
|
||||
let data = JSON.parse( event.data );
|
||||
if( data && data.namespace === 'reveal-notes' && data.type === 'connected' ) {
|
||||
clearInterval( connectInterval );
|
||||
onConnected();
|
||||
}
|
||||
if( data && data.namespace === 'reveal-notes' && data.type === 'call' ) {
|
||||
callRevealApi( data.methodName, data.arguments, data.callId );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the specified Reveal.js method with the provided argument
|
||||
* and then pushes the result to the notes frame.
|
||||
*/
|
||||
function callRevealApi( methodName, methodArguments, callId ) {
|
||||
|
||||
let result = deck[methodName].apply( deck, methodArguments );
|
||||
popup.postMessage( JSON.stringify( {
|
||||
namespace: 'reveal-notes',
|
||||
type: 'return',
|
||||
result: result,
|
||||
callId: callId
|
||||
} ), '*' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Posts the current slide data to the notes window
|
||||
*/
|
||||
function post( event ) {
|
||||
|
||||
let slideElement = deck.getCurrentSlide(),
|
||||
notesElement = slideElement.querySelector( 'aside.notes' ),
|
||||
fragmentElement = slideElement.querySelector( '.current-fragment' );
|
||||
|
||||
let messageData = {
|
||||
namespace: 'reveal-notes',
|
||||
type: 'state',
|
||||
notes: '',
|
||||
markdown: false,
|
||||
whitespace: 'normal',
|
||||
state: deck.getState()
|
||||
};
|
||||
|
||||
// Look for notes defined in a slide attribute
|
||||
if( slideElement.hasAttribute( 'data-notes' ) ) {
|
||||
messageData.notes = slideElement.getAttribute( 'data-notes' );
|
||||
messageData.whitespace = 'pre-wrap';
|
||||
}
|
||||
|
||||
// Look for notes defined in a fragment
|
||||
if( fragmentElement ) {
|
||||
let fragmentNotes = fragmentElement.querySelector( 'aside.notes' );
|
||||
if( fragmentNotes ) {
|
||||
notesElement = fragmentNotes;
|
||||
}
|
||||
else if( fragmentElement.hasAttribute( 'data-notes' ) ) {
|
||||
messageData.notes = fragmentElement.getAttribute( 'data-notes' );
|
||||
messageData.whitespace = 'pre-wrap';
|
||||
|
||||
// In case there are slide notes
|
||||
notesElement = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Look for notes defined in an aside element
|
||||
if( notesElement ) {
|
||||
messageData.notes = notesElement.innerHTML;
|
||||
messageData.markdown = typeof notesElement.getAttribute( 'data-markdown' ) === 'string';
|
||||
}
|
||||
|
||||
popup.postMessage( JSON.stringify( messageData ), '*' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Called once we have established a connection to the notes
|
||||
* window.
|
||||
*/
|
||||
function onConnected() {
|
||||
|
||||
// Monitor events that trigger a change in state
|
||||
deck.on( 'slidechanged', post );
|
||||
deck.on( 'fragmentshown', post );
|
||||
deck.on( 'fragmenthidden', post );
|
||||
deck.on( 'overviewhidden', post );
|
||||
deck.on( 'overviewshown', post );
|
||||
deck.on( 'paused', post );
|
||||
deck.on( 'resumed', post );
|
||||
|
||||
// Post the initial state
|
||||
post();
|
||||
|
||||
}
|
||||
|
||||
connect();
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
id: 'notes',
|
||||
|
||||
init: function( reveal ) {
|
||||
|
||||
deck = reveal;
|
||||
|
||||
if( !/receiver/i.test( window.location.search ) ) {
|
||||
|
||||
// If the there's a 'notes' query set, open directly
|
||||
if( window.location.search.match( /(\?|\&)notes/gi ) !== null ) {
|
||||
openNotes();
|
||||
}
|
||||
|
||||
// Open the notes when the 's' key is hit
|
||||
deck.addKeyBinding({keyCode: 83, key: 'S', description: 'Speaker notes view'}, function() {
|
||||
openNotes();
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
open: openNotes
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
export default Plugin;
|
|
@ -0,0 +1,852 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<title>reveal.js - Speaker View</title>
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-family: Helvetica;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
#current-slide,
|
||||
#upcoming-slide,
|
||||
#speaker-controls {
|
||||
padding: 6px;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
}
|
||||
|
||||
#current-slide iframe,
|
||||
#upcoming-slide iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
#current-slide .label,
|
||||
#upcoming-slide .label {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#connection-status {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 20;
|
||||
padding: 30% 20% 20% 20%;
|
||||
font-size: 18px;
|
||||
color: #222;
|
||||
background: #fff;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.overlay-element {
|
||||
height: 34px;
|
||||
line-height: 34px;
|
||||
padding: 0 10px;
|
||||
text-shadow: none;
|
||||
background: rgba( 220, 220, 220, 0.8 );
|
||||
color: #222;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.overlay-element.interactive:hover {
|
||||
background: rgba( 220, 220, 220, 1 );
|
||||
}
|
||||
|
||||
#current-slide {
|
||||
position: absolute;
|
||||
width: 60%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
#upcoming-slide {
|
||||
position: absolute;
|
||||
width: 40%;
|
||||
height: 40%;
|
||||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
/* Speaker controls */
|
||||
#speaker-controls {
|
||||
position: absolute;
|
||||
top: 40%;
|
||||
right: 0;
|
||||
width: 40%;
|
||||
height: 60%;
|
||||
overflow: auto;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.speaker-controls-time.hidden,
|
||||
.speaker-controls-notes.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.speaker-controls-time .label,
|
||||
.speaker-controls-pace .label,
|
||||
.speaker-controls-notes .label {
|
||||
text-transform: uppercase;
|
||||
font-weight: normal;
|
||||
font-size: 0.66em;
|
||||
color: #666;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.speaker-controls-time, .speaker-controls-pace {
|
||||
border-bottom: 1px solid rgba( 200, 200, 200, 0.5 );
|
||||
margin-bottom: 10px;
|
||||
padding: 10px 16px;
|
||||
padding-bottom: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.speaker-controls-time .reset-button {
|
||||
opacity: 0;
|
||||
float: right;
|
||||
color: #666;
|
||||
text-decoration: none;
|
||||
}
|
||||
.speaker-controls-time:hover .reset-button {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.speaker-controls-time .timer,
|
||||
.speaker-controls-time .clock {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.speaker-controls-time .timer,
|
||||
.speaker-controls-time .clock,
|
||||
.speaker-controls-time .pacing .hours-value,
|
||||
.speaker-controls-time .pacing .minutes-value,
|
||||
.speaker-controls-time .pacing .seconds-value {
|
||||
font-size: 1.9em;
|
||||
}
|
||||
|
||||
.speaker-controls-time .timer {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.speaker-controls-time .clock {
|
||||
float: right;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.speaker-controls-time span.mute {
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.speaker-controls-time .pacing-title {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.speaker-controls-time .pacing.ahead {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.speaker-controls-time .pacing.on-track {
|
||||
color: green;
|
||||
}
|
||||
|
||||
.speaker-controls-time .pacing.behind {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.speaker-controls-notes {
|
||||
padding: 10px 16px;
|
||||
}
|
||||
|
||||
.speaker-controls-notes .value {
|
||||
margin-top: 5px;
|
||||
line-height: 1.4;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
/* Layout selector */
|
||||
#speaker-layout {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
color: #222;
|
||||
z-index: 10;
|
||||
}
|
||||
#speaker-layout select {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
border: 0;
|
||||
box-shadow: 0;
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
|
||||
font-size: 1em;
|
||||
background-color: transparent;
|
||||
|
||||
-moz-appearance: none;
|
||||
-webkit-appearance: none;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
#speaker-layout select:focus {
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.clear {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/* Speaker layout: Wide */
|
||||
body[data-speaker-layout="wide"] #current-slide,
|
||||
body[data-speaker-layout="wide"] #upcoming-slide {
|
||||
width: 50%;
|
||||
height: 45%;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
body[data-speaker-layout="wide"] #current-slide {
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
body[data-speaker-layout="wide"] #upcoming-slide {
|
||||
top: 0;
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
body[data-speaker-layout="wide"] #speaker-controls {
|
||||
top: 45%;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 50%;
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
/* Speaker layout: Tall */
|
||||
body[data-speaker-layout="tall"] #current-slide,
|
||||
body[data-speaker-layout="tall"] #upcoming-slide {
|
||||
width: 45%;
|
||||
height: 50%;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
body[data-speaker-layout="tall"] #current-slide {
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
body[data-speaker-layout="tall"] #upcoming-slide {
|
||||
top: 50%;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
body[data-speaker-layout="tall"] #speaker-controls {
|
||||
padding-top: 40px;
|
||||
top: 0;
|
||||
left: 45%;
|
||||
width: 55%;
|
||||
height: 100%;
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
/* Speaker layout: Notes only */
|
||||
body[data-speaker-layout="notes-only"] #current-slide,
|
||||
body[data-speaker-layout="notes-only"] #upcoming-slide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
body[data-speaker-layout="notes-only"] #speaker-controls {
|
||||
padding-top: 40px;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1080px) {
|
||||
body[data-speaker-layout="default"] #speaker-controls {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 900px) {
|
||||
body[data-speaker-layout="default"] #speaker-controls {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 800px) {
|
||||
body[data-speaker-layout="default"] #speaker-controls {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="connection-status">Loading speaker view...</div>
|
||||
|
||||
<div id="current-slide"></div>
|
||||
<div id="upcoming-slide"><span class="overlay-element label">Upcoming</span></div>
|
||||
<div id="speaker-controls">
|
||||
<div class="speaker-controls-time">
|
||||
<h4 class="label">Time <span class="reset-button">Click to Reset</span></h4>
|
||||
<div class="clock">
|
||||
<span class="clock-value">0:00 AM</span>
|
||||
</div>
|
||||
<div class="timer">
|
||||
<span class="hours-value">00</span><span class="minutes-value">:00</span><span class="seconds-value">:00</span>
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
|
||||
<h4 class="label pacing-title" style="display: none">Pacing – Time to finish current slide</h4>
|
||||
<div class="pacing" style="display: none">
|
||||
<span class="hours-value">00</span><span class="minutes-value">:00</span><span class="seconds-value">:00</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="speaker-controls-notes hidden">
|
||||
<h4 class="label">Notes</h4>
|
||||
<div class="value"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="speaker-layout" class="overlay-element interactive">
|
||||
<span class="speaker-layout-label"></span>
|
||||
<select class="speaker-layout-dropdown"></select>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
||||
(function() {
|
||||
|
||||
var notes,
|
||||
notesValue,
|
||||
currentState,
|
||||
currentSlide,
|
||||
upcomingSlide,
|
||||
layoutLabel,
|
||||
layoutDropdown,
|
||||
pendingCalls = {},
|
||||
lastRevealApiCallId = 0,
|
||||
connected = false;
|
||||
|
||||
var SPEAKER_LAYOUTS = {
|
||||
'default': 'Default',
|
||||
'wide': 'Wide',
|
||||
'tall': 'Tall',
|
||||
'notes-only': 'Notes only'
|
||||
};
|
||||
|
||||
setupLayout();
|
||||
|
||||
var connectionStatus = document.querySelector( '#connection-status' );
|
||||
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 ) {
|
||||
|
||||
clearTimeout( connectionTimeout );
|
||||
connectionStatus.style.display = 'none';
|
||||
|
||||
var data = JSON.parse( event.data );
|
||||
|
||||
// The overview mode is only useful to the reveal.js instance
|
||||
// where navigation occurs so we don't sync it
|
||||
if( data.state ) delete data.state.overview;
|
||||
|
||||
// Messages sent by the notes plugin inside of the main window
|
||||
if( data && data.namespace === 'reveal-notes' ) {
|
||||
if( data.type === 'connect' ) {
|
||||
handleConnectMessage( data );
|
||||
}
|
||||
else if( data.type === 'state' ) {
|
||||
handleStateMessage( data );
|
||||
}
|
||||
else if( data.type === 'return' ) {
|
||||
pendingCalls[data.callId](data.result);
|
||||
delete pendingCalls[data.callId];
|
||||
}
|
||||
}
|
||||
// Messages sent by the reveal.js inside of the current slide preview
|
||||
else if( data && data.namespace === 'reveal' ) {
|
||||
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 ) ) {
|
||||
|
||||
window.opener.postMessage( JSON.stringify({ method: 'setState', args: [ data.state ]} ), '*' );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
/**
|
||||
* Asynchronously calls the Reveal.js API of the main frame.
|
||||
*/
|
||||
function callRevealApi( methodName, methodArguments, callback ) {
|
||||
|
||||
var callId = ++lastRevealApiCallId;
|
||||
pendingCalls[callId] = callback;
|
||||
window.opener.postMessage( JSON.stringify( {
|
||||
namespace: 'reveal-notes',
|
||||
type: 'call',
|
||||
callId: callId,
|
||||
methodName: methodName,
|
||||
arguments: methodArguments
|
||||
} ), '*' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the main window is trying to establish a
|
||||
* connection.
|
||||
*/
|
||||
function handleConnectMessage( data ) {
|
||||
|
||||
if( connected === false ) {
|
||||
connected = true;
|
||||
|
||||
setupIframes( data );
|
||||
setupKeyboard();
|
||||
setupNotes();
|
||||
setupTimer();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the main window sends an updated state.
|
||||
*/
|
||||
function handleStateMessage( data ) {
|
||||
|
||||
// Store the most recently set state to avoid circular loops
|
||||
// applying the same state
|
||||
currentState = JSON.stringify( data.state );
|
||||
|
||||
// No need for updating the notes in case of fragment changes
|
||||
if ( data.notes ) {
|
||||
notes.classList.remove( 'hidden' );
|
||||
notesValue.style.whiteSpace = data.whitespace;
|
||||
if( data.markdown ) {
|
||||
notesValue.innerHTML = marked( data.notes );
|
||||
}
|
||||
else {
|
||||
notesValue.innerHTML = data.notes;
|
||||
}
|
||||
}
|
||||
else {
|
||||
notes.classList.add( 'hidden' );
|
||||
}
|
||||
|
||||
// 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: 'next' }), '*' );
|
||||
|
||||
}
|
||||
|
||||
// Limit to max one state update per X ms
|
||||
handleStateMessage = debounce( handleStateMessage, 200 );
|
||||
|
||||
/**
|
||||
* Forward keyboard events to the current slide window.
|
||||
* This enables keyboard events to work even if focus
|
||||
* isn't set on the current slide iframe.
|
||||
*
|
||||
* Block F5 default handling, it reloads and disconnects
|
||||
* the speaker notes window.
|
||||
*/
|
||||
function setupKeyboard() {
|
||||
|
||||
document.addEventListener( 'keydown', function( event ) {
|
||||
if( event.keyCode === 116 || ( event.metaKey && event.keyCode === 82 ) ) {
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
currentSlide.contentWindow.postMessage( JSON.stringify({ method: 'triggerKey', args: [ event.keyCode ] }), '*' );
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the preview iframes.
|
||||
*/
|
||||
function setupIframes( data ) {
|
||||
|
||||
var params = [
|
||||
'receiver',
|
||||
'progress=false',
|
||||
'history=false',
|
||||
'transition=none',
|
||||
'autoSlide=0',
|
||||
'backgroundTransition=none'
|
||||
].join( '&' );
|
||||
|
||||
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;
|
||||
|
||||
currentSlide = document.createElement( 'iframe' );
|
||||
currentSlide.setAttribute( 'width', 1280 );
|
||||
currentSlide.setAttribute( 'height', 1024 );
|
||||
currentSlide.setAttribute( 'src', currentURL );
|
||||
document.querySelector( '#current-slide' ).appendChild( currentSlide );
|
||||
|
||||
upcomingSlide = document.createElement( 'iframe' );
|
||||
upcomingSlide.setAttribute( 'width', 640 );
|
||||
upcomingSlide.setAttribute( 'height', 512 );
|
||||
upcomingSlide.setAttribute( 'src', upcomingURL );
|
||||
document.querySelector( '#upcoming-slide' ).appendChild( upcomingSlide );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the notes UI.
|
||||
*/
|
||||
function setupNotes() {
|
||||
|
||||
notes = document.querySelector( '.speaker-controls-notes' );
|
||||
notesValue = document.querySelector( '.speaker-controls-notes .value' );
|
||||
|
||||
}
|
||||
|
||||
function getTimings( callback ) {
|
||||
|
||||
callRevealApi( 'getSlidesAttributes', [], function ( slideAttributes ) {
|
||||
callRevealApi( 'getConfig', [], function ( config ) {
|
||||
var totalTime = config.totalTime;
|
||||
var minTimePerSlide = config.minimumTimePerSlide || 0;
|
||||
var defaultTiming = config.defaultTiming;
|
||||
if ((defaultTiming == null) && (totalTime == null)) {
|
||||
callback(null);
|
||||
return;
|
||||
}
|
||||
// Setting totalTime overrides defaultTiming
|
||||
if (totalTime) {
|
||||
defaultTiming = 0;
|
||||
}
|
||||
var timings = [];
|
||||
for ( var i in slideAttributes ) {
|
||||
var slide = slideAttributes[ i ];
|
||||
var timing = defaultTiming;
|
||||
if( slide.hasOwnProperty( 'data-timing' )) {
|
||||
var t = slide[ 'data-timing' ];
|
||||
timing = parseInt(t);
|
||||
if( isNaN(timing) ) {
|
||||
console.warn("Could not parse timing '" + t + "' of slide " + i + "; using default of " + defaultTiming);
|
||||
timing = defaultTiming;
|
||||
}
|
||||
}
|
||||
timings.push(timing);
|
||||
}
|
||||
if ( totalTime ) {
|
||||
// After we've allocated time to individual slides, we summarize it and
|
||||
// subtract it from the total time
|
||||
var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
|
||||
// The remaining time is divided by the number of slides that have 0 seconds
|
||||
// allocated at the moment, giving the average time-per-slide on the remaining slides
|
||||
var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
|
||||
var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
|
||||
// And now we replace every zero-value timing with that average
|
||||
timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
|
||||
}
|
||||
var slidesUnderMinimum = timings.filter( function(x) { return (x < minTimePerSlide) } ).length
|
||||
if ( slidesUnderMinimum ) {
|
||||
message = "The pacing time for " + slidesUnderMinimum + " slide(s) is under the configured minimum of " + minTimePerSlide + " seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).";
|
||||
alert(message);
|
||||
}
|
||||
callback( timings );
|
||||
} );
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of seconds allocated for presenting
|
||||
* all slides up to and including this one.
|
||||
*/
|
||||
function getTimeAllocated( timings, callback ) {
|
||||
|
||||
callRevealApi( 'getSlidePastCount', [], function ( currentSlide ) {
|
||||
var allocated = 0;
|
||||
for (var i in timings.slice(0, currentSlide + 1)) {
|
||||
allocated += timings[i];
|
||||
}
|
||||
callback( allocated );
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the timer and clock and start updating them
|
||||
* at an interval.
|
||||
*/
|
||||
function setupTimer() {
|
||||
|
||||
var start = new Date(),
|
||||
timeEl = document.querySelector( '.speaker-controls-time' ),
|
||||
clockEl = timeEl.querySelector( '.clock-value' ),
|
||||
hoursEl = timeEl.querySelector( '.hours-value' ),
|
||||
minutesEl = timeEl.querySelector( '.minutes-value' ),
|
||||
secondsEl = timeEl.querySelector( '.seconds-value' ),
|
||||
pacingTitleEl = timeEl.querySelector( '.pacing-title' ),
|
||||
pacingEl = timeEl.querySelector( '.pacing' ),
|
||||
pacingHoursEl = pacingEl.querySelector( '.hours-value' ),
|
||||
pacingMinutesEl = pacingEl.querySelector( '.minutes-value' ),
|
||||
pacingSecondsEl = pacingEl.querySelector( '.seconds-value' );
|
||||
|
||||
var timings = null;
|
||||
getTimings( function ( _timings ) {
|
||||
|
||||
timings = _timings;
|
||||
if (_timings !== null) {
|
||||
pacingTitleEl.style.removeProperty('display');
|
||||
pacingEl.style.removeProperty('display');
|
||||
}
|
||||
|
||||
// Update once directly
|
||||
_updateTimer();
|
||||
|
||||
// Then update every second
|
||||
setInterval( _updateTimer, 1000 );
|
||||
|
||||
} );
|
||||
|
||||
|
||||
function _resetTimer() {
|
||||
|
||||
if (timings == null) {
|
||||
start = new Date();
|
||||
_updateTimer();
|
||||
}
|
||||
else {
|
||||
// Reset timer to beginning of current slide
|
||||
getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
|
||||
var slideEndTiming = slideEndTimingSeconds * 1000;
|
||||
callRevealApi( 'getSlidePastCount', [], function ( currentSlide ) {
|
||||
var currentSlideTiming = timings[currentSlide] * 1000;
|
||||
var previousSlidesTiming = slideEndTiming - currentSlideTiming;
|
||||
var now = new Date();
|
||||
start = new Date(now.getTime() - previousSlidesTiming);
|
||||
_updateTimer();
|
||||
} );
|
||||
} );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
timeEl.addEventListener( 'click', function() {
|
||||
_resetTimer();
|
||||
return false;
|
||||
} );
|
||||
|
||||
function _displayTime( hrEl, minEl, secEl, time) {
|
||||
|
||||
var sign = Math.sign(time) == -1 ? "-" : "";
|
||||
time = Math.abs(Math.round(time / 1000));
|
||||
var seconds = time % 60;
|
||||
var minutes = Math.floor( time / 60 ) % 60 ;
|
||||
var hours = Math.floor( time / ( 60 * 60 )) ;
|
||||
hrEl.innerHTML = sign + zeroPadInteger( hours );
|
||||
if (hours == 0) {
|
||||
hrEl.classList.add( 'mute' );
|
||||
}
|
||||
else {
|
||||
hrEl.classList.remove( 'mute' );
|
||||
}
|
||||
minEl.innerHTML = ':' + zeroPadInteger( minutes );
|
||||
if (hours == 0 && minutes == 0) {
|
||||
minEl.classList.add( 'mute' );
|
||||
}
|
||||
else {
|
||||
minEl.classList.remove( 'mute' );
|
||||
}
|
||||
secEl.innerHTML = ':' + zeroPadInteger( seconds );
|
||||
}
|
||||
|
||||
function _updateTimer() {
|
||||
|
||||
var diff, hours, minutes, seconds,
|
||||
now = new Date();
|
||||
|
||||
diff = now.getTime() - start.getTime();
|
||||
|
||||
clockEl.innerHTML = now.toLocaleTimeString( 'en-US', { hour12: true, hour: '2-digit', minute:'2-digit' } );
|
||||
_displayTime( hoursEl, minutesEl, secondsEl, diff );
|
||||
if (timings !== null) {
|
||||
_updatePacing(diff);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function _updatePacing(diff) {
|
||||
|
||||
getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
|
||||
var slideEndTiming = slideEndTimingSeconds * 1000;
|
||||
|
||||
callRevealApi( 'getSlidePastCount', [], function ( currentSlide ) {
|
||||
var currentSlideTiming = timings[currentSlide] * 1000;
|
||||
var timeLeftCurrentSlide = slideEndTiming - diff;
|
||||
if (timeLeftCurrentSlide < 0) {
|
||||
pacingEl.className = 'pacing behind';
|
||||
}
|
||||
else if (timeLeftCurrentSlide < currentSlideTiming) {
|
||||
pacingEl.className = 'pacing on-track';
|
||||
}
|
||||
else {
|
||||
pacingEl.className = 'pacing ahead';
|
||||
}
|
||||
_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
|
||||
} );
|
||||
} );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the speaker view layout and layout selector.
|
||||
*/
|
||||
function setupLayout() {
|
||||
|
||||
layoutDropdown = document.querySelector( '.speaker-layout-dropdown' );
|
||||
layoutLabel = document.querySelector( '.speaker-layout-label' );
|
||||
|
||||
// Render the list of available layouts
|
||||
for( var id in SPEAKER_LAYOUTS ) {
|
||||
var option = document.createElement( 'option' );
|
||||
option.setAttribute( 'value', id );
|
||||
option.textContent = SPEAKER_LAYOUTS[ id ];
|
||||
layoutDropdown.appendChild( option );
|
||||
}
|
||||
|
||||
// Monitor the dropdown for changes
|
||||
layoutDropdown.addEventListener( 'change', function( event ) {
|
||||
|
||||
setLayout( layoutDropdown.value );
|
||||
|
||||
}, false );
|
||||
|
||||
// Restore any currently persisted layout
|
||||
setLayout( getLayout() );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new speaker view layout. The layout is persisted
|
||||
* in local storage.
|
||||
*/
|
||||
function setLayout( value ) {
|
||||
|
||||
var title = SPEAKER_LAYOUTS[ value ];
|
||||
|
||||
layoutLabel.innerHTML = 'Layout' + ( title ? ( ': ' + title ) : '' );
|
||||
layoutDropdown.value = value;
|
||||
|
||||
document.body.setAttribute( 'data-speaker-layout', value );
|
||||
|
||||
// Persist locally
|
||||
if( supportsLocalStorage() ) {
|
||||
window.localStorage.setItem( 'reveal-speaker-layout', value );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ID of the most recently set speaker layout
|
||||
* or our default layout if none has been set.
|
||||
*/
|
||||
function getLayout() {
|
||||
|
||||
if( supportsLocalStorage() ) {
|
||||
var layout = window.localStorage.getItem( 'reveal-speaker-layout' );
|
||||
if( layout ) {
|
||||
return layout;
|
||||
}
|
||||
}
|
||||
|
||||
// Default to the first record in the layouts hash
|
||||
for( var id in SPEAKER_LAYOUTS ) {
|
||||
return id;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function supportsLocalStorage() {
|
||||
|
||||
try {
|
||||
localStorage.setItem('test', 'test');
|
||||
localStorage.removeItem('test');
|
||||
return true;
|
||||
}
|
||||
catch( e ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function zeroPadInteger( num ) {
|
||||
|
||||
var str = '00' + parseInt( num );
|
||||
return str.substring( str.length - 2 );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Limits the frequency at which a function can be called.
|
||||
*/
|
||||
function debounce( fn, ms ) {
|
||||
|
||||
var lastTime = 0,
|
||||
timeout;
|
||||
|
||||
return function() {
|
||||
|
||||
var args = arguments;
|
||||
var context = this;
|
||||
|
||||
clearTimeout( timeout );
|
||||
|
||||
var timeSinceLastCall = Date.now() - lastTime;
|
||||
if( timeSinceLastCall > ms ) {
|
||||
fn.apply( context, args );
|
||||
lastTime = Date.now();
|
||||
}
|
||||
else {
|
||||
timeout = setTimeout( function() {
|
||||
fn.apply( context, args );
|
||||
lastTime = Date.now();
|
||||
}, ms - timeSinceLastCall );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,243 @@
|
|||
/*!
|
||||
* Handles finding a text string anywhere in the slides and showing the next occurrence to the user
|
||||
* by navigatating to that slide and highlighting it.
|
||||
*
|
||||
* @author Jon Snyder <snyder.jon@gmail.com>, February 2013
|
||||
*/
|
||||
|
||||
const Plugin = () => {
|
||||
|
||||
// The reveal.js instance this plugin is attached to
|
||||
let deck;
|
||||
|
||||
let searchElement;
|
||||
let searchButton;
|
||||
let searchInput;
|
||||
|
||||
let matchedSlides;
|
||||
let currentMatchedIndex;
|
||||
let searchboxDirty;
|
||||
let hilitor;
|
||||
|
||||
function render() {
|
||||
|
||||
searchElement = document.createElement( 'div' );
|
||||
searchElement.classList.add( 'searchbox' );
|
||||
searchElement.style.position = 'absolute';
|
||||
searchElement.style.top = '10px';
|
||||
searchElement.style.right = '10px';
|
||||
searchElement.style.zIndex = 10;
|
||||
|
||||
//embedded base64 search icon Designed by Sketchdock - http://www.sketchdock.com/:
|
||||
searchElement.innerHTML = `<input type="search" class="searchinput" placeholder="Search..." style="vertical-align: top;"/>
|
||||
</span>`;
|
||||
|
||||
searchInput = searchElement.querySelector( '.searchinput' );
|
||||
searchInput.style.width = '240px';
|
||||
searchInput.style.fontSize = '14px';
|
||||
searchInput.style.padding = '4px 6px';
|
||||
searchInput.style.color = '#000';
|
||||
searchInput.style.background = '#fff';
|
||||
searchInput.style.borderRadius = '2px';
|
||||
searchInput.style.border = '0';
|
||||
searchInput.style.outline = '0';
|
||||
searchInput.style.boxShadow = '0 2px 18px rgba(0, 0, 0, 0.2)';
|
||||
searchInput.style['-webkit-appearance'] = 'none';
|
||||
|
||||
deck.getRevealElement().appendChild( searchElement );
|
||||
|
||||
// searchButton.addEventListener( 'click', function(event) {
|
||||
// doSearch();
|
||||
// }, false );
|
||||
|
||||
searchInput.addEventListener( 'keyup', function( event ) {
|
||||
switch (event.keyCode) {
|
||||
case 13:
|
||||
event.preventDefault();
|
||||
doSearch();
|
||||
searchboxDirty = false;
|
||||
break;
|
||||
default:
|
||||
searchboxDirty = true;
|
||||
}
|
||||
}, false );
|
||||
|
||||
closeSearch();
|
||||
|
||||
}
|
||||
|
||||
function openSearch() {
|
||||
if( !searchElement ) render();
|
||||
|
||||
searchElement.style.display = 'inline';
|
||||
searchInput.focus();
|
||||
searchInput.select();
|
||||
}
|
||||
|
||||
function closeSearch() {
|
||||
if( !searchElement ) render();
|
||||
|
||||
searchElement.style.display = 'none';
|
||||
if(hilitor) hilitor.remove();
|
||||
}
|
||||
|
||||
function toggleSearch() {
|
||||
if( !searchElement ) render();
|
||||
|
||||
if (searchElement.style.display !== 'inline') {
|
||||
openSearch();
|
||||
}
|
||||
else {
|
||||
closeSearch();
|
||||
}
|
||||
}
|
||||
|
||||
function doSearch() {
|
||||
//if there's been a change in the search term, perform a new search:
|
||||
if (searchboxDirty) {
|
||||
var searchstring = searchInput.value;
|
||||
|
||||
if (searchstring === '') {
|
||||
if(hilitor) hilitor.remove();
|
||||
matchedSlides = null;
|
||||
}
|
||||
else {
|
||||
//find the keyword amongst the slides
|
||||
hilitor = new Hilitor("slidecontent");
|
||||
matchedSlides = hilitor.apply(searchstring);
|
||||
currentMatchedIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (matchedSlides) {
|
||||
//navigate to the next slide that has the keyword, wrapping to the first if necessary
|
||||
if (matchedSlides.length && (matchedSlides.length <= currentMatchedIndex)) {
|
||||
currentMatchedIndex = 0;
|
||||
}
|
||||
if (matchedSlides.length > currentMatchedIndex) {
|
||||
deck.slide(matchedSlides[currentMatchedIndex].h, matchedSlides[currentMatchedIndex].v);
|
||||
currentMatchedIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Original JavaScript code by Chirp Internet: www.chirp.com.au
|
||||
// Please acknowledge use of this code by including this header.
|
||||
// 2/2013 jon: modified regex to display any match, not restricted to word boundaries.
|
||||
function Hilitor(id, tag) {
|
||||
|
||||
var targetNode = document.getElementById(id) || document.body;
|
||||
var hiliteTag = tag || "EM";
|
||||
var skipTags = new RegExp("^(?:" + hiliteTag + "|SCRIPT|FORM)$");
|
||||
var colors = ["#ff6", "#a0ffff", "#9f9", "#f99", "#f6f"];
|
||||
var wordColor = [];
|
||||
var colorIdx = 0;
|
||||
var matchRegex = "";
|
||||
var matchingSlides = [];
|
||||
|
||||
this.setRegex = function(input)
|
||||
{
|
||||
input = input.replace(/^[^\w]+|[^\w]+$/g, "").replace(/[^\w'-]+/g, "|");
|
||||
matchRegex = new RegExp("(" + input + ")","i");
|
||||
}
|
||||
|
||||
this.getRegex = function()
|
||||
{
|
||||
return matchRegex.toString().replace(/^\/\\b\(|\)\\b\/i$/g, "").replace(/\|/g, " ");
|
||||
}
|
||||
|
||||
// recursively apply word highlighting
|
||||
this.hiliteWords = function(node)
|
||||
{
|
||||
if(node == undefined || !node) return;
|
||||
if(!matchRegex) return;
|
||||
if(skipTags.test(node.nodeName)) return;
|
||||
|
||||
if(node.hasChildNodes()) {
|
||||
for(var i=0; i < node.childNodes.length; i++)
|
||||
this.hiliteWords(node.childNodes[i]);
|
||||
}
|
||||
if(node.nodeType == 3) { // NODE_TEXT
|
||||
var nv, regs;
|
||||
if((nv = node.nodeValue) && (regs = matchRegex.exec(nv))) {
|
||||
//find the slide's section element and save it in our list of matching slides
|
||||
var secnode = node;
|
||||
while (secnode != null && secnode.nodeName != 'SECTION') {
|
||||
secnode = secnode.parentNode;
|
||||
}
|
||||
|
||||
var slideIndex = deck.getIndices(secnode);
|
||||
var slidelen = matchingSlides.length;
|
||||
var alreadyAdded = false;
|
||||
for (var i=0; i < slidelen; i++) {
|
||||
if ( (matchingSlides[i].h === slideIndex.h) && (matchingSlides[i].v === slideIndex.v) ) {
|
||||
alreadyAdded = true;
|
||||
}
|
||||
}
|
||||
if (! alreadyAdded) {
|
||||
matchingSlides.push(slideIndex);
|
||||
}
|
||||
|
||||
if(!wordColor[regs[0].toLowerCase()]) {
|
||||
wordColor[regs[0].toLowerCase()] = colors[colorIdx++ % colors.length];
|
||||
}
|
||||
|
||||
var match = document.createElement(hiliteTag);
|
||||
match.appendChild(document.createTextNode(regs[0]));
|
||||
match.style.backgroundColor = wordColor[regs[0].toLowerCase()];
|
||||
match.style.fontStyle = "inherit";
|
||||
match.style.color = "#000";
|
||||
|
||||
var after = node.splitText(regs.index);
|
||||
after.nodeValue = after.nodeValue.substring(regs[0].length);
|
||||
node.parentNode.insertBefore(match, after);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// remove highlighting
|
||||
this.remove = function()
|
||||
{
|
||||
var arr = document.getElementsByTagName(hiliteTag);
|
||||
var el;
|
||||
while(arr.length && (el = arr[0])) {
|
||||
el.parentNode.replaceChild(el.firstChild, el);
|
||||
}
|
||||
};
|
||||
|
||||
// start highlighting at target node
|
||||
this.apply = function(input)
|
||||
{
|
||||
if(input == undefined || !input) return;
|
||||
this.remove();
|
||||
this.setRegex(input);
|
||||
this.hiliteWords(targetNode);
|
||||
return matchingSlides;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
id: 'search',
|
||||
|
||||
init: reveal => {
|
||||
|
||||
deck = reveal;
|
||||
deck.registerKeyboardShortcut( 'CTRL + Shift + F', 'Search' );
|
||||
|
||||
document.addEventListener( 'keydown', function( event ) {
|
||||
if( event.key == "F" && (event.ctrlKey || event.metaKey) ) { //Control+Shift+f
|
||||
event.preventDefault();
|
||||
toggleSearch();
|
||||
}
|
||||
}, false );
|
||||
|
||||
},
|
||||
|
||||
open: openSearch
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
export default Plugin;
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,279 @@
|
|||
/*!
|
||||
* reveal.js Zoom plugin
|
||||
*/
|
||||
const Plugin = {
|
||||
|
||||
id: 'zoom',
|
||||
|
||||
init: function( reveal ) {
|
||||
|
||||
reveal.getRevealElement().addEventListener( 'mousedown', function( event ) {
|
||||
var defaultModifier = /Linux/.test( window.navigator.platform ) ? 'ctrl' : 'alt';
|
||||
|
||||
var modifier = ( reveal.getConfig().zoomKey ? reveal.getConfig().zoomKey : defaultModifier ) + 'Key';
|
||||
var zoomLevel = ( reveal.getConfig().zoomLevel ? reveal.getConfig().zoomLevel : 2 );
|
||||
|
||||
if( event[ modifier ] && !reveal.isOverview() ) {
|
||||
event.preventDefault();
|
||||
|
||||
zoom.to({
|
||||
x: event.clientX,
|
||||
y: event.clientY,
|
||||
scale: zoomLevel,
|
||||
pan: false
|
||||
});
|
||||
}
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
export default () => Plugin;
|
||||
|
||||
/*!
|
||||
* 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
|
||||
*/
|
||||
var zoom = (function(){
|
||||
|
||||
// The current zoom level (scale)
|
||||
var level = 1;
|
||||
|
||||
// The current mouse position, used for panning
|
||||
var mouseX = 0,
|
||||
mouseY = 0;
|
||||
|
||||
// Timeout before pan is activated
|
||||
var panEngageTimeout = -1,
|
||||
panUpdateInterval = -1;
|
||||
|
||||
// Check for transform support so that we can fallback otherwise
|
||||
var supportsTransforms = 'WebkitTransform' in document.body.style ||
|
||||
'MozTransform' in document.body.style ||
|
||||
'msTransform' in document.body.style ||
|
||||
'OTransform' in document.body.style ||
|
||||
'transform' in document.body.style;
|
||||
|
||||
if( supportsTransforms ) {
|
||||
// The easing that will be applied when we zoom in/out
|
||||
document.body.style.transition = 'transform 0.8s ease';
|
||||
document.body.style.OTransition = '-o-transform 0.8s ease';
|
||||
document.body.style.msTransition = '-ms-transform 0.8s ease';
|
||||
document.body.style.MozTransition = '-moz-transform 0.8s ease';
|
||||
document.body.style.WebkitTransition = '-webkit-transform 0.8s ease';
|
||||
}
|
||||
|
||||
// Zoom out if the user hits escape
|
||||
document.addEventListener( 'keyup', function( event ) {
|
||||
if( level !== 1 && event.keyCode === 27 ) {
|
||||
zoom.out();
|
||||
}
|
||||
} );
|
||||
|
||||
// Monitor mouse movement for panning
|
||||
document.addEventListener( 'mousemove', function( event ) {
|
||||
if( level !== 1 ) {
|
||||
mouseX = event.clientX;
|
||||
mouseY = event.clientY;
|
||||
}
|
||||
} );
|
||||
|
||||
/**
|
||||
* Applies the CSS required to zoom in, prefers the use of CSS3
|
||||
* transforms but falls back on zoom for IE.
|
||||
*
|
||||
* @param {Object} rect
|
||||
* @param {Number} scale
|
||||
*/
|
||||
function magnify( rect, scale ) {
|
||||
|
||||
var scrollOffset = getScrollOffset();
|
||||
|
||||
// Ensure a width/height is set
|
||||
rect.width = rect.width || 1;
|
||||
rect.height = rect.height || 1;
|
||||
|
||||
// Center the rect within the zoomed viewport
|
||||
rect.x -= ( window.innerWidth - ( rect.width * scale ) ) / 2;
|
||||
rect.y -= ( window.innerHeight - ( rect.height * scale ) ) / 2;
|
||||
|
||||
if( supportsTransforms ) {
|
||||
// Reset
|
||||
if( scale === 1 ) {
|
||||
document.body.style.transform = '';
|
||||
document.body.style.OTransform = '';
|
||||
document.body.style.msTransform = '';
|
||||
document.body.style.MozTransform = '';
|
||||
document.body.style.WebkitTransform = '';
|
||||
}
|
||||
// Scale
|
||||
else {
|
||||
var origin = scrollOffset.x +'px '+ scrollOffset.y +'px',
|
||||
transform = 'translate('+ -rect.x +'px,'+ -rect.y +'px) scale('+ scale +')';
|
||||
|
||||
document.body.style.transformOrigin = origin;
|
||||
document.body.style.OTransformOrigin = origin;
|
||||
document.body.style.msTransformOrigin = origin;
|
||||
document.body.style.MozTransformOrigin = origin;
|
||||
document.body.style.WebkitTransformOrigin = origin;
|
||||
|
||||
document.body.style.transform = transform;
|
||||
document.body.style.OTransform = transform;
|
||||
document.body.style.msTransform = transform;
|
||||
document.body.style.MozTransform = transform;
|
||||
document.body.style.WebkitTransform = transform;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Reset
|
||||
if( scale === 1 ) {
|
||||
document.body.style.position = '';
|
||||
document.body.style.left = '';
|
||||
document.body.style.top = '';
|
||||
document.body.style.width = '';
|
||||
document.body.style.height = '';
|
||||
document.body.style.zoom = '';
|
||||
}
|
||||
// Scale
|
||||
else {
|
||||
document.body.style.position = 'relative';
|
||||
document.body.style.left = ( - ( scrollOffset.x + rect.x ) / scale ) + 'px';
|
||||
document.body.style.top = ( - ( scrollOffset.y + rect.y ) / scale ) + 'px';
|
||||
document.body.style.width = ( scale * 100 ) + '%';
|
||||
document.body.style.height = ( scale * 100 ) + '%';
|
||||
document.body.style.zoom = scale;
|
||||
}
|
||||
}
|
||||
|
||||
level = scale;
|
||||
|
||||
if( document.documentElement.classList ) {
|
||||
if( level !== 1 ) {
|
||||
document.documentElement.classList.add( 'zoomed' );
|
||||
}
|
||||
else {
|
||||
document.documentElement.classList.remove( 'zoomed' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pan the document when the mosue cursor approaches the edges
|
||||
* of the window.
|
||||
*/
|
||||
function pan() {
|
||||
var range = 0.12,
|
||||
rangeX = window.innerWidth * range,
|
||||
rangeY = window.innerHeight * range,
|
||||
scrollOffset = getScrollOffset();
|
||||
|
||||
// Up
|
||||
if( mouseY < rangeY ) {
|
||||
window.scroll( scrollOffset.x, scrollOffset.y - ( 1 - ( mouseY / rangeY ) ) * ( 14 / level ) );
|
||||
}
|
||||
// Down
|
||||
else if( mouseY > window.innerHeight - rangeY ) {
|
||||
window.scroll( scrollOffset.x, scrollOffset.y + ( 1 - ( window.innerHeight - mouseY ) / rangeY ) * ( 14 / level ) );
|
||||
}
|
||||
|
||||
// Left
|
||||
if( mouseX < rangeX ) {
|
||||
window.scroll( scrollOffset.x - ( 1 - ( mouseX / rangeX ) ) * ( 14 / level ), scrollOffset.y );
|
||||
}
|
||||
// Right
|
||||
else if( mouseX > window.innerWidth - rangeX ) {
|
||||
window.scroll( scrollOffset.x + ( 1 - ( window.innerWidth - mouseX ) / rangeX ) * ( 14 / level ), scrollOffset.y );
|
||||
}
|
||||
}
|
||||
|
||||
function getScrollOffset() {
|
||||
return {
|
||||
x: window.scrollX !== undefined ? window.scrollX : window.pageXOffset,
|
||||
y: window.scrollY !== undefined ? window.scrollY : window.pageYOffset
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
/**
|
||||
* Zooms in on either a rectangle or HTML element.
|
||||
*
|
||||
* @param {Object} options
|
||||
* - element: HTML element to zoom in on
|
||||
* OR
|
||||
* - x/y: coordinates in non-transformed space to zoom in on
|
||||
* - width/height: the portion of the screen to zoom in on
|
||||
* - scale: can be used instead of width/height to explicitly set scale
|
||||
*/
|
||||
to: function( options ) {
|
||||
|
||||
// Due to an implementation limitation we can't zoom in
|
||||
// to another element without zooming out first
|
||||
if( level !== 1 ) {
|
||||
zoom.out();
|
||||
}
|
||||
else {
|
||||
options.x = options.x || 0;
|
||||
options.y = options.y || 0;
|
||||
|
||||
// If an element is set, that takes precedence
|
||||
if( !!options.element ) {
|
||||
// Space around the zoomed in element to leave on screen
|
||||
var padding = 20;
|
||||
var bounds = options.element.getBoundingClientRect();
|
||||
|
||||
options.x = bounds.left - padding;
|
||||
options.y = bounds.top - padding;
|
||||
options.width = bounds.width + ( padding * 2 );
|
||||
options.height = bounds.height + ( padding * 2 );
|
||||
}
|
||||
|
||||
// If width/height values are set, calculate scale from those values
|
||||
if( options.width !== undefined && options.height !== undefined ) {
|
||||
options.scale = Math.max( Math.min( window.innerWidth / options.width, window.innerHeight / options.height ), 1 );
|
||||
}
|
||||
|
||||
if( options.scale > 1 ) {
|
||||
options.x *= options.scale;
|
||||
options.y *= options.scale;
|
||||
|
||||
magnify( options, options.scale );
|
||||
|
||||
if( options.pan !== false ) {
|
||||
|
||||
// Wait with engaging panning as it may conflict with the
|
||||
// zoom transition
|
||||
panEngageTimeout = setTimeout( function() {
|
||||
panUpdateInterval = setInterval( pan, 1000 / 60 );
|
||||
}, 800 );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Resets the document zoom state to its default.
|
||||
*/
|
||||
out: function() {
|
||||
clearTimeout( panEngageTimeout );
|
||||
clearInterval( panUpdateInterval );
|
||||
|
||||
magnify( { x: 0, y: 0 }, 1 );
|
||||
|
||||
level = 1;
|
||||
},
|
||||
|
||||
// Alias
|
||||
magnify: function( options ) { this.to( options ) },
|
||||
reset: function() { this.out() },
|
||||
|
||||
zoomLevel: function() {
|
||||
return level;
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
|
@ -0,0 +1,4 @@
|
|||
/*!
|
||||
* 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}))}))}},t=function(){var e=1,o=0,n=0,i=-1,d=-1,s="WebkitTransform"in document.body.style||"MozTransform"in document.body.style||"msTransform"in document.body.style||"OTransform"in document.body.style||"transform"in document.body.style;function r(t,o){var n=y();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,s)if(1===o)document.body.style.transform="",document.body.style.OTransform="",document.body.style.msTransform="",document.body.style.MozTransform="",document.body.style.WebkitTransform="";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.OTransformOrigin=i,document.body.style.msTransformOrigin=i,document.body.style.MozTransformOrigin=i,document.body.style.WebkitTransformOrigin=i,document.body.style.transform=d,document.body.style.OTransform=d,document.body.style.msTransform=d,document.body.style.MozTransform=d,document.body.style.WebkitTransform=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 m(){var t=.12*window.innerWidth,i=.12*window.innerHeight,d=y();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 y(){return{x:void 0!==window.scrollX?window.scrollX:window.pageXOffset,y:void 0!==window.scrollY?window.scrollY:window.pageYOffset}}return s&&(document.body.style.transition="transform 0.8s ease",document.body.style.OTransition="-o-transform 0.8s ease",document.body.style.msTransition="-ms-transform 0.8s ease",document.body.style.MozTransition="-moz-transform 0.8s ease",document.body.style.WebkitTransition="-webkit-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,r(o,o.scale),!1!==o.pan&&(i=setTimeout((function(){d=setInterval(m,1e3/60)}),800)))}},out:function(){clearTimeout(i),clearInterval(d),r({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}
|
|
@ -0,0 +1,4 @@
|
|||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=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}))}))}},t=function(){var e=1,o=0,n=0,i=-1,d=-1,s="WebkitTransform"in document.body.style||"MozTransform"in document.body.style||"msTransform"in document.body.style||"OTransform"in document.body.style||"transform"in document.body.style;function r(t,o){var n=y();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,s)if(1===o)document.body.style.transform="",document.body.style.OTransform="",document.body.style.msTransform="",document.body.style.MozTransform="",document.body.style.WebkitTransform="";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.OTransformOrigin=i,document.body.style.msTransformOrigin=i,document.body.style.MozTransformOrigin=i,document.body.style.WebkitTransformOrigin=i,document.body.style.transform=d,document.body.style.OTransform=d,document.body.style.msTransform=d,document.body.style.MozTransform=d,document.body.style.WebkitTransform=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 m(){var t=.12*window.innerWidth,i=.12*window.innerHeight,d=y();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 y(){return{x:void 0!==window.scrollX?window.scrollX:window.pageXOffset,y:void 0!==window.scrollY?window.scrollY:window.pageYOffset}}return s&&(document.body.style.transition="transform 0.8s ease",document.body.style.OTransition="-o-transform 0.8s ease",document.body.style.msTransition="-ms-transform 0.8s ease",document.body.style.MozTransition="-moz-transform 0.8s ease",document.body.style.WebkitTransition="-webkit-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,r(o,o.scale),!1!==o.pan&&(i=setTimeout((function(){d=setInterval(m,1e3/60)}),800)))}},out:function(){clearTimeout(i),clearInterval(d),r({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}}));
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "zargon-now.github.io",
|
||||
"homepage": "https://github.com/zargon-now/zargon-now.github.io",
|
||||
"name": "zrgn.github.io",
|
||||
"homepage": "https://github.com/zrgn/zrgn.github.io",
|
||||
"authors": [
|
||||
"Patrick Connelly <patrick@deadlypenguin.com>"
|
||||
],
|
||||
|
@ -17,6 +17,7 @@
|
|||
],
|
||||
"dependencies": {
|
||||
"jquery": "^3.4.1",
|
||||
"bulma": "^0.7.4"
|
||||
"bulma": "^0.7.4",
|
||||
"reveal.js": "^4.0.2"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -648,42 +648,35 @@
|
|||
}
|
||||
},
|
||||
"grunt-bowercopy": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/grunt-bowercopy/-/grunt-bowercopy-1.2.4.tgz",
|
||||
"integrity": "sha1-DCafaBs4u9+hOwHayBJInvMiTFc=",
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/grunt-bowercopy/-/grunt-bowercopy-1.2.5.tgz",
|
||||
"integrity": "sha512-add3pqWmE5vt2o+TkgV4hr6jQLCZRtupuGXgDGDzfQAzka+EGMPsjGmVC8wUYhoAC+6j46zUIc3cv4dMmXC3zA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bower": "^1.3.5",
|
||||
"glob": "^4.3.5",
|
||||
"lodash": "^3.1.0"
|
||||
"glob": "^7.1.6",
|
||||
"lodash": "^4.17.15"
|
||||
},
|
||||
"dependencies": {
|
||||
"glob": {
|
||||
"version": "4.5.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz",
|
||||
"integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=",
|
||||
"version": "7.1.6",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
|
||||
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^2.0.1",
|
||||
"once": "^1.3.0"
|
||||
"minimatch": "^3.0.4",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "3.10.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
|
||||
"integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=",
|
||||
"version": "4.17.19",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
|
||||
"integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
|
||||
"dev": true
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "2.0.10",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz",
|
||||
"integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
"devDependencies": {
|
||||
"eslint": "^5.16.0",
|
||||
"grunt": "^1.0.4",
|
||||
"grunt-bowercopy": "^1.2.3",
|
||||
"grunt-bowercopy": "^1.2.5",
|
||||
"grunt-contrib-clean": "^2.0.0"
|
||||
},
|
||||
"dependencies": {}
|
||||
|
|
Loading…
Reference in New Issue