Skip to content

Commit

Permalink
File Highlight & JSONP Highlight update (#1974)
Browse files Browse the repository at this point in the history
  • Loading branch information
RunDevelopment committed Jun 28, 2020
1 parent 05c9f20 commit afea17d
Show file tree
Hide file tree
Showing 7 changed files with 343 additions and 167 deletions.
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);
}

// 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.

0 comments on commit afea17d

Please sign in to comment.