Skip to content

Commit afea17d

Browse files
authoredJun 28, 2020
File Highlight & JSONP Highlight update (#1974)
1 parent 05c9f20 commit afea17d

File tree

7 files changed

+343
-167
lines changed

7 files changed

+343
-167
lines changed
 

‎plugins/copy-to-clipboard/prism-copy-to-clipboard.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
var linkCopy = document.createElement('button');
4040
linkCopy.textContent = 'Copy';
4141

42+
var element = env.element;
43+
4244
if (!ClipboardJS) {
4345
callbacks.push(registerClipboard);
4446
} else {
@@ -50,7 +52,7 @@
5052
function registerClipboard() {
5153
var clip = new ClipboardJS(linkCopy, {
5254
'text': function () {
53-
return env.code;
55+
return element.textContent;
5456
}
5557
});
5658

‎plugins/copy-to-clipboard/prism-copy-to-clipboard.min.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
+111-59
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,141 @@
11
(function () {
2-
if (typeof self === 'undefined' || !self.Prism || !self.document || !document.querySelector) {
2+
if (typeof self === 'undefined' || !self.Prism || !self.document) {
33
return;
44
}
55

6+
var Prism = window.Prism;
7+
8+
var LOADING_MESSAGE = 'Loading…';
9+
var FAILURE_MESSAGE = function (status, message) {
10+
return '✖ Error ' + status + ' while fetching file: ' + message;
11+
};
12+
var FAILURE_EMPTY_MESSAGE = '✖ Error: File does not exist or is empty';
13+
14+
var EXTENSIONS = {
15+
'js': 'javascript',
16+
'py': 'python',
17+
'rb': 'ruby',
18+
'ps1': 'powershell',
19+
'psm1': 'powershell',
20+
'sh': 'bash',
21+
'bat': 'batch',
22+
'h': 'c',
23+
'tex': 'latex'
24+
};
25+
26+
var STATUS_ATTR = 'data-src-status';
27+
var STATUS_LOADING = 'loading';
28+
var STATUS_LOADED = 'loaded';
29+
var STATUS_FAILED = 'failed';
30+
31+
var SELECTOR = 'pre[data-src]:not([' + STATUS_ATTR + '="' + STATUS_LOADED + '"])'
32+
+ ':not([' + STATUS_ATTR + '="' + STATUS_LOADING + '"])';
33+
34+
var lang = /\blang(?:uage)?-([\w-]+)\b/i;
35+
636
/**
7-
* @param {Element} [container=document]
37+
* Sets the Prism `language-xxxx` or `lang-xxxx` class to the given language.
38+
*
39+
* @param {HTMLElement} element
40+
* @param {string} language
41+
* @returns {void}
842
*/
9-
self.Prism.fileHighlight = function(container) {
10-
container = container || document;
11-
12-
var Extensions = {
13-
'js': 'javascript',
14-
'py': 'python',
15-
'rb': 'ruby',
16-
'ps1': 'powershell',
17-
'psm1': 'powershell',
18-
'sh': 'bash',
19-
'bat': 'batch',
20-
'h': 'c',
21-
'tex': 'latex'
22-
};
23-
24-
Array.prototype.slice.call(container.querySelectorAll('pre[data-src]')).forEach(function (pre) {
25-
// ignore if already loaded
26-
if (pre.hasAttribute('data-src-loaded')) {
27-
return;
28-
}
43+
function setLanguageClass(element, language) {
44+
var className = element.className;
45+
className = className.replace(lang, ' ') + ' language-' + language;
46+
element.className = className.replace(/\s+/g, ' ').trim();
47+
}
2948

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

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

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

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

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

51-
pre.textContent = '';
65+
var src = pre.getAttribute('data-src');
5266

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

55-
pre.appendChild(code);
75+
// set language classes
76+
setLanguageClass(code, language);
77+
setLanguageClass(pre, language);
5678

57-
var xhr = new XMLHttpRequest();
79+
// preload the language
80+
var autoloader = Prism.plugins.autoloader;
81+
if (autoloader) {
82+
autoloader.loadLanguages(language);
83+
}
5884

85+
// load file
86+
var xhr = new XMLHttpRequest();
5987
xhr.open('GET', src, true);
60-
6188
xhr.onreadystatechange = function () {
6289
if (xhr.readyState == 4) {
63-
6490
if (xhr.status < 400 && xhr.responseText) {
65-
code.textContent = xhr.responseText;
91+
// mark as loaded
92+
pre.setAttribute(STATUS_ATTR, STATUS_LOADED);
6693

94+
// highlight code
95+
code.textContent = xhr.responseText;
6796
Prism.highlightElement(code);
68-
// mark as loaded
69-
pre.setAttribute('data-src-loaded', '');
70-
}
71-
else if (xhr.status >= 400) {
72-
code.textContent = '✖ Error ' + xhr.status + ' while fetching file: ' + xhr.statusText;
73-
}
74-
else {
75-
code.textContent = '✖ Error: File does not exist or is empty';
97+
98+
} else {
99+
// mark as failed
100+
pre.setAttribute(STATUS_ATTR, STATUS_FAILED);
101+
102+
if (xhr.status >= 400) {
103+
code.textContent = FAILURE_MESSAGE(xhr.status, xhr.statusText);
104+
} else {
105+
code.textContent = FAILURE_EMPTY_MESSAGE;
106+
}
76107
}
77108
}
78109
};
79-
80110
xhr.send(null);
81-
});
111+
}
112+
});
113+
114+
Prism.plugins.fileHighlight = {
115+
/**
116+
* Executes the File Highlight plugin for all matching `pre` elements under the given container.
117+
*
118+
* Note: Elements which are already loaded or currently loading will not be touched by this method.
119+
*
120+
* @param {ParentNode} [container=document]
121+
*/
122+
highlight: function highlight(container) {
123+
var elements = (container || document).querySelectorAll(SELECTOR);
124+
125+
for (var i = 0, element; element = elements[i++];) {
126+
Prism.highlightElement(element);
127+
}
128+
}
82129
};
83130

84-
document.addEventListener('DOMContentLoaded', function () {
85-
// execute inside handler, for dropping Event as argument
86-
self.Prism.fileHighlight();
87-
});
131+
var logged = false;
132+
/** @deprecated Use `Prism.plugins.fileHighlight.highlight` instead. */
133+
Prism.fileHighlight = function () {
134+
if (!logged) {
135+
console.warn('Prism.fileHighlight is deprecated. Use `Prism.plugins.fileHighlight.highlight` instead.');
136+
logged = true;
137+
}
138+
Prism.plugins.fileHighlight.highlight.apply(this, arguments);
139+
}
88140

89141
})();

‎plugins/file-highlight/prism-file-highlight.min.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
Please sign in to comment.