| Index: lib/src/prism/plugins/previewer-base/prism-previewer-base.js
|
| diff --git a/lib/src/prism/plugins/previewer-base/prism-previewer-base.js b/lib/src/prism/plugins/previewer-base/prism-previewer-base.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..a5eb59adc6fd6626b86f00bf5a3ccb64f2c2e5e6
|
| --- /dev/null
|
| +++ b/lib/src/prism/plugins/previewer-base/prism-previewer-base.js
|
| @@ -0,0 +1,201 @@
|
| +(function() {
|
| +
|
| + if (typeof self === 'undefined' || !self.Prism || !self.document) {
|
| + return;
|
| + }
|
| +
|
| + /**
|
| + * Returns the absolute X, Y offsets for an element
|
| + * @param {HTMLElement} element
|
| + * @returns {{top: number, right: number, bottom: number, left: number}}
|
| + */
|
| + var getOffset = function (element) {
|
| + var left = 0, top = 0, el = element;
|
| +
|
| + if (el.parentNode) {
|
| + do {
|
| + left += el.offsetLeft;
|
| + top += el.offsetTop;
|
| + } while ((el = el.offsetParent) && el.nodeType < 9);
|
| +
|
| + el = element;
|
| +
|
| + do {
|
| + left -= el.scrollLeft;
|
| + top -= el.scrollTop;
|
| + } while ((el = el.parentNode) && !/body/i.test(el.nodeName));
|
| + }
|
| +
|
| + return {
|
| + top: top,
|
| + right: innerWidth - left - element.offsetWidth,
|
| + bottom: innerHeight - top - element.offsetHeight,
|
| + left: left
|
| + };
|
| + };
|
| +
|
| + var tokenRegexp = /(?:^|\s)token(?=$|\s)/;
|
| + var activeRegexp = /(?:^|\s)active(?=$|\s)/g;
|
| + var flippedRegexp = /(?:^|\s)flipped(?=$|\s)/g;
|
| +
|
| + /**
|
| + * Previewer constructor
|
| + * @param {string} type Unique previewer type
|
| + * @param {function} updater Function that will be called on mouseover.
|
| + * @param {string[]|string=} supportedLanguages Aliases of the languages this previewer must be enabled for. Defaults to "*", all languages.
|
| + * @constructor
|
| + */
|
| + var Previewer = function (type, updater, supportedLanguages, initializer) {
|
| + this._elt = null;
|
| + this._type = type;
|
| + this._clsRegexp = RegExp('(?:^|\\s)' + type + '(?=$|\\s)');
|
| + this._token = null;
|
| + this.updater = updater;
|
| + this._mouseout = this.mouseout.bind(this);
|
| + this.initializer = initializer;
|
| +
|
| + var self = this;
|
| +
|
| + if (!supportedLanguages) {
|
| + supportedLanguages = ['*'];
|
| + }
|
| + if (Prism.util.type(supportedLanguages) !== 'Array') {
|
| + supportedLanguages = [supportedLanguages];
|
| + }
|
| + supportedLanguages.forEach(function (lang) {
|
| + if (typeof lang !== 'string') {
|
| + lang = lang.lang;
|
| + }
|
| + if (!Previewer.byLanguages[lang]) {
|
| + Previewer.byLanguages[lang] = [];
|
| + }
|
| + if (Previewer.byLanguages[lang].indexOf(self) < 0) {
|
| + Previewer.byLanguages[lang].push(self);
|
| + }
|
| + });
|
| + Previewer.byType[type] = this;
|
| + };
|
| +
|
| + /**
|
| + * Creates the HTML element for the previewer.
|
| + */
|
| + Previewer.prototype.init = function () {
|
| + if (this._elt) {
|
| + return;
|
| + }
|
| + this._elt = document.createElement('div');
|
| + this._elt.className = 'prism-previewer prism-previewer-' + this._type;
|
| + document.body.appendChild(this._elt);
|
| + if(this.initializer) {
|
| + this.initializer();
|
| + }
|
| + };
|
| +
|
| + /**
|
| + * Checks the class name of each hovered element
|
| + * @param token
|
| + */
|
| + Previewer.prototype.check = function (token) {
|
| + do {
|
| + if (tokenRegexp.test(token.className) && this._clsRegexp.test(token.className)) {
|
| + break;
|
| + }
|
| + } while(token = token.parentNode);
|
| +
|
| + if (token && token !== this._token) {
|
| + this._token = token;
|
| + this.show();
|
| + }
|
| + };
|
| +
|
| + /**
|
| + * Called on mouseout
|
| + */
|
| + Previewer.prototype.mouseout = function() {
|
| + this._token.removeEventListener('mouseout', this._mouseout, false);
|
| + this._token = null;
|
| + this.hide();
|
| + };
|
| +
|
| + /**
|
| + * Shows the previewer positioned properly for the current token.
|
| + */
|
| + Previewer.prototype.show = function () {
|
| + if (!this._elt) {
|
| + this.init();
|
| + }
|
| + if (!this._token) {
|
| + return;
|
| + }
|
| +
|
| + if (this.updater.call(this._elt, this._token.textContent)) {
|
| + this._token.addEventListener('mouseout', this._mouseout, false);
|
| +
|
| + var offset = getOffset(this._token);
|
| + this._elt.className += ' active';
|
| +
|
| + if (offset.top - this._elt.offsetHeight > 0) {
|
| + this._elt.className = this._elt.className.replace(flippedRegexp, '');
|
| + this._elt.style.top = offset.top + 'px';
|
| + this._elt.style.bottom = '';
|
| + } else {
|
| + this._elt.className += ' flipped';
|
| + this._elt.style.bottom = offset.bottom + 'px';
|
| + this._elt.style.top = '';
|
| + }
|
| +
|
| + this._elt.style.left = offset.left + Math.min(200, this._token.offsetWidth / 2) + 'px';
|
| + } else {
|
| + this.hide();
|
| + }
|
| + };
|
| +
|
| + /**
|
| + * Hides the previewer.
|
| + */
|
| + Previewer.prototype.hide = function () {
|
| + this._elt.className = this._elt.className.replace(activeRegexp, '');
|
| + };
|
| +
|
| + /**
|
| + * Map of all registered previewers by language
|
| + * @type {{}}
|
| + */
|
| + Previewer.byLanguages = {};
|
| +
|
| + /**
|
| + * Map of all registered previewers by type
|
| + * @type {{}}
|
| + */
|
| + Previewer.byType = {};
|
| +
|
| + /**
|
| + * Initializes the mouseover event on the code block.
|
| + * @param {HTMLElement} elt The code block (env.element)
|
| + * @param {string} lang The language (env.language)
|
| + */
|
| + Previewer.initEvents = function (elt, lang) {
|
| + var previewers = [];
|
| + if (Previewer.byLanguages[lang]) {
|
| + previewers = previewers.concat(Previewer.byLanguages[lang]);
|
| + }
|
| + if (Previewer.byLanguages['*']) {
|
| + previewers = previewers.concat(Previewer.byLanguages['*']);
|
| + }
|
| + elt.addEventListener('mouseover', function (e) {
|
| + var target = e.target;
|
| + previewers.forEach(function (previewer) {
|
| + previewer.check(target);
|
| + });
|
| + }, false);
|
| + };
|
| + Prism.plugins.Previewer = Previewer;
|
| +
|
| + // Initialize the previewers only when needed
|
| + Prism.hooks.add('after-highlight', function (env) {
|
| + if(Previewer.byLanguages['*'] || Previewer.byLanguages[env.language]) {
|
| + Previewer.initEvents(env.element, env.language);
|
| + }
|
| + });
|
| +
|
| +}());
|
|
|