6491 lines
283 KiB
JavaScript
6491 lines
283 KiB
JavaScript
|
require=(function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({"components/printing":[function(require,module,exports){
|
|||
|
module.exports=require('nZr0zp');
|
|||
|
},{}],"nZr0zp":[function(require,module,exports){
|
|||
|
var EventEmitter = require('events').EventEmitter
|
|||
|
, styler = require('components/styler')
|
|||
|
;
|
|||
|
|
|||
|
var LANDSCAPE = 'landscape'
|
|||
|
, PORTRAIT = 'portrait'
|
|||
|
, PAGE_HEIGHT = 681
|
|||
|
, PAGE_WIDTH = 908
|
|||
|
;
|
|||
|
|
|||
|
function PrintComponent () {}
|
|||
|
|
|||
|
// Add eventing
|
|||
|
PrintComponent.prototype = new EventEmitter();
|
|||
|
|
|||
|
// Sets up listener for printing
|
|||
|
PrintComponent.prototype.init = function () {
|
|||
|
var self = this;
|
|||
|
|
|||
|
this.setPageOrientation(LANDSCAPE);
|
|||
|
|
|||
|
if (!window.matchMedia) {
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
window.matchMedia('print').addListener(function (e) {
|
|||
|
self.onPrint(e);
|
|||
|
});
|
|||
|
};
|
|||
|
|
|||
|
// Handles printing event
|
|||
|
PrintComponent.prototype.onPrint = function (e) {
|
|||
|
var slideHeight;
|
|||
|
|
|||
|
if (!e.matches) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
this.emit('print', {
|
|||
|
isPortrait: this._orientation === 'portrait'
|
|||
|
, pageHeight: this._pageHeight
|
|||
|
, pageWidth: this._pageWidth
|
|||
|
});
|
|||
|
};
|
|||
|
|
|||
|
PrintComponent.prototype.setPageOrientation = function (orientation) {
|
|||
|
if (orientation === PORTRAIT) {
|
|||
|
// Flip dimensions for portrait orientation
|
|||
|
this._pageHeight = PAGE_WIDTH;
|
|||
|
this._pageWidth = PAGE_HEIGHT;
|
|||
|
}
|
|||
|
else if (orientation === LANDSCAPE) {
|
|||
|
this._pageHeight = PAGE_HEIGHT;
|
|||
|
this._pageWidth = PAGE_WIDTH;
|
|||
|
}
|
|||
|
else {
|
|||
|
throw new Error('Unknown print orientation: ' + orientation);
|
|||
|
}
|
|||
|
|
|||
|
this._orientation = orientation;
|
|||
|
|
|||
|
styler.setPageSize(this._pageWidth + 'px ' + this._pageHeight + 'px');
|
|||
|
};
|
|||
|
|
|||
|
// Export singleton instance
|
|||
|
module.exports = new PrintComponent();
|
|||
|
|
|||
|
},{"events":1,"components/styler":"t5Lx4S"}],"components/slide-number":[function(require,module,exports){
|
|||
|
module.exports=require('aIW4aw');
|
|||
|
},{}],"aIW4aw":[function(require,module,exports){
|
|||
|
module.exports = SlideNumberViewModel;
|
|||
|
|
|||
|
function SlideNumberViewModel (slide, slideshow) {
|
|||
|
var self = this;
|
|||
|
|
|||
|
self.slide = slide;
|
|||
|
self.slideshow = slideshow;
|
|||
|
|
|||
|
self.element = document.createElement('div');
|
|||
|
self.element.className = 'remark-slide-number';
|
|||
|
self.element.innerHTML = formatSlideNumber(self.slide, self.slideshow);
|
|||
|
}
|
|||
|
|
|||
|
function formatSlideNumber (slide, slideshow) {
|
|||
|
var format = slideshow.getSlideNumberFormat()
|
|||
|
, slides = slideshow.getSlides()
|
|||
|
, current = getSlideNo(slide, slideshow)
|
|||
|
, total = getSlideNo(slides[slides.length - 1], slideshow)
|
|||
|
;
|
|||
|
|
|||
|
if (typeof format === 'function') {
|
|||
|
return format.call(slideshow, current, total);
|
|||
|
}
|
|||
|
|
|||
|
return format
|
|||
|
.replace('%current%', current)
|
|||
|
.replace('%total%', total);
|
|||
|
}
|
|||
|
|
|||
|
function getSlideNo (slide, slideshow) {
|
|||
|
var slides = slideshow.getSlides(), i, slideNo = 0;
|
|||
|
|
|||
|
for (i = 0; i <= slide.getSlideIndex() && i < slides.length; ++i) {
|
|||
|
if (slides[i].properties.count !== 'false') {
|
|||
|
slideNo += 1;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return Math.max(1, slideNo);
|
|||
|
}
|
|||
|
|
|||
|
},{}],2:[function(require,module,exports){
|
|||
|
// shim for using process in browser
|
|||
|
|
|||
|
var process = module.exports = {};
|
|||
|
|
|||
|
process.nextTick = (function () {
|
|||
|
var canSetImmediate = typeof window !== 'undefined'
|
|||
|
&& window.setImmediate;
|
|||
|
var canPost = typeof window !== 'undefined'
|
|||
|
&& window.postMessage && window.addEventListener
|
|||
|
;
|
|||
|
|
|||
|
if (canSetImmediate) {
|
|||
|
return function (f) { return window.setImmediate(f) };
|
|||
|
}
|
|||
|
|
|||
|
if (canPost) {
|
|||
|
var queue = [];
|
|||
|
window.addEventListener('message', function (ev) {
|
|||
|
var source = ev.source;
|
|||
|
if ((source === window || source === null) && ev.data === 'process-tick') {
|
|||
|
ev.stopPropagation();
|
|||
|
if (queue.length > 0) {
|
|||
|
var fn = queue.shift();
|
|||
|
fn();
|
|||
|
}
|
|||
|
}
|
|||
|
}, true);
|
|||
|
|
|||
|
return function nextTick(fn) {
|
|||
|
queue.push(fn);
|
|||
|
window.postMessage('process-tick', '*');
|
|||
|
};
|
|||
|
}
|
|||
|
|
|||
|
return function nextTick(fn) {
|
|||
|
setTimeout(fn, 0);
|
|||
|
};
|
|||
|
})();
|
|||
|
|
|||
|
process.title = 'browser';
|
|||
|
process.browser = true;
|
|||
|
process.env = {};
|
|||
|
process.argv = [];
|
|||
|
|
|||
|
process.binding = function (name) {
|
|||
|
throw new Error('process.binding is not supported');
|
|||
|
}
|
|||
|
|
|||
|
// TODO(shtylman)
|
|||
|
process.cwd = function () { return '/' };
|
|||
|
process.chdir = function (dir) {
|
|||
|
throw new Error('process.chdir is not supported');
|
|||
|
};
|
|||
|
|
|||
|
},{}],1:[function(require,module,exports){
|
|||
|
(function(process){if (!process.EventEmitter) process.EventEmitter = function () {};
|
|||
|
|
|||
|
var EventEmitter = exports.EventEmitter = process.EventEmitter;
|
|||
|
var isArray = typeof Array.isArray === 'function'
|
|||
|
? Array.isArray
|
|||
|
: function (xs) {
|
|||
|
return Object.prototype.toString.call(xs) === '[object Array]'
|
|||
|
}
|
|||
|
;
|
|||
|
function indexOf (xs, x) {
|
|||
|
if (xs.indexOf) return xs.indexOf(x);
|
|||
|
for (var i = 0; i < xs.length; i++) {
|
|||
|
if (x === xs[i]) return i;
|
|||
|
}
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
// By default EventEmitters will print a warning if more than
|
|||
|
// 10 listeners are added to it. This is a useful default which
|
|||
|
// helps finding memory leaks.
|
|||
|
//
|
|||
|
// Obviously not all Emitters should be limited to 10. This function allows
|
|||
|
// that to be increased. Set to zero for unlimited.
|
|||
|
var defaultMaxListeners = 10;
|
|||
|
EventEmitter.prototype.setMaxListeners = function(n) {
|
|||
|
if (!this._events) this._events = {};
|
|||
|
this._events.maxListeners = n;
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
EventEmitter.prototype.emit = function(type) {
|
|||
|
// If there is no 'error' event listener then throw.
|
|||
|
if (type === 'error') {
|
|||
|
if (!this._events || !this._events.error ||
|
|||
|
(isArray(this._events.error) && !this._events.error.length))
|
|||
|
{
|
|||
|
if (arguments[1] instanceof Error) {
|
|||
|
throw arguments[1]; // Unhandled 'error' event
|
|||
|
} else {
|
|||
|
throw new Error("Uncaught, unspecified 'error' event.");
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!this._events) return false;
|
|||
|
var handler = this._events[type];
|
|||
|
if (!handler) return false;
|
|||
|
|
|||
|
if (typeof handler == 'function') {
|
|||
|
switch (arguments.length) {
|
|||
|
// fast cases
|
|||
|
case 1:
|
|||
|
handler.call(this);
|
|||
|
break;
|
|||
|
case 2:
|
|||
|
handler.call(this, arguments[1]);
|
|||
|
break;
|
|||
|
case 3:
|
|||
|
handler.call(this, arguments[1], arguments[2]);
|
|||
|
break;
|
|||
|
// slower
|
|||
|
default:
|
|||
|
var args = Array.prototype.slice.call(arguments, 1);
|
|||
|
handler.apply(this, args);
|
|||
|
}
|
|||
|
return true;
|
|||
|
|
|||
|
} else if (isArray(handler)) {
|
|||
|
var args = Array.prototype.slice.call(arguments, 1);
|
|||
|
|
|||
|
var listeners = handler.slice();
|
|||
|
for (var i = 0, l = listeners.length; i < l; i++) {
|
|||
|
listeners[i].apply(this, args);
|
|||
|
}
|
|||
|
return true;
|
|||
|
|
|||
|
} else {
|
|||
|
return false;
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
// EventEmitter is defined in src/node_events.cc
|
|||
|
// EventEmitter.prototype.emit() is also defined there.
|
|||
|
EventEmitter.prototype.addListener = function(type, listener) {
|
|||
|
if ('function' !== typeof listener) {
|
|||
|
throw new Error('addListener only takes instances of Function');
|
|||
|
}
|
|||
|
|
|||
|
if (!this._events) this._events = {};
|
|||
|
|
|||
|
// To avoid recursion in the case that type == "newListeners"! Before
|
|||
|
// adding it to the listeners, first emit "newListeners".
|
|||
|
this.emit('newListener', type, listener);
|
|||
|
|
|||
|
if (!this._events[type]) {
|
|||
|
// Optimize the case of one listener. Don't need the extra array object.
|
|||
|
this._events[type] = listener;
|
|||
|
} else if (isArray(this._events[type])) {
|
|||
|
|
|||
|
// Check for listener leak
|
|||
|
if (!this._events[type].warned) {
|
|||
|
var m;
|
|||
|
if (this._events.maxListeners !== undefined) {
|
|||
|
m = this._events.maxListeners;
|
|||
|
} else {
|
|||
|
m = defaultMaxListeners;
|
|||
|
}
|
|||
|
|
|||
|
if (m && m > 0 && this._events[type].length > m) {
|
|||
|
this._events[type].warned = true;
|
|||
|
console.error('(node) warning: possible EventEmitter memory ' +
|
|||
|
'leak detected. %d listeners added. ' +
|
|||
|
'Use emitter.setMaxListeners() to increase limit.',
|
|||
|
this._events[type].length);
|
|||
|
console.trace();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// If we've already got an array, just append.
|
|||
|
this._events[type].push(listener);
|
|||
|
} else {
|
|||
|
// Adding the second element, need to change to array.
|
|||
|
this._events[type] = [this._events[type], listener];
|
|||
|
}
|
|||
|
|
|||
|
return this;
|
|||
|
};
|
|||
|
|
|||
|
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
|
|||
|
|
|||
|
EventEmitter.prototype.once = function(type, listener) {
|
|||
|
var self = this;
|
|||
|
self.on(type, function g() {
|
|||
|
self.removeListener(type, g);
|
|||
|
listener.apply(this, arguments);
|
|||
|
});
|
|||
|
|
|||
|
return this;
|
|||
|
};
|
|||
|
|
|||
|
EventEmitter.prototype.removeListener = function(type, listener) {
|
|||
|
if ('function' !== typeof listener) {
|
|||
|
throw new Error('removeListener only takes instances of Function');
|
|||
|
}
|
|||
|
|
|||
|
// does not use listeners(), so no side effect of creating _events[type]
|
|||
|
if (!this._events || !this._events[type]) return this;
|
|||
|
|
|||
|
var list = this._events[type];
|
|||
|
|
|||
|
if (isArray(list)) {
|
|||
|
var i = indexOf(list, listener);
|
|||
|
if (i < 0) return this;
|
|||
|
list.splice(i, 1);
|
|||
|
if (list.length == 0)
|
|||
|
delete this._events[type];
|
|||
|
} else if (this._events[type] === listener) {
|
|||
|
delete this._events[type];
|
|||
|
}
|
|||
|
|
|||
|
return this;
|
|||
|
};
|
|||
|
|
|||
|
EventEmitter.prototype.removeAllListeners = function(type) {
|
|||
|
if (arguments.length === 0) {
|
|||
|
this._events = {};
|
|||
|
return this;
|
|||
|
}
|
|||
|
|
|||
|
// does not use listeners(), so no side effect of creating _events[type]
|
|||
|
if (type && this._events && this._events[type]) this._events[type] = null;
|
|||
|
return this;
|
|||
|
};
|
|||
|
|
|||
|
EventEmitter.prototype.listeners = function(type) {
|
|||
|
if (!this._events) this._events = {};
|
|||
|
if (!this._events[type]) this._events[type] = [];
|
|||
|
if (!isArray(this._events[type])) {
|
|||
|
this._events[type] = [this._events[type]];
|
|||
|
}
|
|||
|
return this._events[type];
|
|||
|
};
|
|||
|
|
|||
|
})(require("__browserify_process"))
|
|||
|
},{"__browserify_process":2}],3:[function(require,module,exports){
|
|||
|
var Api = require('./remark/api')
|
|||
|
, polyfills = require('./polyfills')
|
|||
|
, styler = require('components/styler')
|
|||
|
;
|
|||
|
|
|||
|
// Expose API as `remark`
|
|||
|
window.remark = new Api();
|
|||
|
|
|||
|
// Apply polyfills as needed
|
|||
|
polyfills.apply();
|
|||
|
|
|||
|
// Apply embedded styles to document
|
|||
|
styler.styleDocument();
|
|||
|
|
|||
|
},{"components/styler":"t5Lx4S","./remark/api":4,"./polyfills":5}],"components/styler":[function(require,module,exports){
|
|||
|
module.exports=require('t5Lx4S');
|
|||
|
},{}],"t5Lx4S":[function(require,module,exports){
|
|||
|
var resources = require('../../resources')
|
|||
|
, highlighter = require('../../highlighter')
|
|||
|
;
|
|||
|
|
|||
|
module.exports = {
|
|||
|
styleDocument: styleDocument
|
|||
|
, setPageSize: setPageSize
|
|||
|
};
|
|||
|
|
|||
|
// Applies bundled styles to document
|
|||
|
function styleDocument () {
|
|||
|
var headElement, styleElement, style;
|
|||
|
|
|||
|
// Bail out if document has already been styled
|
|||
|
if (getRemarkStylesheet()) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
headElement = document.getElementsByTagName('head')[0];
|
|||
|
styleElement = document.createElement('style');
|
|||
|
styleElement.type = 'text/css';
|
|||
|
|
|||
|
// Set title in order to enable lookup
|
|||
|
styleElement.title = 'remark';
|
|||
|
|
|||
|
// Set document styles
|
|||
|
styleElement.innerHTML = resources.documentStyles;
|
|||
|
|
|||
|
// Append highlighting styles
|
|||
|
for (style in highlighter.styles) {
|
|||
|
if (highlighter.styles.hasOwnProperty(style)) {
|
|||
|
styleElement.innerHTML = styleElement.innerHTML +
|
|||
|
highlighter.styles[style];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Put element first to prevent overriding user styles
|
|||
|
headElement.insertBefore(styleElement, headElement.firstChild);
|
|||
|
}
|
|||
|
|
|||
|
function setPageSize (size) {
|
|||
|
var stylesheet = getRemarkStylesheet()
|
|||
|
, pageRule = getPageRule(stylesheet)
|
|||
|
;
|
|||
|
|
|||
|
pageRule.style.size = size;
|
|||
|
}
|
|||
|
|
|||
|
// Locates the embedded remark stylesheet
|
|||
|
function getRemarkStylesheet () {
|
|||
|
var i, l = document.styleSheets.length;
|
|||
|
|
|||
|
for (i = 0; i < l; ++i) {
|
|||
|
if (document.styleSheets[i].title === 'remark') {
|
|||
|
return document.styleSheets[i];
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Locates the CSS @page rule
|
|||
|
function getPageRule (stylesheet) {
|
|||
|
var i, l = stylesheet.cssRules.length;
|
|||
|
|
|||
|
for (i = 0; i < l; ++i) {
|
|||
|
if (stylesheet.cssRules[i] instanceof window.CSSPageRule) {
|
|||
|
return stylesheet.cssRules[i];
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
},{"../../resources":6,"../../highlighter":7}],5:[function(require,module,exports){
|
|||
|
exports.apply = function () {
|
|||
|
forEach([Array, window.NodeList, window.HTMLCollection], extend);
|
|||
|
};
|
|||
|
|
|||
|
function forEach (list, f) {
|
|||
|
var i;
|
|||
|
|
|||
|
for (i = 0; i < list.length; ++i) {
|
|||
|
f(list[i], i);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function extend (object) {
|
|||
|
var prototype = object && object.prototype;
|
|||
|
|
|||
|
if (!prototype) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
prototype.forEach = prototype.forEach || function (f) {
|
|||
|
forEach(this, f);
|
|||
|
};
|
|||
|
|
|||
|
prototype.filter = prototype.filter || function (f) {
|
|||
|
var result = [];
|
|||
|
|
|||
|
this.forEach(function (element) {
|
|||
|
if (f(element, result.length)) {
|
|||
|
result.push(element);
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
return result;
|
|||
|
};
|
|||
|
|
|||
|
prototype.map = prototype.map || function (f) {
|
|||
|
var result = [];
|
|||
|
|
|||
|
this.forEach(function (element) {
|
|||
|
result.push(f(element, result.length));
|
|||
|
});
|
|||
|
|
|||
|
return result;
|
|||
|
};
|
|||
|
}
|
|||
|
},{}],"components/timer":[function(require,module,exports){
|
|||
|
module.exports=require('yAcg0L');
|
|||
|
},{}],"yAcg0L":[function(require,module,exports){
|
|||
|
var utils = require('../../utils');
|
|||
|
|
|||
|
module.exports = TimerViewModel;
|
|||
|
|
|||
|
function TimerViewModel (events, element) {
|
|||
|
var self = this;
|
|||
|
|
|||
|
self.events = events;
|
|||
|
self.element = element;
|
|||
|
|
|||
|
self.startTime = null;
|
|||
|
self.pauseStart = null;
|
|||
|
self.pauseLength = 0;
|
|||
|
|
|||
|
element.innerHTML = '0:00:00';
|
|||
|
|
|||
|
setInterval(function() {
|
|||
|
self.updateTimer();
|
|||
|
}, 100);
|
|||
|
|
|||
|
events.on('start', function () {
|
|||
|
// When we do the first slide change, start the clock.
|
|||
|
self.startTime = new Date();
|
|||
|
});
|
|||
|
|
|||
|
events.on('resetTimer', function () {
|
|||
|
// If we reset the timer, clear everything.
|
|||
|
self.startTime = null;
|
|||
|
self.pauseStart = null;
|
|||
|
self.pauseLength = 0;
|
|||
|
self.element.innerHTML = '0:00:00';
|
|||
|
});
|
|||
|
|
|||
|
events.on('pause', function () {
|
|||
|
self.pauseStart = new Date();
|
|||
|
});
|
|||
|
|
|||
|
events.on('resume', function () {
|
|||
|
self.pauseLength += new Date() - self.pauseStart;
|
|||
|
self.pauseStart = null;
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
TimerViewModel.prototype.updateTimer = function () {
|
|||
|
var self = this;
|
|||
|
|
|||
|
if (self.startTime) {
|
|||
|
var millis;
|
|||
|
// If we're currently paused, measure elapsed time from the pauseStart.
|
|||
|
// Otherwise, use "now".
|
|||
|
if (self.pauseStart) {
|
|||
|
millis = self.pauseStart - self.startTime - self.pauseLength;
|
|||
|
} else {
|
|||
|
millis = new Date() - self.startTime - self.pauseLength;
|
|||
|
}
|
|||
|
|
|||
|
var seconds = Math.floor(millis / 1000) % 60;
|
|||
|
var minutes = Math.floor(millis / 60000) % 60;
|
|||
|
var hours = Math.floor(millis / 3600000);
|
|||
|
|
|||
|
self.element.innerHTML = hours + (minutes > 9 ? ':' : ':0') + minutes + (seconds > 9 ? ':' : ':0') + seconds;
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
},{"../../utils":8}],6:[function(require,module,exports){
|
|||
|
/* Automatically generated */
|
|||
|
|
|||
|
module.exports = {
|
|||
|
documentStyles: "html.remark-container,body.remark-container{height:100%;width:100%;-webkit-print-color-adjust:exact;}.remark-container{background:#d7d8d2;margin:0;overflow:hidden;}.remark-container:focus{outline-style:solid;outline-width:1px;}:-webkit-full-screen .remark-container{width:100%;height:100%;}.remark-slides-area{position:relative;height:100%;width:100%;}.remark-slide-container{display:none;position:absolute;height:100%;width:100%;page-break-after:always;}.remark-slide-scaler{background-color:transparent;overflow:hidden;position:absolute;-webkit-transform-origin:top left;-moz-transform-origin:top left;transform-origin:top-left;-moz-box-shadow:0 0 30px #888;-webkit-box-shadow:0 0 30px #888;box-shadow:0 0 30px #888;}.remark-slide{height:100%;width:100%;display:table;table-layout:fixed;}.remark-slide>.left{text-align:left;}.remark-slide>.center{text-align:center;}.remark-slide>.right{text-align:right;}.remark-slide>.top{vertical-align:top;}.remark-slide>.middle{vertical-align:middle;}.remark-slide>.bottom{vertical-align:bottom;}.remark-slide-content{background-color:#fff;background-position:center;background-repeat:no-repeat;display:table-cell;font-size:20px;padding:1em 4em 1em 4em;}.remark-slide-content h1{font-size:55px;}.remark-slide-content h2{font-size:45px;}.remark-slide-content h3{font-size:35px;}.remark-slide-content .left{display:block;text-align:left;}.remark-slide-content .center{display:block;text-align:center;}.remark-slide-content .right{display:block;text-align:right;}.remark-slide-number{bottom:12px;opacity:0.5;position:absolute;right:20px;}.remark-slide-notes{border-top:3px solid black;position:absolute;display:none;}.remark-code{font-size:18px;}.remark-code-line{min-height:1em;}.remark-code-line-highlighted{background-color:rgba(255, 255, 0, 0.5);}.remark-code-span-highlighted{background-color:rgba(255, 255, 0, 0.5);padding:1px 2px 2px 2px;}.remark-visible{display:block;z-index:2;}.remark-fading{display:block;z-index:1;}.remark-fading .remark-slide-scaler{-moz-box-shadow:none;-webkit-box-shadow:none;box-shadow:none;}.remark-backdrop{position:absolute;top:0;bottom:0;left:0;right:0;display:none;background:#000;z-index:2;}.remark-pause{bottom:0;top:0;right:0;left:0;display:none;position:absolute;z-index:1000;}.remark-pause .remark-pause-lozenge{margin-top:30%;text-align:center;}.remark-pause .remark-pause-lozenge span{color:white;background:black;border:2px solid black;border-radius:20px;padding:20px 30px;font-family:Helvetica,arial,freesans,clean,sans-serif;font-size:42pt;font-weight:bold;}.remark-container.remark-presenter-mode.remark-pause-mode .remark-pause{display:block;}.remark-container.remark-presenter-mode.remark-pause-mode .remark-backdrop{display:block;opacity:0.5;}.remark-help{bottom:0;top:0;right:0;left:0;display:none;position:absolute;z-index:1000;-webkit-transform-origin:top left;-moz-transform-origin:top left;transform-origin:top-left;}.remark-help .remark-help-content{color:white;font-family:Helvetica,arial,freesans,clean,sans-serif;font-size:12pt;position:absolute;top:5%;bottom:10%;height:10%;left:5%;width:90%;}.remark-help .remark-help-content h1{font-size:36px;}.remark-help .remark-help-content td{color:white;font-size:12pt;padding:10px;}.remark-help .remark-help-content td:first-child{padding-left:0;}.remark-help .remark-help-content .key{background:white;color:black;min-width:1em;display:inline-block;padding:3px 6px;text-align:center;border-radius:4px;font-size:14px;}.remark-help .dismiss{top:85%;}.remark-container.remark-help-mode .remark-help{display:block;}.remark-container.remark-help-mode .remark-backdrop{display:block;opacity:0.95;}.remark-preview-area{bottom:2%;left:2%;display:none;opacity:0.5;position:absolute;height:47.25%;width:48%;}.remark-preview-area .remark-slide-container{display:block;}.remark-notes-area{background:#e7e8e2;bottom:0;display:none;left:52%;overflow:hidden;position:absolute;right:0;top:0;}.remark-notes-area .remark-top-area{height:50px;left:20px;position:absolute;right:10px;top:10px;}.remark-notes-area .remark-bottom-area{position:absolute;top:
|
|||
|
containerLayout: "<div class=\"remark-notes-area\">\n <div class=\"remark-top-area\">\n <div class=\"remark-toolbar\">\n <a class=\"remark-toolbar-link\" href=\"#increase\">+</a>\n <a class=\"remark-toolbar-link\" href=\"#decrease\">-</a>\n <span class=\"remark-toolbar-timer\"></span>\n </div>\n </div>\n <div class=\"remark-bottom-area\">\n <div class=\"remark-notes-current-area\">\n <div class=\"remark-toggle\">Notes for current slide</div>\n <div class=\"remark-notes\"></div>\n </div>\n <div class=\"remark-notes-preview-area\">\n <div class=\"remark-toggle\">Notes for next slide</div>\n <div class=\"remark-notes-preview\"></div>\n </div>\n </div>\n</div>\n<div class=\"remark-slides-area\"></div>\n<div class=\"remark-preview-area\"></div>\n<div class=\"remark-backdrop\"></div>\n<div class=\"remark-pause\">\n <div class=\"remark-pause-lozenge\">\n <span>Paused</span>\n </div>\n</div>\n<div class=\"remark-help\">\n <div class=\"remark-help-content\">\n <h1>Help</h1>\n <p><b>Keyboard shortcuts</b></p>\n <table class=\"light-keys\">\n <tr>\n <td>\n <span class=\"key\"><b>↑</b></span>,\n <span class=\"key\"><b>←</b></span>,\n <span class=\"key\">Pg Up</span>,\n <span class=\"key\">k</span>\n </td>\n <td>Go to previous slide</td>\n </tr>\n <tr>\n <td>\n <span class=\"key\"><b>↓</b></span>,\n <span class=\"key\"><b>→</b></span>,\n <span class=\"key\">Pg Dn</span>,\n <span class=\"key\">Space</span>,\n <span class=\"key\">j</span>\n </td>\n <td>Go to next slide</td>\n </tr>\n <tr>\n <td>\n <span class=\"key\">Home</span>\n </td>\n <td>Go to first slide</td>\n </tr>\n <tr>\n <td>\n <span class=\"key\">End</span>\n </td>\n <td>Go to last slide</td>\n </tr>\n <tr>\n <td>\n <span class=\"key\">b</span> /\n <span class=\"key\">m</span> /\n <span class=\"key\">f</span>\n </td>\n <td>Toggle blackout / mirrored / fullscreen mode</td>\n </tr>\n <tr>\n <td>\n <span class=\"key\">c</span>\n </td>\n <td>Clone slideshow</td>\n </tr>\n <tr>\n <td>\n <span class=\"key\">p</span>\n </td>\n <td>Toggle presenter mode</td>\n </tr>\n <tr>\n <td>\n <span class=\"key\">t</span>\n </td>\n <td>Restart the presentation timer</td>\n </tr>\n <tr>\n <td>\n <span class=\"key\">?</span>,\n <span class=\"key\">h</span>\n </td>\n <td>Toggle this help</td>\n </tr>\n </table>\n </div>\n <div class=\"content dismiss\">\n <table class=\"light-keys\">\n <tr>\n <td>\n <span class=\"key\">Esc</span>\n </td>\n <td>Back to slideshow</td>\n </tr>\n </table>\n </div>\n</div>\n"
|
|||
|
};
|
|||
|
|
|||
|
},{}],7:[function(require,module,exports){
|
|||
|
(function(){/* Automatically generated */
|
|||
|
|
|||
|
var hljs = new (/*
|
|||
|
Syntax highlighting with language autodetection.
|
|||
|
http://highlightjs.org/
|
|||
|
*/
|
|||
|
|
|||
|
function() {
|
|||
|
|
|||
|
/* Utility functions */
|
|||
|
|
|||
|
function escape(value) {
|
|||
|
return value.replace(/&/gm, '&').replace(/</gm, '<').replace(/>/gm, '>');
|
|||
|
}
|
|||
|
|
|||
|
function tag(node) {
|
|||
|
return node.nodeName.toLowerCase();
|
|||
|
}
|
|||
|
|
|||
|
function testRe(re, lexeme) {
|
|||
|
var match = re && re.exec(lexeme);
|
|||
|
return match && match.index == 0;
|
|||
|
}
|
|||
|
|
|||
|
function blockLanguage(block) {
|
|||
|
var classes = (block.className + ' ' + (block.parentNode ? block.parentNode.className : '')).split(/\s+/);
|
|||
|
classes = classes.map(function(c) {return c.replace(/^lang(uage)?-/, '');});
|
|||
|
return classes.filter(function(c) {return getLanguage(c) || c == 'no-highlight';})[0];
|
|||
|
}
|
|||
|
|
|||
|
function inherit(parent, obj) {
|
|||
|
var result = {};
|
|||
|
for (var key in parent)
|
|||
|
result[key] = parent[key];
|
|||
|
if (obj)
|
|||
|
for (var key in obj)
|
|||
|
result[key] = obj[key];
|
|||
|
return result;
|
|||
|
};
|
|||
|
|
|||
|
/* Stream merging */
|
|||
|
|
|||
|
function nodeStream(node) {
|
|||
|
var result = [];
|
|||
|
(function _nodeStream(node, offset) {
|
|||
|
for (var child = node.firstChild; child; child = child.nextSibling) {
|
|||
|
if (child.nodeType == 3)
|
|||
|
offset += child.nodeValue.length;
|
|||
|
else if (tag(child) == 'br')
|
|||
|
offset += 1;
|
|||
|
else if (child.nodeType == 1) {
|
|||
|
result.push({
|
|||
|
event: 'start',
|
|||
|
offset: offset,
|
|||
|
node: child
|
|||
|
});
|
|||
|
offset = _nodeStream(child, offset);
|
|||
|
result.push({
|
|||
|
event: 'stop',
|
|||
|
offset: offset,
|
|||
|
node: child
|
|||
|
});
|
|||
|
}
|
|||
|
}
|
|||
|
return offset;
|
|||
|
})(node, 0);
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
function mergeStreams(original, highlighted, value) {
|
|||
|
var processed = 0;
|
|||
|
var result = '';
|
|||
|
var nodeStack = [];
|
|||
|
|
|||
|
function selectStream() {
|
|||
|
if (!original.length || !highlighted.length) {
|
|||
|
return original.length ? original : highlighted;
|
|||
|
}
|
|||
|
if (original[0].offset != highlighted[0].offset) {
|
|||
|
return (original[0].offset < highlighted[0].offset) ? original : highlighted;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
To avoid starting the stream just before it should stop the order is
|
|||
|
ensured that original always starts first and closes last:
|
|||
|
|
|||
|
if (event1 == 'start' && event2 == 'start')
|
|||
|
return original;
|
|||
|
if (event1 == 'start' && event2 == 'stop')
|
|||
|
return highlighted;
|
|||
|
if (event1 == 'stop' && event2 == 'start')
|
|||
|
return original;
|
|||
|
if (event1 == 'stop' && event2 == 'stop')
|
|||
|
return highlighted;
|
|||
|
|
|||
|
... which is collapsed to:
|
|||
|
*/
|
|||
|
return highlighted[0].event == 'start' ? original : highlighted;
|
|||
|
}
|
|||
|
|
|||
|
function open(node) {
|
|||
|
function attr_str(a) {return ' ' + a.nodeName + '="' + escape(a.value) + '"';}
|
|||
|
result += '<' + tag(node) + Array.prototype.map.call(node.attributes, attr_str).join('') + '>';
|
|||
|
}
|
|||
|
|
|||
|
function close(node) {
|
|||
|
result += '</' + tag(node) + '>';
|
|||
|
}
|
|||
|
|
|||
|
function render(event) {
|
|||
|
(event.event == 'start' ? open : close)(event.node);
|
|||
|
}
|
|||
|
|
|||
|
while (original.length || highlighted.length) {
|
|||
|
var stream = selectStream();
|
|||
|
result += escape(value.substr(processed, stream[0].offset - processed));
|
|||
|
processed = stream[0].offset;
|
|||
|
if (stream == original) {
|
|||
|
/*
|
|||
|
On any opening or closing tag of the original markup we first close
|
|||
|
the entire highlighted node stack, then render the original tag along
|
|||
|
with all the following original tags at the same offset and then
|
|||
|
reopen all the tags on the highlighted stack.
|
|||
|
*/
|
|||
|
nodeStack.reverse().forEach(close);
|
|||
|
do {
|
|||
|
render(stream.splice(0, 1)[0]);
|
|||
|
stream = selectStream();
|
|||
|
} while (stream == original && stream.length && stream[0].offset == processed);
|
|||
|
nodeStack.reverse().forEach(open);
|
|||
|
} else {
|
|||
|
if (stream[0].event == 'start') {
|
|||
|
nodeStack.push(stream[0].node);
|
|||
|
} else {
|
|||
|
nodeStack.pop();
|
|||
|
}
|
|||
|
render(stream.splice(0, 1)[0]);
|
|||
|
}
|
|||
|
}
|
|||
|
return result + escape(value.substr(processed));
|
|||
|
}
|
|||
|
|
|||
|
/* Initialization */
|
|||
|
|
|||
|
function compileLanguage(language) {
|
|||
|
|
|||
|
function reStr(re) {
|
|||
|
return (re && re.source) || re;
|
|||
|
}
|
|||
|
|
|||
|
function langRe(value, global) {
|
|||
|
return RegExp(
|
|||
|
reStr(value),
|
|||
|
'm' + (language.case_insensitive ? 'i' : '') + (global ? 'g' : '')
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
function compileMode(mode, parent) {
|
|||
|
if (mode.compiled)
|
|||
|
return;
|
|||
|
mode.compiled = true;
|
|||
|
|
|||
|
mode.keywords = mode.keywords || mode.beginKeywords;
|
|||
|
if (mode.keywords) {
|
|||
|
var compiled_keywords = {};
|
|||
|
|
|||
|
function flatten(className, str) {
|
|||
|
if (language.case_insensitive) {
|
|||
|
str = str.toLowerCase();
|
|||
|
}
|
|||
|
str.split(' ').forEach(function(kw) {
|
|||
|
var pair = kw.split('|');
|
|||
|
compiled_keywords[pair[0]] = [className, pair[1] ? Number(pair[1]) : 1];
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
if (typeof mode.keywords == 'string') { // string
|
|||
|
flatten('keyword', mode.keywords);
|
|||
|
} else {
|
|||
|
Object.keys(mode.keywords).forEach(function (className) {
|
|||
|
flatten(className, mode.keywords[className]);
|
|||
|
});
|
|||
|
}
|
|||
|
mode.keywords = compiled_keywords;
|
|||
|
}
|
|||
|
mode.lexemesRe = langRe(mode.lexemes || /\b[A-Za-z0-9_]+\b/, true);
|
|||
|
|
|||
|
if (parent) {
|
|||
|
if (mode.beginKeywords) {
|
|||
|
mode.begin = '\\b(' + mode.beginKeywords.split(' ').join('|') + ')\\b';
|
|||
|
}
|
|||
|
if (!mode.begin)
|
|||
|
mode.begin = /\B|\b/;
|
|||
|
mode.beginRe = langRe(mode.begin);
|
|||
|
if (!mode.end && !mode.endsWithParent)
|
|||
|
mode.end = /\B|\b/;
|
|||
|
if (mode.end)
|
|||
|
mode.endRe = langRe(mode.end);
|
|||
|
mode.terminator_end = reStr(mode.end) || '';
|
|||
|
if (mode.endsWithParent && parent.terminator_end)
|
|||
|
mode.terminator_end += (mode.end ? '|' : '') + parent.terminator_end;
|
|||
|
}
|
|||
|
if (mode.illegal)
|
|||
|
mode.illegalRe = langRe(mode.illegal);
|
|||
|
if (mode.relevance === undefined)
|
|||
|
mode.relevance = 1;
|
|||
|
if (!mode.contains) {
|
|||
|
mode.contains = [];
|
|||
|
}
|
|||
|
var expanded_contains = [];
|
|||
|
mode.contains.forEach(function(c) {
|
|||
|
if (c.variants) {
|
|||
|
c.variants.forEach(function(v) {expanded_contains.push(inherit(c, v));});
|
|||
|
} else {
|
|||
|
expanded_contains.push(c == 'self' ? mode : c);
|
|||
|
}
|
|||
|
});
|
|||
|
mode.contains = expanded_contains;
|
|||
|
mode.contains.forEach(function(c) {compileMode(c, mode);});
|
|||
|
|
|||
|
if (mode.starts) {
|
|||
|
compileMode(mode.starts, parent);
|
|||
|
}
|
|||
|
|
|||
|
var terminators =
|
|||
|
mode.contains.map(function(c) {
|
|||
|
return c.beginKeywords ? '\\.?(' + c.begin + ')\\.?' : c.begin;
|
|||
|
})
|
|||
|
.concat([mode.terminator_end, mode.illegal])
|
|||
|
.map(reStr)
|
|||
|
.filter(Boolean);
|
|||
|
mode.terminators = terminators.length ? langRe(terminators.join('|'), true) : {exec: function(s) {return null;}};
|
|||
|
|
|||
|
mode.continuation = {};
|
|||
|
}
|
|||
|
|
|||
|
compileMode(language);
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
Core highlighting function. Accepts a language name, or an alias, and a
|
|||
|
string with the code to highlight. Returns an object with the following
|
|||
|
properties:
|
|||
|
|
|||
|
- relevance (int)
|
|||
|
- value (an HTML string with highlighting markup)
|
|||
|
|
|||
|
*/
|
|||
|
function highlight(name, value, ignore_illegals, continuation) {
|
|||
|
|
|||
|
function subMode(lexeme, mode) {
|
|||
|
for (var i = 0; i < mode.contains.length; i++) {
|
|||
|
if (testRe(mode.contains[i].beginRe, lexeme)) {
|
|||
|
return mode.contains[i];
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function endOfMode(mode, lexeme) {
|
|||
|
if (testRe(mode.endRe, lexeme)) {
|
|||
|
return mode;
|
|||
|
}
|
|||
|
if (mode.endsWithParent) {
|
|||
|
return endOfMode(mode.parent, lexeme);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function isIllegal(lexeme, mode) {
|
|||
|
return !ignore_illegals && testRe(mode.illegalRe, lexeme);
|
|||
|
}
|
|||
|
|
|||
|
function keywordMatch(mode, match) {
|
|||
|
var match_str = language.case_insensitive ? match[0].toLowerCase() : match[0];
|
|||
|
return mode.keywords.hasOwnProperty(match_str) && mode.keywords[match_str];
|
|||
|
}
|
|||
|
|
|||
|
function buildSpan(classname, insideSpan, leaveOpen, noPrefix) {
|
|||
|
var classPrefix = noPrefix ? '' : options.classPrefix,
|
|||
|
openSpan = '<span class="' + classPrefix,
|
|||
|
closeSpan = leaveOpen ? '' : '</span>';
|
|||
|
|
|||
|
openSpan += classname + '">';
|
|||
|
|
|||
|
return openSpan + insideSpan + closeSpan;
|
|||
|
}
|
|||
|
|
|||
|
function processKeywords() {
|
|||
|
if (!top.keywords)
|
|||
|
return escape(mode_buffer);
|
|||
|
var result = '';
|
|||
|
var last_index = 0;
|
|||
|
top.lexemesRe.lastIndex = 0;
|
|||
|
var match = top.lexemesRe.exec(mode_buffer);
|
|||
|
while (match) {
|
|||
|
result += escape(mode_buffer.substr(last_index, match.index - last_index));
|
|||
|
var keyword_match = keywordMatch(top, match);
|
|||
|
if (keyword_match) {
|
|||
|
relevance += keyword_match[1];
|
|||
|
result += buildSpan(keyword_match[0], escape(match[0]));
|
|||
|
} else {
|
|||
|
result += escape(match[0]);
|
|||
|
}
|
|||
|
last_index = top.lexemesRe.lastIndex;
|
|||
|
match = top.lexemesRe.exec(mode_buffer);
|
|||
|
}
|
|||
|
return result + escape(mode_buffer.substr(last_index));
|
|||
|
}
|
|||
|
|
|||
|
function processSubLanguage() {
|
|||
|
if (top.subLanguage && !languages[top.subLanguage]) {
|
|||
|
return escape(mode_buffer);
|
|||
|
}
|
|||
|
var result = top.subLanguage ? highlight(top.subLanguage, mode_buffer, true, top.continuation.top) : highlightAuto(mode_buffer);
|
|||
|
// Counting embedded language score towards the host language may be disabled
|
|||
|
// with zeroing the containing mode relevance. Usecase in point is Markdown that
|
|||
|
// allows XML everywhere and makes every XML snippet to have a much larger Markdown
|
|||
|
// score.
|
|||
|
if (top.relevance > 0) {
|
|||
|
relevance += result.relevance;
|
|||
|
}
|
|||
|
if (top.subLanguageMode == 'continuous') {
|
|||
|
top.continuation.top = result.top;
|
|||
|
}
|
|||
|
return buildSpan(result.language, result.value, false, true);
|
|||
|
}
|
|||
|
|
|||
|
function processBuffer() {
|
|||
|
return top.subLanguage !== undefined ? processSubLanguage() : processKeywords();
|
|||
|
}
|
|||
|
|
|||
|
function startNewMode(mode, lexeme) {
|
|||
|
var markup = mode.className? buildSpan(mode.className, '', true): '';
|
|||
|
if (mode.returnBegin) {
|
|||
|
result += markup;
|
|||
|
mode_buffer = '';
|
|||
|
} else if (mode.excludeBegin) {
|
|||
|
result += escape(lexeme) + markup;
|
|||
|
mode_buffer = '';
|
|||
|
} else {
|
|||
|
result += markup;
|
|||
|
mode_buffer = lexeme;
|
|||
|
}
|
|||
|
top = Object.create(mode, {parent: {value: top}});
|
|||
|
}
|
|||
|
|
|||
|
function processLexeme(buffer, lexeme) {
|
|||
|
|
|||
|
mode_buffer += buffer;
|
|||
|
if (lexeme === undefined) {
|
|||
|
result += processBuffer();
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
var new_mode = subMode(lexeme, top);
|
|||
|
if (new_mode) {
|
|||
|
result += processBuffer();
|
|||
|
startNewMode(new_mode, lexeme);
|
|||
|
return new_mode.returnBegin ? 0 : lexeme.length;
|
|||
|
}
|
|||
|
|
|||
|
var end_mode = endOfMode(top, lexeme);
|
|||
|
if (end_mode) {
|
|||
|
var origin = top;
|
|||
|
if (!(origin.returnEnd || origin.excludeEnd)) {
|
|||
|
mode_buffer += lexeme;
|
|||
|
}
|
|||
|
result += processBuffer();
|
|||
|
do {
|
|||
|
if (top.className) {
|
|||
|
result += '</span>';
|
|||
|
}
|
|||
|
relevance += top.relevance;
|
|||
|
top = top.parent;
|
|||
|
} while (top != end_mode.parent);
|
|||
|
if (origin.excludeEnd) {
|
|||
|
result += escape(lexeme);
|
|||
|
}
|
|||
|
mode_buffer = '';
|
|||
|
if (end_mode.starts) {
|
|||
|
startNewMode(end_mode.starts, '');
|
|||
|
}
|
|||
|
return origin.returnEnd ? 0 : lexeme.length;
|
|||
|
}
|
|||
|
|
|||
|
if (isIllegal(lexeme, top))
|
|||
|
throw new Error('Illegal lexeme "' + lexeme + '" for mode "' + (top.className || '<unnamed>') + '"');
|
|||
|
|
|||
|
/*
|
|||
|
Parser should not reach this point as all types of lexemes should be caught
|
|||
|
earlier, but if it does due to some bug make sure it advances at least one
|
|||
|
character forward to prevent infinite looping.
|
|||
|
*/
|
|||
|
mode_buffer += lexeme;
|
|||
|
return lexeme.length || 1;
|
|||
|
}
|
|||
|
|
|||
|
var language = getLanguage(name);
|
|||
|
if (!language) {
|
|||
|
throw new Error('Unknown language: "' + name + '"');
|
|||
|
}
|
|||
|
|
|||
|
compileLanguage(language);
|
|||
|
var top = continuation || language;
|
|||
|
var result = '';
|
|||
|
for(var current = top; current != language; current = current.parent) {
|
|||
|
if (current.className) {
|
|||
|
result += buildSpan(current.className, result, true);
|
|||
|
}
|
|||
|
}
|
|||
|
var mode_buffer = '';
|
|||
|
var relevance = 0;
|
|||
|
try {
|
|||
|
var match, count, index = 0;
|
|||
|
while (true) {
|
|||
|
top.terminators.lastIndex = index;
|
|||
|
match = top.terminators.exec(value);
|
|||
|
if (!match)
|
|||
|
break;
|
|||
|
count = processLexeme(value.substr(index, match.index - index), match[0]);
|
|||
|
index = match.index + count;
|
|||
|
}
|
|||
|
processLexeme(value.substr(index));
|
|||
|
for(var current = top; current.parent; current = current.parent) { // close dangling modes
|
|||
|
if (current.className) {
|
|||
|
result += '</span>';
|
|||
|
}
|
|||
|
};
|
|||
|
return {
|
|||
|
relevance: relevance,
|
|||
|
value: result,
|
|||
|
language: name,
|
|||
|
top: top
|
|||
|
};
|
|||
|
} catch (e) {
|
|||
|
if (e.message.indexOf('Illegal') != -1) {
|
|||
|
return {
|
|||
|
relevance: 0,
|
|||
|
value: escape(value)
|
|||
|
};
|
|||
|
} else {
|
|||
|
throw e;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
Highlighting with language detection. Accepts a string with the code to
|
|||
|
highlight. Returns an object with the following properties:
|
|||
|
|
|||
|
- language (detected language)
|
|||
|
- relevance (int)
|
|||
|
- value (an HTML string with highlighting markup)
|
|||
|
- second_best (object with the same structure for second-best heuristically
|
|||
|
detected language, may be absent)
|
|||
|
|
|||
|
*/
|
|||
|
function highlightAuto(text, languageSubset) {
|
|||
|
languageSubset = languageSubset || options.languages || Object.keys(languages);
|
|||
|
var result = {
|
|||
|
relevance: 0,
|
|||
|
value: escape(text)
|
|||
|
};
|
|||
|
var second_best = result;
|
|||
|
languageSubset.forEach(function(name) {
|
|||
|
if (!getLanguage(name)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
var current = highlight(name, text, false);
|
|||
|
current.language = name;
|
|||
|
if (current.relevance > second_best.relevance) {
|
|||
|
second_best = current;
|
|||
|
}
|
|||
|
if (current.relevance > result.relevance) {
|
|||
|
second_best = result;
|
|||
|
result = current;
|
|||
|
}
|
|||
|
});
|
|||
|
if (second_best.language) {
|
|||
|
result.second_best = second_best;
|
|||
|
}
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
Post-processing of the highlighted markup:
|
|||
|
|
|||
|
- replace TABs with something more useful
|
|||
|
- replace real line-breaks with '<br>' for non-pre containers
|
|||
|
|
|||
|
*/
|
|||
|
function fixMarkup(value) {
|
|||
|
if (options.tabReplace) {
|
|||
|
value = value.replace(/^((<[^>]+>|\t)+)/gm, function(match, p1, offset, s) {
|
|||
|
return p1.replace(/\t/g, options.tabReplace);
|
|||
|
});
|
|||
|
}
|
|||
|
if (options.useBR) {
|
|||
|
value = value.replace(/\n/g, '<br>');
|
|||
|
}
|
|||
|
return value;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
Applies highlighting to a DOM node containing code. Accepts a DOM node and
|
|||
|
two optional parameters for fixMarkup.
|
|||
|
*/
|
|||
|
function highlightBlock(block) {
|
|||
|
var text = options.useBR ? block.innerHTML
|
|||
|
.replace(/\n/g,'').replace(/<br>|<br [^>]*>/g, '\n').replace(/<[^>]*>/g,'')
|
|||
|
: block.textContent;
|
|||
|
var language = blockLanguage(block);
|
|||
|
if (language == 'no-highlight')
|
|||
|
return;
|
|||
|
var result = language ? highlight(language, text, true) : highlightAuto(text);
|
|||
|
var original = nodeStream(block);
|
|||
|
if (original.length) {
|
|||
|
var pre = document.createElementNS('http://www.w3.org/1999/xhtml', 'pre');
|
|||
|
pre.innerHTML = result.value;
|
|||
|
result.value = mergeStreams(original, nodeStream(pre), text);
|
|||
|
}
|
|||
|
result.value = fixMarkup(result.value);
|
|||
|
|
|||
|
block.innerHTML = result.value;
|
|||
|
block.className += ' hljs ' + (!language && result.language || '');
|
|||
|
block.result = {
|
|||
|
language: result.language,
|
|||
|
re: result.relevance
|
|||
|
};
|
|||
|
if (result.second_best) {
|
|||
|
block.second_best = {
|
|||
|
language: result.second_best.language,
|
|||
|
re: result.second_best.relevance
|
|||
|
};
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
var options = {
|
|||
|
classPrefix: 'hljs-',
|
|||
|
tabReplace: null,
|
|||
|
useBR: false,
|
|||
|
languages: undefined
|
|||
|
};
|
|||
|
|
|||
|
/*
|
|||
|
Updates highlight.js global options with values passed in the form of an object
|
|||
|
*/
|
|||
|
function configure(user_options) {
|
|||
|
options = inherit(options, user_options);
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
Applies highlighting to all <pre><code>..</code></pre> blocks on a page.
|
|||
|
*/
|
|||
|
function initHighlighting() {
|
|||
|
if (initHighlighting.called)
|
|||
|
return;
|
|||
|
initHighlighting.called = true;
|
|||
|
|
|||
|
var blocks = document.querySelectorAll('pre code');
|
|||
|
Array.prototype.forEach.call(blocks, highlightBlock);
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
Attaches highlighting to the page load event.
|
|||
|
*/
|
|||
|
function initHighlightingOnLoad() {
|
|||
|
addEventListener('DOMContentLoaded', initHighlighting, false);
|
|||
|
addEventListener('load', initHighlighting, false);
|
|||
|
}
|
|||
|
|
|||
|
var languages = {};
|
|||
|
var aliases = {};
|
|||
|
|
|||
|
function registerLanguage(name, language) {
|
|||
|
var lang = languages[name] = language(this);
|
|||
|
if (lang.aliases) {
|
|||
|
lang.aliases.forEach(function(alias) {aliases[alias] = name;});
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function listLanguages() {
|
|||
|
return Object.keys(languages);
|
|||
|
}
|
|||
|
|
|||
|
function getLanguage(name) {
|
|||
|
return languages[name] || languages[aliases[name]];
|
|||
|
}
|
|||
|
|
|||
|
/* Interface definition */
|
|||
|
|
|||
|
this.highlight = highlight;
|
|||
|
this.highlightAuto = highlightAuto;
|
|||
|
this.fixMarkup = fixMarkup;
|
|||
|
this.highlightBlock = highlightBlock;
|
|||
|
this.configure = configure;
|
|||
|
this.initHighlighting = initHighlighting;
|
|||
|
this.initHighlightingOnLoad = initHighlightingOnLoad;
|
|||
|
this.registerLanguage = registerLanguage;
|
|||
|
this.listLanguages = listLanguages;
|
|||
|
this.getLanguage = getLanguage;
|
|||
|
this.inherit = inherit;
|
|||
|
|
|||
|
// Common regexps
|
|||
|
this.IDENT_RE = '[a-zA-Z][a-zA-Z0-9_]*';
|
|||
|
this.UNDERSCORE_IDENT_RE = '[a-zA-Z_][a-zA-Z0-9_]*';
|
|||
|
this.NUMBER_RE = '\\b\\d+(\\.\\d+)?';
|
|||
|
this.C_NUMBER_RE = '(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)'; // 0x..., 0..., decimal, float
|
|||
|
this.BINARY_NUMBER_RE = '\\b(0b[01]+)'; // 0b...
|
|||
|
this.RE_STARTERS_RE = '!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~';
|
|||
|
|
|||
|
// Common modes
|
|||
|
this.BACKSLASH_ESCAPE = {
|
|||
|
begin: '\\\\[\\s\\S]', relevance: 0
|
|||
|
};
|
|||
|
this.APOS_STRING_MODE = {
|
|||
|
className: 'string',
|
|||
|
begin: '\'', end: '\'',
|
|||
|
illegal: '\\n',
|
|||
|
contains: [this.BACKSLASH_ESCAPE]
|
|||
|
};
|
|||
|
this.QUOTE_STRING_MODE = {
|
|||
|
className: 'string',
|
|||
|
begin: '"', end: '"',
|
|||
|
illegal: '\\n',
|
|||
|
contains: [this.BACKSLASH_ESCAPE]
|
|||
|
};
|
|||
|
this.PHRASAL_WORDS_MODE = {
|
|||
|
begin: /\b(a|an|the|are|I|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such)\b/
|
|||
|
};
|
|||
|
this.C_LINE_COMMENT_MODE = {
|
|||
|
className: 'comment',
|
|||
|
begin: '//', end: '$',
|
|||
|
contains: [this.PHRASAL_WORDS_MODE]
|
|||
|
};
|
|||
|
this.C_BLOCK_COMMENT_MODE = {
|
|||
|
className: 'comment',
|
|||
|
begin: '/\\*', end: '\\*/',
|
|||
|
contains: [this.PHRASAL_WORDS_MODE]
|
|||
|
};
|
|||
|
this.HASH_COMMENT_MODE = {
|
|||
|
className: 'comment',
|
|||
|
begin: '#', end: '$',
|
|||
|
contains: [this.PHRASAL_WORDS_MODE]
|
|||
|
};
|
|||
|
this.NUMBER_MODE = {
|
|||
|
className: 'number',
|
|||
|
begin: this.NUMBER_RE,
|
|||
|
relevance: 0
|
|||
|
};
|
|||
|
this.C_NUMBER_MODE = {
|
|||
|
className: 'number',
|
|||
|
begin: this.C_NUMBER_RE,
|
|||
|
relevance: 0
|
|||
|
};
|
|||
|
this.BINARY_NUMBER_MODE = {
|
|||
|
className: 'number',
|
|||
|
begin: this.BINARY_NUMBER_RE,
|
|||
|
relevance: 0
|
|||
|
};
|
|||
|
this.CSS_NUMBER_MODE = {
|
|||
|
className: 'number',
|
|||
|
begin: this.NUMBER_RE + '(' +
|
|||
|
'%|em|ex|ch|rem' +
|
|||
|
'|vw|vh|vmin|vmax' +
|
|||
|
'|cm|mm|in|pt|pc|px' +
|
|||
|
'|deg|grad|rad|turn' +
|
|||
|
'|s|ms' +
|
|||
|
'|Hz|kHz' +
|
|||
|
'|dpi|dpcm|dppx' +
|
|||
|
')?',
|
|||
|
relevance: 0
|
|||
|
};
|
|||
|
this.REGEXP_MODE = {
|
|||
|
className: 'regexp',
|
|||
|
begin: /\//, end: /\/[gim]*/,
|
|||
|
illegal: /\n/,
|
|||
|
contains: [
|
|||
|
this.BACKSLASH_ESCAPE,
|
|||
|
{
|
|||
|
begin: /\[/, end: /\]/,
|
|||
|
relevance: 0,
|
|||
|
contains: [this.BACKSLASH_ESCAPE]
|
|||
|
}
|
|||
|
]
|
|||
|
};
|
|||
|
this.TITLE_MODE = {
|
|||
|
className: 'title',
|
|||
|
begin: this.IDENT_RE,
|
|||
|
relevance: 0
|
|||
|
};
|
|||
|
this.UNDERSCORE_TITLE_MODE = {
|
|||
|
className: 'title',
|
|||
|
begin: this.UNDERSCORE_IDENT_RE,
|
|||
|
relevance: 0
|
|||
|
};
|
|||
|
}
|
|||
|
)()
|
|||
|
, languages = [{name:"javascript",create:/*
|
|||
|
Language: JavaScript
|
|||
|
*/
|
|||
|
|
|||
|
function(hljs) {
|
|||
|
return {
|
|||
|
aliases: ['js'],
|
|||
|
keywords: {
|
|||
|
keyword:
|
|||
|
'in if for while finally var new function do return void else break catch ' +
|
|||
|
'instanceof with throw case default try this switch continue typeof delete ' +
|
|||
|
'let yield const class',
|
|||
|
literal:
|
|||
|
'true false null undefined NaN Infinity',
|
|||
|
built_in:
|
|||
|
'eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent ' +
|
|||
|
'encodeURI encodeURIComponent escape unescape Object Function Boolean Error ' +
|
|||
|
'EvalError InternalError RangeError ReferenceError StopIteration SyntaxError ' +
|
|||
|
'TypeError URIError Number Math Date String RegExp Array Float32Array ' +
|
|||
|
'Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array ' +
|
|||
|
'Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require ' +
|
|||
|
'module console window document'
|
|||
|
},
|
|||
|
contains: [
|
|||
|
{
|
|||
|
className: 'pi',
|
|||
|
begin: /^\s*('|")use strict('|")/,
|
|||
|
relevance: 10
|
|||
|
},
|
|||
|
hljs.APOS_STRING_MODE,
|
|||
|
hljs.QUOTE_STRING_MODE,
|
|||
|
hljs.C_LINE_COMMENT_MODE,
|
|||
|
hljs.C_BLOCK_COMMENT_MODE,
|
|||
|
hljs.C_NUMBER_MODE,
|
|||
|
{ // "value" container
|
|||
|
begin: '(' + hljs.RE_STARTERS_RE + '|\\b(case|return|throw)\\b)\\s*',
|
|||
|
keywords: 'return throw case',
|
|||
|
contains: [
|
|||
|
hljs.C_LINE_COMMENT_MODE,
|
|||
|
hljs.C_BLOCK_COMMENT_MODE,
|
|||
|
hljs.REGEXP_MODE,
|
|||
|
{ // E4X
|
|||
|
begin: /</, end: />;/,
|
|||
|
relevance: 0,
|
|||
|
subLanguage: 'xml'
|
|||
|
}
|
|||
|
],
|
|||
|
relevance: 0
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'function',
|
|||
|
beginKeywords: 'function', end: /\{/, excludeEnd: true,
|
|||
|
contains: [
|
|||
|
hljs.inherit(hljs.TITLE_MODE, {begin: /[A-Za-z$_][0-9A-Za-z$_]*/}),
|
|||
|
{
|
|||
|
className: 'params',
|
|||
|
begin: /\(/, end: /\)/,
|
|||
|
contains: [
|
|||
|
hljs.C_LINE_COMMENT_MODE,
|
|||
|
hljs.C_BLOCK_COMMENT_MODE
|
|||
|
],
|
|||
|
illegal: /["'\(]/
|
|||
|
}
|
|||
|
],
|
|||
|
illegal: /\[|%/
|
|||
|
},
|
|||
|
{
|
|||
|
begin: /\$[(.]/ // relevance booster for a pattern common to JS libs: `$(something)` and `$.something`
|
|||
|
},
|
|||
|
{
|
|||
|
begin: '\\.' + hljs.IDENT_RE, relevance: 0 // hack: prevents detection of keywords after dots
|
|||
|
}
|
|||
|
]
|
|||
|
};
|
|||
|
}
|
|||
|
},{name:"ruby",create:/*
|
|||
|
Language: Ruby
|
|||
|
Author: Anton Kovalyov <anton@kovalyov.net>
|
|||
|
Contributors: Peter Leonov <gojpeg@yandex.ru>, Vasily Polovnyov <vast@whiteants.net>, Loren Segal <lsegal@soen.ca>
|
|||
|
*/
|
|||
|
|
|||
|
function(hljs) {
|
|||
|
var RUBY_METHOD_RE = '[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?';
|
|||
|
var RUBY_KEYWORDS =
|
|||
|
'and false then defined module in return redo if BEGIN retry end for true self when ' +
|
|||
|
'next until do begin unless END rescue nil else break undef not super class case ' +
|
|||
|
'require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor';
|
|||
|
var YARDOCTAG = {
|
|||
|
className: 'yardoctag',
|
|||
|
begin: '@[A-Za-z]+'
|
|||
|
};
|
|||
|
var COMMENT = {
|
|||
|
className: 'comment',
|
|||
|
variants: [
|
|||
|
{
|
|||
|
begin: '#', end: '$',
|
|||
|
contains: [YARDOCTAG]
|
|||
|
},
|
|||
|
{
|
|||
|
begin: '^\\=begin', end: '^\\=end',
|
|||
|
contains: [YARDOCTAG],
|
|||
|
relevance: 10
|
|||
|
},
|
|||
|
{
|
|||
|
begin: '^__END__', end: '\\n$'
|
|||
|
}
|
|||
|
]
|
|||
|
};
|
|||
|
var SUBST = {
|
|||
|
className: 'subst',
|
|||
|
begin: '#\\{', end: '}',
|
|||
|
keywords: RUBY_KEYWORDS
|
|||
|
};
|
|||
|
var STRING = {
|
|||
|
className: 'string',
|
|||
|
contains: [hljs.BACKSLASH_ESCAPE, SUBST],
|
|||
|
variants: [
|
|||
|
{begin: /'/, end: /'/},
|
|||
|
{begin: /"/, end: /"/},
|
|||
|
{begin: '%[qw]?\\(', end: '\\)'},
|
|||
|
{begin: '%[qw]?\\[', end: '\\]'},
|
|||
|
{begin: '%[qw]?{', end: '}'},
|
|||
|
{
|
|||
|
begin: '%[qw]?<', end: '>',
|
|||
|
relevance: 10
|
|||
|
},
|
|||
|
{
|
|||
|
begin: '%[qw]?/', end: '/',
|
|||
|
relevance: 10
|
|||
|
},
|
|||
|
{
|
|||
|
begin: '%[qw]?%', end: '%',
|
|||
|
relevance: 10
|
|||
|
},
|
|||
|
{
|
|||
|
begin: '%[qw]?-', end: '-',
|
|||
|
relevance: 10
|
|||
|
},
|
|||
|
{
|
|||
|
begin: '%[qw]?\\|', end: '\\|',
|
|||
|
relevance: 10
|
|||
|
},
|
|||
|
{
|
|||
|
// \B in the beginning suppresses recognition of ?-sequences where ?
|
|||
|
// is the last character of a preceding identifier, as in: `func?4`
|
|||
|
begin: /\B\?(\\\d{1,3}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/
|
|||
|
}
|
|||
|
]
|
|||
|
};
|
|||
|
var PARAMS = {
|
|||
|
className: 'params',
|
|||
|
begin: '\\(', end: '\\)',
|
|||
|
keywords: RUBY_KEYWORDS
|
|||
|
};
|
|||
|
|
|||
|
var RUBY_DEFAULT_CONTAINS = [
|
|||
|
STRING,
|
|||
|
COMMENT,
|
|||
|
{
|
|||
|
className: 'class',
|
|||
|
beginKeywords: 'class module', end: '$|;',
|
|||
|
illegal: /=/,
|
|||
|
contains: [
|
|||
|
hljs.inherit(hljs.TITLE_MODE, {begin: '[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?'}),
|
|||
|
{
|
|||
|
className: 'inheritance',
|
|||
|
begin: '<\\s*',
|
|||
|
contains: [{
|
|||
|
className: 'parent',
|
|||
|
begin: '(' + hljs.IDENT_RE + '::)?' + hljs.IDENT_RE
|
|||
|
}]
|
|||
|
},
|
|||
|
COMMENT
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'function',
|
|||
|
beginKeywords: 'def', end: ' |$|;',
|
|||
|
relevance: 0,
|
|||
|
contains: [
|
|||
|
hljs.inherit(hljs.TITLE_MODE, {begin: RUBY_METHOD_RE}),
|
|||
|
PARAMS,
|
|||
|
COMMENT
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'constant',
|
|||
|
begin: '(::)?(\\b[A-Z]\\w*(::)?)+',
|
|||
|
relevance: 0
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'symbol',
|
|||
|
begin: ':',
|
|||
|
contains: [STRING, {begin: RUBY_METHOD_RE}],
|
|||
|
relevance: 0
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'symbol',
|
|||
|
begin: hljs.UNDERSCORE_IDENT_RE + '(\\!|\\?)?:',
|
|||
|
relevance: 0
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'number',
|
|||
|
begin: '(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b',
|
|||
|
relevance: 0
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'variable',
|
|||
|
begin: '(\\$\\W)|((\\$|\\@\\@?)(\\w+))'
|
|||
|
},
|
|||
|
{ // regexp container
|
|||
|
begin: '(' + hljs.RE_STARTERS_RE + ')\\s*',
|
|||
|
contains: [
|
|||
|
COMMENT,
|
|||
|
{
|
|||
|
className: 'regexp',
|
|||
|
contains: [hljs.BACKSLASH_ESCAPE, SUBST],
|
|||
|
illegal: /\n/,
|
|||
|
variants: [
|
|||
|
{begin: '/', end: '/[a-z]*'},
|
|||
|
{begin: '%r{', end: '}[a-z]*'},
|
|||
|
{begin: '%r\\(', end: '\\)[a-z]*'},
|
|||
|
{begin: '%r!', end: '![a-z]*'},
|
|||
|
{begin: '%r\\[', end: '\\][a-z]*'}
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
relevance: 0
|
|||
|
}
|
|||
|
];
|
|||
|
SUBST.contains = RUBY_DEFAULT_CONTAINS;
|
|||
|
PARAMS.contains = RUBY_DEFAULT_CONTAINS;
|
|||
|
|
|||
|
return {
|
|||
|
aliases: ['rb', 'gemspec', 'podspec', 'thor'],
|
|||
|
keywords: RUBY_KEYWORDS,
|
|||
|
contains: RUBY_DEFAULT_CONTAINS
|
|||
|
};
|
|||
|
}
|
|||
|
},{name:"python",create:/*
|
|||
|
Language: Python
|
|||
|
*/
|
|||
|
|
|||
|
function(hljs) {
|
|||
|
var PROMPT = {
|
|||
|
className: 'prompt', begin: /^(>>>|\.\.\.) /
|
|||
|
};
|
|||
|
var STRING = {
|
|||
|
className: 'string',
|
|||
|
contains: [hljs.BACKSLASH_ESCAPE],
|
|||
|
variants: [
|
|||
|
{
|
|||
|
begin: /(u|b)?r?'''/, end: /'''/,
|
|||
|
contains: [PROMPT],
|
|||
|
relevance: 10
|
|||
|
},
|
|||
|
{
|
|||
|
begin: /(u|b)?r?"""/, end: /"""/,
|
|||
|
contains: [PROMPT],
|
|||
|
relevance: 10
|
|||
|
},
|
|||
|
{
|
|||
|
begin: /(u|r|ur)'/, end: /'/,
|
|||
|
relevance: 10
|
|||
|
},
|
|||
|
{
|
|||
|
begin: /(u|r|ur)"/, end: /"/,
|
|||
|
relevance: 10
|
|||
|
},
|
|||
|
{
|
|||
|
begin: /(b|br)'/, end: /'/
|
|||
|
},
|
|||
|
{
|
|||
|
begin: /(b|br)"/, end: /"/
|
|||
|
},
|
|||
|
hljs.APOS_STRING_MODE,
|
|||
|
hljs.QUOTE_STRING_MODE
|
|||
|
]
|
|||
|
};
|
|||
|
var NUMBER = {
|
|||
|
className: 'number', relevance: 0,
|
|||
|
variants: [
|
|||
|
{begin: hljs.BINARY_NUMBER_RE + '[lLjJ]?'},
|
|||
|
{begin: '\\b(0o[0-7]+)[lLjJ]?'},
|
|||
|
{begin: hljs.C_NUMBER_RE + '[lLjJ]?'}
|
|||
|
]
|
|||
|
};
|
|||
|
var PARAMS = {
|
|||
|
className: 'params',
|
|||
|
begin: /\(/, end: /\)/,
|
|||
|
contains: ['self', PROMPT, NUMBER, STRING]
|
|||
|
};
|
|||
|
var FUNC_CLASS_PROTO = {
|
|||
|
end: /:/,
|
|||
|
illegal: /[${=;\n]/,
|
|||
|
contains: [hljs.UNDERSCORE_TITLE_MODE, PARAMS]
|
|||
|
};
|
|||
|
|
|||
|
return {
|
|||
|
aliases: ['py', 'gyp'],
|
|||
|
keywords: {
|
|||
|
keyword:
|
|||
|
'and elif is global as in if from raise for except finally print import pass return ' +
|
|||
|
'exec else break not with class assert yield try while continue del or def lambda ' +
|
|||
|
'nonlocal|10 None True False',
|
|||
|
built_in:
|
|||
|
'Ellipsis NotImplemented'
|
|||
|
},
|
|||
|
illegal: /(<\/|->|\?)/,
|
|||
|
contains: [
|
|||
|
PROMPT,
|
|||
|
NUMBER,
|
|||
|
STRING,
|
|||
|
hljs.HASH_COMMENT_MODE,
|
|||
|
hljs.inherit(FUNC_CLASS_PROTO, {className: 'function', beginKeywords: 'def', relevance: 10}),
|
|||
|
hljs.inherit(FUNC_CLASS_PROTO, {className: 'class', beginKeywords: 'class'}),
|
|||
|
{
|
|||
|
className: 'decorator',
|
|||
|
begin: /@/, end: /$/
|
|||
|
},
|
|||
|
{
|
|||
|
begin: /\b(print|exec)\(/ // don’t highlight keywords-turned-functions in Python 3
|
|||
|
}
|
|||
|
]
|
|||
|
};
|
|||
|
}
|
|||
|
},{name:"bash",create:/*
|
|||
|
Language: Bash
|
|||
|
Author: vah <vahtenberg@gmail.com>
|
|||
|
Contributrors: Benjamin Pannell <contact@sierrasoftworks.com>
|
|||
|
*/
|
|||
|
|
|||
|
function(hljs) {
|
|||
|
var VAR = {
|
|||
|
className: 'variable',
|
|||
|
variants: [
|
|||
|
{begin: /\$[\w\d#@][\w\d_]*/},
|
|||
|
{begin: /\$\{(.*?)\}/}
|
|||
|
]
|
|||
|
};
|
|||
|
var QUOTE_STRING = {
|
|||
|
className: 'string',
|
|||
|
begin: /"/, end: /"/,
|
|||
|
contains: [
|
|||
|
hljs.BACKSLASH_ESCAPE,
|
|||
|
VAR,
|
|||
|
{
|
|||
|
className: 'variable',
|
|||
|
begin: /\$\(/, end: /\)/,
|
|||
|
contains: [hljs.BACKSLASH_ESCAPE]
|
|||
|
}
|
|||
|
]
|
|||
|
};
|
|||
|
var APOS_STRING = {
|
|||
|
className: 'string',
|
|||
|
begin: /'/, end: /'/
|
|||
|
};
|
|||
|
|
|||
|
return {
|
|||
|
aliases: ['sh', 'zsh'],
|
|||
|
lexemes: /-?[a-z\.]+/,
|
|||
|
keywords: {
|
|||
|
keyword:
|
|||
|
'if then else elif fi for break continue while in do done exit return set '+
|
|||
|
'declare case esac export exec',
|
|||
|
literal:
|
|||
|
'true false',
|
|||
|
built_in:
|
|||
|
'printf echo read cd pwd pushd popd dirs let eval unset typeset readonly '+
|
|||
|
'getopts source shopt caller type hash bind help sudo',
|
|||
|
operator:
|
|||
|
'-ne -eq -lt -gt -f -d -e -s -l -a' // relevance booster
|
|||
|
},
|
|||
|
contains: [
|
|||
|
{
|
|||
|
className: 'shebang',
|
|||
|
begin: /^#![^\n]+sh\s*$/,
|
|||
|
relevance: 10
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'function',
|
|||
|
begin: /\w[\w\d_]*\s*\(\s*\)\s*\{/,
|
|||
|
returnBegin: true,
|
|||
|
contains: [hljs.inherit(hljs.TITLE_MODE, {begin: /\w[\w\d_]*/})],
|
|||
|
relevance: 0
|
|||
|
},
|
|||
|
hljs.HASH_COMMENT_MODE,
|
|||
|
hljs.NUMBER_MODE,
|
|||
|
QUOTE_STRING,
|
|||
|
APOS_STRING,
|
|||
|
VAR
|
|||
|
]
|
|||
|
};
|
|||
|
}
|
|||
|
},{name:"java",create:/*
|
|||
|
Language: Java
|
|||
|
Author: Vsevolod Solovyov <vsevolod.solovyov@gmail.com>
|
|||
|
*/
|
|||
|
|
|||
|
function(hljs) {
|
|||
|
var KEYWORDS =
|
|||
|
'false synchronized int abstract float private char boolean static null if const ' +
|
|||
|
'for true while long throw strictfp finally protected import native final return void ' +
|
|||
|
'enum else break transient new catch instanceof byte super volatile case assert short ' +
|
|||
|
'package default double public try this switch continue throws';
|
|||
|
return {
|
|||
|
aliases: ['jsp'],
|
|||
|
keywords: KEYWORDS,
|
|||
|
illegal: /<\//,
|
|||
|
contains: [
|
|||
|
{
|
|||
|
className: 'javadoc',
|
|||
|
begin: '/\\*\\*', end: '\\*/',
|
|||
|
contains: [{
|
|||
|
className: 'javadoctag', begin: '(^|\\s)@[A-Za-z]+'
|
|||
|
}],
|
|||
|
relevance: 10
|
|||
|
},
|
|||
|
hljs.C_LINE_COMMENT_MODE,
|
|||
|
hljs.C_BLOCK_COMMENT_MODE,
|
|||
|
hljs.APOS_STRING_MODE,
|
|||
|
hljs.QUOTE_STRING_MODE,
|
|||
|
{
|
|||
|
beginKeywords: 'protected public private', end: /[{;=]/,
|
|||
|
keywords: KEYWORDS,
|
|||
|
contains: [
|
|||
|
{
|
|||
|
className: 'class',
|
|||
|
beginKeywords: 'class interface', endsWithParent: true, excludeEnd: true,
|
|||
|
illegal: /[:"<>]/,
|
|||
|
contains: [
|
|||
|
{
|
|||
|
beginKeywords: 'extends implements',
|
|||
|
relevance: 10
|
|||
|
},
|
|||
|
hljs.UNDERSCORE_TITLE_MODE
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
begin: hljs.UNDERSCORE_IDENT_RE + '\\s*\\(', returnBegin: true,
|
|||
|
contains: [
|
|||
|
hljs.UNDERSCORE_TITLE_MODE
|
|||
|
]
|
|||
|
}
|
|||
|
]
|
|||
|
},
|
|||
|
hljs.C_NUMBER_MODE,
|
|||
|
{
|
|||
|
className: 'annotation', begin: '@[A-Za-z]+'
|
|||
|
}
|
|||
|
]
|
|||
|
};
|
|||
|
}
|
|||
|
},{name:"php",create:/*
|
|||
|
Language: PHP
|
|||
|
Author: Victor Karamzin <Victor.Karamzin@enterra-inc.com>
|
|||
|
Contributors: Evgeny Stepanischev <imbolk@gmail.com>, Ivan Sagalaev <maniac@softwaremaniacs.org>
|
|||
|
*/
|
|||
|
|
|||
|
function(hljs) {
|
|||
|
var VARIABLE = {
|
|||
|
className: 'variable', begin: '\\$+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'
|
|||
|
};
|
|||
|
var PREPROCESSOR = {
|
|||
|
className: 'preprocessor', begin: /<\?(php)?|\?>/
|
|||
|
};
|
|||
|
var STRING = {
|
|||
|
className: 'string',
|
|||
|
contains: [hljs.BACKSLASH_ESCAPE, PREPROCESSOR],
|
|||
|
variants: [
|
|||
|
{
|
|||
|
begin: 'b"', end: '"'
|
|||
|
},
|
|||
|
{
|
|||
|
begin: 'b\'', end: '\''
|
|||
|
},
|
|||
|
hljs.inherit(hljs.APOS_STRING_MODE, {illegal: null}),
|
|||
|
hljs.inherit(hljs.QUOTE_STRING_MODE, {illegal: null})
|
|||
|
]
|
|||
|
};
|
|||
|
var NUMBER = {variants: [hljs.BINARY_NUMBER_MODE, hljs.C_NUMBER_MODE]};
|
|||
|
return {
|
|||
|
aliases: ['php3', 'php4', 'php5', 'php6'],
|
|||
|
case_insensitive: true,
|
|||
|
keywords:
|
|||
|
'and include_once list abstract global private echo interface as static endswitch ' +
|
|||
|
'array null if endwhile or const for endforeach self var while isset public ' +
|
|||
|
'protected exit foreach throw elseif include __FILE__ empty require_once do xor ' +
|
|||
|
'return parent clone use __CLASS__ __LINE__ else break print eval new ' +
|
|||
|
'catch __METHOD__ case exception default die require __FUNCTION__ ' +
|
|||
|
'enddeclare final try switch continue endfor endif declare unset true false ' +
|
|||
|
'trait goto instanceof insteadof __DIR__ __NAMESPACE__ ' +
|
|||
|
'yield finally',
|
|||
|
contains: [
|
|||
|
hljs.C_LINE_COMMENT_MODE,
|
|||
|
hljs.HASH_COMMENT_MODE,
|
|||
|
{
|
|||
|
className: 'comment',
|
|||
|
begin: '/\\*', end: '\\*/',
|
|||
|
contains: [
|
|||
|
{
|
|||
|
className: 'phpdoc',
|
|||
|
begin: '\\s@[A-Za-z]+'
|
|||
|
},
|
|||
|
PREPROCESSOR
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'comment',
|
|||
|
begin: '__halt_compiler.+?;', endsWithParent: true,
|
|||
|
keywords: '__halt_compiler', lexemes: hljs.UNDERSCORE_IDENT_RE
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'string',
|
|||
|
begin: '<<<[\'"]?\\w+[\'"]?$', end: '^\\w+;',
|
|||
|
contains: [hljs.BACKSLASH_ESCAPE]
|
|||
|
},
|
|||
|
PREPROCESSOR,
|
|||
|
VARIABLE,
|
|||
|
{
|
|||
|
className: 'function',
|
|||
|
beginKeywords: 'function', end: /[;{]/, excludeEnd: true,
|
|||
|
illegal: '\\$|\\[|%',
|
|||
|
contains: [
|
|||
|
hljs.UNDERSCORE_TITLE_MODE,
|
|||
|
{
|
|||
|
className: 'params',
|
|||
|
begin: '\\(', end: '\\)',
|
|||
|
contains: [
|
|||
|
'self',
|
|||
|
VARIABLE,
|
|||
|
hljs.C_BLOCK_COMMENT_MODE,
|
|||
|
STRING,
|
|||
|
NUMBER
|
|||
|
]
|
|||
|
}
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'class',
|
|||
|
beginKeywords: 'class interface', end: '{', excludeEnd: true,
|
|||
|
illegal: /[:\(\$"]/,
|
|||
|
contains: [
|
|||
|
{
|
|||
|
beginKeywords: 'extends implements',
|
|||
|
relevance: 10
|
|||
|
},
|
|||
|
hljs.UNDERSCORE_TITLE_MODE
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
beginKeywords: 'namespace', end: ';',
|
|||
|
illegal: /[\.']/,
|
|||
|
contains: [hljs.UNDERSCORE_TITLE_MODE]
|
|||
|
},
|
|||
|
{
|
|||
|
beginKeywords: 'use', end: ';',
|
|||
|
contains: [hljs.UNDERSCORE_TITLE_MODE]
|
|||
|
},
|
|||
|
{
|
|||
|
begin: '=>' // No markup, just a relevance booster
|
|||
|
},
|
|||
|
STRING,
|
|||
|
NUMBER
|
|||
|
]
|
|||
|
};
|
|||
|
}
|
|||
|
},{name:"perl",create:/*
|
|||
|
Language: Perl
|
|||
|
Author: Peter Leonov <gojpeg@yandex.ru>
|
|||
|
*/
|
|||
|
|
|||
|
function(hljs) {
|
|||
|
var PERL_KEYWORDS = 'getpwent getservent quotemeta msgrcv scalar kill dbmclose undef lc ' +
|
|||
|
'ma syswrite tr send umask sysopen shmwrite vec qx utime local oct semctl localtime ' +
|
|||
|
'readpipe do return format read sprintf dbmopen pop getpgrp not getpwnam rewinddir qq' +
|
|||
|
'fileno qw endprotoent wait sethostent bless s|0 opendir continue each sleep endgrent ' +
|
|||
|
'shutdown dump chomp connect getsockname die socketpair close flock exists index shmget' +
|
|||
|
'sub for endpwent redo lstat msgctl setpgrp abs exit select print ref gethostbyaddr ' +
|
|||
|
'unshift fcntl syscall goto getnetbyaddr join gmtime symlink semget splice x|0 ' +
|
|||
|
'getpeername recv log setsockopt cos last reverse gethostbyname getgrnam study formline ' +
|
|||
|
'endhostent times chop length gethostent getnetent pack getprotoent getservbyname rand ' +
|
|||
|
'mkdir pos chmod y|0 substr endnetent printf next open msgsnd readdir use unlink ' +
|
|||
|
'getsockopt getpriority rindex wantarray hex system getservbyport endservent int chr ' +
|
|||
|
'untie rmdir prototype tell listen fork shmread ucfirst setprotoent else sysseek link ' +
|
|||
|
'getgrgid shmctl waitpid unpack getnetbyname reset chdir grep split require caller ' +
|
|||
|
'lcfirst until warn while values shift telldir getpwuid my getprotobynumber delete and ' +
|
|||
|
'sort uc defined srand accept package seekdir getprotobyname semop our rename seek if q|0 ' +
|
|||
|
'chroot sysread setpwent no crypt getc chown sqrt write setnetent setpriority foreach ' +
|
|||
|
'tie sin msgget map stat getlogin unless elsif truncate exec keys glob tied closedir' +
|
|||
|
'ioctl socket readlink eval xor readline binmode setservent eof ord bind alarm pipe ' +
|
|||
|
'atan2 getgrent exp time push setgrent gt lt or ne m|0 break given say state when';
|
|||
|
var SUBST = {
|
|||
|
className: 'subst',
|
|||
|
begin: '[$@]\\{', end: '\\}',
|
|||
|
keywords: PERL_KEYWORDS
|
|||
|
};
|
|||
|
var METHOD = {
|
|||
|
begin: '->{', end: '}'
|
|||
|
// contains defined later
|
|||
|
};
|
|||
|
var VAR = {
|
|||
|
className: 'variable',
|
|||
|
variants: [
|
|||
|
{begin: /\$\d/},
|
|||
|
{begin: /[\$\%\@\*](\^\w\b|#\w+(\:\:\w+)*|{\w+}|\w+(\:\:\w*)*)/},
|
|||
|
{begin: /[\$\%\@\*][^\s\w{]/, relevance: 0}
|
|||
|
]
|
|||
|
};
|
|||
|
var COMMENT = {
|
|||
|
className: 'comment',
|
|||
|
begin: '^(__END__|__DATA__)', end: '\\n$',
|
|||
|
relevance: 5
|
|||
|
};
|
|||
|
var STRING_CONTAINS = [hljs.BACKSLASH_ESCAPE, SUBST, VAR];
|
|||
|
var PERL_DEFAULT_CONTAINS = [
|
|||
|
VAR,
|
|||
|
hljs.HASH_COMMENT_MODE,
|
|||
|
COMMENT,
|
|||
|
{
|
|||
|
className: 'comment',
|
|||
|
begin: '^\\=\\w', end: '\\=cut', endsWithParent: true
|
|||
|
},
|
|||
|
METHOD,
|
|||
|
{
|
|||
|
className: 'string',
|
|||
|
contains: STRING_CONTAINS,
|
|||
|
variants: [
|
|||
|
{
|
|||
|
begin: 'q[qwxr]?\\s*\\(', end: '\\)',
|
|||
|
relevance: 5
|
|||
|
},
|
|||
|
{
|
|||
|
begin: 'q[qwxr]?\\s*\\[', end: '\\]',
|
|||
|
relevance: 5
|
|||
|
},
|
|||
|
{
|
|||
|
begin: 'q[qwxr]?\\s*\\{', end: '\\}',
|
|||
|
relevance: 5
|
|||
|
},
|
|||
|
{
|
|||
|
begin: 'q[qwxr]?\\s*\\|', end: '\\|',
|
|||
|
relevance: 5
|
|||
|
},
|
|||
|
{
|
|||
|
begin: 'q[qwxr]?\\s*\\<', end: '\\>',
|
|||
|
relevance: 5
|
|||
|
},
|
|||
|
{
|
|||
|
begin: 'qw\\s+q', end: 'q',
|
|||
|
relevance: 5
|
|||
|
},
|
|||
|
{
|
|||
|
begin: '\'', end: '\'',
|
|||
|
contains: [hljs.BACKSLASH_ESCAPE]
|
|||
|
},
|
|||
|
{
|
|||
|
begin: '"', end: '"'
|
|||
|
},
|
|||
|
{
|
|||
|
begin: '`', end: '`',
|
|||
|
contains: [hljs.BACKSLASH_ESCAPE]
|
|||
|
},
|
|||
|
{
|
|||
|
begin: '{\\w+}',
|
|||
|
contains: [],
|
|||
|
relevance: 0
|
|||
|
},
|
|||
|
{
|
|||
|
begin: '\-?\\w+\\s*\\=\\>',
|
|||
|
contains: [],
|
|||
|
relevance: 0
|
|||
|
}
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'number',
|
|||
|
begin: '(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b',
|
|||
|
relevance: 0
|
|||
|
},
|
|||
|
{ // regexp container
|
|||
|
begin: '(\\/\\/|' + hljs.RE_STARTERS_RE + '|\\b(split|return|print|reverse|grep)\\b)\\s*',
|
|||
|
keywords: 'split return print reverse grep',
|
|||
|
relevance: 0,
|
|||
|
contains: [
|
|||
|
hljs.HASH_COMMENT_MODE,
|
|||
|
COMMENT,
|
|||
|
{
|
|||
|
className: 'regexp',
|
|||
|
begin: '(s|tr|y)/(\\\\.|[^/])*/(\\\\.|[^/])*/[a-z]*',
|
|||
|
relevance: 10
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'regexp',
|
|||
|
begin: '(m|qr)?/', end: '/[a-z]*',
|
|||
|
contains: [hljs.BACKSLASH_ESCAPE],
|
|||
|
relevance: 0 // allows empty "//" which is a common comment delimiter in other languages
|
|||
|
}
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'sub',
|
|||
|
beginKeywords: 'sub', end: '(\\s*\\(.*?\\))?[;{]',
|
|||
|
relevance: 5
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'operator',
|
|||
|
begin: '-\\w\\b',
|
|||
|
relevance: 0
|
|||
|
}
|
|||
|
];
|
|||
|
SUBST.contains = PERL_DEFAULT_CONTAINS;
|
|||
|
METHOD.contains = PERL_DEFAULT_CONTAINS;
|
|||
|
|
|||
|
return {
|
|||
|
aliases: ['pl'],
|
|||
|
keywords: PERL_KEYWORDS,
|
|||
|
contains: PERL_DEFAULT_CONTAINS
|
|||
|
};
|
|||
|
}
|
|||
|
},{name:"cpp",create:/*
|
|||
|
Language: C++
|
|||
|
Author: Ivan Sagalaev <maniac@softwaremaniacs.org>
|
|||
|
Contributors: Evgeny Stepanischev <imbolk@gmail.com>, Zaven Muradyan <megalivoithos@gmail.com>
|
|||
|
*/
|
|||
|
|
|||
|
function(hljs) {
|
|||
|
var CPP_KEYWORDS = {
|
|||
|
keyword: 'false int float while private char catch export virtual operator sizeof ' +
|
|||
|
'dynamic_cast|10 typedef const_cast|10 const struct for static_cast|10 union namespace ' +
|
|||
|
'unsigned long throw volatile static protected bool template mutable if public friend ' +
|
|||
|
'do return goto auto void enum else break new extern using true class asm case typeid ' +
|
|||
|
'short reinterpret_cast|10 default double register explicit signed typename try this ' +
|
|||
|
'switch continue wchar_t inline delete alignof char16_t char32_t constexpr decltype ' +
|
|||
|
'noexcept nullptr static_assert thread_local restrict _Bool complex _Complex _Imaginary',
|
|||
|
built_in: 'std string cin cout cerr clog stringstream istringstream ostringstream ' +
|
|||
|
'auto_ptr deque list queue stack vector map set bitset multiset multimap unordered_set ' +
|
|||
|
'unordered_map unordered_multiset unordered_multimap array shared_ptr abort abs acos ' +
|
|||
|
'asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp ' +
|
|||
|
'fscanf isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper ' +
|
|||
|
'isxdigit tolower toupper labs ldexp log10 log malloc memchr memcmp memcpy memset modf pow ' +
|
|||
|
'printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp ' +
|
|||
|
'strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan ' +
|
|||
|
'vfprintf vprintf vsprintf'
|
|||
|
};
|
|||
|
return {
|
|||
|
aliases: ['c', 'h', 'c++', 'h++'],
|
|||
|
keywords: CPP_KEYWORDS,
|
|||
|
illegal: '</',
|
|||
|
contains: [
|
|||
|
hljs.C_LINE_COMMENT_MODE,
|
|||
|
hljs.C_BLOCK_COMMENT_MODE,
|
|||
|
hljs.QUOTE_STRING_MODE,
|
|||
|
{
|
|||
|
className: 'string',
|
|||
|
begin: '\'\\\\?.', end: '\'',
|
|||
|
illegal: '.'
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'number',
|
|||
|
begin: '\\b(\\d+(\\.\\d*)?|\\.\\d+)(u|U|l|L|ul|UL|f|F)'
|
|||
|
},
|
|||
|
hljs.C_NUMBER_MODE,
|
|||
|
{
|
|||
|
className: 'preprocessor',
|
|||
|
begin: '#', end: '$',
|
|||
|
keywords: 'if else elif endif define undef warning error line pragma',
|
|||
|
contains: [
|
|||
|
{
|
|||
|
begin: 'include\\s*[<"]', end: '[>"]',
|
|||
|
keywords: 'include',
|
|||
|
illegal: '\\n'
|
|||
|
},
|
|||
|
hljs.C_LINE_COMMENT_MODE
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'stl_container',
|
|||
|
begin: '\\b(deque|list|queue|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\\s*<', end: '>',
|
|||
|
keywords: CPP_KEYWORDS,
|
|||
|
relevance: 10,
|
|||
|
contains: ['self']
|
|||
|
},
|
|||
|
{
|
|||
|
begin: hljs.IDENT_RE + '::'
|
|||
|
}
|
|||
|
]
|
|||
|
};
|
|||
|
}
|
|||
|
},{name:"objectivec",create:/*
|
|||
|
Language: Objective C
|
|||
|
Author: Valerii Hiora <valerii.hiora@gmail.com>
|
|||
|
Contributors: Angel G. Olloqui <angelgarcia.mail@gmail.com>
|
|||
|
*/
|
|||
|
|
|||
|
function(hljs) {
|
|||
|
var OBJC_KEYWORDS = {
|
|||
|
keyword:
|
|||
|
'int float while char export sizeof typedef const struct for union ' +
|
|||
|
'unsigned long volatile static bool mutable if do return goto void ' +
|
|||
|
'enum else break extern asm case short default double register explicit ' +
|
|||
|
'signed typename this switch continue wchar_t inline readonly assign ' +
|
|||
|
'self synchronized id ' +
|
|||
|
'nonatomic super unichar IBOutlet IBAction strong weak ' +
|
|||
|
'@private @protected @public @try @property @end @throw @catch @finally ' +
|
|||
|
'@synthesize @dynamic @selector @optional @required',
|
|||
|
literal:
|
|||
|
'false true FALSE TRUE nil YES NO NULL',
|
|||
|
built_in:
|
|||
|
'NSString NSDictionary CGRect CGPoint UIButton UILabel UITextView UIWebView MKMapView ' +
|
|||
|
'UISegmentedControl NSObject UITableViewDelegate UITableViewDataSource NSThread ' +
|
|||
|
'UIActivityIndicator UITabbar UIToolBar UIBarButtonItem UIImageView NSAutoreleasePool ' +
|
|||
|
'UITableView BOOL NSInteger CGFloat NSException NSLog NSMutableString NSMutableArray ' +
|
|||
|
'NSMutableDictionary NSURL NSIndexPath CGSize UITableViewCell UIView UIViewController ' +
|
|||
|
'UINavigationBar UINavigationController UITabBarController UIPopoverController ' +
|
|||
|
'UIPopoverControllerDelegate UIImage NSNumber UISearchBar NSFetchedResultsController ' +
|
|||
|
'NSFetchedResultsChangeType UIScrollView UIScrollViewDelegate UIEdgeInsets UIColor ' +
|
|||
|
'UIFont UIApplication NSNotFound NSNotificationCenter NSNotification ' +
|
|||
|
'UILocalNotification NSBundle NSFileManager NSTimeInterval NSDate NSCalendar ' +
|
|||
|
'NSUserDefaults UIWindow NSRange NSArray NSError NSURLRequest NSURLConnection ' +
|
|||
|
'UIInterfaceOrientation MPMoviePlayerController dispatch_once_t ' +
|
|||
|
'dispatch_queue_t dispatch_sync dispatch_async dispatch_once'
|
|||
|
};
|
|||
|
var LEXEMES = /[a-zA-Z@][a-zA-Z0-9_]*/;
|
|||
|
var CLASS_KEYWORDS = '@interface @class @protocol @implementation';
|
|||
|
return {
|
|||
|
aliases: ['m', 'mm', 'objc', 'obj-c'],
|
|||
|
keywords: OBJC_KEYWORDS, lexemes: LEXEMES,
|
|||
|
illegal: '</',
|
|||
|
contains: [
|
|||
|
hljs.C_LINE_COMMENT_MODE,
|
|||
|
hljs.C_BLOCK_COMMENT_MODE,
|
|||
|
hljs.C_NUMBER_MODE,
|
|||
|
hljs.QUOTE_STRING_MODE,
|
|||
|
{
|
|||
|
className: 'string',
|
|||
|
begin: '\'',
|
|||
|
end: '[^\\\\]\'',
|
|||
|
illegal: '[^\\\\][^\']'
|
|||
|
},
|
|||
|
|
|||
|
{
|
|||
|
className: 'preprocessor',
|
|||
|
begin: '#import',
|
|||
|
end: '$',
|
|||
|
contains: [
|
|||
|
{
|
|||
|
className: 'title',
|
|||
|
begin: '\"',
|
|||
|
end: '\"'
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'title',
|
|||
|
begin: '<',
|
|||
|
end: '>'
|
|||
|
}
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'preprocessor',
|
|||
|
begin: '#',
|
|||
|
end: '$'
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'class',
|
|||
|
begin: '(' + CLASS_KEYWORDS.split(' ').join('|') + ')\\b', end: '({|$)', excludeEnd: true,
|
|||
|
keywords: CLASS_KEYWORDS, lexemes: LEXEMES,
|
|||
|
contains: [
|
|||
|
hljs.UNDERSCORE_TITLE_MODE
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'variable',
|
|||
|
begin: '\\.'+hljs.UNDERSCORE_IDENT_RE,
|
|||
|
relevance: 0
|
|||
|
}
|
|||
|
]
|
|||
|
};
|
|||
|
}
|
|||
|
},{name:"cs",create:/*
|
|||
|
Language: C#
|
|||
|
Author: Jason Diamond <jason@diamond.name>
|
|||
|
*/
|
|||
|
|
|||
|
function(hljs) {
|
|||
|
var KEYWORDS =
|
|||
|
// Normal keywords.
|
|||
|
'abstract as base bool break byte case catch char checked const continue decimal ' +
|
|||
|
'default delegate do double else enum event explicit extern false finally fixed float ' +
|
|||
|
'for foreach goto if implicit in int interface internal is lock long new null ' +
|
|||
|
'object operator out override params private protected public readonly ref return sbyte ' +
|
|||
|
'sealed short sizeof stackalloc static string struct switch this throw true try typeof ' +
|
|||
|
'uint ulong unchecked unsafe ushort using virtual volatile void while async await ' +
|
|||
|
// Contextual keywords.
|
|||
|
'ascending descending from get group into join let orderby partial select set value var ' +
|
|||
|
'where yield';
|
|||
|
return {
|
|||
|
keywords: KEYWORDS,
|
|||
|
illegal: /::/,
|
|||
|
contains: [
|
|||
|
{
|
|||
|
className: 'comment',
|
|||
|
begin: '///', end: '$', returnBegin: true,
|
|||
|
contains: [
|
|||
|
{
|
|||
|
className: 'xmlDocTag',
|
|||
|
variants: [
|
|||
|
{
|
|||
|
begin: '///', relevance: 0
|
|||
|
},
|
|||
|
{
|
|||
|
begin: '<!--|-->'
|
|||
|
},
|
|||
|
{
|
|||
|
begin: '</?', end: '>'
|
|||
|
}
|
|||
|
]
|
|||
|
}
|
|||
|
]
|
|||
|
},
|
|||
|
hljs.C_LINE_COMMENT_MODE,
|
|||
|
hljs.C_BLOCK_COMMENT_MODE,
|
|||
|
{
|
|||
|
className: 'preprocessor',
|
|||
|
begin: '#', end: '$',
|
|||
|
keywords: 'if else elif endif define undef warning error line region endregion pragma checksum'
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'string',
|
|||
|
begin: '@"', end: '"',
|
|||
|
contains: [{begin: '""'}]
|
|||
|
},
|
|||
|
hljs.APOS_STRING_MODE,
|
|||
|
hljs.QUOTE_STRING_MODE,
|
|||
|
hljs.C_NUMBER_MODE,
|
|||
|
{
|
|||
|
beginKeywords: 'protected public private internal', end: /[{;=]/,
|
|||
|
keywords: KEYWORDS,
|
|||
|
contains: [
|
|||
|
{
|
|||
|
beginKeywords: 'class namespace interface',
|
|||
|
starts: {
|
|||
|
contains: [hljs.TITLE_MODE]
|
|||
|
}
|
|||
|
},
|
|||
|
{
|
|||
|
begin: hljs.IDENT_RE + '\\s*\\(', returnBegin: true,
|
|||
|
contains: [
|
|||
|
hljs.TITLE_MODE
|
|||
|
]
|
|||
|
}
|
|||
|
]
|
|||
|
}
|
|||
|
]
|
|||
|
};
|
|||
|
}
|
|||
|
},{name:"sql",create:/*
|
|||
|
Language: SQL
|
|||
|
Contributors: Nikolay Lisienko <info@neor.ru>, Heiko August <post@auge8472.de>, Travis Odom <travis.a.odom@gmail.com>
|
|||
|
*/
|
|||
|
|
|||
|
function(hljs) {
|
|||
|
var COMMENT_MODE = {
|
|||
|
className: 'comment',
|
|||
|
begin: '--', end: '$'
|
|||
|
};
|
|||
|
return {
|
|||
|
case_insensitive: true,
|
|||
|
illegal: /[<>]/,
|
|||
|
contains: [
|
|||
|
{
|
|||
|
className: 'operator',
|
|||
|
beginKeywords:
|
|||
|
'begin end start commit rollback savepoint lock alter create drop rename call '+
|
|||
|
'delete do handler insert load replace select truncate update set show pragma grant '+
|
|||
|
'merge describe use explain help declare prepare execute deallocate savepoint release '+
|
|||
|
'unlock purge reset change stop analyze cache flush optimize repair kill '+
|
|||
|
'install uninstall checksum restore check backup',
|
|||
|
end: /;/, endsWithParent: true,
|
|||
|
keywords: {
|
|||
|
keyword:
|
|||
|
'abs absolute acos action add adddate addtime aes_decrypt aes_encrypt after aggregate all allocate alter ' +
|
|||
|
'analyze and any are as asc ascii asin assertion at atan atan2 atn2 authorization authors avg backup ' +
|
|||
|
'before begin benchmark between bin binlog bit_and bit_count bit_length bit_or bit_xor both by ' +
|
|||
|
'cache call cascade cascaded case cast catalog ceil ceiling chain change changed char_length ' +
|
|||
|
'character_length charindex charset check checksum checksum_agg choose close coalesce ' +
|
|||
|
'coercibility collate collation collationproperty column columns columns_updated commit compress concat ' +
|
|||
|
'concat_ws concurrent connect connection connection_id consistent constraint constraints continue ' +
|
|||
|
'contributors conv convert convert_tz corresponding cos cot count count_big crc32 create cross cume_dist ' +
|
|||
|
'curdate current current_date current_time current_timestamp current_user cursor curtime data database ' +
|
|||
|
'databases datalength date_add date_format date_sub dateadd datediff datefromparts datename ' +
|
|||
|
'datepart datetime2fromparts datetimeoffsetfromparts day dayname dayofmonth dayofweek dayofyear ' +
|
|||
|
'deallocate declare decode default deferrable deferred degrees delayed delete des_decrypt ' +
|
|||
|
'des_encrypt des_key_file desc describe descriptor diagnostics difference disconnect distinct ' +
|
|||
|
'distinctrow div do domain double drop dumpfile each else elt enclosed encode encrypt end end-exec ' +
|
|||
|
'engine engines eomonth errors escape escaped event eventdata events except exception exec execute ' +
|
|||
|
'exists exp explain export_set extended external extract fast fetch field fields find_in_set ' +
|
|||
|
'first first_value floor flush for force foreign format found found_rows from from_base64 ' +
|
|||
|
'from_days from_unixtime full function get get_format get_lock getdate getutcdate global go goto grant ' +
|
|||
|
'grants greatest group group_concat grouping grouping_id gtid_subset gtid_subtract handler having help ' +
|
|||
|
'hex high_priority hosts hour ident_current ident_incr ident_seed identified identity if ifnull ignore ' +
|
|||
|
'iif ilike immediate in index indicator inet6_aton inet6_ntoa inet_aton inet_ntoa infile initially inner ' +
|
|||
|
'innodb input insert install instr intersect into is is_free_lock is_ipv4 ' +
|
|||
|
'is_ipv4_compat is_ipv4_mapped is_not is_not_null is_used_lock isdate isnull isolation join key kill ' +
|
|||
|
'language last last_day last_insert_id last_value lcase lead leading least leaves left len lenght level ' +
|
|||
|
'like limit lines ln load load_file local localtime localtimestamp locate lock log log10 log2 logfile ' +
|
|||
|
'logs low_priority lower lpad ltrim make_set makedate maketime master master_pos_wait match matched max ' +
|
|||
|
'md5 medium merge microsecond mid min minute mod mode module month monthname mutex name_const names ' +
|
|||
|
'national natural nchar next no no_write_to_binlog not now nullif nvarchar oct ' +
|
|||
|
'octet_length of old_password on only open optimize option optionally or ord order outer outfile output ' +
|
|||
|
'pad parse partial partition password patindex percent_rank percentile_cont percentile_disc period_add ' +
|
|||
|
'period_diff pi plugin position pow power pragma precision prepare preserve primary prior privileges ' +
|
|||
|
'procedure procedure_analyze processlist profile profiles public publishingservername purge quarter ' +
|
|||
|
'query quick quote quotename radians rand read references regexp relative relaylog release ' +
|
|||
|
'release_lock rename repair repeat replace replicate reset restore restrict return returns reverse ' +
|
|||
|
'revoke right rlike rollback rollup round row row_count rows rpad rtrim savepoint schema scroll ' +
|
|||
|
'sec_to_time second section select serializable server session session_user set sha sha1 sha2 share ' +
|
|||
|
'show sign sin size slave sleep smalldatetimefromparts snapshot some soname soundex ' +
|
|||
|
'sounds_like space sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_no_cache ' +
|
|||
|
'sql_small_result sql_variant_property sqlstate sqrt square start starting status std ' +
|
|||
|
'stddev stddev_pop stddev_samp stdev stdevp stop str str_to_date straight_join strcmp string stuff ' +
|
|||
|
'subdate substr substring subtime subtring_index sum switchoffset sysdate sysdatetime sysdatetimeoffset ' +
|
|||
|
'system_user sysutcdatetime table tables tablespace tan temporary terminated tertiary_weights then time ' +
|
|||
|
'time_format time_to_sec timediff timefromparts timestamp timestampadd timestampdiff timezone_hour ' +
|
|||
|
'timezone_minute to to_base64 to_days to_seconds todatetimeoffset trailing transaction translation ' +
|
|||
|
'trigger trigger_nestlevel triggers trim truncate try_cast try_convert try_parse ucase uncompress ' +
|
|||
|
'uncompressed_length unhex unicode uninstall union unique unix_timestamp unknown unlock update upgrade ' +
|
|||
|
'upped upper usage use user user_resources using utc_date utc_time utc_timestamp uuid uuid_short ' +
|
|||
|
'validate_password_strength value values var var_pop var_samp variables variance varp ' +
|
|||
|
'version view warnings week weekday weekofyear weight_string when whenever where with work write xml ' +
|
|||
|
'xor year yearweek zon',
|
|||
|
literal:
|
|||
|
'true false null',
|
|||
|
built_in:
|
|||
|
'array bigint binary bit blob boolean char character date dec decimal float int integer interval number ' +
|
|||
|
'numeric real serial smallint varchar varying int8 serial8 text'
|
|||
|
},
|
|||
|
contains: [
|
|||
|
{
|
|||
|
className: 'string',
|
|||
|
begin: '\'', end: '\'',
|
|||
|
contains: [hljs.BACKSLASH_ESCAPE, {begin: '\'\''}]
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'string',
|
|||
|
begin: '"', end: '"',
|
|||
|
contains: [hljs.BACKSLASH_ESCAPE, {begin: '""'}]
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'string',
|
|||
|
begin: '`', end: '`',
|
|||
|
contains: [hljs.BACKSLASH_ESCAPE]
|
|||
|
},
|
|||
|
hljs.C_NUMBER_MODE,
|
|||
|
hljs.C_BLOCK_COMMENT_MODE,
|
|||
|
COMMENT_MODE
|
|||
|
]
|
|||
|
},
|
|||
|
hljs.C_BLOCK_COMMENT_MODE,
|
|||
|
COMMENT_MODE
|
|||
|
]
|
|||
|
};
|
|||
|
}
|
|||
|
},{name:"xml",create:/*
|
|||
|
Language: HTML, XML
|
|||
|
*/
|
|||
|
|
|||
|
function(hljs) {
|
|||
|
var XML_IDENT_RE = '[A-Za-z0-9\\._:-]+';
|
|||
|
var PHP = {
|
|||
|
begin: /<\?(php)?(?!\w)/, end: /\?>/,
|
|||
|
subLanguage: 'php', subLanguageMode: 'continuous'
|
|||
|
};
|
|||
|
var TAG_INTERNALS = {
|
|||
|
endsWithParent: true,
|
|||
|
illegal: /</,
|
|||
|
relevance: 0,
|
|||
|
contains: [
|
|||
|
PHP,
|
|||
|
{
|
|||
|
className: 'attribute',
|
|||
|
begin: XML_IDENT_RE,
|
|||
|
relevance: 0
|
|||
|
},
|
|||
|
{
|
|||
|
begin: '=',
|
|||
|
relevance: 0,
|
|||
|
contains: [
|
|||
|
{
|
|||
|
className: 'value',
|
|||
|
variants: [
|
|||
|
{begin: /"/, end: /"/},
|
|||
|
{begin: /'/, end: /'/},
|
|||
|
{begin: /[^\s\/>]+/}
|
|||
|
]
|
|||
|
}
|
|||
|
]
|
|||
|
}
|
|||
|
]
|
|||
|
};
|
|||
|
return {
|
|||
|
aliases: ['html', 'xhtml', 'rss', 'atom', 'xsl', 'plist'],
|
|||
|
case_insensitive: true,
|
|||
|
contains: [
|
|||
|
{
|
|||
|
className: 'doctype',
|
|||
|
begin: '<!DOCTYPE', end: '>',
|
|||
|
relevance: 10,
|
|||
|
contains: [{begin: '\\[', end: '\\]'}]
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'comment',
|
|||
|
begin: '<!--', end: '-->',
|
|||
|
relevance: 10
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'cdata',
|
|||
|
begin: '<\\!\\[CDATA\\[', end: '\\]\\]>',
|
|||
|
relevance: 10
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'tag',
|
|||
|
/*
|
|||
|
The lookahead pattern (?=...) ensures that 'begin' only matches
|
|||
|
'<style' as a single word, followed by a whitespace or an
|
|||
|
ending braket. The '$' is needed for the lexeme to be recognized
|
|||
|
by hljs.subMode() that tests lexemes outside the stream.
|
|||
|
*/
|
|||
|
begin: '<style(?=\\s|>|$)', end: '>',
|
|||
|
keywords: {title: 'style'},
|
|||
|
contains: [TAG_INTERNALS],
|
|||
|
starts: {
|
|||
|
end: '</style>', returnEnd: true,
|
|||
|
subLanguage: 'css'
|
|||
|
}
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'tag',
|
|||
|
// See the comment in the <style tag about the lookahead pattern
|
|||
|
begin: '<script(?=\\s|>|$)', end: '>',
|
|||
|
keywords: {title: 'script'},
|
|||
|
contains: [TAG_INTERNALS],
|
|||
|
starts: {
|
|||
|
end: '</script>', returnEnd: true,
|
|||
|
subLanguage: 'javascript'
|
|||
|
}
|
|||
|
},
|
|||
|
{
|
|||
|
begin: '<%', end: '%>',
|
|||
|
subLanguage: 'vbscript'
|
|||
|
},
|
|||
|
PHP,
|
|||
|
{
|
|||
|
className: 'pi',
|
|||
|
begin: /<\?\w+/, end: /\?>/,
|
|||
|
relevance: 10
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'tag',
|
|||
|
begin: '</?', end: '/?>',
|
|||
|
contains: [
|
|||
|
{
|
|||
|
className: 'title', begin: '[^ /><]+', relevance: 0
|
|||
|
},
|
|||
|
TAG_INTERNALS
|
|||
|
]
|
|||
|
}
|
|||
|
]
|
|||
|
};
|
|||
|
}
|
|||
|
},{name:"css",create:/*
|
|||
|
Language: CSS
|
|||
|
*/
|
|||
|
|
|||
|
function(hljs) {
|
|||
|
var IDENT_RE = '[a-zA-Z-][a-zA-Z0-9_-]*';
|
|||
|
var FUNCTION = {
|
|||
|
className: 'function',
|
|||
|
begin: IDENT_RE + '\\(',
|
|||
|
returnBegin: true,
|
|||
|
excludeEnd: true,
|
|||
|
end: '\\('
|
|||
|
};
|
|||
|
return {
|
|||
|
case_insensitive: true,
|
|||
|
illegal: '[=/|\']',
|
|||
|
contains: [
|
|||
|
hljs.C_BLOCK_COMMENT_MODE,
|
|||
|
{
|
|||
|
className: 'id', begin: '\\#[A-Za-z0-9_-]+'
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'class', begin: '\\.[A-Za-z0-9_-]+',
|
|||
|
relevance: 0
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'attr_selector',
|
|||
|
begin: '\\[', end: '\\]',
|
|||
|
illegal: '$'
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'pseudo',
|
|||
|
begin: ':(:)?[a-zA-Z0-9\\_\\-\\+\\(\\)\\"\\\']+'
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'at_rule',
|
|||
|
begin: '@(font-face|page)',
|
|||
|
lexemes: '[a-z-]+',
|
|||
|
keywords: 'font-face page'
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'at_rule',
|
|||
|
begin: '@', end: '[{;]', // at_rule eating first "{" is a good thing
|
|||
|
// because it doesn’t let it to be parsed as
|
|||
|
// a rule set but instead drops parser into
|
|||
|
// the default mode which is how it should be.
|
|||
|
contains: [
|
|||
|
{
|
|||
|
className: 'keyword',
|
|||
|
begin: /\S+/
|
|||
|
},
|
|||
|
{
|
|||
|
begin: /\s/, endsWithParent: true, excludeEnd: true,
|
|||
|
relevance: 0,
|
|||
|
contains: [
|
|||
|
FUNCTION,
|
|||
|
hljs.APOS_STRING_MODE, hljs.QUOTE_STRING_MODE,
|
|||
|
hljs.CSS_NUMBER_MODE
|
|||
|
]
|
|||
|
}
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'tag', begin: IDENT_RE,
|
|||
|
relevance: 0
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'rules',
|
|||
|
begin: '{', end: '}',
|
|||
|
illegal: '[^\\s]',
|
|||
|
relevance: 0,
|
|||
|
contains: [
|
|||
|
hljs.C_BLOCK_COMMENT_MODE,
|
|||
|
{
|
|||
|
className: 'rule',
|
|||
|
begin: '[^\\s]', returnBegin: true, end: ';', endsWithParent: true,
|
|||
|
contains: [
|
|||
|
{
|
|||
|
className: 'attribute',
|
|||
|
begin: '[A-Z\\_\\.\\-]+', end: ':',
|
|||
|
excludeEnd: true,
|
|||
|
illegal: '[^\\s]',
|
|||
|
starts: {
|
|||
|
className: 'value',
|
|||
|
endsWithParent: true, excludeEnd: true,
|
|||
|
contains: [
|
|||
|
FUNCTION,
|
|||
|
hljs.CSS_NUMBER_MODE,
|
|||
|
hljs.QUOTE_STRING_MODE,
|
|||
|
hljs.APOS_STRING_MODE,
|
|||
|
hljs.C_BLOCK_COMMENT_MODE,
|
|||
|
{
|
|||
|
className: 'hexcolor', begin: '#[0-9A-Fa-f]+'
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'important', begin: '!important'
|
|||
|
}
|
|||
|
]
|
|||
|
}
|
|||
|
}
|
|||
|
]
|
|||
|
}
|
|||
|
]
|
|||
|
}
|
|||
|
]
|
|||
|
};
|
|||
|
}
|
|||
|
},{name:"scala",create:/*
|
|||
|
Language: Scala
|
|||
|
Author: Jan Berkel <jan.berkel@gmail.com>
|
|||
|
*/
|
|||
|
|
|||
|
function(hljs) {
|
|||
|
var ANNOTATION = {
|
|||
|
className: 'annotation', begin: '@[A-Za-z]+'
|
|||
|
};
|
|||
|
var STRING = {
|
|||
|
className: 'string',
|
|||
|
begin: 'u?r?"""', end: '"""',
|
|||
|
relevance: 10
|
|||
|
};
|
|||
|
var SYMBOL = {
|
|||
|
className: 'symbol',
|
|||
|
begin: '\'\\w[\\w\\d_]*(?!\')'
|
|||
|
};
|
|||
|
return {
|
|||
|
keywords:
|
|||
|
'type yield lazy override def with val var false true sealed abstract private trait ' +
|
|||
|
'object null if for while throw finally protected extends import final return else ' +
|
|||
|
'break new catch super class case package default try this match continue throws',
|
|||
|
contains: [
|
|||
|
{
|
|||
|
className: 'javadoc',
|
|||
|
begin: '/\\*\\*', end: '\\*/',
|
|||
|
contains: [{
|
|||
|
className: 'javadoctag',
|
|||
|
begin: '@[A-Za-z]+'
|
|||
|
}],
|
|||
|
relevance: 10
|
|||
|
},
|
|||
|
hljs.C_LINE_COMMENT_MODE, hljs.C_BLOCK_COMMENT_MODE,
|
|||
|
STRING, hljs.QUOTE_STRING_MODE,
|
|||
|
SYMBOL,
|
|||
|
{
|
|||
|
className: 'class',
|
|||
|
begin: '((case )?class |object |trait )', // beginKeywords won't work because a single "case" shouldn't start this mode
|
|||
|
end: '({|$)', excludeEnd: true,
|
|||
|
illegal: ':',
|
|||
|
keywords: 'case class trait object',
|
|||
|
contains: [
|
|||
|
{
|
|||
|
beginKeywords: 'extends with',
|
|||
|
relevance: 10
|
|||
|
},
|
|||
|
hljs.UNDERSCORE_TITLE_MODE,
|
|||
|
{
|
|||
|
className: 'params',
|
|||
|
begin: '\\(', end: '\\)',
|
|||
|
contains: [
|
|||
|
hljs.QUOTE_STRING_MODE, STRING,
|
|||
|
ANNOTATION
|
|||
|
]
|
|||
|
}
|
|||
|
]
|
|||
|
},
|
|||
|
hljs.C_NUMBER_MODE,
|
|||
|
ANNOTATION
|
|||
|
]
|
|||
|
};
|
|||
|
}
|
|||
|
},{name:"coffeescript",create:/*
|
|||
|
Language: CoffeeScript
|
|||
|
Author: Dmytrii Nagirniak <dnagir@gmail.com>
|
|||
|
Contributors: Oleg Efimov <efimovov@gmail.com>, Cédric Néhémie <cedric.nehemie@gmail.com>
|
|||
|
Description: CoffeeScript is a programming language that transcompiles to JavaScript. For info about language see http://coffeescript.org/
|
|||
|
*/
|
|||
|
|
|||
|
function(hljs) {
|
|||
|
var KEYWORDS = {
|
|||
|
keyword:
|
|||
|
// JS keywords
|
|||
|
'in if for while finally new do return else break catch instanceof throw try this ' +
|
|||
|
'switch continue typeof delete debugger super ' +
|
|||
|
// Coffee keywords
|
|||
|
'then unless until loop of by when and or is isnt not',
|
|||
|
literal:
|
|||
|
// JS literals
|
|||
|
'true false null undefined ' +
|
|||
|
// Coffee literals
|
|||
|
'yes no on off',
|
|||
|
reserved:
|
|||
|
'case default function var void with const let enum export import native ' +
|
|||
|
'__hasProp __extends __slice __bind __indexOf',
|
|||
|
built_in:
|
|||
|
'npm require console print module global window document'
|
|||
|
};
|
|||
|
var JS_IDENT_RE = '[A-Za-z$_][0-9A-Za-z$_]*';
|
|||
|
var TITLE = hljs.inherit(hljs.TITLE_MODE, {begin: JS_IDENT_RE});
|
|||
|
var SUBST = {
|
|||
|
className: 'subst',
|
|||
|
begin: /#\{/, end: /}/,
|
|||
|
keywords: KEYWORDS
|
|||
|
};
|
|||
|
var EXPRESSIONS = [
|
|||
|
hljs.BINARY_NUMBER_MODE,
|
|||
|
hljs.inherit(hljs.C_NUMBER_MODE, {starts: {end: '(\\s*/)?', relevance: 0}}), // a number tries to eat the following slash to prevent treating it as a regexp
|
|||
|
{
|
|||
|
className: 'string',
|
|||
|
variants: [
|
|||
|
{
|
|||
|
begin: /'''/, end: /'''/,
|
|||
|
contains: [hljs.BACKSLASH_ESCAPE]
|
|||
|
},
|
|||
|
{
|
|||
|
begin: /'/, end: /'/,
|
|||
|
contains: [hljs.BACKSLASH_ESCAPE]
|
|||
|
},
|
|||
|
{
|
|||
|
begin: /"""/, end: /"""/,
|
|||
|
contains: [hljs.BACKSLASH_ESCAPE, SUBST]
|
|||
|
},
|
|||
|
{
|
|||
|
begin: /"/, end: /"/,
|
|||
|
contains: [hljs.BACKSLASH_ESCAPE, SUBST]
|
|||
|
}
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'regexp',
|
|||
|
variants: [
|
|||
|
{
|
|||
|
begin: '///', end: '///',
|
|||
|
contains: [SUBST, hljs.HASH_COMMENT_MODE]
|
|||
|
},
|
|||
|
{
|
|||
|
begin: '//[gim]*',
|
|||
|
relevance: 0
|
|||
|
},
|
|||
|
{
|
|||
|
begin: '/\\S(\\\\.|[^\\n])*?/[gim]*(?=\\s|\\W|$)' // \S is required to parse x / 2 / 3 as two divisions
|
|||
|
}
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'property',
|
|||
|
begin: '@' + JS_IDENT_RE
|
|||
|
},
|
|||
|
{
|
|||
|
begin: '`', end: '`',
|
|||
|
excludeBegin: true, excludeEnd: true,
|
|||
|
subLanguage: 'javascript'
|
|||
|
}
|
|||
|
];
|
|||
|
SUBST.contains = EXPRESSIONS;
|
|||
|
|
|||
|
return {
|
|||
|
aliases: ['coffee', 'cson', 'iced'],
|
|||
|
keywords: KEYWORDS,
|
|||
|
contains: EXPRESSIONS.concat([
|
|||
|
{
|
|||
|
className: 'comment',
|
|||
|
begin: '###', end: '###'
|
|||
|
},
|
|||
|
hljs.HASH_COMMENT_MODE,
|
|||
|
{
|
|||
|
className: 'function',
|
|||
|
begin: '(' + JS_IDENT_RE + '\\s*=\\s*)?(\\(.*\\))?\\s*\\B[-=]>', end: '[-=]>',
|
|||
|
returnBegin: true,
|
|||
|
contains: [
|
|||
|
TITLE,
|
|||
|
{
|
|||
|
className: 'params',
|
|||
|
begin: '\\(', returnBegin: true,
|
|||
|
/* We need another contained nameless mode to not have every nested
|
|||
|
pair of parens to be called "params" */
|
|||
|
contains: [{
|
|||
|
begin: /\(/, end: /\)/,
|
|||
|
keywords: KEYWORDS,
|
|||
|
contains: ['self'].concat(EXPRESSIONS)
|
|||
|
}]
|
|||
|
}
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'class',
|
|||
|
beginKeywords: 'class',
|
|||
|
end: '$',
|
|||
|
illegal: /[:="\[\]]/,
|
|||
|
contains: [
|
|||
|
{
|
|||
|
beginKeywords: 'extends',
|
|||
|
endsWithParent: true,
|
|||
|
illegal: /[:="\[\]]/,
|
|||
|
contains: [TITLE]
|
|||
|
},
|
|||
|
TITLE
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'attribute',
|
|||
|
begin: JS_IDENT_RE + ':', end: ':',
|
|||
|
returnBegin: true, excludeEnd: true,
|
|||
|
relevance: 0
|
|||
|
}
|
|||
|
])
|
|||
|
};
|
|||
|
}
|
|||
|
},{name:"lisp",create:/*
|
|||
|
Language: Lisp
|
|||
|
Description: Generic lisp syntax
|
|||
|
Author: Vasily Polovnyov <vast@whiteants.net>
|
|||
|
*/
|
|||
|
|
|||
|
function(hljs) {
|
|||
|
var LISP_IDENT_RE = '[a-zA-Z_\\-\\+\\*\\/\\<\\=\\>\\&\\#][a-zA-Z0-9_\\-\\+\\*\\/\\<\\=\\>\\&\\#!]*';
|
|||
|
var LISP_SIMPLE_NUMBER_RE = '(\\-|\\+)?\\d+(\\.\\d+|\\/\\d+)?((d|e|f|l|s)(\\+|\\-)?\\d+)?';
|
|||
|
var SHEBANG = {
|
|||
|
className: 'shebang',
|
|||
|
begin: '^#!', end: '$'
|
|||
|
};
|
|||
|
var LITERAL = {
|
|||
|
className: 'literal',
|
|||
|
begin: '\\b(t{1}|nil)\\b'
|
|||
|
};
|
|||
|
var NUMBER = {
|
|||
|
className: 'number',
|
|||
|
variants: [
|
|||
|
{begin: LISP_SIMPLE_NUMBER_RE, relevance: 0},
|
|||
|
{begin: '#b[0-1]+(/[0-1]+)?'},
|
|||
|
{begin: '#o[0-7]+(/[0-7]+)?'},
|
|||
|
{begin: '#x[0-9a-f]+(/[0-9a-f]+)?'},
|
|||
|
{begin: '#c\\(' + LISP_SIMPLE_NUMBER_RE + ' +' + LISP_SIMPLE_NUMBER_RE, end: '\\)'}
|
|||
|
]
|
|||
|
};
|
|||
|
var STRING = hljs.inherit(hljs.QUOTE_STRING_MODE, {illegal: null});
|
|||
|
var COMMENT = {
|
|||
|
className: 'comment',
|
|||
|
begin: ';', end: '$'
|
|||
|
};
|
|||
|
var VARIABLE = {
|
|||
|
className: 'variable',
|
|||
|
begin: '\\*', end: '\\*'
|
|||
|
};
|
|||
|
var KEYWORD = {
|
|||
|
className: 'keyword',
|
|||
|
begin: '[:&]' + LISP_IDENT_RE
|
|||
|
};
|
|||
|
var QUOTED_LIST = {
|
|||
|
begin: '\\(', end: '\\)',
|
|||
|
contains: ['self', LITERAL, STRING, NUMBER]
|
|||
|
};
|
|||
|
var QUOTED = {
|
|||
|
className: 'quoted',
|
|||
|
contains: [NUMBER, STRING, VARIABLE, KEYWORD, QUOTED_LIST],
|
|||
|
variants: [
|
|||
|
{
|
|||
|
begin: '[\'`]\\(', end: '\\)'
|
|||
|
},
|
|||
|
{
|
|||
|
begin: '\\(quote ', end: '\\)',
|
|||
|
keywords: {title: 'quote'}
|
|||
|
}
|
|||
|
]
|
|||
|
};
|
|||
|
var LIST = {
|
|||
|
className: 'list',
|
|||
|
begin: '\\(', end: '\\)'
|
|||
|
};
|
|||
|
var BODY = {
|
|||
|
endsWithParent: true,
|
|||
|
relevance: 0
|
|||
|
};
|
|||
|
LIST.contains = [{className: 'title', begin: LISP_IDENT_RE}, BODY];
|
|||
|
BODY.contains = [QUOTED, LIST, LITERAL, NUMBER, STRING, COMMENT, VARIABLE, KEYWORD];
|
|||
|
|
|||
|
return {
|
|||
|
illegal: /\S/,
|
|||
|
contains: [
|
|||
|
NUMBER,
|
|||
|
SHEBANG,
|
|||
|
LITERAL,
|
|||
|
STRING,
|
|||
|
COMMENT,
|
|||
|
QUOTED,
|
|||
|
LIST
|
|||
|
]
|
|||
|
};
|
|||
|
}
|
|||
|
},{name:"clojure",create:/*
|
|||
|
Language: Clojure
|
|||
|
Description: Clojure syntax (based on lisp.js)
|
|||
|
Author: mfornos
|
|||
|
*/
|
|||
|
|
|||
|
function(hljs) {
|
|||
|
var keywords = {
|
|||
|
built_in:
|
|||
|
// Clojure keywords
|
|||
|
'def cond apply if-not if-let if not not= = < < > <= <= >= == + / * - rem '+
|
|||
|
'quot neg? pos? delay? symbol? keyword? true? false? integer? empty? coll? list? '+
|
|||
|
'set? ifn? fn? associative? sequential? sorted? counted? reversible? number? decimal? '+
|
|||
|
'class? distinct? isa? float? rational? reduced? ratio? odd? even? char? seq? vector? '+
|
|||
|
'string? map? nil? contains? zero? instance? not-every? not-any? libspec? -> ->> .. . '+
|
|||
|
'inc compare do dotimes mapcat take remove take-while drop letfn drop-last take-last '+
|
|||
|
'drop-while while intern condp case reduced cycle split-at split-with repeat replicate '+
|
|||
|
'iterate range merge zipmap declare line-seq sort comparator sort-by dorun doall nthnext '+
|
|||
|
'nthrest partition eval doseq await await-for let agent atom send send-off release-pending-sends '+
|
|||
|
'add-watch mapv filterv remove-watch agent-error restart-agent set-error-handler error-handler '+
|
|||
|
'set-error-mode! error-mode shutdown-agents quote var fn loop recur throw try monitor-enter '+
|
|||
|
'monitor-exit defmacro defn defn- macroexpand macroexpand-1 for dosync and or '+
|
|||
|
'when when-not when-let comp juxt partial sequence memoize constantly complement identity assert '+
|
|||
|
'peek pop doto proxy defstruct first rest cons defprotocol cast coll deftype defrecord last butlast '+
|
|||
|
'sigs reify second ffirst fnext nfirst nnext defmulti defmethod meta with-meta ns in-ns create-ns import '+
|
|||
|
'refer keys select-keys vals key val rseq name namespace promise into transient persistent! conj! '+
|
|||
|
'assoc! dissoc! pop! disj! use class type num float double short byte boolean bigint biginteger '+
|
|||
|
'bigdec print-method print-dup throw-if printf format load compile get-in update-in pr pr-on newline '+
|
|||
|
'flush read slurp read-line subvec with-open memfn time re-find re-groups rand-int rand mod locking '+
|
|||
|
'assert-valid-fdecl alias resolve ref deref refset swap! reset! set-validator! compare-and-set! alter-meta! '+
|
|||
|
'reset-meta! commute get-validator alter ref-set ref-history-count ref-min-history ref-max-history ensure sync io! '+
|
|||
|
'new next conj set! to-array future future-call into-array aset gen-class reduce map filter find empty '+
|
|||
|
'hash-map hash-set sorted-map sorted-map-by sorted-set sorted-set-by vec vector seq flatten reverse assoc dissoc list '+
|
|||
|
'disj get union difference intersection extend extend-type extend-protocol int nth delay count concat chunk chunk-buffer '+
|
|||
|
'chunk-append chunk-first chunk-rest max min dec unchecked-inc-int unchecked-inc unchecked-dec-inc unchecked-dec unchecked-negate '+
|
|||
|
'unchecked-add-int unchecked-add unchecked-subtract-int unchecked-subtract chunk-next chunk-cons chunked-seq? prn vary-meta '+
|
|||
|
'lazy-seq spread list* str find-keyword keyword symbol gensym force rationalize'
|
|||
|
};
|
|||
|
|
|||
|
var CLJ_IDENT_RE = '[a-zA-Z_0-9\\!\\.\\?\\-\\+\\*\\/\\<\\=\\>\\&\\#\\$\';]+';
|
|||
|
var SIMPLE_NUMBER_RE = '[\\s:\\(\\{]+\\d+(\\.\\d+)?';
|
|||
|
|
|||
|
var NUMBER = {
|
|||
|
className: 'number', begin: SIMPLE_NUMBER_RE,
|
|||
|
relevance: 0
|
|||
|
};
|
|||
|
var STRING = hljs.inherit(hljs.QUOTE_STRING_MODE, {illegal: null});
|
|||
|
var COMMENT = {
|
|||
|
className: 'comment',
|
|||
|
begin: ';', end: '$',
|
|||
|
relevance: 0
|
|||
|
};
|
|||
|
var COLLECTION = {
|
|||
|
className: 'collection',
|
|||
|
begin: '[\\[\\{]', end: '[\\]\\}]'
|
|||
|
};
|
|||
|
var HINT = {
|
|||
|
className: 'comment',
|
|||
|
begin: '\\^' + CLJ_IDENT_RE
|
|||
|
};
|
|||
|
var HINT_COL = {
|
|||
|
className: 'comment',
|
|||
|
begin: '\\^\\{', end: '\\}'
|
|||
|
|
|||
|
};
|
|||
|
var KEY = {
|
|||
|
className: 'attribute',
|
|||
|
begin: '[:]' + CLJ_IDENT_RE
|
|||
|
};
|
|||
|
var LIST = {
|
|||
|
className: 'list',
|
|||
|
begin: '\\(', end: '\\)'
|
|||
|
};
|
|||
|
var BODY = {
|
|||
|
endsWithParent: true,
|
|||
|
keywords: {literal: 'true false nil'},
|
|||
|
relevance: 0
|
|||
|
};
|
|||
|
var TITLE = {
|
|||
|
keywords: keywords,
|
|||
|
lexemes: CLJ_IDENT_RE,
|
|||
|
className: 'title', begin: CLJ_IDENT_RE,
|
|||
|
starts: BODY
|
|||
|
};
|
|||
|
|
|||
|
LIST.contains = [{className: 'comment', begin: 'comment'}, TITLE, BODY];
|
|||
|
BODY.contains = [LIST, STRING, HINT, HINT_COL, COMMENT, KEY, COLLECTION, NUMBER];
|
|||
|
COLLECTION.contains = [LIST, STRING, HINT, COMMENT, KEY, COLLECTION, NUMBER];
|
|||
|
|
|||
|
return {
|
|||
|
aliases: ['clj'],
|
|||
|
illegal: /\S/,
|
|||
|
contains: [
|
|||
|
COMMENT,
|
|||
|
LIST,
|
|||
|
{
|
|||
|
className: 'prompt',
|
|||
|
begin: /^=> /,
|
|||
|
starts: {end: /\n\n|\Z/} // eat up prompt output to not interfere with the illegal
|
|||
|
}
|
|||
|
]
|
|||
|
}
|
|||
|
}
|
|||
|
},{name:"http",create:/*
|
|||
|
Language: HTTP
|
|||
|
Description: HTTP request and response headers with automatic body highlighting
|
|||
|
Author: Ivan Sagalaev <maniac@softwaremaniacs.org>
|
|||
|
*/
|
|||
|
|
|||
|
function(hljs) {
|
|||
|
return {
|
|||
|
illegal: '\\S',
|
|||
|
contains: [
|
|||
|
{
|
|||
|
className: 'status',
|
|||
|
begin: '^HTTP/[0-9\\.]+', end: '$',
|
|||
|
contains: [{className: 'number', begin: '\\b\\d{3}\\b'}]
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'request',
|
|||
|
begin: '^[A-Z]+ (.*?) HTTP/[0-9\\.]+$', returnBegin: true, end: '$',
|
|||
|
contains: [
|
|||
|
{
|
|||
|
className: 'string',
|
|||
|
begin: ' ', end: ' ',
|
|||
|
excludeBegin: true, excludeEnd: true
|
|||
|
}
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'attribute',
|
|||
|
begin: '^\\w', end: ': ', excludeEnd: true,
|
|||
|
illegal: '\\n|\\s|=',
|
|||
|
starts: {className: 'string', end: '$'}
|
|||
|
},
|
|||
|
{
|
|||
|
begin: '\\n\\n',
|
|||
|
starts: {subLanguage: '', endsWithParent: true}
|
|||
|
}
|
|||
|
]
|
|||
|
};
|
|||
|
}
|
|||
|
},{name:"haskell",create:/*
|
|||
|
Language: Haskell
|
|||
|
Author: Jeremy Hull <sourdrums@gmail.com>
|
|||
|
Contributors: Zena Treep <zena.treep@gmail.com>
|
|||
|
*/
|
|||
|
|
|||
|
function(hljs) {
|
|||
|
|
|||
|
var COMMENT = {
|
|||
|
className: 'comment',
|
|||
|
variants: [
|
|||
|
{ begin: '--', end: '$' },
|
|||
|
{ begin: '{-', end: '-}'
|
|||
|
, contains: ['self']
|
|||
|
}
|
|||
|
]
|
|||
|
};
|
|||
|
|
|||
|
var PRAGMA = {
|
|||
|
className: 'pragma',
|
|||
|
begin: '{-#', end: '#-}'
|
|||
|
};
|
|||
|
|
|||
|
var PREPROCESSOR = {
|
|||
|
className: 'preprocessor',
|
|||
|
begin: '^#', end: '$'
|
|||
|
};
|
|||
|
|
|||
|
var CONSTRUCTOR = {
|
|||
|
className: 'type',
|
|||
|
begin: '\\b[A-Z][\\w\']*', // TODO: other constructors (build-in, infix).
|
|||
|
relevance: 0
|
|||
|
};
|
|||
|
|
|||
|
var LIST = {
|
|||
|
className: 'container',
|
|||
|
begin: '\\(', end: '\\)',
|
|||
|
illegal: '"',
|
|||
|
contains: [
|
|||
|
PRAGMA,
|
|||
|
COMMENT,
|
|||
|
PREPROCESSOR,
|
|||
|
{className: 'type', begin: '\\b[A-Z][\\w]*(\\((\\.\\.|,|\\w+)\\))?'},
|
|||
|
hljs.inherit(hljs.TITLE_MODE, {begin: '[_a-z][\\w\']*'})
|
|||
|
]
|
|||
|
};
|
|||
|
|
|||
|
var RECORD = {
|
|||
|
className: 'container',
|
|||
|
begin: '{', end: '}',
|
|||
|
contains: LIST.contains
|
|||
|
};
|
|||
|
|
|||
|
return {
|
|||
|
aliases: ['hs'],
|
|||
|
keywords:
|
|||
|
'let in if then else case of where do module import hiding ' +
|
|||
|
'qualified type data newtype deriving class instance as default ' +
|
|||
|
'infix infixl infixr foreign export ccall stdcall cplusplus ' +
|
|||
|
'jvm dotnet safe unsafe family forall mdo proc rec',
|
|||
|
contains: [
|
|||
|
|
|||
|
// Top-level constructions.
|
|||
|
|
|||
|
{
|
|||
|
className: 'module',
|
|||
|
begin: '\\bmodule\\b', end: 'where',
|
|||
|
keywords: 'module where',
|
|||
|
contains: [LIST, COMMENT],
|
|||
|
illegal: '\\W\\.|;'
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'import',
|
|||
|
begin: '\\bimport\\b', end: '$',
|
|||
|
keywords: 'import|0 qualified as hiding',
|
|||
|
contains: [LIST, COMMENT],
|
|||
|
illegal: '\\W\\.|;'
|
|||
|
},
|
|||
|
|
|||
|
{
|
|||
|
className: 'class',
|
|||
|
begin: '^(\\s*)?(class|instance)\\b', end: 'where',
|
|||
|
keywords: 'class family instance where',
|
|||
|
contains: [CONSTRUCTOR, LIST, COMMENT]
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'typedef',
|
|||
|
begin: '\\b(data|(new)?type)\\b', end: '$',
|
|||
|
keywords: 'data family type newtype deriving',
|
|||
|
contains: [PRAGMA, COMMENT, CONSTRUCTOR, LIST, RECORD]
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'default',
|
|||
|
beginKeywords: 'default', end: '$',
|
|||
|
contains: [CONSTRUCTOR, LIST, COMMENT]
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'infix',
|
|||
|
beginKeywords: 'infix infixl infixr', end: '$',
|
|||
|
contains: [hljs.C_NUMBER_MODE, COMMENT]
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'foreign',
|
|||
|
begin: '\\bforeign\\b', end: '$',
|
|||
|
keywords: 'foreign import export ccall stdcall cplusplus jvm ' +
|
|||
|
'dotnet safe unsafe',
|
|||
|
contains: [CONSTRUCTOR, hljs.QUOTE_STRING_MODE, COMMENT]
|
|||
|
},
|
|||
|
{
|
|||
|
className: 'shebang',
|
|||
|
begin: '#!\\/usr\\/bin\\/env\ runhaskell', end: '$'
|
|||
|
},
|
|||
|
|
|||
|
// "Whitespaces".
|
|||
|
|
|||
|
PRAGMA,
|
|||
|
COMMENT,
|
|||
|
PREPROCESSOR,
|
|||
|
|
|||
|
// Literals and names.
|
|||
|
|
|||
|
// TODO: characters.
|
|||
|
hljs.QUOTE_STRING_MODE,
|
|||
|
hljs.C_NUMBER_MODE,
|
|||
|
CONSTRUCTOR,
|
|||
|
hljs.inherit(hljs.TITLE_MODE, {begin: '^[_a-z][\\w\']*'}),
|
|||
|
|
|||
|
{begin: '->|<-'} // No markup, relevance booster
|
|||
|
]
|
|||
|
};
|
|||
|
}
|
|||
|
}]
|
|||
|
;
|
|||
|
|
|||
|
for (var i = 0; i < languages.length; ++i) {
|
|||
|
hljs.registerLanguage(languages[i].name, languages[i].create);
|
|||
|
}
|
|||
|
|
|||
|
module.exports = {
|
|||
|
styles: {"arta":".hljs-arta{}.hljs-arta .hljs{display:block;padding:0.5em;background:#222;}.hljs-arta .profile .hljs-header *,.hljs-arta .ini .hljs-title,.hljs-arta .nginx .hljs-title{color:#fff;}.hljs-arta .hljs-comment,.hljs-arta .hljs-javadoc,.hljs-arta .hljs-preprocessor,.hljs-arta .hljs-preprocessor .hljs-title,.hljs-arta .hljs-pragma,.hljs-arta .hljs-shebang,.hljs-arta .profile .hljs-summary,.hljs-arta .diff,.hljs-arta .hljs-pi,.hljs-arta .hljs-doctype,.hljs-arta .hljs-tag,.hljs-arta .hljs-template_comment,.hljs-arta .css .hljs-rules,.hljs-arta .tex .hljs-special{color:#444;}.hljs-arta .hljs-string,.hljs-arta .hljs-symbol,.hljs-arta .diff .hljs-change,.hljs-arta .hljs-regexp,.hljs-arta .xml .hljs-attribute,.hljs-arta .smalltalk .hljs-char,.hljs-arta .xml .hljs-value,.hljs-arta .ini .hljs-value,.hljs-arta .clojure .hljs-attribute,.hljs-arta .coffeescript .hljs-attribute{color:#ffcc33;}.hljs-arta .hljs-number,.hljs-arta .hljs-addition{color:#00cc66;}.hljs-arta .hljs-built_in,.hljs-arta .hljs-literal,.hljs-arta .vhdl .hljs-typename,.hljs-arta .go .hljs-constant,.hljs-arta .go .hljs-typename,.hljs-arta .ini .hljs-keyword,.hljs-arta .lua .hljs-title,.hljs-arta .perl .hljs-variable,.hljs-arta .php .hljs-variable,.hljs-arta .mel .hljs-variable,.hljs-arta .django .hljs-variable,.hljs-arta .css .funtion,.hljs-arta .smalltalk .method,.hljs-arta .hljs-hexcolor,.hljs-arta .hljs-important,.hljs-arta .hljs-flow,.hljs-arta .hljs-inheritance,.hljs-arta .parser3 .hljs-variable{color:#32aaee;}.hljs-arta .hljs-keyword,.hljs-arta .hljs-tag .hljs-title,.hljs-arta .css .hljs-tag,.hljs-arta .css .hljs-class,.hljs-arta .css .hljs-id,.hljs-arta .css .hljs-pseudo,.hljs-arta .css .hljs-attr_selector,.hljs-arta .lisp .hljs-title,.hljs-arta .clojure .hljs-built_in,.hljs-arta .hljs-winutils,.hljs-arta .tex .hljs-command,.hljs-arta .hljs-request,.hljs-arta .hljs-status{color:#6644aa;}.hljs-arta .hljs-title,.hljs-arta .ruby .hljs-constant,.hljs-arta .vala .hljs-constant,.hljs-arta .hljs-parent,.hljs-arta .hljs-deletion,.hljs-arta .hljs-template_tag,.hljs-arta .css .hljs-keyword,.hljs-arta .objectivec .hljs-class .hljs-id,.hljs-arta .smalltalk .hljs-class,.hljs-arta .lisp .hljs-keyword,.hljs-arta .apache .hljs-tag,.hljs-arta .nginx .hljs-variable,.hljs-arta .hljs-envvar,.hljs-arta .bash .hljs-variable,.hljs-arta .go .hljs-built_in,.hljs-arta .vbscript .hljs-built_in,.hljs-arta .lua .hljs-built_in,.hljs-arta .rsl .hljs-built_in,.hljs-arta .tail,.hljs-arta .avrasm .hljs-label,.hljs-arta .tex .hljs-formula,.hljs-arta .tex .hljs-formula *{color:#bb1166;}.hljs-arta .hljs-yardoctag,.hljs-arta .hljs-phpdoc,.hljs-arta .profile .hljs-header,.hljs-arta .ini .hljs-title,.hljs-arta .apache .hljs-tag,.hljs-arta .parser3 .hljs-title{font-weight:bold;}.hljs-arta .coffeescript .javascript,.hljs-arta .javascript .xml,.hljs-arta .tex .hljs-formula,.hljs-arta .xml .javascript,.hljs-arta .xml .vbscript,.hljs-arta .xml .css,.hljs-arta .xml .hljs-cdata{opacity:0.6;}.hljs-arta .hljs,.hljs-arta .hljs-subst,.hljs-arta .diff .hljs-chunk,.hljs-arta .css .hljs-value,.hljs-arta .css .hljs-attribute{color:#aaa;}","ascetic":".hljs-ascetic{}.hljs-ascetic .hljs{display:block;padding:0.5em;background:white;color:black;}.hljs-ascetic .hljs-string,.hljs-ascetic .hljs-tag .hljs-value,.hljs-ascetic .hljs-filter .hljs-argument,.hljs-ascetic .hljs-addition,.hljs-ascetic .hljs-change,.hljs-ascetic .apache .hljs-tag,.hljs-ascetic .apache .hljs-cbracket,.hljs-ascetic .nginx .hljs-built_in,.hljs-ascetic .tex .hljs-formula{color:#888;}.hljs-ascetic .hljs-comment,.hljs-ascetic .hljs-template_comment,.hljs-ascetic .hljs-shebang,.hljs-ascetic .hljs-doctype,.hljs-ascetic .hljs-pi,.hljs-ascetic .hljs-javadoc,.hljs-ascetic .hljs-deletion,.hljs-ascetic .apache .hljs-sqbracket{color:#ccc;}.hljs-ascetic .hljs-keyword,.hljs-ascetic .hljs-tag .hljs-title,.hljs-ascetic .ini .hljs-title,.hljs-ascetic .lisp .hljs-title,.hljs-ascetic .clojure .hljs-title,.hljs-ascetic .http .hljs-title,.hljs-ascetic .nginx .hljs-title,.hljs-ascetic .css .hljs-tag,.hljs-ascetic .hljs-winutils,.hljs-ascetic .hljs-flow,.hl
|
|||
|
engine: hljs
|
|||
|
};
|
|||
|
|
|||
|
})()
|
|||
|
},{}],8:[function(require,module,exports){
|
|||
|
exports.addClass = function (element, className) {
|
|||
|
element.className = exports.getClasses(element)
|
|||
|
.concat([className])
|
|||
|
.join(' ');
|
|||
|
};
|
|||
|
|
|||
|
exports.removeClass = function (element, className) {
|
|||
|
element.className = exports.getClasses(element)
|
|||
|
.filter(function (klass) { return klass !== className; })
|
|||
|
.join(' ');
|
|||
|
};
|
|||
|
|
|||
|
exports.toggleClass = function (element, className) {
|
|||
|
var classes = exports.getClasses(element),
|
|||
|
index = classes.indexOf(className);
|
|||
|
|
|||
|
if (index !== -1) {
|
|||
|
classes.splice(index, 1);
|
|||
|
}
|
|||
|
else {
|
|||
|
classes.push(className);
|
|||
|
}
|
|||
|
|
|||
|
element.className = classes.join(' ');
|
|||
|
};
|
|||
|
|
|||
|
exports.getClasses = function (element) {
|
|||
|
return element.className
|
|||
|
.split(' ')
|
|||
|
.filter(function (s) { return s !== ''; });
|
|||
|
};
|
|||
|
|
|||
|
exports.hasClass = function (element, className) {
|
|||
|
return exports.getClasses(element).indexOf(className) !== -1;
|
|||
|
};
|
|||
|
|
|||
|
exports.getPrefixedProperty = function (element, propertyName) {
|
|||
|
var capitalizedPropertName = propertyName[0].toUpperCase() +
|
|||
|
propertyName.slice(1);
|
|||
|
|
|||
|
return element[propertyName] || element['moz' + capitalizedPropertName] ||
|
|||
|
element['webkit' + capitalizedPropertName];
|
|||
|
};
|
|||
|
|
|||
|
},{}],4:[function(require,module,exports){
|
|||
|
var EventEmitter = require('events').EventEmitter
|
|||
|
, highlighter = require('./highlighter')
|
|||
|
, converter = require('./converter')
|
|||
|
, Parser = require('./parser')
|
|||
|
, Slideshow = require('./models/slideshow')
|
|||
|
, SlideshowView = require('./views/slideshowView')
|
|||
|
, DefaultController = require('./controllers/defaultController')
|
|||
|
, Dom = require('./dom')
|
|||
|
, macros = require('./macros')
|
|||
|
;
|
|||
|
|
|||
|
module.exports = Api;
|
|||
|
|
|||
|
function Api (dom) {
|
|||
|
this.dom = dom || new Dom();
|
|||
|
this.macros = macros;
|
|||
|
}
|
|||
|
|
|||
|
// Expose highlighter to allow enumerating available styles and
|
|||
|
// including external language grammars
|
|||
|
Api.prototype.highlighter = highlighter;
|
|||
|
|
|||
|
Api.prototype.convert = function (markdown) {
|
|||
|
var parser = new Parser()
|
|||
|
, content = parser.parse(markdown || '', macros)[0].content
|
|||
|
;
|
|||
|
|
|||
|
return converter.convertMarkdown(content, {}, true);
|
|||
|
};
|
|||
|
|
|||
|
// Creates slideshow initialized from options
|
|||
|
Api.prototype.create = function (options) {
|
|||
|
var events
|
|||
|
, slideshow
|
|||
|
, slideshowView
|
|||
|
, controller
|
|||
|
;
|
|||
|
|
|||
|
options = applyDefaults(this.dom, options);
|
|||
|
|
|||
|
events = new EventEmitter();
|
|||
|
events.setMaxListeners(0);
|
|||
|
|
|||
|
slideshow = new Slideshow(events, options);
|
|||
|
slideshowView = new SlideshowView(events, this.dom, options.container, slideshow);
|
|||
|
controller = options.controller || new DefaultController(events, this.dom, slideshowView, options.navigation);
|
|||
|
|
|||
|
return slideshow;
|
|||
|
};
|
|||
|
|
|||
|
function applyDefaults (dom, options) {
|
|||
|
var sourceElement;
|
|||
|
|
|||
|
options = options || {};
|
|||
|
|
|||
|
if (options.hasOwnProperty('sourceUrl')) {
|
|||
|
var req = new dom.XMLHttpRequest();
|
|||
|
req.open('GET', options.sourceUrl, false);
|
|||
|
req.send();
|
|||
|
options.source = req.responseText.replace(/\r\n/g, '\n');
|
|||
|
}
|
|||
|
else if (!options.hasOwnProperty('source')) {
|
|||
|
sourceElement = dom.getElementById('source');
|
|||
|
if (sourceElement) {
|
|||
|
options.source = unescape(sourceElement.innerHTML);
|
|||
|
sourceElement.style.display = 'none';
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!(options.container instanceof window.HTMLElement)) {
|
|||
|
options.container = dom.getBodyElement();
|
|||
|
}
|
|||
|
|
|||
|
return options;
|
|||
|
}
|
|||
|
|
|||
|
function unescape (source) {
|
|||
|
source = source.replace(/&[l|g]t;/g,
|
|||
|
function (match) {
|
|||
|
return match === '<' ? '<' : '>';
|
|||
|
});
|
|||
|
|
|||
|
source = source.replace(/&/g, '&');
|
|||
|
source = source.replace(/"/g, '"');
|
|||
|
|
|||
|
return source;
|
|||
|
}
|
|||
|
|
|||
|
},{"events":1,"./highlighter":7,"./converter":9,"./parser":10,"./dom":11,"./controllers/defaultController":12,"./views/slideshowView":13,"./models/slideshow":14,"./macros":15}],11:[function(require,module,exports){
|
|||
|
module.exports = Dom;
|
|||
|
|
|||
|
function Dom () { }
|
|||
|
|
|||
|
Dom.prototype.XMLHttpRequest = XMLHttpRequest;
|
|||
|
|
|||
|
Dom.prototype.getHTMLElement = function () {
|
|||
|
return document.getElementsByTagName('html')[0];
|
|||
|
};
|
|||
|
|
|||
|
Dom.prototype.getBodyElement = function () {
|
|||
|
return document.body;
|
|||
|
};
|
|||
|
|
|||
|
Dom.prototype.getElementById = function (id) {
|
|||
|
return document.getElementById(id);
|
|||
|
};
|
|||
|
|
|||
|
Dom.prototype.getLocationHash = function () {
|
|||
|
return window.location.hash;
|
|||
|
};
|
|||
|
|
|||
|
Dom.prototype.setLocationHash = function (hash) {
|
|||
|
if (typeof window.history.replaceState === 'function') {
|
|||
|
window.history.replaceState(undefined, undefined, hash);
|
|||
|
}
|
|||
|
else {
|
|||
|
window.location.hash = hash;
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
},{}],15:[function(require,module,exports){
|
|||
|
var macros = module.exports = {};
|
|||
|
|
|||
|
macros.hello = function () {
|
|||
|
return 'hello!';
|
|||
|
};
|
|||
|
|
|||
|
},{}],10:[function(require,module,exports){
|
|||
|
(function(){var Lexer = require('./lexer');
|
|||
|
|
|||
|
module.exports = Parser;
|
|||
|
|
|||
|
function Parser () { }
|
|||
|
|
|||
|
/*
|
|||
|
* Parses source string into list of slides.
|
|||
|
*
|
|||
|
* Output format:
|
|||
|
*
|
|||
|
* [
|
|||
|
* // Per slide
|
|||
|
* {
|
|||
|
* // Properties
|
|||
|
* properties: {
|
|||
|
* name: 'value'
|
|||
|
* },
|
|||
|
* // Notes (optional, same format as content list)
|
|||
|
* notes: [...],
|
|||
|
* // Link definitions
|
|||
|
* links: {
|
|||
|
* id: { href: 'url', title: 'optional title' },
|
|||
|
* ...
|
|||
|
* ],
|
|||
|
* content: [
|
|||
|
* // Any content but content classes are represented as strings
|
|||
|
* 'plain text ',
|
|||
|
* // Content classes are represented as objects
|
|||
|
* { block: false, class: 'the-class', content: [...] },
|
|||
|
* { block: true, class: 'the-class', content: [...] },
|
|||
|
* ...
|
|||
|
* ]
|
|||
|
* },
|
|||
|
* ...
|
|||
|
* ]
|
|||
|
*/
|
|||
|
Parser.prototype.parse = function (src, macros) {
|
|||
|
var self = this,
|
|||
|
lexer = new Lexer(),
|
|||
|
tokens = lexer.lex(cleanInput(src)),
|
|||
|
slides = [],
|
|||
|
|
|||
|
// The last item on the stack contains the current slide or
|
|||
|
// content class we're currently appending content to.
|
|||
|
stack = [createSlide()];
|
|||
|
|
|||
|
macros = macros || {};
|
|||
|
|
|||
|
tokens.forEach(function (token) {
|
|||
|
switch (token.type) {
|
|||
|
case 'text':
|
|||
|
case 'code':
|
|||
|
case 'fences':
|
|||
|
// Text, code and fenced code tokens are appended to their
|
|||
|
// respective parents as string literals, and are only included
|
|||
|
// in the parse process in order to reason about structure
|
|||
|
// (like ignoring a slide separator inside fenced code).
|
|||
|
appendTo(stack[stack.length - 1], token.text);
|
|||
|
break;
|
|||
|
case 'def':
|
|||
|
// Link definition
|
|||
|
stack[0].links[token.id] = {
|
|||
|
href: token.href,
|
|||
|
title: token.title
|
|||
|
};
|
|||
|
break;
|
|||
|
case 'macro':
|
|||
|
// Macro
|
|||
|
var macro = macros[token.name];
|
|||
|
if (typeof macro !== 'function') {
|
|||
|
throw new Error('Macro "' + token.name + '" not found. ' +
|
|||
|
'You need to define macro using remark.macros[\'' +
|
|||
|
token.name + '\'] = function () { ... };');
|
|||
|
}
|
|||
|
var value = macro.apply(token.obj, token.args);
|
|||
|
if (typeof value === 'string') {
|
|||
|
value = self.parse(value, macros);
|
|||
|
appendTo(stack[stack.length - 1], value[0].content[0]);
|
|||
|
}
|
|||
|
else {
|
|||
|
appendTo(stack[stack.length - 1], value === undefined ?
|
|||
|
'' : value.toString());
|
|||
|
}
|
|||
|
break;
|
|||
|
case 'content_start':
|
|||
|
// Entering content class, so create stack entry for appending
|
|||
|
// upcoming content to.
|
|||
|
//
|
|||
|
// Lexer handles open/close bracket balance, so there's no need
|
|||
|
// to worry about there being a matching closing bracket.
|
|||
|
stack.push(createContentClass(token));
|
|||
|
break;
|
|||
|
case 'content_end':
|
|||
|
// Exiting content class, so remove entry from stack and
|
|||
|
// append to previous item (outer content class or slide).
|
|||
|
appendTo(stack[stack.length - 2], stack[stack.length - 1]);
|
|||
|
stack.pop();
|
|||
|
break;
|
|||
|
case 'separator':
|
|||
|
// Slide separator (--- or --), so add current slide to list of
|
|||
|
// slides and re-initialize stack with new, blank slide.
|
|||
|
slides.push(stack[0]);
|
|||
|
stack = [createSlide()];
|
|||
|
// Tag the new slide as a continued slide if the separator
|
|||
|
// used was -- instead of --- (2 vs. 3 dashes).
|
|||
|
stack[0].properties.continued = (token.text === '--').toString();
|
|||
|
break;
|
|||
|
case 'notes_separator':
|
|||
|
// Notes separator (???), so create empty content list on slide
|
|||
|
// in which all remaining slide content will be put.
|
|||
|
stack[0].notes = [];
|
|||
|
break;
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
// Push current slide to list of slides.
|
|||
|
slides.push(stack[0]);
|
|||
|
|
|||
|
slides.forEach(function (slide) {
|
|||
|
slide.content[0] = extractProperties(slide.content[0] || '', slide.properties);
|
|||
|
});
|
|||
|
|
|||
|
return slides.filter(function (slide) {
|
|||
|
var exclude = (slide.properties.exclude || '').toLowerCase();
|
|||
|
|
|||
|
if (exclude === 'true') {
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
return true;
|
|||
|
});
|
|||
|
};
|
|||
|
|
|||
|
function createSlide () {
|
|||
|
return {
|
|||
|
content: [],
|
|||
|
properties: {
|
|||
|
continued: 'false'
|
|||
|
},
|
|||
|
links: {}
|
|||
|
};
|
|||
|
}
|
|||
|
|
|||
|
function createContentClass (token) {
|
|||
|
return {
|
|||
|
class: token.classes.join(' '),
|
|||
|
block: token.block,
|
|||
|
content: []
|
|||
|
};
|
|||
|
}
|
|||
|
|
|||
|
function appendTo (element, content) {
|
|||
|
var target = element.content;
|
|||
|
|
|||
|
if (element.notes !== undefined) {
|
|||
|
target = element.notes;
|
|||
|
}
|
|||
|
|
|||
|
// If two string are added after one another, we can just as well
|
|||
|
// go ahead and concatenate them into a single string.
|
|||
|
var lastIdx = target.length - 1;
|
|||
|
if (typeof target[lastIdx] === 'string' && typeof content === 'string') {
|
|||
|
target[lastIdx] += content;
|
|||
|
}
|
|||
|
else {
|
|||
|
target.push(content);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function extractProperties (source, properties) {
|
|||
|
var propertyFinder = /^\n*([-\w]+):([^$\n]*)/i
|
|||
|
, match
|
|||
|
;
|
|||
|
|
|||
|
while ((match = propertyFinder.exec(source)) !== null) {
|
|||
|
source = source.substr(0, match.index) +
|
|||
|
source.substr(match.index + match[0].length);
|
|||
|
|
|||
|
properties[match[1].trim()] = match[2].trim();
|
|||
|
|
|||
|
propertyFinder.lastIndex = match.index;
|
|||
|
}
|
|||
|
|
|||
|
return source;
|
|||
|
}
|
|||
|
|
|||
|
function cleanInput(source) {
|
|||
|
// If all lines are indented, we should trim them all to the same point so that code doesn't
|
|||
|
// need to start at column 0 in the source (see GitHub Issue #105)
|
|||
|
|
|||
|
// Helper to extract captures from the regex
|
|||
|
var getMatchCaptures = function (source, pattern) {
|
|||
|
var results = [], match;
|
|||
|
while ((match = pattern.exec(source)) !== null)
|
|||
|
results.push(match[1]);
|
|||
|
return results;
|
|||
|
};
|
|||
|
|
|||
|
// Calculate the minimum leading whitespace
|
|||
|
// Ensure there's at least one char that's not newline nor whitespace to ignore empty and blank lines
|
|||
|
var leadingWhitespacePattern = /^([ \t]*)[^ \t\n]/gm;
|
|||
|
var whitespace = getMatchCaptures(source, leadingWhitespacePattern).map(function (s) { return s.length; });
|
|||
|
var minWhitespace = Math.min.apply(Math, whitespace);
|
|||
|
|
|||
|
// Trim off the exact amount of whitespace, or less for blank lines (non-empty)
|
|||
|
var trimWhitespacePattern = new RegExp('^[ \\t]{0,' + minWhitespace + '}', 'gm');
|
|||
|
return source.replace(trimWhitespacePattern, '');
|
|||
|
}
|
|||
|
|
|||
|
})()
|
|||
|
},{"./lexer":16}],13:[function(require,module,exports){
|
|||
|
var SlideView = require('./slideView')
|
|||
|
, Timer = require('components/timer')
|
|||
|
, NotesView = require('./notesView')
|
|||
|
, Scaler = require('../scaler')
|
|||
|
, resources = require('../resources')
|
|||
|
, utils = require('../utils')
|
|||
|
, printing = require('components/printing')
|
|||
|
;
|
|||
|
|
|||
|
module.exports = SlideshowView;
|
|||
|
|
|||
|
function SlideshowView (events, dom, containerElement, slideshow) {
|
|||
|
var self = this;
|
|||
|
|
|||
|
self.events = events;
|
|||
|
self.dom = dom;
|
|||
|
self.slideshow = slideshow;
|
|||
|
self.scaler = new Scaler(events, slideshow);
|
|||
|
self.slideViews = [];
|
|||
|
|
|||
|
self.configureContainerElement(containerElement);
|
|||
|
self.configureChildElements();
|
|||
|
|
|||
|
self.updateDimensions();
|
|||
|
self.scaleElements();
|
|||
|
self.updateSlideViews();
|
|||
|
|
|||
|
self.timer = new Timer(events, self.timerElement);
|
|||
|
|
|||
|
events.on('slidesChanged', function () {
|
|||
|
self.updateSlideViews();
|
|||
|
});
|
|||
|
|
|||
|
events.on('hideSlide', function (slideIndex) {
|
|||
|
// To make sure that there is only one element fading at a time,
|
|||
|
// remove the fading class from all slides before hiding
|
|||
|
// the new slide.
|
|||
|
self.elementArea.getElementsByClassName('remark-fading').forEach(function (slide) {
|
|||
|
utils.removeClass(slide, 'remark-fading');
|
|||
|
});
|
|||
|
self.hideSlide(slideIndex);
|
|||
|
});
|
|||
|
|
|||
|
events.on('showSlide', function (slideIndex) {
|
|||
|
self.showSlide(slideIndex);
|
|||
|
});
|
|||
|
|
|||
|
events.on('forcePresenterMode', function () {
|
|||
|
|
|||
|
if (!utils.hasClass(self.containerElement, 'remark-presenter-mode')) {
|
|||
|
utils.toggleClass(self.containerElement, 'remark-presenter-mode');
|
|||
|
self.scaleElements();
|
|||
|
printing.setPageOrientation('landscape');
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
events.on('togglePresenterMode', function () {
|
|||
|
utils.toggleClass(self.containerElement, 'remark-presenter-mode');
|
|||
|
self.scaleElements();
|
|||
|
|
|||
|
if (utils.hasClass(self.containerElement, 'remark-presenter-mode')) {
|
|||
|
printing.setPageOrientation('portrait');
|
|||
|
}
|
|||
|
else {
|
|||
|
printing.setPageOrientation('landscape');
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
events.on('toggleHelp', function () {
|
|||
|
utils.toggleClass(self.containerElement, 'remark-help-mode');
|
|||
|
});
|
|||
|
|
|||
|
events.on('toggleBlackout', function () {
|
|||
|
utils.toggleClass(self.containerElement, 'remark-blackout-mode');
|
|||
|
});
|
|||
|
|
|||
|
events.on('toggleMirrored', function () {
|
|||
|
utils.toggleClass(self.containerElement, 'remark-mirrored-mode');
|
|||
|
});
|
|||
|
|
|||
|
events.on('hideOverlay', function () {
|
|||
|
utils.removeClass(self.containerElement, 'remark-blackout-mode');
|
|||
|
utils.removeClass(self.containerElement, 'remark-help-mode');
|
|||
|
});
|
|||
|
|
|||
|
events.on('pause', function () {
|
|||
|
utils.toggleClass(self.containerElement, 'remark-pause-mode');
|
|||
|
});
|
|||
|
|
|||
|
events.on('resume', function () {
|
|||
|
utils.toggleClass(self.containerElement, 'remark-pause-mode');
|
|||
|
});
|
|||
|
|
|||
|
handleFullscreen(self);
|
|||
|
}
|
|||
|
|
|||
|
function handleFullscreen(self) {
|
|||
|
var requestFullscreen = utils.getPrefixedProperty(self.containerElement, 'requestFullScreen')
|
|||
|
, cancelFullscreen = utils.getPrefixedProperty(document, 'cancelFullScreen')
|
|||
|
;
|
|||
|
|
|||
|
self.events.on('toggleFullscreen', function () {
|
|||
|
var fullscreenElement = utils.getPrefixedProperty(document, 'fullscreenElement') ||
|
|||
|
utils.getPrefixedProperty(document, 'fullScreenElement');
|
|||
|
|
|||
|
if (!fullscreenElement && requestFullscreen) {
|
|||
|
requestFullscreen.call(self.containerElement, Element.ALLOW_KEYBOARD_INPUT);
|
|||
|
}
|
|||
|
else if (cancelFullscreen) {
|
|||
|
cancelFullscreen.call(document);
|
|||
|
}
|
|||
|
self.scaleElements();
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
SlideshowView.prototype.isEmbedded = function () {
|
|||
|
return this.containerElement !== this.dom.getBodyElement();
|
|||
|
};
|
|||
|
|
|||
|
SlideshowView.prototype.configureContainerElement = function (element) {
|
|||
|
var self = this;
|
|||
|
|
|||
|
self.containerElement = element;
|
|||
|
|
|||
|
utils.addClass(element, 'remark-container');
|
|||
|
|
|||
|
if (element === self.dom.getBodyElement()) {
|
|||
|
utils.addClass(self.dom.getHTMLElement(), 'remark-container');
|
|||
|
|
|||
|
forwardEvents(self.events, window, [
|
|||
|
'hashchange', 'resize', 'keydown', 'keypress', 'mousewheel',
|
|||
|
'message', 'DOMMouseScroll'
|
|||
|
]);
|
|||
|
forwardEvents(self.events, self.containerElement, [
|
|||
|
'touchstart', 'touchmove', 'touchend', 'click', 'contextmenu'
|
|||
|
]);
|
|||
|
}
|
|||
|
else {
|
|||
|
element.style.position = 'absolute';
|
|||
|
element.tabIndex = -1;
|
|||
|
|
|||
|
forwardEvents(self.events, window, ['resize']);
|
|||
|
forwardEvents(self.events, element, [
|
|||
|
'keydown', 'keypress', 'mousewheel',
|
|||
|
'touchstart', 'touchmove', 'touchend'
|
|||
|
]);
|
|||
|
}
|
|||
|
|
|||
|
// Tap event is handled in slideshow view
|
|||
|
// rather than controller as knowledge of
|
|||
|
// container width is needed to determine
|
|||
|
// whether to move backwards or forwards
|
|||
|
self.events.on('tap', function (endX) {
|
|||
|
if (endX < self.getContainerWidth() / 2) {
|
|||
|
self.slideshow.gotoPreviousSlide();
|
|||
|
}
|
|||
|
else {
|
|||
|
self.slideshow.gotoNextSlide();
|
|||
|
}
|
|||
|
});
|
|||
|
};
|
|||
|
|
|||
|
function forwardEvents (target, source, events) {
|
|||
|
events.forEach(function (eventName) {
|
|||
|
source.addEventListener(eventName, function () {
|
|||
|
var args = Array.prototype.slice.call(arguments);
|
|||
|
target.emit.apply(target, [eventName].concat(args));
|
|||
|
});
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
SlideshowView.prototype.configureChildElements = function () {
|
|||
|
var self = this;
|
|||
|
|
|||
|
self.containerElement.innerHTML += resources.containerLayout;
|
|||
|
|
|||
|
self.elementArea = self.containerElement.getElementsByClassName('remark-slides-area')[0];
|
|||
|
self.previewArea = self.containerElement.getElementsByClassName('remark-preview-area')[0];
|
|||
|
self.notesArea = self.containerElement.getElementsByClassName('remark-notes-area')[0];
|
|||
|
|
|||
|
self.notesView = new NotesView (self.events, self.notesArea, function () {
|
|||
|
return self.slideViews;
|
|||
|
});
|
|||
|
|
|||
|
self.backdropElement = self.containerElement.getElementsByClassName('remark-backdrop')[0];
|
|||
|
self.helpElement = self.containerElement.getElementsByClassName('remark-help')[0];
|
|||
|
|
|||
|
self.timerElement = self.notesArea.getElementsByClassName('remark-toolbar-timer')[0];
|
|||
|
self.pauseElement = self.containerElement.getElementsByClassName('remark-pause')[0];
|
|||
|
|
|||
|
self.events.on('propertiesChanged', function (changes) {
|
|||
|
if (changes.hasOwnProperty('ratio')) {
|
|||
|
self.updateDimensions();
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
self.events.on('resize', onResize);
|
|||
|
|
|||
|
printing.init();
|
|||
|
printing.on('print', onPrint);
|
|||
|
|
|||
|
function onResize () {
|
|||
|
self.scaleElements();
|
|||
|
}
|
|||
|
|
|||
|
function onPrint (e) {
|
|||
|
var slideHeight;
|
|||
|
|
|||
|
if (e.isPortrait) {
|
|||
|
slideHeight = e.pageHeight * 0.4;
|
|||
|
}
|
|||
|
else {
|
|||
|
slideHeight = e.pageHeight;
|
|||
|
}
|
|||
|
|
|||
|
self.slideViews.forEach(function (slideView) {
|
|||
|
slideView.scale({
|
|||
|
clientWidth: e.pageWidth,
|
|||
|
clientHeight: slideHeight
|
|||
|
});
|
|||
|
|
|||
|
if (e.isPortrait) {
|
|||
|
slideView.scalingElement.style.top = '20px';
|
|||
|
slideView.notesElement.style.top = slideHeight + 40 + 'px';
|
|||
|
}
|
|||
|
});
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
SlideshowView.prototype.updateSlideViews = function () {
|
|||
|
var self = this;
|
|||
|
|
|||
|
self.slideViews.forEach(function (slideView) {
|
|||
|
self.elementArea.removeChild(slideView.containerElement);
|
|||
|
});
|
|||
|
|
|||
|
self.slideViews = self.slideshow.getSlides().map(function (slide) {
|
|||
|
return new SlideView(self.events, self.slideshow, self.scaler, slide);
|
|||
|
});
|
|||
|
|
|||
|
self.slideViews.forEach(function (slideView) {
|
|||
|
self.elementArea.appendChild(slideView.containerElement);
|
|||
|
});
|
|||
|
|
|||
|
self.updateDimensions();
|
|||
|
|
|||
|
if (self.slideshow.getCurrentSlideIndex() > -1) {
|
|||
|
self.showSlide(self.slideshow.getCurrentSlideIndex());
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
SlideshowView.prototype.scaleSlideBackgroundImages = function (dimensions) {
|
|||
|
var self = this;
|
|||
|
|
|||
|
self.slideViews.forEach(function (slideView) {
|
|||
|
slideView.scaleBackgroundImage(dimensions);
|
|||
|
});
|
|||
|
};
|
|||
|
|
|||
|
SlideshowView.prototype.showSlide = function (slideIndex) {
|
|||
|
var self = this
|
|||
|
, slideView = self.slideViews[slideIndex]
|
|||
|
, nextSlideView = self.slideViews[slideIndex + 1]
|
|||
|
;
|
|||
|
|
|||
|
self.events.emit("beforeShowSlide", slideIndex);
|
|||
|
|
|||
|
slideView.show();
|
|||
|
|
|||
|
if (nextSlideView) {
|
|||
|
self.previewArea.innerHTML = nextSlideView.containerElement.outerHTML;
|
|||
|
}
|
|||
|
else {
|
|||
|
self.previewArea.innerHTML = '';
|
|||
|
}
|
|||
|
|
|||
|
self.events.emit("afterShowSlide", slideIndex);
|
|||
|
};
|
|||
|
|
|||
|
SlideshowView.prototype.hideSlide = function (slideIndex) {
|
|||
|
var self = this
|
|||
|
, slideView = self.slideViews[slideIndex]
|
|||
|
;
|
|||
|
|
|||
|
self.events.emit("beforeHideSlide", slideIndex);
|
|||
|
slideView.hide();
|
|||
|
self.events.emit("afterHideSlide", slideIndex);
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
SlideshowView.prototype.updateDimensions = function () {
|
|||
|
var self = this
|
|||
|
, dimensions = self.scaler.dimensions
|
|||
|
;
|
|||
|
|
|||
|
self.helpElement.style.width = dimensions.width + 'px';
|
|||
|
self.helpElement.style.height = dimensions.height + 'px';
|
|||
|
|
|||
|
self.scaleSlideBackgroundImages(dimensions);
|
|||
|
self.scaleElements();
|
|||
|
};
|
|||
|
|
|||
|
SlideshowView.prototype.scaleElements = function () {
|
|||
|
var self = this;
|
|||
|
|
|||
|
self.slideViews.forEach(function (slideView) {
|
|||
|
slideView.scale(self.elementArea);
|
|||
|
});
|
|||
|
|
|||
|
if (self.previewArea.children.length) {
|
|||
|
self.scaler.scaleToFit(self.previewArea.children[0].children[0], self.previewArea);
|
|||
|
}
|
|||
|
self.scaler.scaleToFit(self.helpElement, self.containerElement);
|
|||
|
self.scaler.scaleToFit(self.pauseElement, self.containerElement);
|
|||
|
};
|
|||
|
|
|||
|
},{"components/timer":"yAcg0L","components/printing":"nZr0zp","./slideView":17,"./notesView":18,"../resources":6,"../utils":8,"../scaler":19}],14:[function(require,module,exports){
|
|||
|
var Navigation = require('./slideshow/navigation')
|
|||
|
, Events = require('./slideshow/events')
|
|||
|
, utils = require('../utils')
|
|||
|
, Slide = require('./slide')
|
|||
|
, Parser = require('../parser')
|
|||
|
, macros = require('../macros')
|
|||
|
;
|
|||
|
|
|||
|
module.exports = Slideshow;
|
|||
|
|
|||
|
function Slideshow (events, options) {
|
|||
|
var self = this
|
|||
|
, slides = []
|
|||
|
, links = {}
|
|||
|
;
|
|||
|
|
|||
|
options = options || {};
|
|||
|
|
|||
|
// Extend slideshow functionality
|
|||
|
Events.call(self, events);
|
|||
|
Navigation.call(self, events);
|
|||
|
|
|||
|
self.loadFromString = loadFromString;
|
|||
|
self.update = update;
|
|||
|
self.getLinks = getLinks;
|
|||
|
self.getSlides = getSlides;
|
|||
|
self.getSlideCount = getSlideCount;
|
|||
|
self.getSlideByName = getSlideByName;
|
|||
|
|
|||
|
self.togglePresenterMode = togglePresenterMode;
|
|||
|
self.toggleHelp = toggleHelp;
|
|||
|
self.toggleBlackout = toggleBlackout;
|
|||
|
self.toggleMirrored = toggleMirrored;
|
|||
|
self.toggleFullscreen = toggleFullscreen;
|
|||
|
self.createClone = createClone;
|
|||
|
|
|||
|
self.resetTimer = resetTimer;
|
|||
|
|
|||
|
self.getRatio = getOrDefault('ratio', '4:3');
|
|||
|
self.getHighlightStyle = getOrDefault('highlightStyle', 'default');
|
|||
|
self.getHighlightLanguage = getOrDefault('highlightLanguage', '');
|
|||
|
self.getSlideNumberFormat = getOrDefault('slideNumberFormat', '%current% / %total%');
|
|||
|
|
|||
|
loadFromString(options.source);
|
|||
|
|
|||
|
events.on('toggleBlackout', function () {
|
|||
|
if (self.clone && !self.clone.closed) {
|
|||
|
self.clone.postMessage('toggleBlackout', '*');
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
function loadFromString (source) {
|
|||
|
source = source || '';
|
|||
|
|
|||
|
slides = createSlides(source, options);
|
|||
|
expandVariables(slides);
|
|||
|
|
|||
|
links = {};
|
|||
|
slides.forEach(function (slide) {
|
|||
|
for (var id in slide.links) {
|
|||
|
if (slide.links.hasOwnProperty(id)) {
|
|||
|
links[id] = slide.links[id];
|
|||
|
}
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
events.emit('slidesChanged');
|
|||
|
}
|
|||
|
|
|||
|
function update () {
|
|||
|
events.emit('resize');
|
|||
|
}
|
|||
|
|
|||
|
function getLinks () {
|
|||
|
return links;
|
|||
|
}
|
|||
|
|
|||
|
function getSlides () {
|
|||
|
return slides.map(function (slide) { return slide; });
|
|||
|
}
|
|||
|
|
|||
|
function getSlideCount () {
|
|||
|
return slides.length;
|
|||
|
}
|
|||
|
|
|||
|
function getSlideByName (name) {
|
|||
|
return slides.byName[name];
|
|||
|
}
|
|||
|
|
|||
|
function togglePresenterMode () {
|
|||
|
events.emit('togglePresenterMode');
|
|||
|
}
|
|||
|
|
|||
|
function toggleHelp () {
|
|||
|
events.emit('toggleHelp');
|
|||
|
}
|
|||
|
|
|||
|
function toggleBlackout () {
|
|||
|
events.emit('toggleBlackout');
|
|||
|
}
|
|||
|
|
|||
|
function toggleMirrored() {
|
|||
|
events.emit('toggleMirrored');
|
|||
|
}
|
|||
|
|
|||
|
function toggleFullscreen () {
|
|||
|
events.emit('toggleFullscreen');
|
|||
|
}
|
|||
|
|
|||
|
function createClone () {
|
|||
|
events.emit('createClone');
|
|||
|
}
|
|||
|
|
|||
|
function resetTimer () {
|
|||
|
events.emit('resetTimer');
|
|||
|
}
|
|||
|
|
|||
|
function getOrDefault (key, defaultValue) {
|
|||
|
return function () {
|
|||
|
if (options[key] === undefined) {
|
|||
|
return defaultValue;
|
|||
|
}
|
|||
|
|
|||
|
return options[key];
|
|||
|
};
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function createSlides (slideshowSource, options) {
|
|||
|
var parser = new Parser()
|
|||
|
, parsedSlides = parser.parse(slideshowSource, macros)
|
|||
|
, slides = []
|
|||
|
, byName = {}
|
|||
|
, layoutSlide
|
|||
|
;
|
|||
|
|
|||
|
slides.byName = {};
|
|||
|
|
|||
|
parsedSlides.forEach(function (slide, i) {
|
|||
|
var template, slideViewModel;
|
|||
|
|
|||
|
if (slide.properties.continued === 'true' && i > 0) {
|
|||
|
template = slides[slides.length - 1];
|
|||
|
}
|
|||
|
else if (byName[slide.properties.template]) {
|
|||
|
template = byName[slide.properties.template];
|
|||
|
}
|
|||
|
else if (slide.properties.layout === 'false') {
|
|||
|
layoutSlide = undefined;
|
|||
|
}
|
|||
|
else if (layoutSlide && slide.properties.layout !== 'true') {
|
|||
|
template = layoutSlide;
|
|||
|
}
|
|||
|
|
|||
|
if (slide.properties.continued === 'true' &&
|
|||
|
options.countIncrementalSlides === false &&
|
|||
|
slide.properties.count === undefined) {
|
|||
|
slide.properties.count = 'false';
|
|||
|
}
|
|||
|
|
|||
|
slideViewModel = new Slide(slides.length, slide, template);
|
|||
|
|
|||
|
if (slide.properties.layout === 'true') {
|
|||
|
layoutSlide = slideViewModel;
|
|||
|
}
|
|||
|
|
|||
|
if (slide.properties.name) {
|
|||
|
byName[slide.properties.name] = slideViewModel;
|
|||
|
}
|
|||
|
|
|||
|
if (slide.properties.layout !== 'true') {
|
|||
|
slides.push(slideViewModel);
|
|||
|
if (slide.properties.name) {
|
|||
|
slides.byName[slide.properties.name] = slideViewModel;
|
|||
|
}
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
return slides;
|
|||
|
}
|
|||
|
|
|||
|
function expandVariables (slides) {
|
|||
|
slides.forEach(function (slide) {
|
|||
|
slide.expandVariables();
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
},{"./slideshow/events":20,"./slideshow/navigation":21,"./slide":22,"../utils":8,"../parser":10,"../macros":15}],12:[function(require,module,exports){
|
|||
|
(function(){// Allow override of global `location`
|
|||
|
/* global location:true */
|
|||
|
|
|||
|
module.exports = Controller;
|
|||
|
|
|||
|
var keyboard = require('./inputs/keyboard')
|
|||
|
, mouse = require('./inputs/mouse')
|
|||
|
, touch = require('./inputs/touch')
|
|||
|
, message = require('./inputs/message')
|
|||
|
, location = require('./inputs/location')
|
|||
|
;
|
|||
|
|
|||
|
function Controller (events, dom, slideshowView, options) {
|
|||
|
options = options || {};
|
|||
|
|
|||
|
message.register(events);
|
|||
|
location.register(events, dom, slideshowView);
|
|||
|
keyboard.register(events);
|
|||
|
mouse.register(events, options);
|
|||
|
touch.register(events, options);
|
|||
|
|
|||
|
addApiEventListeners(events, slideshowView, options);
|
|||
|
}
|
|||
|
|
|||
|
function addApiEventListeners(events, slideshowView, options) {
|
|||
|
events.on('pause', function(event) {
|
|||
|
keyboard.unregister(events);
|
|||
|
mouse.unregister(events);
|
|||
|
touch.unregister(events);
|
|||
|
});
|
|||
|
|
|||
|
events.on('resume', function(event) {
|
|||
|
keyboard.register(events);
|
|||
|
mouse.register(events, options);
|
|||
|
touch.register(events, options);
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
})()
|
|||
|
},{"./inputs/keyboard":23,"./inputs/mouse":24,"./inputs/touch":25,"./inputs/message":26,"./inputs/location":27}],16:[function(require,module,exports){
|
|||
|
module.exports = Lexer;
|
|||
|
|
|||
|
var CODE = 1,
|
|||
|
INLINE_CODE = 2,
|
|||
|
CONTENT = 3,
|
|||
|
FENCES = 4,
|
|||
|
DEF = 5,
|
|||
|
DEF_HREF = 6,
|
|||
|
DEF_TITLE = 7,
|
|||
|
MACRO = 8,
|
|||
|
MACRO_ARGS = 9,
|
|||
|
MACRO_OBJ = 10,
|
|||
|
SEPARATOR = 11,
|
|||
|
NOTES_SEPARATOR = 12;
|
|||
|
|
|||
|
var regexByName = {
|
|||
|
CODE: /(?:^|\n)( {4}[^\n]+\n*)+/,
|
|||
|
INLINE_CODE: /`([^`]+?)`/,
|
|||
|
CONTENT: /(?:\\)?((?:\.[a-zA-Z_\-][a-zA-Z\-_0-9]*)+)\[/,
|
|||
|
FENCES: /(?:^|\n) *(`{3,}|~{3,}) *(?:\S+)? *\n(?:[\s\S]+?)\s*\4 *(?:\n+|$)/,
|
|||
|
DEF: /(?:^|\n) *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
|
|||
|
MACRO: /!\[:([^\] ]+)([^\]]*)\](?:\(([^\)]*)\))?/,
|
|||
|
SEPARATOR: /(?:^|\n)(---?)(?:\n|$)/,
|
|||
|
NOTES_SEPARATOR: /(?:^|\n)(\?{3})(?:\n|$)/
|
|||
|
};
|
|||
|
|
|||
|
var block = replace(/CODE|INLINE_CODE|CONTENT|FENCES|DEF|MACRO|SEPARATOR|NOTES_SEPARATOR/, regexByName),
|
|||
|
inline = replace(/CODE|INLINE_CODE|CONTENT|FENCES|DEF|MACRO/, regexByName);
|
|||
|
|
|||
|
function Lexer () { }
|
|||
|
|
|||
|
Lexer.prototype.lex = function (src) {
|
|||
|
var tokens = lex(src, block),
|
|||
|
i;
|
|||
|
|
|||
|
for (i = tokens.length - 2; i >= 0; i--) {
|
|||
|
if (tokens[i].type === 'text' && tokens[i+1].type === 'text') {
|
|||
|
tokens[i].text += tokens[i+1].text;
|
|||
|
tokens.splice(i+1, 1);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return tokens;
|
|||
|
};
|
|||
|
|
|||
|
function lex (src, regex, tokens) {
|
|||
|
var cap, text;
|
|||
|
|
|||
|
tokens = tokens || [];
|
|||
|
|
|||
|
while ((cap = regex.exec(src)) !== null) {
|
|||
|
if (cap.index > 0) {
|
|||
|
tokens.push({
|
|||
|
type: 'text',
|
|||
|
text: src.substring(0, cap.index)
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
if (cap[CODE]) {
|
|||
|
tokens.push({
|
|||
|
type: 'code',
|
|||
|
text: cap[0]
|
|||
|
});
|
|||
|
}
|
|||
|
else if (cap[INLINE_CODE]) {
|
|||
|
tokens.push({
|
|||
|
type: 'text',
|
|||
|
text: cap[0]
|
|||
|
});
|
|||
|
}
|
|||
|
else if (cap[FENCES]) {
|
|||
|
tokens.push({
|
|||
|
type: 'fences',
|
|||
|
text: cap[0]
|
|||
|
});
|
|||
|
}
|
|||
|
else if (cap[DEF]) {
|
|||
|
tokens.push({
|
|||
|
type: 'def',
|
|||
|
id: cap[DEF],
|
|||
|
href: cap[DEF_HREF],
|
|||
|
title: cap[DEF_TITLE]
|
|||
|
});
|
|||
|
}
|
|||
|
else if (cap[MACRO]) {
|
|||
|
tokens.push({
|
|||
|
type: 'macro',
|
|||
|
name: cap[MACRO],
|
|||
|
args: (cap[MACRO_ARGS] || '').split(',').map(trim),
|
|||
|
obj: cap[MACRO_OBJ]
|
|||
|
});
|
|||
|
}
|
|||
|
else if (cap[SEPARATOR]) {
|
|||
|
tokens.push({
|
|||
|
type: 'separator',
|
|||
|
text: cap[SEPARATOR]
|
|||
|
});
|
|||
|
}
|
|||
|
else if (cap[NOTES_SEPARATOR]) {
|
|||
|
tokens.push({
|
|||
|
type: 'notes_separator',
|
|||
|
text: cap[NOTES_SEPARATOR]
|
|||
|
});
|
|||
|
}
|
|||
|
else if (cap[CONTENT]) {
|
|||
|
text = getTextInBrackets(src, cap.index + cap[0].length);
|
|||
|
if (text !== undefined) {
|
|||
|
src = src.substring(text.length + 1);
|
|||
|
|
|||
|
if (cap[0][0] !== '\\') {
|
|||
|
tokens.push({
|
|||
|
type: 'content_start',
|
|||
|
classes: cap[CONTENT].substring(1).split('.'),
|
|||
|
block: text.indexOf('\n') !== -1
|
|||
|
});
|
|||
|
lex(text, inline, tokens);
|
|||
|
tokens.push({
|
|||
|
type: 'content_end',
|
|||
|
block: text.indexOf('\n') !== -1
|
|||
|
});
|
|||
|
}
|
|||
|
else {
|
|||
|
tokens.push({
|
|||
|
type: 'text',
|
|||
|
text: cap[0].substring(1) + text + ']'
|
|||
|
});
|
|||
|
}
|
|||
|
}
|
|||
|
else {
|
|||
|
tokens.push({
|
|||
|
type: 'text',
|
|||
|
text: cap[0]
|
|||
|
});
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
src = src.substring(cap.index + cap[0].length);
|
|||
|
}
|
|||
|
|
|||
|
if (src || (!src && tokens.length === 0)) {
|
|||
|
tokens.push({
|
|||
|
type: 'text',
|
|||
|
text: src
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
return tokens;
|
|||
|
}
|
|||
|
|
|||
|
function replace (regex, replacements) {
|
|||
|
return new RegExp(regex.source.replace(/\w{2,}/g, function (key) {
|
|||
|
return replacements[key].source;
|
|||
|
}));
|
|||
|
}
|
|||
|
|
|||
|
function trim (text) {
|
|||
|
if (typeof text === 'string') {
|
|||
|
return text.trim();
|
|||
|
}
|
|||
|
|
|||
|
return text;
|
|||
|
}
|
|||
|
|
|||
|
function getTextInBrackets (src, offset) {
|
|||
|
var depth = 1,
|
|||
|
pos = offset,
|
|||
|
chr;
|
|||
|
|
|||
|
while (depth > 0 && pos < src.length) {
|
|||
|
chr = src[pos++];
|
|||
|
depth += (chr === '[' && 1) || (chr === ']' && -1) || 0;
|
|||
|
}
|
|||
|
|
|||
|
if (depth === 0) {
|
|||
|
src = src.substr(offset, pos - offset - 1);
|
|||
|
return src;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
},{}],24:[function(require,module,exports){
|
|||
|
exports.register = function (events, options) {
|
|||
|
addMouseEventListeners(events, options);
|
|||
|
};
|
|||
|
|
|||
|
exports.unregister = function (events) {
|
|||
|
removeMouseEventListeners(events);
|
|||
|
};
|
|||
|
|
|||
|
function addMouseEventListeners (events, options) {
|
|||
|
if (options.click) {
|
|||
|
events.on('click', function (event) {
|
|||
|
if (event.target.nodeName === 'A') {
|
|||
|
// Don't interfere when clicking link
|
|||
|
return;
|
|||
|
}
|
|||
|
else if (event.button === 0) {
|
|||
|
events.emit('gotoNextSlide');
|
|||
|
}
|
|||
|
});
|
|||
|
events.on('contextmenu', function (event) {
|
|||
|
if (event.target.nodeName === 'A') {
|
|||
|
// Don't interfere when right-clicking link
|
|||
|
return;
|
|||
|
}
|
|||
|
event.preventDefault();
|
|||
|
events.emit('gotoPreviousSlide');
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
if (options.scroll !== false) {
|
|||
|
var scrollHandler = function (event) {
|
|||
|
if (event.wheelDeltaY > 0 || event.detail < 0) {
|
|||
|
events.emit('gotoPreviousSlide');
|
|||
|
}
|
|||
|
else if (event.wheelDeltaY < 0 || event.detail > 0) {
|
|||
|
events.emit('gotoNextSlide');
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
// IE9, Chrome, Safari, Opera
|
|||
|
events.on('mousewheel', scrollHandler);
|
|||
|
// Firefox
|
|||
|
events.on('DOMMouseScroll', scrollHandler);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function removeMouseEventListeners(events) {
|
|||
|
events.removeAllListeners('click');
|
|||
|
events.removeAllListeners('contextmenu');
|
|||
|
events.removeAllListeners('mousewheel');
|
|||
|
}
|
|||
|
|
|||
|
},{}],23:[function(require,module,exports){
|
|||
|
exports.register = function (events) {
|
|||
|
addKeyboardEventListeners(events);
|
|||
|
};
|
|||
|
|
|||
|
exports.unregister = function (events) {
|
|||
|
removeKeyboardEventListeners(events);
|
|||
|
};
|
|||
|
|
|||
|
function addKeyboardEventListeners (events) {
|
|||
|
events.on('keydown', function (event) {
|
|||
|
if (event.metaKey || event.ctrlKey) {
|
|||
|
// Bail out if meta or ctrl key was pressed
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
switch (event.keyCode) {
|
|||
|
case 33: // Page up
|
|||
|
case 37: // Left
|
|||
|
case 38: // Up
|
|||
|
events.emit('gotoPreviousSlide');
|
|||
|
break;
|
|||
|
case 32: // Space
|
|||
|
case 34: // Page down
|
|||
|
case 39: // Right
|
|||
|
case 40: // Down
|
|||
|
events.emit('gotoNextSlide');
|
|||
|
break;
|
|||
|
case 36: // Home
|
|||
|
events.emit('gotoFirstSlide');
|
|||
|
break;
|
|||
|
case 35: // End
|
|||
|
events.emit('gotoLastSlide');
|
|||
|
break;
|
|||
|
case 27: // Escape
|
|||
|
events.emit('hideOverlay');
|
|||
|
break;
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
events.on('keypress', function (event) {
|
|||
|
if (event.metaKey || event.ctrlKey) {
|
|||
|
// Bail out if meta or ctrl key was pressed
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
switch (String.fromCharCode(event.which)) {
|
|||
|
case 'j':
|
|||
|
events.emit('gotoNextSlide');
|
|||
|
break;
|
|||
|
case 'k':
|
|||
|
events.emit('gotoPreviousSlide');
|
|||
|
break;
|
|||
|
case 'b':
|
|||
|
events.emit('toggleBlackout');
|
|||
|
break;
|
|||
|
case 'm':
|
|||
|
events.emit('toggleMirrored');
|
|||
|
break;
|
|||
|
case 'c':
|
|||
|
events.emit('createClone');
|
|||
|
break;
|
|||
|
case 'p':
|
|||
|
events.emit('togglePresenterMode');
|
|||
|
break;
|
|||
|
case 'f':
|
|||
|
events.emit('toggleFullscreen');
|
|||
|
break;
|
|||
|
case 't':
|
|||
|
events.emit('resetTimer');
|
|||
|
break;
|
|||
|
case 'h':
|
|||
|
case '?':
|
|||
|
events.emit('toggleHelp');
|
|||
|
break;
|
|||
|
}
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
function removeKeyboardEventListeners(events) {
|
|||
|
events.removeAllListeners("keydown");
|
|||
|
events.removeAllListeners("keypress");
|
|||
|
}
|
|||
|
|
|||
|
},{}],25:[function(require,module,exports){
|
|||
|
exports.register = function (events, options) {
|
|||
|
addTouchEventListeners(events, options);
|
|||
|
};
|
|||
|
|
|||
|
exports.unregister = function (events) {
|
|||
|
removeTouchEventListeners(events);
|
|||
|
};
|
|||
|
|
|||
|
function addTouchEventListeners (events, options) {
|
|||
|
var touch
|
|||
|
, startX
|
|||
|
, endX
|
|||
|
;
|
|||
|
|
|||
|
if (options.touch === false) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
var isTap = function () {
|
|||
|
return Math.abs(startX - endX) < 10;
|
|||
|
};
|
|||
|
|
|||
|
var handleTap = function () {
|
|||
|
events.emit('tap', endX);
|
|||
|
};
|
|||
|
|
|||
|
var handleSwipe = function () {
|
|||
|
if (startX > endX) {
|
|||
|
events.emit('gotoNextSlide');
|
|||
|
}
|
|||
|
else {
|
|||
|
events.emit('gotoPreviousSlide');
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
events.on('touchstart', function (event) {
|
|||
|
touch = event.touches[0];
|
|||
|
startX = touch.clientX;
|
|||
|
});
|
|||
|
|
|||
|
events.on('touchend', function (event) {
|
|||
|
if (event.target.nodeName.toUpperCase() === 'A') {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
touch = event.changedTouches[0];
|
|||
|
endX = touch.clientX;
|
|||
|
|
|||
|
if (isTap()) {
|
|||
|
handleTap();
|
|||
|
}
|
|||
|
else {
|
|||
|
handleSwipe();
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
events.on('touchmove', function (event) {
|
|||
|
event.preventDefault();
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
function removeTouchEventListeners(events) {
|
|||
|
events.removeAllListeners("touchstart");
|
|||
|
events.removeAllListeners("touchend");
|
|||
|
events.removeAllListeners("touchmove");
|
|||
|
}
|
|||
|
|
|||
|
},{}],21:[function(require,module,exports){
|
|||
|
module.exports = Navigation;
|
|||
|
|
|||
|
function Navigation (events) {
|
|||
|
var self = this
|
|||
|
, currentSlideIndex = -1
|
|||
|
, started = null
|
|||
|
;
|
|||
|
|
|||
|
self.getCurrentSlideIndex = getCurrentSlideIndex;
|
|||
|
self.gotoSlide = gotoSlide;
|
|||
|
self.gotoPreviousSlide = gotoPreviousSlide;
|
|||
|
self.gotoNextSlide = gotoNextSlide;
|
|||
|
self.gotoFirstSlide = gotoFirstSlide;
|
|||
|
self.gotoLastSlide = gotoLastSlide;
|
|||
|
self.pause = pause;
|
|||
|
self.resume = resume;
|
|||
|
|
|||
|
events.on('gotoSlide', gotoSlide);
|
|||
|
events.on('gotoPreviousSlide', gotoPreviousSlide);
|
|||
|
events.on('gotoNextSlide', gotoNextSlide);
|
|||
|
events.on('gotoFirstSlide', gotoFirstSlide);
|
|||
|
events.on('gotoLastSlide', gotoLastSlide);
|
|||
|
|
|||
|
events.on('slidesChanged', function () {
|
|||
|
if (currentSlideIndex > self.getSlideCount()) {
|
|||
|
currentSlideIndex = self.getSlideCount();
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
events.on('createClone', function () {
|
|||
|
if (!self.clone || self.clone.closed) {
|
|||
|
self.clone = window.open(location.href, '_blank', 'location=no');
|
|||
|
}
|
|||
|
else {
|
|||
|
self.clone.focus();
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
events.on('resetTimer', function() {
|
|||
|
started = false;
|
|||
|
});
|
|||
|
|
|||
|
function pause () {
|
|||
|
events.emit('pause');
|
|||
|
}
|
|||
|
|
|||
|
function resume () {
|
|||
|
events.emit('resume');
|
|||
|
}
|
|||
|
|
|||
|
function getCurrentSlideIndex () {
|
|||
|
return currentSlideIndex;
|
|||
|
}
|
|||
|
|
|||
|
function gotoSlideByIndex(slideIndex, noMessage) {
|
|||
|
var alreadyOnSlide = slideIndex === currentSlideIndex
|
|||
|
, slideOutOfRange = slideIndex < 0 || slideIndex > self.getSlideCount()-1
|
|||
|
;
|
|||
|
|
|||
|
if (noMessage === undefined) noMessage = false;
|
|||
|
|
|||
|
if (alreadyOnSlide || slideOutOfRange) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (currentSlideIndex !== -1) {
|
|||
|
events.emit('hideSlide', currentSlideIndex, false);
|
|||
|
}
|
|||
|
|
|||
|
// Use some tri-state logic here.
|
|||
|
// null = We haven't shown the first slide yet.
|
|||
|
// false = We've shown the initial slide, but we haven't progressed beyond that.
|
|||
|
// true = We've issued the first slide change command.
|
|||
|
if (started === null) {
|
|||
|
started = false;
|
|||
|
} else if (started === false) {
|
|||
|
// We've shown the initial slide previously - that means this is a
|
|||
|
// genuine move to a new slide.
|
|||
|
events.emit('start');
|
|||
|
started = true;
|
|||
|
}
|
|||
|
|
|||
|
events.emit('showSlide', slideIndex);
|
|||
|
|
|||
|
currentSlideIndex = slideIndex;
|
|||
|
|
|||
|
events.emit('slideChanged', slideIndex + 1);
|
|||
|
|
|||
|
if (!noMessage) {
|
|||
|
if (self.clone && !self.clone.closed) {
|
|||
|
self.clone.postMessage('gotoSlide:' + (currentSlideIndex + 1), '*');
|
|||
|
}
|
|||
|
|
|||
|
if (window.opener) {
|
|||
|
window.opener.postMessage('gotoSlide:' + (currentSlideIndex + 1), '*');
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function gotoSlide (slideNoOrName, noMessage) {
|
|||
|
var slideIndex = getSlideIndex(slideNoOrName);
|
|||
|
|
|||
|
gotoSlideByIndex(slideIndex, noMessage);
|
|||
|
}
|
|||
|
|
|||
|
function gotoPreviousSlide() {
|
|||
|
gotoSlideByIndex(currentSlideIndex - 1);
|
|||
|
}
|
|||
|
|
|||
|
function gotoNextSlide() {
|
|||
|
gotoSlideByIndex(currentSlideIndex + 1);
|
|||
|
}
|
|||
|
|
|||
|
function gotoFirstSlide () {
|
|||
|
gotoSlideByIndex(0);
|
|||
|
}
|
|||
|
|
|||
|
function gotoLastSlide () {
|
|||
|
gotoSlideByIndex(self.getSlideCount() - 1);
|
|||
|
}
|
|||
|
|
|||
|
function getSlideIndex (slideNoOrName) {
|
|||
|
var slideNo
|
|||
|
, slide
|
|||
|
;
|
|||
|
|
|||
|
if (typeof slideNoOrName === 'number') {
|
|||
|
return slideNoOrName - 1;
|
|||
|
}
|
|||
|
|
|||
|
slideNo = parseInt(slideNoOrName, 10);
|
|||
|
if (slideNo.toString() === slideNoOrName) {
|
|||
|
return slideNo - 1;
|
|||
|
}
|
|||
|
|
|||
|
if(slideNoOrName.match(/^p\d+$/)){
|
|||
|
events.emit('forcePresenterMode');
|
|||
|
return parseInt(slideNoOrName.substr(1), 10)-1;
|
|||
|
}
|
|||
|
|
|||
|
slide = self.getSlideByName(slideNoOrName);
|
|||
|
if (slide) {
|
|||
|
return slide.getSlideIndex();
|
|||
|
}
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
},{}],20:[function(require,module,exports){
|
|||
|
var EventEmitter = require('events').EventEmitter;
|
|||
|
|
|||
|
module.exports = Events;
|
|||
|
|
|||
|
function Events (events) {
|
|||
|
var self = this
|
|||
|
, externalEvents = new EventEmitter()
|
|||
|
;
|
|||
|
|
|||
|
externalEvents.setMaxListeners(0);
|
|||
|
|
|||
|
self.on = function () {
|
|||
|
externalEvents.on.apply(externalEvents, arguments);
|
|||
|
return self;
|
|||
|
};
|
|||
|
|
|||
|
['showSlide', 'hideSlide', 'beforeShowSlide', 'afterShowSlide', 'beforeHideSlide', 'afterHideSlide'].map(function (eventName) {
|
|||
|
events.on(eventName, function (slideIndex) {
|
|||
|
var slide = self.getSlides()[slideIndex];
|
|||
|
externalEvents.emit(eventName, slide);
|
|||
|
});
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
},{"events":1}],22:[function(require,module,exports){
|
|||
|
module.exports = Slide;
|
|||
|
|
|||
|
function Slide (slideIndex, slide, template) {
|
|||
|
var self = this;
|
|||
|
|
|||
|
self.properties = slide.properties || {};
|
|||
|
self.links = slide.links || {};
|
|||
|
self.content = slide.content || [];
|
|||
|
self.notes = slide.notes || '';
|
|||
|
|
|||
|
self.getSlideIndex = function () { return slideIndex; };
|
|||
|
|
|||
|
if (template) {
|
|||
|
inherit(self, template);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function inherit (slide, template) {
|
|||
|
inheritProperties(slide, template);
|
|||
|
inheritContent(slide, template);
|
|||
|
inheritNotes(slide, template);
|
|||
|
}
|
|||
|
|
|||
|
function inheritProperties (slide, template) {
|
|||
|
var property
|
|||
|
, value
|
|||
|
;
|
|||
|
|
|||
|
for (property in template.properties) {
|
|||
|
if (!template.properties.hasOwnProperty(property) ||
|
|||
|
ignoreProperty(property)) {
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
value = [template.properties[property]];
|
|||
|
|
|||
|
if (property === 'class' && slide.properties[property]) {
|
|||
|
value.push(slide.properties[property]);
|
|||
|
}
|
|||
|
|
|||
|
if (property === 'class' || slide.properties[property] === undefined) {
|
|||
|
slide.properties[property] = value.join(', ');
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function ignoreProperty (property) {
|
|||
|
return property === 'name' ||
|
|||
|
property === 'layout' ||
|
|||
|
property === 'count';
|
|||
|
}
|
|||
|
|
|||
|
function inheritContent (slide, template) {
|
|||
|
var expandedVariables;
|
|||
|
|
|||
|
slide.properties.content = slide.content.slice();
|
|||
|
slide.content = template.content.slice();
|
|||
|
|
|||
|
expandedVariables = slide.expandVariables(/* contentOnly: */ true);
|
|||
|
|
|||
|
if (expandedVariables.content === undefined) {
|
|||
|
slide.content = slide.content.concat(slide.properties.content);
|
|||
|
}
|
|||
|
|
|||
|
delete slide.properties.content;
|
|||
|
}
|
|||
|
|
|||
|
function inheritNotes (slide, template) {
|
|||
|
if (template.notes) {
|
|||
|
slide.notes = template.notes + '\n\n' + slide.notes;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Slide.prototype.expandVariables = function (contentOnly, content, expandResult) {
|
|||
|
var properties = this.properties
|
|||
|
, i
|
|||
|
;
|
|||
|
|
|||
|
content = content !== undefined ? content : this.content;
|
|||
|
expandResult = expandResult || {};
|
|||
|
|
|||
|
for (i = 0; i < content.length; ++i) {
|
|||
|
if (typeof content[i] === 'string') {
|
|||
|
content[i] = content[i].replace(/(\\)?(\{\{([^\}\n]+)\}\})/g, expand);
|
|||
|
}
|
|||
|
else {
|
|||
|
this.expandVariables(contentOnly, content[i].content, expandResult);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function expand (match, escaped, unescapedMatch, property) {
|
|||
|
var propertyName = property.trim()
|
|||
|
, propertyValue
|
|||
|
;
|
|||
|
|
|||
|
if (escaped) {
|
|||
|
return contentOnly ? match[0] : unescapedMatch;
|
|||
|
}
|
|||
|
|
|||
|
if (contentOnly && propertyName !== 'content') {
|
|||
|
return match;
|
|||
|
}
|
|||
|
|
|||
|
propertyValue = properties[propertyName];
|
|||
|
|
|||
|
if (propertyValue !== undefined) {
|
|||
|
expandResult[propertyName] = propertyValue;
|
|||
|
return propertyValue;
|
|||
|
}
|
|||
|
|
|||
|
return propertyName === 'content' ? '' : unescapedMatch;
|
|||
|
}
|
|||
|
|
|||
|
return expandResult;
|
|||
|
};
|
|||
|
|
|||
|
},{}],19:[function(require,module,exports){
|
|||
|
var referenceWidth = 908
|
|||
|
, referenceHeight = 681
|
|||
|
, referenceRatio = referenceWidth / referenceHeight
|
|||
|
;
|
|||
|
|
|||
|
module.exports = Scaler;
|
|||
|
|
|||
|
function Scaler (events, slideshow) {
|
|||
|
var self = this;
|
|||
|
|
|||
|
self.events = events;
|
|||
|
self.slideshow = slideshow;
|
|||
|
self.ratio = getRatio(slideshow);
|
|||
|
self.dimensions = getDimensions(self.ratio);
|
|||
|
|
|||
|
self.events.on('propertiesChanged', function (changes) {
|
|||
|
if (changes.hasOwnProperty('ratio')) {
|
|||
|
self.ratio = getRatio(slideshow);
|
|||
|
self.dimensions = getDimensions(self.ratio);
|
|||
|
}
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
Scaler.prototype.scaleToFit = function (element, container) {
|
|||
|
var self = this
|
|||
|
, containerHeight = container.clientHeight
|
|||
|
, containerWidth = container.clientWidth
|
|||
|
, scale
|
|||
|
, scaledWidth
|
|||
|
, scaledHeight
|
|||
|
, ratio = self.ratio
|
|||
|
, dimensions = self.dimensions
|
|||
|
, direction
|
|||
|
, left
|
|||
|
, top
|
|||
|
;
|
|||
|
|
|||
|
if (containerWidth / ratio.width > containerHeight / ratio.height) {
|
|||
|
scale = containerHeight / dimensions.height;
|
|||
|
}
|
|||
|
else {
|
|||
|
scale = containerWidth / dimensions.width;
|
|||
|
}
|
|||
|
|
|||
|
scaledWidth = dimensions.width * scale;
|
|||
|
scaledHeight = dimensions.height * scale;
|
|||
|
|
|||
|
left = (containerWidth - scaledWidth) / 2;
|
|||
|
top = (containerHeight - scaledHeight) / 2;
|
|||
|
|
|||
|
element.style['-webkit-transform'] = 'scale(' + scale + ')';
|
|||
|
element.style.MozTransform = 'scale(' + scale + ')';
|
|||
|
element.style.left = Math.max(left, 0) + 'px';
|
|||
|
element.style.top = Math.max(top, 0) + 'px';
|
|||
|
};
|
|||
|
|
|||
|
function getRatio (slideshow) {
|
|||
|
var ratioComponents = slideshow.getRatio().split(':')
|
|||
|
, ratio
|
|||
|
;
|
|||
|
|
|||
|
ratio = {
|
|||
|
width: parseInt(ratioComponents[0], 10)
|
|||
|
, height: parseInt(ratioComponents[1], 10)
|
|||
|
};
|
|||
|
|
|||
|
ratio.ratio = ratio.width / ratio.height;
|
|||
|
|
|||
|
return ratio;
|
|||
|
}
|
|||
|
|
|||
|
function getDimensions (ratio) {
|
|||
|
return {
|
|||
|
width: Math.floor(referenceWidth / referenceRatio * ratio.ratio)
|
|||
|
, height: referenceHeight
|
|||
|
};
|
|||
|
}
|
|||
|
|
|||
|
},{}],26:[function(require,module,exports){
|
|||
|
exports.register = function (events) {
|
|||
|
addMessageEventListeners(events);
|
|||
|
};
|
|||
|
|
|||
|
function addMessageEventListeners (events) {
|
|||
|
events.on('message', navigateByMessage);
|
|||
|
|
|||
|
function navigateByMessage(message) {
|
|||
|
var cap;
|
|||
|
|
|||
|
if ((cap = /^gotoSlide:(\d+)$/.exec(message.data)) !== null) {
|
|||
|
events.emit('gotoSlide', parseInt(cap[1], 10), true);
|
|||
|
}
|
|||
|
else if (message.data === 'toggleBlackout') {
|
|||
|
events.emit('toggleBlackout');
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
},{}],27:[function(require,module,exports){
|
|||
|
exports.register = function (events, dom, slideshowView) {
|
|||
|
addLocationEventListeners(events, dom, slideshowView);
|
|||
|
};
|
|||
|
|
|||
|
function addLocationEventListeners (events, dom, slideshowView) {
|
|||
|
// If slideshow is embedded into custom DOM element, we don't
|
|||
|
// hook up to location hash changes, so just go to first slide.
|
|||
|
if (slideshowView.isEmbedded()) {
|
|||
|
events.emit('gotoSlide', 1);
|
|||
|
}
|
|||
|
// When slideshow is not embedded into custom DOM element, but
|
|||
|
// rather hosted directly inside document.body, we hook up to
|
|||
|
// location hash changes, and trigger initial navigation.
|
|||
|
else {
|
|||
|
events.on('hashchange', navigateByHash);
|
|||
|
events.on('slideChanged', updateHash);
|
|||
|
|
|||
|
navigateByHash();
|
|||
|
}
|
|||
|
|
|||
|
function navigateByHash () {
|
|||
|
var slideNoOrName = (dom.getLocationHash() || '').substr(1);
|
|||
|
events.emit('gotoSlide', slideNoOrName);
|
|||
|
}
|
|||
|
|
|||
|
function updateHash (slideNoOrName) {
|
|||
|
dom.setLocationHash('#' + slideNoOrName);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
},{}],18:[function(require,module,exports){
|
|||
|
var converter = require('../converter');
|
|||
|
|
|||
|
module.exports = NotesView;
|
|||
|
|
|||
|
function NotesView (events, element, slideViewsAccessor) {
|
|||
|
var self = this;
|
|||
|
|
|||
|
self.events = events;
|
|||
|
self.element = element;
|
|||
|
self.slideViewsAccessor = slideViewsAccessor;
|
|||
|
|
|||
|
self.configureElements();
|
|||
|
|
|||
|
events.on('showSlide', function (slideIndex) {
|
|||
|
self.showSlide(slideIndex);
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
NotesView.prototype.showSlide = function (slideIndex) {
|
|||
|
var self = this
|
|||
|
, slideViews = self.slideViewsAccessor()
|
|||
|
, slideView = slideViews[slideIndex]
|
|||
|
, nextSlideView = slideViews[slideIndex + 1]
|
|||
|
;
|
|||
|
|
|||
|
self.notesElement.innerHTML = slideView.notesElement.innerHTML;
|
|||
|
|
|||
|
if (nextSlideView) {
|
|||
|
self.notesPreviewElement.innerHTML = nextSlideView.notesElement.innerHTML;
|
|||
|
}
|
|||
|
else {
|
|||
|
self.notesPreviewElement.innerHTML = '';
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
NotesView.prototype.configureElements = function () {
|
|||
|
var self = this;
|
|||
|
|
|||
|
self.notesElement = self.element.getElementsByClassName('remark-notes')[0];
|
|||
|
self.notesPreviewElement = self.element.getElementsByClassName('remark-notes-preview')[0];
|
|||
|
|
|||
|
self.notesElement.addEventListener('mousewheel', function (event) {
|
|||
|
event.stopPropagation();
|
|||
|
});
|
|||
|
|
|||
|
self.notesPreviewElement.addEventListener('mousewheel', function (event) {
|
|||
|
event.stopPropagation();
|
|||
|
});
|
|||
|
|
|||
|
self.toolbarElement = self.element.getElementsByClassName('remark-toolbar')[0];
|
|||
|
|
|||
|
var commands = {
|
|||
|
increase: function () {
|
|||
|
self.notesElement.style.fontSize = (parseFloat(self.notesElement.style.fontSize) || 1) + 0.1 + 'em';
|
|||
|
self.notesPreviewElement.style.fontsize = self.notesElement.style.fontSize;
|
|||
|
},
|
|||
|
decrease: function () {
|
|||
|
self.notesElement.style.fontSize = (parseFloat(self.notesElement.style.fontSize) || 1) - 0.1 + 'em';
|
|||
|
self.notesPreviewElement.style.fontsize = self.notesElement.style.fontSize;
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
self.toolbarElement.getElementsByTagName('a').forEach(function (link) {
|
|||
|
link.addEventListener('click', function (e) {
|
|||
|
var command = e.target.hash.substr(1);
|
|||
|
commands[command]();
|
|||
|
e.preventDefault();
|
|||
|
});
|
|||
|
});
|
|||
|
};
|
|||
|
|
|||
|
},{"../converter":9}],17:[function(require,module,exports){
|
|||
|
var SlideNumber = require('components/slide-number')
|
|||
|
, converter = require('../converter')
|
|||
|
, highlighter = require('../highlighter')
|
|||
|
, utils = require('../utils')
|
|||
|
;
|
|||
|
|
|||
|
module.exports = SlideView;
|
|||
|
|
|||
|
function SlideView (events, slideshow, scaler, slide) {
|
|||
|
var self = this;
|
|||
|
|
|||
|
self.events = events;
|
|||
|
self.slideshow = slideshow;
|
|||
|
self.scaler = scaler;
|
|||
|
self.slide = slide;
|
|||
|
|
|||
|
self.slideNumber = new SlideNumber(slide, slideshow);
|
|||
|
|
|||
|
self.configureElements();
|
|||
|
self.updateDimensions();
|
|||
|
|
|||
|
self.events.on('propertiesChanged', function (changes) {
|
|||
|
if (changes.hasOwnProperty('ratio')) {
|
|||
|
self.updateDimensions();
|
|||
|
}
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
SlideView.prototype.updateDimensions = function () {
|
|||
|
var self = this
|
|||
|
, dimensions = self.scaler.dimensions
|
|||
|
;
|
|||
|
|
|||
|
self.scalingElement.style.width = dimensions.width + 'px';
|
|||
|
self.scalingElement.style.height = dimensions.height + 'px';
|
|||
|
};
|
|||
|
|
|||
|
SlideView.prototype.scale = function (containerElement) {
|
|||
|
var self = this;
|
|||
|
|
|||
|
self.scaler.scaleToFit(self.scalingElement, containerElement);
|
|||
|
};
|
|||
|
|
|||
|
SlideView.prototype.show = function () {
|
|||
|
utils.addClass(this.containerElement, 'remark-visible');
|
|||
|
utils.removeClass(this.containerElement, 'remark-fading');
|
|||
|
};
|
|||
|
|
|||
|
SlideView.prototype.hide = function () {
|
|||
|
var self = this;
|
|||
|
utils.removeClass(this.containerElement, 'remark-visible');
|
|||
|
// Don't just disappear the slide. Mark it as fading, which
|
|||
|
// keeps it on the screen, but at a reduced z-index.
|
|||
|
// Then set a timer to remove the fading state in 1s.
|
|||
|
utils.addClass(this.containerElement, 'remark-fading');
|
|||
|
setTimeout(function(){
|
|||
|
utils.removeClass(self.containerElement, 'remark-fading');
|
|||
|
}, 1000);
|
|||
|
};
|
|||
|
|
|||
|
SlideView.prototype.configureElements = function () {
|
|||
|
var self = this;
|
|||
|
|
|||
|
self.containerElement = document.createElement('div');
|
|||
|
self.containerElement.className = 'remark-slide-container';
|
|||
|
|
|||
|
self.scalingElement = document.createElement('div');
|
|||
|
self.scalingElement.className = 'remark-slide-scaler';
|
|||
|
|
|||
|
self.element = document.createElement('div');
|
|||
|
self.element.className = 'remark-slide';
|
|||
|
|
|||
|
self.contentElement = createContentElement(self.events, self.slideshow, self.slide);
|
|||
|
self.notesElement = createNotesElement(self.slideshow, self.slide.notes);
|
|||
|
|
|||
|
self.contentElement.appendChild(self.slideNumber.element);
|
|||
|
self.element.appendChild(self.contentElement);
|
|||
|
self.scalingElement.appendChild(self.element);
|
|||
|
self.containerElement.appendChild(self.scalingElement);
|
|||
|
self.containerElement.appendChild(self.notesElement);
|
|||
|
};
|
|||
|
|
|||
|
SlideView.prototype.scaleBackgroundImage = function (dimensions) {
|
|||
|
var self = this
|
|||
|
, styles = window.getComputedStyle(this.contentElement)
|
|||
|
, backgroundImage = styles.backgroundImage
|
|||
|
, match
|
|||
|
, image
|
|||
|
, scale
|
|||
|
;
|
|||
|
|
|||
|
if ((match = /^url\(("?)([^\)]+?)\1\)/.exec(backgroundImage)) !== null) {
|
|||
|
image = new Image();
|
|||
|
image.onload = function () {
|
|||
|
if (image.width > dimensions.width ||
|
|||
|
image.height > dimensions.height) {
|
|||
|
// Background image is larger than slide
|
|||
|
if (!self.originalBackgroundSize) {
|
|||
|
// No custom background size has been set
|
|||
|
self.originalBackgroundSize = self.contentElement.style.backgroundSize;
|
|||
|
self.originalBackgroundPosition = self.contentElement.style.backgroundPosition;
|
|||
|
self.backgroundSizeSet = true;
|
|||
|
|
|||
|
if (dimensions.width / image.width < dimensions.height / image.height) {
|
|||
|
scale = dimensions.width / image.width;
|
|||
|
}
|
|||
|
else {
|
|||
|
scale = dimensions.height / image.height;
|
|||
|
}
|
|||
|
|
|||
|
self.contentElement.style.backgroundSize = image.width * scale +
|
|||
|
'px ' + image.height * scale + 'px';
|
|||
|
self.contentElement.style.backgroundPosition = '50% ' +
|
|||
|
((dimensions.height - (image.height * scale)) / 2) + 'px';
|
|||
|
}
|
|||
|
}
|
|||
|
else {
|
|||
|
// Revert to previous background size setting
|
|||
|
if (self.backgroundSizeSet) {
|
|||
|
self.contentElement.style.backgroundSize = self.originalBackgroundSize;
|
|||
|
self.contentElement.style.backgroundPosition = self.originalBackgroundPosition;
|
|||
|
self.backgroundSizeSet = false;
|
|||
|
}
|
|||
|
}
|
|||
|
};
|
|||
|
image.src = match[2];
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
function createContentElement (events, slideshow, slide) {
|
|||
|
var element = document.createElement('div');
|
|||
|
|
|||
|
if (slide.properties.name) {
|
|||
|
element.id = 'slide-' + slide.properties.name;
|
|||
|
}
|
|||
|
|
|||
|
styleContentElement(slideshow, element, slide.properties);
|
|||
|
|
|||
|
element.innerHTML = converter.convertMarkdown(slide.content, slideshow.getLinks());
|
|||
|
|
|||
|
highlightCodeBlocks(element, slideshow);
|
|||
|
|
|||
|
return element;
|
|||
|
}
|
|||
|
|
|||
|
function styleContentElement (slideshow, element, properties) {
|
|||
|
element.className = '';
|
|||
|
|
|||
|
setClassFromProperties(element, properties);
|
|||
|
setHighlightStyleFromProperties(element, properties, slideshow);
|
|||
|
setBackgroundFromProperties(element, properties);
|
|||
|
}
|
|||
|
|
|||
|
function createNotesElement (slideshow, notes) {
|
|||
|
var element = document.createElement('div');
|
|||
|
|
|||
|
element.className = 'remark-slide-notes';
|
|||
|
|
|||
|
element.innerHTML = converter.convertMarkdown(notes);
|
|||
|
|
|||
|
highlightCodeBlocks(element, slideshow);
|
|||
|
|
|||
|
return element;
|
|||
|
}
|
|||
|
|
|||
|
function setBackgroundFromProperties (element, properties) {
|
|||
|
var backgroundImage = properties['background-image'];
|
|||
|
|
|||
|
if (backgroundImage) {
|
|||
|
element.style.backgroundImage = backgroundImage;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function setHighlightStyleFromProperties (element, properties, slideshow) {
|
|||
|
var highlightStyle = properties['highlight-style'] ||
|
|||
|
slideshow.getHighlightStyle();
|
|||
|
|
|||
|
if (highlightStyle) {
|
|||
|
utils.addClass(element, 'hljs-' + highlightStyle);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function setClassFromProperties (element, properties) {
|
|||
|
utils.addClass(element, 'remark-slide-content');
|
|||
|
|
|||
|
(properties['class'] || '').split(/,| /)
|
|||
|
.filter(function (s) { return s !== ''; })
|
|||
|
.forEach(function (c) { utils.addClass(element, c); });
|
|||
|
}
|
|||
|
|
|||
|
function highlightCodeBlocks (content, slideshow) {
|
|||
|
var codeBlocks = content.getElementsByTagName('code')
|
|||
|
;
|
|||
|
|
|||
|
codeBlocks.forEach(function (block) {
|
|||
|
if (block.parentElement.tagName !== 'PRE') {
|
|||
|
utils.addClass(block, 'remark-inline-code');
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (block.className === '') {
|
|||
|
block.className = slideshow.getHighlightLanguage();
|
|||
|
}
|
|||
|
|
|||
|
var meta = extractMetadata(block);
|
|||
|
|
|||
|
if (block.className !== '') {
|
|||
|
highlighter.engine.highlightBlock(block, ' ');
|
|||
|
}
|
|||
|
|
|||
|
wrapLines(block);
|
|||
|
highlightBlockLines(block, meta.highlightedLines);
|
|||
|
highlightBlockSpans(block);
|
|||
|
|
|||
|
utils.addClass(block, 'remark-code');
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
function extractMetadata (block) {
|
|||
|
var highlightedLines = [];
|
|||
|
|
|||
|
block.innerHTML = block.innerHTML.split(/\r?\n/).map(function (line, i) {
|
|||
|
if (line.indexOf('*') === 0) {
|
|||
|
highlightedLines.push(i);
|
|||
|
return line.replace(/^\*( )?/, '$1$1');
|
|||
|
}
|
|||
|
|
|||
|
return line;
|
|||
|
}).join('\n');
|
|||
|
|
|||
|
return {
|
|||
|
highlightedLines: highlightedLines
|
|||
|
};
|
|||
|
}
|
|||
|
|
|||
|
function wrapLines (block) {
|
|||
|
var lines = block.innerHTML.split(/\r?\n/).map(function (line) {
|
|||
|
return '<div class="remark-code-line">' + line + '</div>';
|
|||
|
});
|
|||
|
|
|||
|
// Remove empty last line (due to last \n)
|
|||
|
if (lines.length && lines[lines.length - 1].indexOf('><') !== -1) {
|
|||
|
lines.pop();
|
|||
|
}
|
|||
|
|
|||
|
block.innerHTML = lines.join('');
|
|||
|
}
|
|||
|
|
|||
|
function highlightBlockLines (block, lines) {
|
|||
|
lines.forEach(function (i) {
|
|||
|
utils.addClass(block.childNodes[i], 'remark-code-line-highlighted');
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
function highlightBlockSpans (block) {
|
|||
|
var pattern = /([^\\`])`([^`]+?)`/g
|
|||
|
, replacement = '$1<span class="remark-code-span-highlighted">$2</span>'
|
|||
|
;
|
|||
|
|
|||
|
block.childNodes.forEach(function (element) {
|
|||
|
element.innerHTML = element.innerHTML.replace(pattern, replacement);
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
},{"components/slide-number":"aIW4aw","../converter":9,"../highlighter":7,"../utils":8}],9:[function(require,module,exports){
|
|||
|
var marked = require('marked')
|
|||
|
, converter = module.exports = {}
|
|||
|
, element = document.createElement('div')
|
|||
|
;
|
|||
|
|
|||
|
marked.setOptions({
|
|||
|
gfm: true,
|
|||
|
tables: true,
|
|||
|
breaks: false,
|
|||
|
|
|||
|
// Without this set to true, converting something like
|
|||
|
// <p>*</p><p>*</p> will become <p><em></p><p></em></p>
|
|||
|
pedantic: true,
|
|||
|
|
|||
|
sanitize: false,
|
|||
|
smartLists: true,
|
|||
|
langPrefix: ''
|
|||
|
});
|
|||
|
|
|||
|
converter.convertMarkdown = function (content, links, inline) {
|
|||
|
element.innerHTML = convertMarkdown(content, links || {}, inline);
|
|||
|
element.innerHTML = element.innerHTML.replace(/<p>\s*<\/p>/g, '');
|
|||
|
return element.innerHTML.replace(/\n\r?$/, '');
|
|||
|
};
|
|||
|
|
|||
|
function convertMarkdown (content, links, insideContentClass) {
|
|||
|
var i, tag, markdown = '', html;
|
|||
|
|
|||
|
for (i = 0; i < content.length; ++i) {
|
|||
|
if (typeof content[i] === 'string') {
|
|||
|
markdown += content[i];
|
|||
|
}
|
|||
|
else {
|
|||
|
tag = content[i].block ? 'div' : 'span';
|
|||
|
markdown += '<' + tag + ' class="' + content[i].class + '">';
|
|||
|
markdown += convertMarkdown(content[i].content, links, true);
|
|||
|
markdown += '</' + tag + '>';
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
var tokens = marked.Lexer.lex(markdown.replace(/^\s+/, ''));
|
|||
|
tokens.links = links;
|
|||
|
html = marked.Parser.parse(tokens);
|
|||
|
|
|||
|
if (insideContentClass) {
|
|||
|
element.innerHTML = html;
|
|||
|
if (element.children.length === 1 && element.children[0].tagName === 'P') {
|
|||
|
html = element.children[0].innerHTML;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return html;
|
|||
|
}
|
|||
|
|
|||
|
},{"marked":28}],28:[function(require,module,exports){
|
|||
|
(function(global){/**
|
|||
|
* marked - a markdown parser
|
|||
|
* Copyright (c) 2011-2013, Christopher Jeffrey. (MIT Licensed)
|
|||
|
* https://github.com/chjj/marked
|
|||
|
*/
|
|||
|
|
|||
|
;(function() {
|
|||
|
|
|||
|
/**
|
|||
|
* Block-Level Grammar
|
|||
|
*/
|
|||
|
|
|||
|
var block = {
|
|||
|
newline: /^\n+/,
|
|||
|
code: /^( {4}[^\n]+\n*)+/,
|
|||
|
fences: noop,
|
|||
|
hr: /^( *[-*_]){3,} *(?:\n+|$)/,
|
|||
|
heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
|
|||
|
nptable: noop,
|
|||
|
lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
|
|||
|
blockquote: /^( *>[^\n]+(\n[^\n]+)*\n*)+/,
|
|||
|
list: /^( *)(bull) [\s\S]+?(?:hr|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
|
|||
|
html: /^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/,
|
|||
|
def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
|
|||
|
table: noop,
|
|||
|
paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
|
|||
|
text: /^[^\n]+/
|
|||
|
};
|
|||
|
|
|||
|
block.bullet = /(?:[*+-]|\d+\.)/;
|
|||
|
block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
|
|||
|
block.item = replace(block.item, 'gm')
|
|||
|
(/bull/g, block.bullet)
|
|||
|
();
|
|||
|
|
|||
|
block.list = replace(block.list)
|
|||
|
(/bull/g, block.bullet)
|
|||
|
('hr', /\n+(?=(?: *[-*_]){3,} *(?:\n+|$))/)
|
|||
|
();
|
|||
|
|
|||
|
block._tag = '(?!(?:'
|
|||
|
+ 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
|
|||
|
+ '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
|
|||
|
+ '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b';
|
|||
|
|
|||
|
block.html = replace(block.html)
|
|||
|
('comment', /<!--[\s\S]*?-->/)
|
|||
|
('closed', /<(tag)[\s\S]+?<\/\1>/)
|
|||
|
('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
|
|||
|
(/tag/g, block._tag)
|
|||
|
();
|
|||
|
|
|||
|
block.paragraph = replace(block.paragraph)
|
|||
|
('hr', block.hr)
|
|||
|
('heading', block.heading)
|
|||
|
('lheading', block.lheading)
|
|||
|
('blockquote', block.blockquote)
|
|||
|
('tag', '<' + block._tag)
|
|||
|
('def', block.def)
|
|||
|
();
|
|||
|
|
|||
|
/**
|
|||
|
* Normal Block Grammar
|
|||
|
*/
|
|||
|
|
|||
|
block.normal = merge({}, block);
|
|||
|
|
|||
|
/**
|
|||
|
* GFM Block Grammar
|
|||
|
*/
|
|||
|
|
|||
|
block.gfm = merge({}, block.normal, {
|
|||
|
fences: /^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,
|
|||
|
paragraph: /^/
|
|||
|
});
|
|||
|
|
|||
|
block.gfm.paragraph = replace(block.paragraph)
|
|||
|
('(?!', '(?!'
|
|||
|
+ block.gfm.fences.source.replace('\\1', '\\2') + '|'
|
|||
|
+ block.list.source.replace('\\1', '\\3') + '|')
|
|||
|
();
|
|||
|
|
|||
|
/**
|
|||
|
* GFM + Tables Block Grammar
|
|||
|
*/
|
|||
|
|
|||
|
block.tables = merge({}, block.gfm, {
|
|||
|
nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
|
|||
|
table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
|
|||
|
});
|
|||
|
|
|||
|
/**
|
|||
|
* Block Lexer
|
|||
|
*/
|
|||
|
|
|||
|
function Lexer(options) {
|
|||
|
this.tokens = [];
|
|||
|
this.tokens.links = {};
|
|||
|
this.options = options || marked.defaults;
|
|||
|
this.rules = block.normal;
|
|||
|
|
|||
|
if (this.options.gfm) {
|
|||
|
if (this.options.tables) {
|
|||
|
this.rules = block.tables;
|
|||
|
} else {
|
|||
|
this.rules = block.gfm;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Expose Block Rules
|
|||
|
*/
|
|||
|
|
|||
|
Lexer.rules = block;
|
|||
|
|
|||
|
/**
|
|||
|
* Static Lex Method
|
|||
|
*/
|
|||
|
|
|||
|
Lexer.lex = function(src, options) {
|
|||
|
var lexer = new Lexer(options);
|
|||
|
return lexer.lex(src);
|
|||
|
};
|
|||
|
|
|||
|
/**
|
|||
|
* Preprocessing
|
|||
|
*/
|
|||
|
|
|||
|
Lexer.prototype.lex = function(src) {
|
|||
|
src = src
|
|||
|
.replace(/\r\n|\r/g, '\n')
|
|||
|
.replace(/\t/g, ' ')
|
|||
|
.replace(/\u00a0/g, ' ')
|
|||
|
.replace(/\u2424/g, '\n');
|
|||
|
|
|||
|
return this.token(src, true);
|
|||
|
};
|
|||
|
|
|||
|
/**
|
|||
|
* Lexing
|
|||
|
*/
|
|||
|
|
|||
|
Lexer.prototype.token = function(src, top) {
|
|||
|
var src = src.replace(/^ +$/gm, '')
|
|||
|
, next
|
|||
|
, loose
|
|||
|
, cap
|
|||
|
, bull
|
|||
|
, b
|
|||
|
, item
|
|||
|
, space
|
|||
|
, i
|
|||
|
, l;
|
|||
|
|
|||
|
while (src) {
|
|||
|
// newline
|
|||
|
if (cap = this.rules.newline.exec(src)) {
|
|||
|
src = src.substring(cap[0].length);
|
|||
|
if (cap[0].length > 1) {
|
|||
|
this.tokens.push({
|
|||
|
type: 'space'
|
|||
|
});
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// code
|
|||
|
if (cap = this.rules.code.exec(src)) {
|
|||
|
src = src.substring(cap[0].length);
|
|||
|
cap = cap[0].replace(/^ {4}/gm, '');
|
|||
|
this.tokens.push({
|
|||
|
type: 'code',
|
|||
|
text: !this.options.pedantic
|
|||
|
? cap.replace(/\n+$/, '')
|
|||
|
: cap
|
|||
|
});
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// fences (gfm)
|
|||
|
if (cap = this.rules.fences.exec(src)) {
|
|||
|
src = src.substring(cap[0].length);
|
|||
|
this.tokens.push({
|
|||
|
type: 'code',
|
|||
|
lang: cap[2],
|
|||
|
text: cap[3]
|
|||
|
});
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// heading
|
|||
|
if (cap = this.rules.heading.exec(src)) {
|
|||
|
src = src.substring(cap[0].length);
|
|||
|
this.tokens.push({
|
|||
|
type: 'heading',
|
|||
|
depth: cap[1].length,
|
|||
|
text: cap[2]
|
|||
|
});
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// table no leading pipe (gfm)
|
|||
|
if (top && (cap = this.rules.nptable.exec(src))) {
|
|||
|
src = src.substring(cap[0].length);
|
|||
|
|
|||
|
item = {
|
|||
|
type: 'table',
|
|||
|
header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
|
|||
|
align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
|
|||
|
cells: cap[3].replace(/\n$/, '').split('\n')
|
|||
|
};
|
|||
|
|
|||
|
for (i = 0; i < item.align.length; i++) {
|
|||
|
if (/^ *-+: *$/.test(item.align[i])) {
|
|||
|
item.align[i] = 'right';
|
|||
|
} else if (/^ *:-+: *$/.test(item.align[i])) {
|
|||
|
item.align[i] = 'center';
|
|||
|
} else if (/^ *:-+ *$/.test(item.align[i])) {
|
|||
|
item.align[i] = 'left';
|
|||
|
} else {
|
|||
|
item.align[i] = null;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
for (i = 0; i < item.cells.length; i++) {
|
|||
|
item.cells[i] = item.cells[i].split(/ *\| */);
|
|||
|
}
|
|||
|
|
|||
|
this.tokens.push(item);
|
|||
|
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// lheading
|
|||
|
if (cap = this.rules.lheading.exec(src)) {
|
|||
|
src = src.substring(cap[0].length);
|
|||
|
this.tokens.push({
|
|||
|
type: 'heading',
|
|||
|
depth: cap[2] === '=' ? 1 : 2,
|
|||
|
text: cap[1]
|
|||
|
});
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// hr
|
|||
|
if (cap = this.rules.hr.exec(src)) {
|
|||
|
src = src.substring(cap[0].length);
|
|||
|
this.tokens.push({
|
|||
|
type: 'hr'
|
|||
|
});
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// blockquote
|
|||
|
if (cap = this.rules.blockquote.exec(src)) {
|
|||
|
src = src.substring(cap[0].length);
|
|||
|
|
|||
|
this.tokens.push({
|
|||
|
type: 'blockquote_start'
|
|||
|
});
|
|||
|
|
|||
|
cap = cap[0].replace(/^ *> ?/gm, '');
|
|||
|
|
|||
|
// Pass `top` to keep the current
|
|||
|
// "toplevel" state. This is exactly
|
|||
|
// how markdown.pl works.
|
|||
|
this.token(cap, top);
|
|||
|
|
|||
|
this.tokens.push({
|
|||
|
type: 'blockquote_end'
|
|||
|
});
|
|||
|
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// list
|
|||
|
if (cap = this.rules.list.exec(src)) {
|
|||
|
src = src.substring(cap[0].length);
|
|||
|
bull = cap[2];
|
|||
|
|
|||
|
this.tokens.push({
|
|||
|
type: 'list_start',
|
|||
|
ordered: bull.length > 1
|
|||
|
});
|
|||
|
|
|||
|
// Get each top-level item.
|
|||
|
cap = cap[0].match(this.rules.item);
|
|||
|
|
|||
|
next = false;
|
|||
|
l = cap.length;
|
|||
|
i = 0;
|
|||
|
|
|||
|
for (; i < l; i++) {
|
|||
|
item = cap[i];
|
|||
|
|
|||
|
// Remove the list item's bullet
|
|||
|
// so it is seen as the next token.
|
|||
|
space = item.length;
|
|||
|
item = item.replace(/^ *([*+-]|\d+\.) +/, '');
|
|||
|
|
|||
|
// Outdent whatever the
|
|||
|
// list item contains. Hacky.
|
|||
|
if (~item.indexOf('\n ')) {
|
|||
|
space -= item.length;
|
|||
|
item = !this.options.pedantic
|
|||
|
? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
|
|||
|
: item.replace(/^ {1,4}/gm, '');
|
|||
|
}
|
|||
|
|
|||
|
// Determine whether the next list item belongs here.
|
|||
|
// Backpedal if it does not belong in this list.
|
|||
|
if (this.options.smartLists && i !== l - 1) {
|
|||
|
b = block.bullet.exec(cap[i + 1])[0];
|
|||
|
if (bull !== b && !(bull.length > 1 && b.length > 1)) {
|
|||
|
src = cap.slice(i + 1).join('\n') + src;
|
|||
|
i = l - 1;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Determine whether item is loose or not.
|
|||
|
// Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
|
|||
|
// for discount behavior.
|
|||
|
loose = next || /\n\n(?!\s*$)/.test(item);
|
|||
|
if (i !== l - 1) {
|
|||
|
next = item.charAt(item.length - 1) === '\n';
|
|||
|
if (!loose) loose = next;
|
|||
|
}
|
|||
|
|
|||
|
this.tokens.push({
|
|||
|
type: loose
|
|||
|
? 'loose_item_start'
|
|||
|
: 'list_item_start'
|
|||
|
});
|
|||
|
|
|||
|
// Recurse.
|
|||
|
this.token(item, false);
|
|||
|
|
|||
|
this.tokens.push({
|
|||
|
type: 'list_item_end'
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
this.tokens.push({
|
|||
|
type: 'list_end'
|
|||
|
});
|
|||
|
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// html
|
|||
|
if (cap = this.rules.html.exec(src)) {
|
|||
|
src = src.substring(cap[0].length);
|
|||
|
this.tokens.push({
|
|||
|
type: this.options.sanitize
|
|||
|
? 'paragraph'
|
|||
|
: 'html',
|
|||
|
pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style',
|
|||
|
text: cap[0]
|
|||
|
});
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// def
|
|||
|
if (top && (cap = this.rules.def.exec(src))) {
|
|||
|
src = src.substring(cap[0].length);
|
|||
|
this.tokens.links[cap[1].toLowerCase()] = {
|
|||
|
href: cap[2],
|
|||
|
title: cap[3]
|
|||
|
};
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// table (gfm)
|
|||
|
if (top && (cap = this.rules.table.exec(src))) {
|
|||
|
src = src.substring(cap[0].length);
|
|||
|
|
|||
|
item = {
|
|||
|
type: 'table',
|
|||
|
header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
|
|||
|
align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
|
|||
|
cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
|
|||
|
};
|
|||
|
|
|||
|
for (i = 0; i < item.align.length; i++) {
|
|||
|
if (/^ *-+: *$/.test(item.align[i])) {
|
|||
|
item.align[i] = 'right';
|
|||
|
} else if (/^ *:-+: *$/.test(item.align[i])) {
|
|||
|
item.align[i] = 'center';
|
|||
|
} else if (/^ *:-+ *$/.test(item.align[i])) {
|
|||
|
item.align[i] = 'left';
|
|||
|
} else {
|
|||
|
item.align[i] = null;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
for (i = 0; i < item.cells.length; i++) {
|
|||
|
item.cells[i] = item.cells[i]
|
|||
|
.replace(/^ *\| *| *\| *$/g, '')
|
|||
|
.split(/ *\| */);
|
|||
|
}
|
|||
|
|
|||
|
this.tokens.push(item);
|
|||
|
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// top-level paragraph
|
|||
|
if (top && (cap = this.rules.paragraph.exec(src))) {
|
|||
|
src = src.substring(cap[0].length);
|
|||
|
this.tokens.push({
|
|||
|
type: 'paragraph',
|
|||
|
text: cap[1].charAt(cap[1].length - 1) === '\n'
|
|||
|
? cap[1].slice(0, -1)
|
|||
|
: cap[1]
|
|||
|
});
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// text
|
|||
|
if (cap = this.rules.text.exec(src)) {
|
|||
|
// Top-level should never reach here.
|
|||
|
src = src.substring(cap[0].length);
|
|||
|
this.tokens.push({
|
|||
|
type: 'text',
|
|||
|
text: cap[0]
|
|||
|
});
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if (src) {
|
|||
|
throw new
|
|||
|
Error('Infinite loop on byte: ' + src.charCodeAt(0));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return this.tokens;
|
|||
|
};
|
|||
|
|
|||
|
/**
|
|||
|
* Inline-Level Grammar
|
|||
|
*/
|
|||
|
|
|||
|
var inline = {
|
|||
|
escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
|
|||
|
autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
|
|||
|
url: noop,
|
|||
|
tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
|
|||
|
link: /^!?\[(inside)\]\(href\)/,
|
|||
|
reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
|
|||
|
nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
|
|||
|
strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
|
|||
|
em: /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
|
|||
|
code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
|
|||
|
br: /^ {2,}\n(?!\s*$)/,
|
|||
|
del: noop,
|
|||
|
text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
|
|||
|
};
|
|||
|
|
|||
|
inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;
|
|||
|
inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
|
|||
|
|
|||
|
inline.link = replace(inline.link)
|
|||
|
('inside', inline._inside)
|
|||
|
('href', inline._href)
|
|||
|
();
|
|||
|
|
|||
|
inline.reflink = replace(inline.reflink)
|
|||
|
('inside', inline._inside)
|
|||
|
();
|
|||
|
|
|||
|
/**
|
|||
|
* Normal Inline Grammar
|
|||
|
*/
|
|||
|
|
|||
|
inline.normal = merge({}, inline);
|
|||
|
|
|||
|
/**
|
|||
|
* Pedantic Inline Grammar
|
|||
|
*/
|
|||
|
|
|||
|
inline.pedantic = merge({}, inline.normal, {
|
|||
|
strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
|
|||
|
em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
|
|||
|
});
|
|||
|
|
|||
|
/**
|
|||
|
* GFM Inline Grammar
|
|||
|
*/
|
|||
|
|
|||
|
inline.gfm = merge({}, inline.normal, {
|
|||
|
escape: replace(inline.escape)('])', '~|])')(),
|
|||
|
url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
|
|||
|
del: /^~~(?=\S)([\s\S]*?\S)~~/,
|
|||
|
text: replace(inline.text)
|
|||
|
(']|', '~]|')
|
|||
|
('|', '|https?://|')
|
|||
|
()
|
|||
|
});
|
|||
|
|
|||
|
/**
|
|||
|
* GFM + Line Breaks Inline Grammar
|
|||
|
*/
|
|||
|
|
|||
|
inline.breaks = merge({}, inline.gfm, {
|
|||
|
br: replace(inline.br)('{2,}', '*')(),
|
|||
|
text: replace(inline.gfm.text)('{2,}', '*')()
|
|||
|
});
|
|||
|
|
|||
|
/**
|
|||
|
* Inline Lexer & Compiler
|
|||
|
*/
|
|||
|
|
|||
|
function InlineLexer(links, options) {
|
|||
|
this.options = options || marked.defaults;
|
|||
|
this.links = links;
|
|||
|
this.rules = inline.normal;
|
|||
|
this.renderer = this.options.renderer || new Renderer;
|
|||
|
this.renderer.options = this.options;
|
|||
|
|
|||
|
if (!this.links) {
|
|||
|
throw new
|
|||
|
Error('Tokens array requires a `links` property.');
|
|||
|
}
|
|||
|
|
|||
|
if (this.options.gfm) {
|
|||
|
if (this.options.breaks) {
|
|||
|
this.rules = inline.breaks;
|
|||
|
} else {
|
|||
|
this.rules = inline.gfm;
|
|||
|
}
|
|||
|
} else if (this.options.pedantic) {
|
|||
|
this.rules = inline.pedantic;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Expose Inline Rules
|
|||
|
*/
|
|||
|
|
|||
|
InlineLexer.rules = inline;
|
|||
|
|
|||
|
/**
|
|||
|
* Static Lexing/Compiling Method
|
|||
|
*/
|
|||
|
|
|||
|
InlineLexer.output = function(src, links, options) {
|
|||
|
var inline = new InlineLexer(links, options);
|
|||
|
return inline.output(src);
|
|||
|
};
|
|||
|
|
|||
|
/**
|
|||
|
* Lexing/Compiling
|
|||
|
*/
|
|||
|
|
|||
|
InlineLexer.prototype.output = function(src) {
|
|||
|
var out = ''
|
|||
|
, link
|
|||
|
, text
|
|||
|
, href
|
|||
|
, cap;
|
|||
|
|
|||
|
while (src) {
|
|||
|
// escape
|
|||
|
if (cap = this.rules.escape.exec(src)) {
|
|||
|
src = src.substring(cap[0].length);
|
|||
|
out += cap[1];
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// autolink
|
|||
|
if (cap = this.rules.autolink.exec(src)) {
|
|||
|
src = src.substring(cap[0].length);
|
|||
|
if (cap[2] === '@') {
|
|||
|
text = cap[1].charAt(6) === ':'
|
|||
|
? this.mangle(cap[1].substring(7))
|
|||
|
: this.mangle(cap[1]);
|
|||
|
href = this.mangle('mailto:') + text;
|
|||
|
} else {
|
|||
|
text = escape(cap[1]);
|
|||
|
href = text;
|
|||
|
}
|
|||
|
out += this.renderer.link(href, null, text);
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// url (gfm)
|
|||
|
if (cap = this.rules.url.exec(src)) {
|
|||
|
src = src.substring(cap[0].length);
|
|||
|
text = escape(cap[1]);
|
|||
|
href = text;
|
|||
|
out += this.renderer.link(href, null, text);
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// tag
|
|||
|
if (cap = this.rules.tag.exec(src)) {
|
|||
|
src = src.substring(cap[0].length);
|
|||
|
out += this.options.sanitize
|
|||
|
? escape(cap[0])
|
|||
|
: cap[0];
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// link
|
|||
|
if (cap = this.rules.link.exec(src)) {
|
|||
|
src = src.substring(cap[0].length);
|
|||
|
out += this.outputLink(cap, {
|
|||
|
href: cap[2],
|
|||
|
title: cap[3]
|
|||
|
});
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// reflink, nolink
|
|||
|
if ((cap = this.rules.reflink.exec(src))
|
|||
|
|| (cap = this.rules.nolink.exec(src))) {
|
|||
|
src = src.substring(cap[0].length);
|
|||
|
link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
|
|||
|
link = this.links[link.toLowerCase()];
|
|||
|
if (!link || !link.href) {
|
|||
|
out += cap[0].charAt(0);
|
|||
|
src = cap[0].substring(1) + src;
|
|||
|
continue;
|
|||
|
}
|
|||
|
out += this.outputLink(cap, link);
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// strong
|
|||
|
if (cap = this.rules.strong.exec(src)) {
|
|||
|
src = src.substring(cap[0].length);
|
|||
|
out += this.renderer.strong(this.output(cap[2] || cap[1]));
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// em
|
|||
|
if (cap = this.rules.em.exec(src)) {
|
|||
|
src = src.substring(cap[0].length);
|
|||
|
out += this.renderer.em(this.output(cap[2] || cap[1]));
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// code
|
|||
|
if (cap = this.rules.code.exec(src)) {
|
|||
|
src = src.substring(cap[0].length);
|
|||
|
out += this.renderer.codespan(escape(cap[2], true));
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// br
|
|||
|
if (cap = this.rules.br.exec(src)) {
|
|||
|
src = src.substring(cap[0].length);
|
|||
|
out += this.renderer.br();
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// del (gfm)
|
|||
|
if (cap = this.rules.del.exec(src)) {
|
|||
|
src = src.substring(cap[0].length);
|
|||
|
out += this.renderer.del(this.output(cap[1]));
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// text
|
|||
|
if (cap = this.rules.text.exec(src)) {
|
|||
|
src = src.substring(cap[0].length);
|
|||
|
out += escape(this.smartypants(cap[0]));
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if (src) {
|
|||
|
throw new
|
|||
|
Error('Infinite loop on byte: ' + src.charCodeAt(0));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return out;
|
|||
|
};
|
|||
|
|
|||
|
/**
|
|||
|
* Compile Link
|
|||
|
*/
|
|||
|
|
|||
|
InlineLexer.prototype.outputLink = function(cap, link) {
|
|||
|
var href = escape(link.href)
|
|||
|
, title = link.title ? escape(link.title) : null;
|
|||
|
|
|||
|
return cap[0].charAt(0) !== '!'
|
|||
|
? this.renderer.link(href, title, this.output(cap[1]))
|
|||
|
: this.renderer.image(href, title, escape(cap[1]));
|
|||
|
};
|
|||
|
|
|||
|
/**
|
|||
|
* Smartypants Transformations
|
|||
|
*/
|
|||
|
|
|||
|
InlineLexer.prototype.smartypants = function(text) {
|
|||
|
if (!this.options.smartypants) return text;
|
|||
|
return text
|
|||
|
// em-dashes
|
|||
|
.replace(/--/g, '\u2014')
|
|||
|
// opening singles
|
|||
|
.replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
|
|||
|
// closing singles & apostrophes
|
|||
|
.replace(/'/g, '\u2019')
|
|||
|
// opening doubles
|
|||
|
.replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
|
|||
|
// closing doubles
|
|||
|
.replace(/"/g, '\u201d')
|
|||
|
// ellipses
|
|||
|
.replace(/\.{3}/g, '\u2026');
|
|||
|
};
|
|||
|
|
|||
|
/**
|
|||
|
* Mangle Links
|
|||
|
*/
|
|||
|
|
|||
|
InlineLexer.prototype.mangle = function(text) {
|
|||
|
var out = ''
|
|||
|
, l = text.length
|
|||
|
, i = 0
|
|||
|
, ch;
|
|||
|
|
|||
|
for (; i < l; i++) {
|
|||
|
ch = text.charCodeAt(i);
|
|||
|
if (Math.random() > 0.5) {
|
|||
|
ch = 'x' + ch.toString(16);
|
|||
|
}
|
|||
|
out += '&#' + ch + ';';
|
|||
|
}
|
|||
|
|
|||
|
return out;
|
|||
|
};
|
|||
|
|
|||
|
/**
|
|||
|
* Renderer
|
|||
|
*/
|
|||
|
|
|||
|
function Renderer(options) {
|
|||
|
this.options = options || {};
|
|||
|
}
|
|||
|
|
|||
|
Renderer.prototype.code = function(code, lang, escaped) {
|
|||
|
if (this.options.highlight) {
|
|||
|
var out = this.options.highlight(code, lang);
|
|||
|
if (out != null && out !== code) {
|
|||
|
escaped = true;
|
|||
|
code = out;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!lang) {
|
|||
|
return '<pre><code>'
|
|||
|
+ (escaped ? code : escape(code, true))
|
|||
|
+ '\n</code></pre>';
|
|||
|
}
|
|||
|
|
|||
|
return '<pre><code class="'
|
|||
|
+ this.options.langPrefix
|
|||
|
+ escape(lang, true)
|
|||
|
+ '">'
|
|||
|
+ (escaped ? code : escape(code, true))
|
|||
|
+ '\n</code></pre>\n';
|
|||
|
};
|
|||
|
|
|||
|
Renderer.prototype.blockquote = function(quote) {
|
|||
|
return '<blockquote>\n' + quote + '</blockquote>\n';
|
|||
|
};
|
|||
|
|
|||
|
Renderer.prototype.html = function(html) {
|
|||
|
return html;
|
|||
|
};
|
|||
|
|
|||
|
Renderer.prototype.heading = function(text, level, raw) {
|
|||
|
return '<h'
|
|||
|
+ level
|
|||
|
+ ' id="'
|
|||
|
+ this.options.headerPrefix
|
|||
|
+ raw.toLowerCase().replace(/[^\w]+/g, '-')
|
|||
|
+ '">'
|
|||
|
+ text
|
|||
|
+ '</h'
|
|||
|
+ level
|
|||
|
+ '>\n';
|
|||
|
};
|
|||
|
|
|||
|
Renderer.prototype.hr = function() {
|
|||
|
return '<hr>\n';
|
|||
|
};
|
|||
|
|
|||
|
Renderer.prototype.list = function(body, ordered) {
|
|||
|
var type = ordered ? 'ol' : 'ul';
|
|||
|
return '<' + type + '>\n' + body + '</' + type + '>\n';
|
|||
|
};
|
|||
|
|
|||
|
Renderer.prototype.listitem = function(text) {
|
|||
|
return '<li>' + text + '</li>\n';
|
|||
|
};
|
|||
|
|
|||
|
Renderer.prototype.paragraph = function(text) {
|
|||
|
return '<p>' + text + '</p>\n';
|
|||
|
};
|
|||
|
|
|||
|
Renderer.prototype.table = function(header, body) {
|
|||
|
return '<table>\n'
|
|||
|
+ '<thead>\n'
|
|||
|
+ header
|
|||
|
+ '</thead>\n'
|
|||
|
+ '<tbody>\n'
|
|||
|
+ body
|
|||
|
+ '</tbody>\n'
|
|||
|
+ '</table>\n';
|
|||
|
};
|
|||
|
|
|||
|
Renderer.prototype.tablerow = function(content) {
|
|||
|
return '<tr>\n' + content + '</tr>\n';
|
|||
|
};
|
|||
|
|
|||
|
Renderer.prototype.tablecell = function(content, flags) {
|
|||
|
var type = flags.header ? 'th' : 'td';
|
|||
|
var tag = flags.align
|
|||
|
? '<' + type + ' style="text-align:' + flags.align + '">'
|
|||
|
: '<' + type + '>';
|
|||
|
return tag + content + '</' + type + '>\n';
|
|||
|
};
|
|||
|
|
|||
|
// span level renderer
|
|||
|
Renderer.prototype.strong = function(text) {
|
|||
|
return '<strong>' + text + '</strong>';
|
|||
|
};
|
|||
|
|
|||
|
Renderer.prototype.em = function(text) {
|
|||
|
return '<em>' + text + '</em>';
|
|||
|
};
|
|||
|
|
|||
|
Renderer.prototype.codespan = function(text) {
|
|||
|
return '<code>' + text + '</code>';
|
|||
|
};
|
|||
|
|
|||
|
Renderer.prototype.br = function() {
|
|||
|
return '<br>';
|
|||
|
};
|
|||
|
|
|||
|
Renderer.prototype.del = function(text) {
|
|||
|
return '<del>' + text + '</del>';
|
|||
|
};
|
|||
|
|
|||
|
Renderer.prototype.link = function(href, title, text) {
|
|||
|
if (this.options.sanitize) {
|
|||
|
try {
|
|||
|
var prot = decodeURIComponent(unescape(href))
|
|||
|
.replace(/[^\w:]/g, '')
|
|||
|
.toLowerCase();
|
|||
|
} catch (e) {
|
|||
|
return '';
|
|||
|
}
|
|||
|
if (prot.indexOf('javascript:') === 0) {
|
|||
|
return '';
|
|||
|
}
|
|||
|
}
|
|||
|
var out = '<a href="' + href + '"';
|
|||
|
if (title) {
|
|||
|
out += ' title="' + title + '"';
|
|||
|
}
|
|||
|
out += '>' + text + '</a>';
|
|||
|
return out;
|
|||
|
};
|
|||
|
|
|||
|
Renderer.prototype.image = function(href, title, text) {
|
|||
|
var out = '<img src="' + href + '" alt="' + text + '"';
|
|||
|
if (title) {
|
|||
|
out += ' title="' + title + '"';
|
|||
|
}
|
|||
|
out += '>';
|
|||
|
return out;
|
|||
|
};
|
|||
|
|
|||
|
/**
|
|||
|
* Parsing & Compiling
|
|||
|
*/
|
|||
|
|
|||
|
function Parser(options) {
|
|||
|
this.tokens = [];
|
|||
|
this.token = null;
|
|||
|
this.options = options || marked.defaults;
|
|||
|
this.options.renderer = this.options.renderer || new Renderer;
|
|||
|
this.renderer = this.options.renderer;
|
|||
|
this.renderer.options = this.options;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Static Parse Method
|
|||
|
*/
|
|||
|
|
|||
|
Parser.parse = function(src, options, renderer) {
|
|||
|
var parser = new Parser(options, renderer);
|
|||
|
return parser.parse(src);
|
|||
|
};
|
|||
|
|
|||
|
/**
|
|||
|
* Parse Loop
|
|||
|
*/
|
|||
|
|
|||
|
Parser.prototype.parse = function(src) {
|
|||
|
this.inline = new InlineLexer(src.links, this.options, this.renderer);
|
|||
|
this.tokens = src.reverse();
|
|||
|
|
|||
|
var out = '';
|
|||
|
while (this.next()) {
|
|||
|
out += this.tok();
|
|||
|
}
|
|||
|
|
|||
|
return out;
|
|||
|
};
|
|||
|
|
|||
|
/**
|
|||
|
* Next Token
|
|||
|
*/
|
|||
|
|
|||
|
Parser.prototype.next = function() {
|
|||
|
return this.token = this.tokens.pop();
|
|||
|
};
|
|||
|
|
|||
|
/**
|
|||
|
* Preview Next Token
|
|||
|
*/
|
|||
|
|
|||
|
Parser.prototype.peek = function() {
|
|||
|
return this.tokens[this.tokens.length - 1] || 0;
|
|||
|
};
|
|||
|
|
|||
|
/**
|
|||
|
* Parse Text Tokens
|
|||
|
*/
|
|||
|
|
|||
|
Parser.prototype.parseText = function() {
|
|||
|
var body = this.token.text;
|
|||
|
|
|||
|
while (this.peek().type === 'text') {
|
|||
|
body += '\n' + this.next().text;
|
|||
|
}
|
|||
|
|
|||
|
return this.inline.output(body);
|
|||
|
};
|
|||
|
|
|||
|
/**
|
|||
|
* Parse Current Token
|
|||
|
*/
|
|||
|
|
|||
|
Parser.prototype.tok = function() {
|
|||
|
switch (this.token.type) {
|
|||
|
case 'space': {
|
|||
|
return '';
|
|||
|
}
|
|||
|
case 'hr': {
|
|||
|
return this.renderer.hr();
|
|||
|
}
|
|||
|
case 'heading': {
|
|||
|
return this.renderer.heading(
|
|||
|
this.inline.output(this.token.text),
|
|||
|
this.token.depth,
|
|||
|
this.token.text);
|
|||
|
}
|
|||
|
case 'code': {
|
|||
|
return this.renderer.code(this.token.text,
|
|||
|
this.token.lang,
|
|||
|
this.token.escaped);
|
|||
|
}
|
|||
|
case 'table': {
|
|||
|
var header = ''
|
|||
|
, body = ''
|
|||
|
, i
|
|||
|
, row
|
|||
|
, cell
|
|||
|
, flags
|
|||
|
, j;
|
|||
|
|
|||
|
// header
|
|||
|
cell = '';
|
|||
|
for (i = 0; i < this.token.header.length; i++) {
|
|||
|
flags = { header: true, align: this.token.align[i] };
|
|||
|
cell += this.renderer.tablecell(
|
|||
|
this.inline.output(this.token.header[i]),
|
|||
|
{ header: true, align: this.token.align[i] }
|
|||
|
);
|
|||
|
}
|
|||
|
header += this.renderer.tablerow(cell);
|
|||
|
|
|||
|
for (i = 0; i < this.token.cells.length; i++) {
|
|||
|
row = this.token.cells[i];
|
|||
|
|
|||
|
cell = '';
|
|||
|
for (j = 0; j < row.length; j++) {
|
|||
|
cell += this.renderer.tablecell(
|
|||
|
this.inline.output(row[j]),
|
|||
|
{ header: false, align: this.token.align[j] }
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
body += this.renderer.tablerow(cell);
|
|||
|
}
|
|||
|
return this.renderer.table(header, body);
|
|||
|
}
|
|||
|
case 'blockquote_start': {
|
|||
|
var body = '';
|
|||
|
|
|||
|
while (this.next().type !== 'blockquote_end') {
|
|||
|
body += this.tok();
|
|||
|
}
|
|||
|
|
|||
|
return this.renderer.blockquote(body);
|
|||
|
}
|
|||
|
case 'list_start': {
|
|||
|
var body = ''
|
|||
|
, ordered = this.token.ordered;
|
|||
|
|
|||
|
while (this.next().type !== 'list_end') {
|
|||
|
body += this.tok();
|
|||
|
}
|
|||
|
|
|||
|
return this.renderer.list(body, ordered);
|
|||
|
}
|
|||
|
case 'list_item_start': {
|
|||
|
var body = '';
|
|||
|
|
|||
|
while (this.next().type !== 'list_item_end') {
|
|||
|
body += this.token.type === 'text'
|
|||
|
? this.parseText()
|
|||
|
: this.tok();
|
|||
|
}
|
|||
|
|
|||
|
return this.renderer.listitem(body);
|
|||
|
}
|
|||
|
case 'loose_item_start': {
|
|||
|
var body = '';
|
|||
|
|
|||
|
while (this.next().type !== 'list_item_end') {
|
|||
|
body += this.tok();
|
|||
|
}
|
|||
|
|
|||
|
return this.renderer.listitem(body);
|
|||
|
}
|
|||
|
case 'html': {
|
|||
|
var html = !this.token.pre && !this.options.pedantic
|
|||
|
? this.inline.output(this.token.text)
|
|||
|
: this.token.text;
|
|||
|
return this.renderer.html(html);
|
|||
|
}
|
|||
|
case 'paragraph': {
|
|||
|
return this.renderer.paragraph(this.inline.output(this.token.text));
|
|||
|
}
|
|||
|
case 'text': {
|
|||
|
return this.renderer.paragraph(this.parseText());
|
|||
|
}
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
/**
|
|||
|
* Helpers
|
|||
|
*/
|
|||
|
|
|||
|
function escape(html, encode) {
|
|||
|
return html
|
|||
|
.replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&')
|
|||
|
.replace(/</g, '<')
|
|||
|
.replace(/>/g, '>')
|
|||
|
.replace(/"/g, '"')
|
|||
|
.replace(/'/g, ''');
|
|||
|
}
|
|||
|
|
|||
|
function unescape(html) {
|
|||
|
return html.replace(/&([#\w]+);/g, function(_, n) {
|
|||
|
n = n.toLowerCase();
|
|||
|
if (n === 'colon') return ':';
|
|||
|
if (n.charAt(0) === '#') {
|
|||
|
return n.charAt(1) === 'x'
|
|||
|
? String.fromCharCode(parseInt(n.substring(2), 16))
|
|||
|
: String.fromCharCode(+n.substring(1));
|
|||
|
}
|
|||
|
return '';
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
function replace(regex, opt) {
|
|||
|
regex = regex.source;
|
|||
|
opt = opt || '';
|
|||
|
return function self(name, val) {
|
|||
|
if (!name) return new RegExp(regex, opt);
|
|||
|
val = val.source || val;
|
|||
|
val = val.replace(/(^|[^\[])\^/g, '$1');
|
|||
|
regex = regex.replace(name, val);
|
|||
|
return self;
|
|||
|
};
|
|||
|
}
|
|||
|
|
|||
|
function noop() {}
|
|||
|
noop.exec = noop;
|
|||
|
|
|||
|
function merge(obj) {
|
|||
|
var i = 1
|
|||
|
, target
|
|||
|
, key;
|
|||
|
|
|||
|
for (; i < arguments.length; i++) {
|
|||
|
target = arguments[i];
|
|||
|
for (key in target) {
|
|||
|
if (Object.prototype.hasOwnProperty.call(target, key)) {
|
|||
|
obj[key] = target[key];
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return obj;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Marked
|
|||
|
*/
|
|||
|
|
|||
|
function marked(src, opt, callback) {
|
|||
|
if (callback || typeof opt === 'function') {
|
|||
|
if (!callback) {
|
|||
|
callback = opt;
|
|||
|
opt = null;
|
|||
|
}
|
|||
|
|
|||
|
opt = merge({}, marked.defaults, opt || {});
|
|||
|
|
|||
|
var highlight = opt.highlight
|
|||
|
, tokens
|
|||
|
, pending
|
|||
|
, i = 0;
|
|||
|
|
|||
|
try {
|
|||
|
tokens = Lexer.lex(src, opt)
|
|||
|
} catch (e) {
|
|||
|
return callback(e);
|
|||
|
}
|
|||
|
|
|||
|
pending = tokens.length;
|
|||
|
|
|||
|
var done = function() {
|
|||
|
var out, err;
|
|||
|
|
|||
|
try {
|
|||
|
out = Parser.parse(tokens, opt);
|
|||
|
} catch (e) {
|
|||
|
err = e;
|
|||
|
}
|
|||
|
|
|||
|
opt.highlight = highlight;
|
|||
|
|
|||
|
return err
|
|||
|
? callback(err)
|
|||
|
: callback(null, out);
|
|||
|
};
|
|||
|
|
|||
|
if (!highlight || highlight.length < 3) {
|
|||
|
return done();
|
|||
|
}
|
|||
|
|
|||
|
delete opt.highlight;
|
|||
|
|
|||
|
if (!pending) return done();
|
|||
|
|
|||
|
for (; i < tokens.length; i++) {
|
|||
|
(function(token) {
|
|||
|
if (token.type !== 'code') {
|
|||
|
return --pending || done();
|
|||
|
}
|
|||
|
return highlight(token.text, token.lang, function(err, code) {
|
|||
|
if (code == null || code === token.text) {
|
|||
|
return --pending || done();
|
|||
|
}
|
|||
|
token.text = code;
|
|||
|
token.escaped = true;
|
|||
|
--pending || done();
|
|||
|
});
|
|||
|
})(tokens[i]);
|
|||
|
}
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
try {
|
|||
|
if (opt) opt = merge({}, marked.defaults, opt);
|
|||
|
return Parser.parse(Lexer.lex(src, opt), opt);
|
|||
|
} catch (e) {
|
|||
|
e.message += '\nPlease report this to https://github.com/chjj/marked.';
|
|||
|
if ((opt || marked.defaults).silent) {
|
|||
|
return '<p>An error occured:</p><pre>'
|
|||
|
+ escape(e.message + '', true)
|
|||
|
+ '</pre>';
|
|||
|
}
|
|||
|
throw e;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Options
|
|||
|
*/
|
|||
|
|
|||
|
marked.options =
|
|||
|
marked.setOptions = function(opt) {
|
|||
|
merge(marked.defaults, opt);
|
|||
|
return marked;
|
|||
|
};
|
|||
|
|
|||
|
marked.defaults = {
|
|||
|
gfm: true,
|
|||
|
tables: true,
|
|||
|
breaks: false,
|
|||
|
pedantic: false,
|
|||
|
sanitize: false,
|
|||
|
smartLists: false,
|
|||
|
silent: false,
|
|||
|
highlight: null,
|
|||
|
langPrefix: 'lang-',
|
|||
|
smartypants: false,
|
|||
|
headerPrefix: '',
|
|||
|
renderer: new Renderer
|
|||
|
};
|
|||
|
|
|||
|
/**
|
|||
|
* Expose
|
|||
|
*/
|
|||
|
|
|||
|
marked.Parser = Parser;
|
|||
|
marked.parser = Parser.parse;
|
|||
|
|
|||
|
marked.Renderer = Renderer;
|
|||
|
|
|||
|
marked.Lexer = Lexer;
|
|||
|
marked.lexer = Lexer.lex;
|
|||
|
|
|||
|
marked.InlineLexer = InlineLexer;
|
|||
|
marked.inlineLexer = InlineLexer.output;
|
|||
|
|
|||
|
marked.parse = marked;
|
|||
|
|
|||
|
if (typeof exports === 'object') {
|
|||
|
module.exports = marked;
|
|||
|
} else if (typeof define === 'function' && define.amd) {
|
|||
|
define(function() { return marked; });
|
|||
|
} else {
|
|||
|
this.marked = marked;
|
|||
|
}
|
|||
|
|
|||
|
}).call(function() {
|
|||
|
return this || (typeof window !== 'undefined' ? window : global);
|
|||
|
}());
|
|||
|
|
|||
|
})(window)
|
|||
|
},{}]},{},[3])
|
|||
|
;
|