Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

File Highlight & JSONP Highlight update #1974

Merged
4 changes: 3 additions & 1 deletion plugins/copy-to-clipboard/prism-copy-to-clipboard.js
Expand Up @@ -39,6 +39,8 @@
var linkCopy = document.createElement('button');
linkCopy.textContent = 'Copy';

var element = env.element;

if (!ClipboardJS) {
callbacks.push(registerClipboard);
} else {
Expand All @@ -50,7 +52,7 @@
function registerClipboard() {
var clip = new ClipboardJS(linkCopy, {
'text': function () {
return env.code;
return element.textContent;
}
});

Expand Down
2 changes: 1 addition & 1 deletion plugins/copy-to-clipboard/prism-copy-to-clipboard.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

170 changes: 111 additions & 59 deletions plugins/file-highlight/prism-file-highlight.js
@@ -1,89 +1,141 @@
(function () {
if (typeof self === 'undefined' || !self.Prism || !self.document || !document.querySelector) {
if (typeof self === 'undefined' || !self.Prism || !self.document) {
return;
}

var Prism = window.Prism;

var LOADING_MESSAGE = 'Loading…';
var FAILURE_MESSAGE = function (status, message) {
return '✖ Error ' + status + ' while fetching file: ' + message;
};
var FAILURE_EMPTY_MESSAGE = '✖ Error: File does not exist or is empty';

var EXTENSIONS = {
'js': 'javascript',
'py': 'python',
'rb': 'ruby',
'ps1': 'powershell',
'psm1': 'powershell',
'sh': 'bash',
'bat': 'batch',
'h': 'c',
'tex': 'latex'
};

var STATUS_ATTR = 'data-src-status';
var STATUS_LOADING = 'loading';
var STATUS_LOADED = 'loaded';
var STATUS_FAILED = 'failed';

var SELECTOR = 'pre[data-src]:not([' + STATUS_ATTR + '="' + STATUS_LOADED + '"])'
+ ':not([' + STATUS_ATTR + '="' + STATUS_LOADING + '"])';

var lang = /\blang(?:uage)?-([\w-]+)\b/i;

/**
* @param {Element} [container=document]
* Sets the Prism `language-xxxx` or `lang-xxxx` class to the given language.
*
* @param {HTMLElement} element
* @param {string} language
* @returns {void}
*/
self.Prism.fileHighlight = function(container) {
container = container || document;

var Extensions = {
'js': 'javascript',
'py': 'python',
'rb': 'ruby',
'ps1': 'powershell',
'psm1': 'powershell',
'sh': 'bash',
'bat': 'batch',
'h': 'c',
'tex': 'latex'
};

Array.prototype.slice.call(container.querySelectorAll('pre[data-src]')).forEach(function (pre) {
// ignore if already loaded
if (pre.hasAttribute('data-src-loaded')) {
return;
}
function setLanguageClass(element, language) {
var className = element.className;
className = className.replace(lang, ' ') + ' language-' + language;
element.className = className.replace(/\s+/g, ' ').trim();
}

// load current
var src = pre.getAttribute('data-src');

var language, parent = pre;
var lang = /\blang(?:uage)?-([\w-]+)\b/i;
while (parent && !lang.test(parent.className)) {
parent = parent.parentNode;
}
Prism.hooks.add('before-highlightall', function (env) {
env.selector += ', ' + SELECTOR;
});

if (parent) {
language = (pre.className.match(lang) || [, ''])[1];
}
Prism.hooks.add('before-sanity-check', function (env) {
var pre = /** @type {HTMLPreElement} */ (env.element);
if (pre.matches(SELECTOR)) {
env.code = ''; // fast-path the whole thing and go to complete

if (!language) {
var extension = (src.match(/\.(\w+)$/) || [, ''])[1];
language = Extensions[extension] || extension;
}
pre.setAttribute(STATUS_ATTR, STATUS_LOADING); // mark as loading

var code = document.createElement('code');
code.className = 'language-' + language;
// add code element with loading message
var code = pre.appendChild(document.createElement('CODE'));
code.textContent = LOADING_MESSAGE;

pre.textContent = '';
var src = pre.getAttribute('data-src');

code.textContent = 'Loading…';
var language = env.language;
if (language === 'none') {
// the language might be 'none' because there is no language set;
// in this case, we want to use the extension as the language
var extension = (/\.(\w+)$/.exec(src) || [, 'none'])[1];
language = EXTENSIONS[extension] || extension;
}

pre.appendChild(code);
// set language classes
setLanguageClass(code, language);
setLanguageClass(pre, language);

var xhr = new XMLHttpRequest();
// preload the language
var autoloader = Prism.plugins.autoloader;
if (autoloader) {
autoloader.loadLanguages(language);
}
RunDevelopment marked this conversation as resolved.
Show resolved Hide resolved

// load file
var xhr = new XMLHttpRequest();
xhr.open('GET', src, true);

xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {

if (xhr.status < 400 && xhr.responseText) {
code.textContent = xhr.responseText;
// mark as loaded
pre.setAttribute(STATUS_ATTR, STATUS_LOADED);

// highlight code
code.textContent = xhr.responseText;
Prism.highlightElement(code);
// mark as loaded
pre.setAttribute('data-src-loaded', '');
}
else if (xhr.status >= 400) {
code.textContent = '✖ Error ' + xhr.status + ' while fetching file: ' + xhr.statusText;
}
else {
code.textContent = '✖ Error: File does not exist or is empty';

} else {
// mark as failed
pre.setAttribute(STATUS_ATTR, STATUS_FAILED);

if (xhr.status >= 400) {
code.textContent = FAILURE_MESSAGE(xhr.status, xhr.statusText);
} else {
code.textContent = FAILURE_EMPTY_MESSAGE;
}
}
}
};

xhr.send(null);
});
}
});

Prism.plugins.fileHighlight = {
/**
* Executes the File Highlight plugin for all matching `pre` elements under the given container.
*
* Note: Elements which are already loaded or currently loading will not be touched by this method.
*
* @param {ParentNode} [container=document]
*/
highlight: function highlight(container) {
var elements = (container || document).querySelectorAll(SELECTOR);

for (var i = 0, element; element = elements[i++];) {
Prism.highlightElement(element);
}
}
};

document.addEventListener('DOMContentLoaded', function () {
// execute inside handler, for dropping Event as argument
self.Prism.fileHighlight();
});
var logged = false;
/** @deprecated Use `Prism.plugins.fileHighlight.highlight` instead. */
Prism.fileHighlight = function () {
if (!logged) {
console.warn('Prism.fileHighlight is deprecated. Use `Prism.plugins.fileHighlight.highlight` instead.');
logged = true;
}
Prism.plugins.fileHighlight.highlight.apply(this, arguments);
}

})();
2 changes: 1 addition & 1 deletion plugins/file-highlight/prism-file-highlight.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.