Отобразить два слайда с Markdown
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# Ignore Mac files.
|
||||||
|
.DS_Store
|
||||||
|
# Ignore VIM files.
|
||||||
|
*.swp
|
||||||
30
css/reset.css
Normal file
30
css/reset.css
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/* http://meyerweb.com/eric/tools/css/reset/
|
||||||
|
v4.0 | 20180602
|
||||||
|
License: none (public domain)
|
||||||
|
*/
|
||||||
|
|
||||||
|
html, body, div, span, applet, object, iframe,
|
||||||
|
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||||
|
a, abbr, acronym, address, big, cite, code,
|
||||||
|
del, dfn, em, img, ins, kbd, q, s, samp,
|
||||||
|
small, strike, strong, sub, sup, tt, var,
|
||||||
|
b, u, i, center,
|
||||||
|
dl, dt, dd, ol, ul, li,
|
||||||
|
fieldset, form, label, legend,
|
||||||
|
table, caption, tbody, tfoot, thead, tr, th, td,
|
||||||
|
article, aside, canvas, details, embed,
|
||||||
|
figure, figcaption, footer, header, hgroup,
|
||||||
|
main, menu, nav, output, ruby, section, summary,
|
||||||
|
time, mark, audio, video {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
font-size: 100%;
|
||||||
|
font: inherit;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
/* HTML5 display-role reset for older browsers */
|
||||||
|
article, aside, details, figcaption, figure,
|
||||||
|
footer, header, hgroup, main, menu, nav, section {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
1598
css/reveal.css
Normal file
1598
css/reveal.css
Normal file
File diff suppressed because it is too large
Load Diff
273
css/theme/black.css
Normal file
273
css/theme/black.css
Normal file
@@ -0,0 +1,273 @@
|
|||||||
|
/**
|
||||||
|
* Black theme for reveal.js. This is the opposite of the 'white' theme.
|
||||||
|
*
|
||||||
|
* By Hakim El Hattab, http://hakim.se
|
||||||
|
*/
|
||||||
|
@import url(../../lib/font/source-sans-pro/source-sans-pro.css);
|
||||||
|
section.has-light-background, section.has-light-background h1, section.has-light-background h2, section.has-light-background h3, section.has-light-background h4, section.has-light-background h5, section.has-light-background h6 {
|
||||||
|
color: #222; }
|
||||||
|
|
||||||
|
/*********************************************
|
||||||
|
* GLOBAL STYLES
|
||||||
|
*********************************************/
|
||||||
|
body {
|
||||||
|
background: #191919;
|
||||||
|
background-color: #191919; }
|
||||||
|
|
||||||
|
.reveal {
|
||||||
|
font-family: "Source Sans Pro", Helvetica, sans-serif;
|
||||||
|
font-size: 42px;
|
||||||
|
font-weight: normal;
|
||||||
|
color: #fff; }
|
||||||
|
|
||||||
|
::selection {
|
||||||
|
color: #fff;
|
||||||
|
background: #bee4fd;
|
||||||
|
text-shadow: none; }
|
||||||
|
|
||||||
|
::-moz-selection {
|
||||||
|
color: #fff;
|
||||||
|
background: #bee4fd;
|
||||||
|
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: 0 0 20px 0;
|
||||||
|
color: #fff;
|
||||||
|
font-family: "Source Sans Pro", Helvetica, sans-serif;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.2;
|
||||||
|
letter-spacing: normal;
|
||||||
|
text-transform: uppercase;
|
||||||
|
text-shadow: none;
|
||||||
|
word-wrap: break-word; }
|
||||||
|
|
||||||
|
.reveal h1 {
|
||||||
|
font-size: 2.5em; }
|
||||||
|
|
||||||
|
.reveal h2 {
|
||||||
|
font-size: 1.6em; }
|
||||||
|
|
||||||
|
.reveal h3 {
|
||||||
|
font-size: 1.3em; }
|
||||||
|
|
||||||
|
.reveal h4 {
|
||||||
|
font-size: 1em; }
|
||||||
|
|
||||||
|
.reveal h1 {
|
||||||
|
text-shadow: none; }
|
||||||
|
|
||||||
|
/*********************************************
|
||||||
|
* OTHER
|
||||||
|
*********************************************/
|
||||||
|
.reveal p {
|
||||||
|
margin: 20px 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: 20px 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: 20px auto;
|
||||||
|
text-align: left;
|
||||||
|
font-size: 0.55em;
|
||||||
|
font-family: monospace;
|
||||||
|
line-height: 1.2em;
|
||||||
|
word-wrap: break-word;
|
||||||
|
box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); }
|
||||||
|
|
||||||
|
.reveal code {
|
||||||
|
font-family: monospace;
|
||||||
|
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; }
|
||||||
|
|
||||||
|
/*********************************************
|
||||||
|
* LINKS
|
||||||
|
*********************************************/
|
||||||
|
.reveal a {
|
||||||
|
color: #42affa;
|
||||||
|
text-decoration: none;
|
||||||
|
-webkit-transition: color .15s ease;
|
||||||
|
-moz-transition: color .15s ease;
|
||||||
|
transition: color .15s ease; }
|
||||||
|
|
||||||
|
.reveal a:hover {
|
||||||
|
color: #8dcffc;
|
||||||
|
text-shadow: none;
|
||||||
|
border: none; }
|
||||||
|
|
||||||
|
.reveal .roll span:after {
|
||||||
|
color: #fff;
|
||||||
|
background: #068de9; }
|
||||||
|
|
||||||
|
/*********************************************
|
||||||
|
* IMAGES
|
||||||
|
*********************************************/
|
||||||
|
.reveal section img {
|
||||||
|
margin: 15px 0px;
|
||||||
|
background: rgba(255, 255, 255, 0.12);
|
||||||
|
border: 4px solid #fff;
|
||||||
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); }
|
||||||
|
|
||||||
|
.reveal section img.plain {
|
||||||
|
border: 0;
|
||||||
|
box-shadow: none; }
|
||||||
|
|
||||||
|
.reveal a img {
|
||||||
|
-webkit-transition: all .15s linear;
|
||||||
|
-moz-transition: all .15s linear;
|
||||||
|
transition: all .15s linear; }
|
||||||
|
|
||||||
|
.reveal a:hover img {
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
border-color: #42affa;
|
||||||
|
box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); }
|
||||||
|
|
||||||
|
/*********************************************
|
||||||
|
* NAVIGATION CONTROLS
|
||||||
|
*********************************************/
|
||||||
|
.reveal .controls {
|
||||||
|
color: #42affa; }
|
||||||
|
|
||||||
|
/*********************************************
|
||||||
|
* PROGRESS BAR
|
||||||
|
*********************************************/
|
||||||
|
.reveal .progress {
|
||||||
|
background: rgba(0, 0, 0, 0.2);
|
||||||
|
color: #42affa; }
|
||||||
|
|
||||||
|
.reveal .progress span {
|
||||||
|
-webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
|
||||||
|
-moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
|
||||||
|
transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); }
|
||||||
|
|
||||||
|
/*********************************************
|
||||||
|
* PRINT BACKGROUND
|
||||||
|
*********************************************/
|
||||||
|
@media print {
|
||||||
|
.backgrounds {
|
||||||
|
background-color: #191919; } }
|
||||||
46
index.html
Normal file
46
index.html
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||||
|
|
||||||
|
<title>Обучение детей программированию</title>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="css/reset.css">
|
||||||
|
<link rel="stylesheet" href="css/reveal.css">
|
||||||
|
<link rel="stylesheet" href="css/theme/black.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="reveal">
|
||||||
|
<div class="slides">
|
||||||
|
|
||||||
|
<section data-markdown><textarea data-template>
|
||||||
|
|
||||||
|
Slide 1 contains some points:
|
||||||
|
|
||||||
|
* point no. 1
|
||||||
|
* point no. 2
|
||||||
|
|
||||||
|
</textarea></section>
|
||||||
|
|
||||||
|
<section data-markdown><textarea data-template>
|
||||||
|
|
||||||
|
Slide 2 will be here, too
|
||||||
|
|
||||||
|
</textarea></section>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="js/reveal.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
Reveal.initialize({
|
||||||
|
dependencies: [
|
||||||
|
{ src: 'plugin/markdown/marked.js' },
|
||||||
|
{ src: 'plugin/markdown/markdown.js' },
|
||||||
|
]
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
6028
js/reveal.js
Normal file
6028
js/reveal.js
Normal file
File diff suppressed because it is too large
Load Diff
446
plugin/markdown/markdown.js
Executable file
446
plugin/markdown/markdown.js
Executable file
@@ -0,0 +1,446 @@
|
|||||||
|
/**
|
||||||
|
* The reveal.js markdown plugin. Handles parsing of
|
||||||
|
* markdown inside of presentations as well as loading
|
||||||
|
* of external markdown documents.
|
||||||
|
*/
|
||||||
|
(function( root, factory ) {
|
||||||
|
if (typeof define === 'function' && define.amd) {
|
||||||
|
root.marked = require( './marked' );
|
||||||
|
root.RevealMarkdown = factory( root.marked );
|
||||||
|
} else if( typeof exports === 'object' ) {
|
||||||
|
module.exports = factory( require( './marked' ) );
|
||||||
|
} else {
|
||||||
|
// Browser globals (root is window)
|
||||||
|
root.RevealMarkdown = factory( root.marked );
|
||||||
|
}
|
||||||
|
}( this, function( marked ) {
|
||||||
|
|
||||||
|
var DEFAULT_SLIDE_SEPARATOR = '^\r?\n---\r?\n$',
|
||||||
|
DEFAULT_NOTES_SEPARATOR = 'notes?:',
|
||||||
|
DEFAULT_ELEMENT_ATTRIBUTES_SEPARATOR = '\\\.element\\\s*?(.+?)$',
|
||||||
|
DEFAULT_SLIDE_ATTRIBUTES_SEPARATOR = '\\\.slide:\\\s*?(\\\S.+?)$';
|
||||||
|
|
||||||
|
var SCRIPT_END_PLACEHOLDER = '__SCRIPT_END__';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 ) ) {
|
||||||
|
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() {
|
||||||
|
|
||||||
|
return new Promise( function( resolve ) {
|
||||||
|
|
||||||
|
var externalPromises = [];
|
||||||
|
|
||||||
|
[].slice.call( document.querySelectorAll( '[data-markdown]') ).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' );
|
||||||
|
|
||||||
|
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 ) {
|
||||||
|
alert( '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( "([^\"= ]+?)=\"([^\"=]+?)\"", 'mg' );
|
||||||
|
var nodeValue = node.nodeValue;
|
||||||
|
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 ) ) {
|
||||||
|
elementTarget.setAttribute( matchesClass[1], matchesClass[2] );
|
||||||
|
}
|
||||||
|
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 ) {
|
||||||
|
previousParentElement = element;
|
||||||
|
for( var i = 0; i < element.childNodes.length; i++ ) {
|
||||||
|
childElement = element.childNodes[i];
|
||||||
|
if ( i > 0 ) {
|
||||||
|
j = i - 1;
|
||||||
|
while ( j >= 0 ) {
|
||||||
|
aPreviousChildElement = element.childNodes[j];
|
||||||
|
if ( typeof aPreviousChildElement.setAttribute == 'function' && aPreviousChildElement.tagName != "BR" ) {
|
||||||
|
previousParentElement = aPreviousChildElement;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
j = j - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 = document.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();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// API
|
||||||
|
var RevealMarkdown = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts processing and converting Markdown within the
|
||||||
|
* current reveal.js deck.
|
||||||
|
*
|
||||||
|
* @param {function} callback function to invoke once
|
||||||
|
* we've finished loading and parsing Markdown
|
||||||
|
*/
|
||||||
|
init: function( callback ) {
|
||||||
|
|
||||||
|
if( typeof marked === 'undefined' ) {
|
||||||
|
throw 'The reveal.js Markdown plugin requires marked to be loaded';
|
||||||
|
}
|
||||||
|
|
||||||
|
if( typeof hljs !== 'undefined' ) {
|
||||||
|
marked.setOptions({
|
||||||
|
highlight: function( code, lang ) {
|
||||||
|
return hljs.highlightAuto( code, [lang] ).value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// marked can be configured via reveal.js config options
|
||||||
|
var options = Reveal.getConfig().markdown;
|
||||||
|
if( options ) {
|
||||||
|
marked.setOptions( options );
|
||||||
|
}
|
||||||
|
|
||||||
|
return processSlides().then( convertSlides );
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
// TODO: Do these belong in the API?
|
||||||
|
processSlides: processSlides,
|
||||||
|
convertSlides: convertSlides,
|
||||||
|
slidify: slidify
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// Register our plugin so that reveal.js will call our
|
||||||
|
// plugin 'init' method as part of the initialization
|
||||||
|
Reveal.registerPlugin( 'markdown', RevealMarkdown );
|
||||||
|
|
||||||
|
return RevealMarkdown;
|
||||||
|
|
||||||
|
}));
|
||||||
6
plugin/markdown/marked.js
Normal file
6
plugin/markdown/marked.js
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user