Skip to content

Commit

Permalink
Improve markdown support.
Browse files Browse the repository at this point in the history
1. Support `marked`, you can using it instead. #811
2. Auto detect slide title (using first non-blank line). #816
3. Auto trim the indentation, so it can be indent like regular HTML.
   #812
  • Loading branch information
thawk committed Jun 26, 2022
1 parent 78c954a commit 6e0b372
Show file tree
Hide file tree
Showing 3 changed files with 203 additions and 74 deletions.
1 change: 1 addition & 0 deletions examples/markdown/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ <h1>CSS &amp; JavaScript magic</h1>
<script type="text/javascript" src="../../extras/highlight/highlight.pack.js"></script>
<script type="text/javascript" src="../../extras/mermaid/mermaid.min.js"></script>
<script type="text/javascript" src="../../extras/markdown/markdown.js"></script>
<!-- <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> -->

<!--
To make all described above really work, you need to include impress.js in the page.
Expand Down
138 changes: 101 additions & 37 deletions js/impress.js
Original file line number Diff line number Diff line change
Expand Up @@ -2023,48 +2023,112 @@
* Copyright 2016 Henrik Ingo (@henrikingo)
* Released under the MIT license.
*/
/* global markdown, hljs, mermaid, impress, document, window */
/* global markdown, marked, hljs, mermaid, impress */

( function( document, window ) {
"use strict";

var preInit = function() {
if ( window.markdown ) {

// Unlike the other extras, Markdown.js doesn't by default do anything in
// particular. We do it ourselves here.
// In addition, we use "-----" as a delimiter for new slide.

// Query all .markdown elements and translate to HTML
var markdownDivs = document.querySelectorAll( ".markdown" );
for ( var idx = 0; idx < markdownDivs.length; idx++ ) {
var element = markdownDivs[ idx ];
var dialect = element.dataset.markdownDialect;

var slides = element.textContent.split( /^-----$/m );
var i = slides.length - 1;
element.innerHTML = markdown.toHTML( slides[ i ], dialect );

// If there's an id, unset it for last, and all other, elements,
// and then set it for the first.
var id = null;
if ( element.id ) {
id = element.id;
element.id = "";
}
i--;
while ( i >= 0 ) {
var newElement = element.cloneNode( false );
newElement.innerHTML = markdown.toHTML( slides[ i ], dialect );
element.parentNode.insertBefore( newElement, element );
element = newElement;
i--;
}
if ( id !== null ) {
element.id = id;
}
const SLIDE_SEPARATOR = /^-----$/m;
const MAX_TITLE_LEN = 30;

const findTitle = function( text ) {
for ( var line of text.split( "\n" ) ) {
line = line.trim( );
if ( line.length > 0 ) {
if ( line.length <= MAX_TITLE_LEN ) {
return line;
}

// The first line isn't blank, but too long to be a title
return "";
}
} // Markdown
}
return "";
};

const getMarkdownSlides = function( elem ) {
var text = elem.textContent;

// Using first not blank line to detect leading whitespaces.
// can't properly handle the mixing of space and tabs
var m = text.match( /^([ \t]*)\S/m );
if ( m !== null ) {
text = text.replace( new RegExp( "^" + m[ 1 ], "mg" ), "" );
}

return text.split( SLIDE_SEPARATOR );
};

const convertMarkdowns = function( selector ) {

// Detect markdown engine
var parseMarkdown = null;

if ( window.hasOwnProperty( "marked" ) ) {

// Using marked
parseMarkdown = function( elem, src ) {
return marked.parse( src );
};
} else if ( window.hasOwnProperty( "markdown" ) ) {

// Using builtin markdown engine
parseMarkdown = function( elem, src ) {
var dialect = elem.dataset.markdownDialect;
return markdown.toHTML( src, dialect );
};
} else {
return;
}

for ( var elem of document.querySelectorAll( selector ) ) {
var id = null;
if ( elem.id ) {
id = elem.id;
elem.id = "";
}

var origTitle = null;
if ( elem.title ) {
origTitle = elem.title;
elem.title = "";
}

var slides = getMarkdownSlides( elem );
var slideElems = [ elem ];

for ( var j = 1; j < slides.length; ++j ) {
var newElem = elem.cloneNode( false );
newElem.id = "";
elem.parentNode.insertBefore( newElem, slideElems[ 0 ] );
slideElems.splice( 0, 0, newElem );
}

if ( id ) {
slideElems[ 0 ].id = id;
}

for ( var i = 0; i < slides.length; ++i ) {
slideElems[ i ].innerHTML =
parseMarkdown( slideElems[ i ], slides[ i ] );

// Set the slide title.
// The first slide will use original title if exists.
var title = findTitle( slideElems[ i ].innerText );

if ( origTitle && ( i === 0 ) ) {
slideElems[ i ].title = origTitle;
} else if ( title ) {
slideElems[ i ].title = title;
}
}
}
};

var preInit = function() {

// Query all .markdown elements and translate to HTML
convertMarkdowns( ".markdown" );

if ( window.hljs ) {
hljs.initHighlightingOnLoad();
Expand Down
138 changes: 101 additions & 37 deletions src/plugins/extras/extras.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,48 +9,112 @@
* Copyright 2016 Henrik Ingo (@henrikingo)
* Released under the MIT license.
*/
/* global markdown, hljs, mermaid, impress, document, window */
/* global markdown, marked, hljs, mermaid, impress */

( function( document, window ) {
"use strict";

var preInit = function() {
if ( window.markdown ) {

// Unlike the other extras, Markdown.js doesn't by default do anything in
// particular. We do it ourselves here.
// In addition, we use "-----" as a delimiter for new slide.

// Query all .markdown elements and translate to HTML
var markdownDivs = document.querySelectorAll( ".markdown" );
for ( var idx = 0; idx < markdownDivs.length; idx++ ) {
var element = markdownDivs[ idx ];
var dialect = element.dataset.markdownDialect;

var slides = element.textContent.split( /^-----$/m );
var i = slides.length - 1;
element.innerHTML = markdown.toHTML( slides[ i ], dialect );

// If there's an id, unset it for last, and all other, elements,
// and then set it for the first.
var id = null;
if ( element.id ) {
id = element.id;
element.id = "";
}
i--;
while ( i >= 0 ) {
var newElement = element.cloneNode( false );
newElement.innerHTML = markdown.toHTML( slides[ i ], dialect );
element.parentNode.insertBefore( newElement, element );
element = newElement;
i--;
}
if ( id !== null ) {
element.id = id;
}
const SLIDE_SEPARATOR = /^-----$/m;
const MAX_TITLE_LEN = 30;

const findTitle = function( text ) {
for ( var line of text.split( "\n" ) ) {
line = line.trim( );
if ( line.length > 0 ) {
if ( line.length <= MAX_TITLE_LEN ) {
return line;
}

// The first line isn't blank, but too long to be a title
return "";
}
}
return "";
};

const getMarkdownSlides = function( elem ) {
var text = elem.textContent;

// Using first not blank line to detect leading whitespaces.
// can't properly handle the mixing of space and tabs
var m = text.match( /^([ \t]*)\S/m );
if ( m !== null ) {
text = text.replace( new RegExp( "^" + m[ 1 ], "mg" ), "" );
}

return text.split( SLIDE_SEPARATOR );
};

const convertMarkdowns = function( selector ) {

// Detect markdown engine
var parseMarkdown = null;

if ( window.hasOwnProperty( "marked" ) ) {

// Using marked
parseMarkdown = function( elem, src ) {
return marked.parse( src );
};
} else if ( window.hasOwnProperty( "markdown" ) ) {

// Using builtin markdown engine
parseMarkdown = function( elem, src ) {
var dialect = elem.dataset.markdownDialect;
return markdown.toHTML( src, dialect );
};
} else {
return;
}

for ( var elem of document.querySelectorAll( selector ) ) {
var id = null;
if ( elem.id ) {
id = elem.id;
elem.id = "";
}

var origTitle = null;
if ( elem.title ) {
origTitle = elem.title;
elem.title = "";
}
} // Markdown

var slides = getMarkdownSlides( elem );
var slideElems = [ elem ];

for ( var j = 1; j < slides.length; ++j ) {
var newElem = elem.cloneNode( false );
newElem.id = "";
elem.parentNode.insertBefore( newElem, slideElems[ 0 ] );
slideElems.splice( 0, 0, newElem );
}

if ( id ) {
slideElems[ 0 ].id = id;
}

for ( var i = 0; i < slides.length; ++i ) {
slideElems[ i ].innerHTML =
parseMarkdown( slideElems[ i ], slides[ i ] );

// Set the slide title.
// The first slide will use original title if exists.
var title = findTitle( slideElems[ i ].innerText );

if ( origTitle && ( i === 0 ) ) {
slideElems[ i ].title = origTitle;
} else if ( title ) {
slideElems[ i ].title = title;
}
}
}
};

var preInit = function() {

// Query all .markdown elements and translate to HTML
convertMarkdowns( ".markdown" );

if ( window.hljs ) {
hljs.initHighlightingOnLoad();
Expand Down

0 comments on commit 6e0b372

Please sign in to comment.