diff options
Diffstat (limited to 'plugin/markdown/markdown.js')
-rwxr-xr-x | plugin/markdown/markdown.js | 116 |
1 files changed, 103 insertions, 13 deletions
diff --git a/plugin/markdown/markdown.js b/plugin/markdown/markdown.js index 42c847f..9564208 100755 --- a/plugin/markdown/markdown.js +++ b/plugin/markdown/markdown.js @@ -27,7 +27,9 @@ } var DEFAULT_SLIDE_SEPARATOR = '^\n---\n$', - DEFAULT_NOTES_SEPARATOR = 'note:'; + DEFAULT_NOTES_SEPARATOR = 'note:', + DEFAULT_ELEMENT_ATTRIBUTES_SEPARATOR = '{\\\.\s*?([^}]+?)}', + DEFAULT_SLIDE_ATTRIBUTES_SEPARATOR = '^.*?<!--\\\sslide-attributes:\\\s(.*?)-->'; /** @@ -71,7 +73,7 @@ value = attributes[i].value; // disregard attributes that are used for markdown loading/parsing - if( /data\-(markdown|separator|vertical|notes)/gi.test( name ) ) continue; + if( /data\-(markdown|separator|vertical|notes|attributes)/gi.test( name ) ) continue; if( value ) { result.push( name + '=' + value ); @@ -95,6 +97,7 @@ options.separator = options.separator || DEFAULT_SLIDE_SEPARATOR; options.notesSeparator = options.notesSeparator || DEFAULT_NOTES_SEPARATOR; options.attributes = options.attributes || ''; + options.slideAttributesSeparator = options.slideAttributesSeparator || DEFAULT_SLIDE_ATTRIBUTES_SEPARATOR; return options; @@ -126,14 +129,17 @@ options = getSlidifyOptions( options ); var separatorRegex = new RegExp( options.separator + ( options.verticalSeparator ? '|' + options.verticalSeparator : '' ), 'mg' ), - horizontalSeparatorRegex = new RegExp( options.separator ); + horizontalSeparatorRegex = new RegExp( options.separator ), + slideAttributesSeparatorRegex = new RegExp( options.slideAttributesSeparator, 'm' ); var matches, lastIndex = 0, isHorizontal, wasHorizontal = true, content, - sectionStack = []; + sectionStack = [], + matchAttributes, + slideAttributes = ""; // iterate until all blocks between separators are stacked up while( matches = separatorRegex.exec( markdown ) ) { @@ -171,20 +177,36 @@ // flatten the hierarchical stack, and insert <section data-markdown> tags for( var i = 0, len = sectionStack.length; i < len; i++ ) { // vertical - if( sectionStack[i].propertyIsEnumerable( length ) && typeof sectionStack[i].splice === 'function' ) { - markdownSections += '<section '+ options.attributes +'>'; + if( sectionStack[i] instanceof Array ) { + // The 'data-xxx' attributes of the first child must be set on the wrapping parent section to be effective + // Mainly for data-transition (otherwise, it is ignored for the first vertical slide) + firstChild = sectionStack[i][0]; + matchAttributes = slideAttributesSeparatorRegex.exec( firstChild ); + slideAttributes = matchAttributes ? matchAttributes[1] : ""; + dataAttributes = ""; + if( slideAttributes != "" ) { + // http://stackoverflow.com/questions/18025762/javascript-regex-replace-all-word-characters-except-word-characters-between-ch + // Keep only data-attributes for the parent slide section. + dataAttributes = slideAttributes.replace( /(data-\S+=\"[^\"]+?\")|\w|[\"=]/g, function(a, b) { return b || ''; }); + } + markdownSections += '<section '+ options.attributes + ' ' + dataAttributes + '>'; sectionStack[i].forEach( function( child ) { - markdownSections += '<section data-markdown>' + createMarkdownSlide( child, options ) + '</section>'; + matchAttributes = slideAttributesSeparatorRegex.exec( child ); + slideAttributes = matchAttributes ? matchAttributes[1] : ""; + child = matchAttributes ? child.replace( slideAttributesSeparatorRegex,"" ) : child + markdownSections += '<section ' + slideAttributes + ' data-markdown>' + createMarkdownSlide( child, options ) + '</section>'; } ); markdownSections += '</section>'; } else { - markdownSections += '<section '+ options.attributes +' data-markdown>' + createMarkdownSlide( sectionStack[i], options ) + '</section>'; + matchAttributes = slideAttributesSeparatorRegex.exec( sectionStack[i] ); + slideAttributes = matchAttributes ? matchAttributes[1] : ""; + content = matchAttributes ? sectionStack[i].replace( slideAttributesSeparatorRegex,"" ) : sectionStack[i] + markdownSections += '<section '+ options.attributes + ' ' + slideAttributes +' data-markdown>' + createMarkdownSlide( content, options ) + '</section>'; } } - return markdownSections; } @@ -218,12 +240,12 @@ xhr.onreadystatechange = function() { if( xhr.readyState === 4 ) { if ( xhr.status >= 200 && xhr.status < 300 ) { - section.outerHTML = slidify( xhr.responseText, { separator: section.getAttribute( 'data-separator' ), verticalSeparator: section.getAttribute( 'data-vertical' ), notesSeparator: section.getAttribute( 'data-notes' ), - attributes: getForwardedAttributes( section ) + attributes: getForwardedAttributes( section ), + slideAttributesSeparator: section.getAttribute( 'data-attributes' ), }); } @@ -255,14 +277,79 @@ separator: section.getAttribute( 'data-separator' ), verticalSeparator: section.getAttribute( 'data-vertical' ), notesSeparator: section.getAttribute( 'data-notes' ), - attributes: getForwardedAttributes( section ) + attributes: getForwardedAttributes( section ), + slideAttributesSeparator: section.getAttribute( 'data-attributes' ), }); } else { + var content = getMarkdownFromSlide( section ); + var slideAttributesSeparatorRegex = new RegExp( section.getAttribute( 'data-attributes' ) || DEFAULT_SLIDE_ATTRIBUTES_SEPARATOR, 'm' ); + var matchAttributes = slideAttributesSeparatorRegex.exec( content ); + if ( matchAttributes ) { + var slideAttributes = matchAttributes[1]; + content = content.replace( slideAttributesSeparatorRegex,"" ); + var slideAttributesRegex = new RegExp( "([^\"= ]+?)=\"([^\"=]+?)\"", 'mg' ); + while( matchesAttributes = slideAttributesRegex.exec( slideAttributes ) ) { + section.setAttribute( matchesAttributes[1], matchesAttributes[2] ); + } + } + section.innerHTML = createMarkdownSlide( content ); + } + } + + } + + /** + * Check if a node value has the attributes pattern. + * If yes, extract it and add that value as one or several attributes + * the the terget 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 ) ) { - section.innerHTML = createMarkdownSlide( getMarkdownFromSlide( section ) ); + 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] ); + } + } + + } + + /** + * Add attributes to the parent element of a text node, + * or the element of an attribute node. + */ + function addAttributes( element, separator ) { + + if( element.childNodes.length > 0 ) { + for( var i = 0; i < element.childNodes.length; i++ ) { + addAttributes( element.childNodes[i], separator ); + } + } + + var nodeValue; + var elementTarget; + + // From http://stackoverflow.com/questions/9178174/find-all-text-nodes + if( element.nodeType == Node.TEXT_NODE && /\S/.test(element.nodeValue) ) { + addAttributeInElement( element, element.parentNode, separator ); + } + if( element.nodeType == Node.ELEMENT_NODE && element.attributes.length > 0 ) { + for( var j = 0; j < element.attributes.length; j++ ){ + var attr = element.attributes[j]; + addAttributeInElement( attr, element, separator ); } } @@ -289,6 +376,9 @@ var markdown = getMarkdownFromSlide( section ); section.innerHTML = marked( markdown ); + addAttributes( section, section.getAttribute( 'data-element-attributes' ) || + section.parentNode.getAttribute( 'data-element-attributes' ) || + DEFAULT_ELEMENT_ATTRIBUTES_SEPARATOR ); // If there were notes, we need to re-add them after // having overwritten the section's HTML |