Added new Filter highlightAll plugin (#2074)
This adds a new plugin to Prism which allows users to filter which elements will be highlighted by the `highlightAll` and `highlightAllUnder` methods.
This commit is contained in:
parent
9908ca69e7
commit
a7f7009019
File diff suppressed because one or more lines are too long
|
@ -1209,6 +1209,12 @@
|
|||
"description": "Highlights the code inside diff blocks.",
|
||||
"owner": "RunDevelopment",
|
||||
"require": "diff"
|
||||
},
|
||||
"filter-highlight-all": {
|
||||
"title": "Filter highlightAll",
|
||||
"description": "Filters the elements the <code>highlightAll</code> and <code>highlightAllUnder</code> methods actually highlight.",
|
||||
"owner": "RunDevelopment",
|
||||
"noCSS": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,24 +18,6 @@ var Prism = (function (_self){
|
|||
var lang = /\blang(?:uage)?-([\w-]+)\b/i;
|
||||
var uniqueId = 0;
|
||||
|
||||
/**
|
||||
* Returns the Prism language of the given element set by a `language-xxxx` or `lang-xxxx` class.
|
||||
*
|
||||
* If no language is set for the element or the element is `null` or `undefined`, `none` will be returned.
|
||||
*
|
||||
* @param {Element} element
|
||||
* @returns {string}
|
||||
*/
|
||||
function getLanguage(element) {
|
||||
while (element && !lang.test(element.className)) {
|
||||
element = element.parentNode;
|
||||
}
|
||||
if (element) {
|
||||
return (element.className.match(lang) || [, 'none'])[1].toLowerCase();
|
||||
}
|
||||
return 'none';
|
||||
}
|
||||
|
||||
|
||||
var _ = {
|
||||
manual: _self.Prism && _self.Prism.manual,
|
||||
|
@ -103,6 +85,24 @@ var _ = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the Prism language of the given element set by a `language-xxxx` or `lang-xxxx` class.
|
||||
*
|
||||
* If no language is set for the element or the element is `null` or `undefined`, `none` will be returned.
|
||||
*
|
||||
* @param {Element} element
|
||||
* @returns {string}
|
||||
*/
|
||||
getLanguage: function (element) {
|
||||
while (element && !lang.test(element.className)) {
|
||||
element = element.parentElement;
|
||||
}
|
||||
if (element) {
|
||||
return (element.className.match(lang) || [, 'none'])[1].toLowerCase();
|
||||
}
|
||||
return 'none';
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the script element that is currently executing.
|
||||
*
|
||||
|
@ -236,21 +236,24 @@ var _ = {
|
|||
highlightAllUnder: function(container, async, callback) {
|
||||
var env = {
|
||||
callback: callback,
|
||||
container: container,
|
||||
selector: 'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'
|
||||
};
|
||||
|
||||
_.hooks.run('before-highlightall', env);
|
||||
|
||||
var elements = container.querySelectorAll(env.selector);
|
||||
env.elements = Array.prototype.slice.apply(env.container.querySelectorAll(env.selector));
|
||||
|
||||
for (var i=0, element; element = elements[i++];) {
|
||||
_.hooks.run('before-all-elements-highlight', env);
|
||||
|
||||
for (var i = 0, element; element = env.elements[i++];) {
|
||||
_.highlightElement(element, async === true, env.callback);
|
||||
}
|
||||
},
|
||||
|
||||
highlightElement: function(element, async, callback) {
|
||||
// Find language
|
||||
var language = getLanguage(element);
|
||||
var language = _.util.getLanguage(element);
|
||||
var grammar = _.languages[language];
|
||||
|
||||
// Set language on the element, if not present
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,146 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="favicon.png" />
|
||||
<title>Filter highlightAll ▲ Prism plugins</title>
|
||||
<base href="../.." />
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
<link rel="stylesheet" href="themes/prism.css" data-noprefix />
|
||||
<script src="scripts/prefixfree.min.js"></script>
|
||||
|
||||
<script>var _gaq = [['_setAccount', 'UA-33746269-1'], ['_trackPageview']];</script>
|
||||
<script src="https://www.google-analytics.com/ga.js" async></script>
|
||||
<style>
|
||||
dt {
|
||||
font-size: 100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header data-plugin-header="filter-highlight-all"></header>
|
||||
|
||||
<section class="language-typescript">
|
||||
<h1>How to use</h1>
|
||||
|
||||
<p>Filter highlightAll provides you with ways to filter the element the <code>highlightAll</code> and <code>highlightAllUnder</code> methods actually highlight. This can be very useful when you use Prism's automatic highlighting when loading the page but want to exclude certain code blocks.</p>
|
||||
</section>
|
||||
|
||||
<section class="language-typescript">
|
||||
<h1>API</h1>
|
||||
|
||||
<p>In <code>Prism.plugins.filterHighlightAll</code> you can find the following:</p>
|
||||
|
||||
<dl>
|
||||
<dt><code>add(condition: (value: { element, language: string }) => boolean): void</code></dt>
|
||||
<dd>
|
||||
Adds a new filter which will only allow an element to be highlighted if the given function returns <code>true</code> for that element. <br>
|
||||
This can be used to define a custom language filter.
|
||||
</dd>
|
||||
|
||||
<dt><code>addSelector(selector: string): void</code></dt>
|
||||
<dd>
|
||||
Adds a new filter which will only allow an element to be highlighted if the element matches the given CSS selector.
|
||||
</dd>
|
||||
|
||||
<dt><code>reject.add(condition: (value: { element, language: string }) => boolean): void</code></dt>
|
||||
<dd>
|
||||
Same as <code>add</code>, but only elements which do <strong>not</strong> fulfill the condition will be highlighted.
|
||||
</dd>
|
||||
|
||||
<dt><code>reject.addSelector(selector: string): void</code></dt>
|
||||
<dd>
|
||||
Same as <code>addSelector</code>, but only elements which do <strong>not</strong> match the selector will be highlighted.
|
||||
</dd>
|
||||
|
||||
<dt><code>filterKnown: boolean = false</code></dt>
|
||||
<dd>
|
||||
Set this to <code>true</code> to only allow known languages.
|
||||
Code blocks without a set language or an unknown language will not be highlighted.
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<p>An element will only be highlighted by the <code>highlightAll</code> and <code>highlightAllUnder</code> methods if all of the above accept the element.</p>
|
||||
|
||||
<h2>Attributes</h2>
|
||||
|
||||
<p>You can also add the following <code class="language-none">data-*</code> attributes to the script which contains the Filter highlightAll plugin.</p>
|
||||
|
||||
<dl>
|
||||
<dt><code class="language-markup"><script src="..." data-filter-selector="<css selector>"></code></dt>
|
||||
<dd>
|
||||
This attribute is a shorthand for <code>Prism.plugins.filterHighlightAll.addSelector</code>.
|
||||
The value of the attribute will be passed as is to the <code>addSelector</code> function.
|
||||
</dd>
|
||||
|
||||
<dt><code class="language-markup"><script src="..." data-reject-selector="<css selector>"></code></dt>
|
||||
<dd>
|
||||
This attribute is a shorthand for <code>Prism.plugins.filterHighlightAll.reject.addSelector</code>.
|
||||
The value of the attribute will be passed as is to the <code>rejectSelector</code> function.
|
||||
</dd>
|
||||
|
||||
<dt><code class="language-markup"><script src="..." data-filter-known></code></dt>
|
||||
<dd>
|
||||
This attribute can be used to set the value of <code>Prism.plugins.filterHighlightAll.filterKnown</code>.
|
||||
<code>filterKnown</code> will be set to <code>true</code> if the attribute is present, <code>false</code> otherwise.
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h1>Examples</h1>
|
||||
|
||||
<p>The following code is used to define a filter on this page.</p>
|
||||
|
||||
<pre><code class="language-javascript">// <code> elements with a .no-highlight class will be ignored
|
||||
Prism.plugins.filterHighlightAll.reject.addSelector('code.no-highlight');
|
||||
Prism.plugins.filterHighlightAll.reject.addSelector('pre.no-highlight > code');
|
||||
|
||||
// don't highlight CSS code
|
||||
Prism.plugins.filterHighlightAll.add(function (env) {
|
||||
return env.language !== 'css';
|
||||
});</code></pre>
|
||||
|
||||
<p>The results:</p>
|
||||
|
||||
<pre class="language-javascript no-highlight"><code class="language-javascript">let foo = "I'm not being highlighted";</code></pre>
|
||||
|
||||
<pre class="language-css"><code class="language-css">a.link::after {
|
||||
content: 'also not being highlighted';
|
||||
color: #F00;
|
||||
}</code></pre>
|
||||
|
||||
<p>Prism will ignore these blocks, so you can even define your own static highlighting which Prism would normally remove.</p>
|
||||
|
||||
<pre class="language-css"><code class="language-css">a.link::before {
|
||||
cont<span class="token selector">ent: 'I just do my o</span>wn highlighted';
|
||||
color: <span class="token constant">#F00</span>;
|
||||
}</code></pre>
|
||||
|
||||
</section>
|
||||
|
||||
<footer data-src="templates/footer.html" data-type="text/html"></footer>
|
||||
|
||||
<script src="prism.js"></script>
|
||||
<script src="components/prism-typescript.js"></script>
|
||||
<script src="plugins/filter-highlight-all/prism-filter-highlight-all.js"></script>
|
||||
<script src="scripts/utopia.js"></script>
|
||||
<script src="components.js"></script>
|
||||
<script src="scripts/code.js"></script>
|
||||
|
||||
<script>
|
||||
// elements with a .no-highlight class will be ignored
|
||||
Prism.plugins.filterHighlightAll.reject.addSelector('code.no-highlight');
|
||||
Prism.plugins.filterHighlightAll.reject.addSelector('pre.no-highlight > code');
|
||||
|
||||
// don't highlight CSS code
|
||||
Prism.plugins.filterHighlightAll.add(function (env) {
|
||||
return env.language !== 'css';
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,125 @@
|
|||
(function () {
|
||||
|
||||
if (typeof self !== 'undefined' && !self.Prism) {
|
||||
return;
|
||||
}
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Element/matches#Polyfill
|
||||
if (!Element.prototype.matches) {
|
||||
Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
|
||||
}
|
||||
|
||||
var script = Prism.util.currentScript();
|
||||
|
||||
|
||||
/**
|
||||
* @type {Array<(element: HTMLElement) => boolean>}
|
||||
*/
|
||||
var filters = [];
|
||||
|
||||
var config = Prism.plugins.filterHighlightAll = {
|
||||
|
||||
/**
|
||||
* Adds a new filter for the elements of `highlightAll` and `highlightAllUnder` such that only elements for
|
||||
* which the given function returns `true` will be highlighted.
|
||||
*
|
||||
* @param {(value: { element: HTMLElement, language: string }) => boolean} condition
|
||||
*/
|
||||
add: function (condition) {
|
||||
filters.push(function (element) {
|
||||
return condition({
|
||||
element: element,
|
||||
language: Prism.util.getLanguage(element)
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a new filter for the elements of `highlightAll` and `highlightAllUnder` such that only elements that
|
||||
* match the given CSS selection will be highlighted.
|
||||
*
|
||||
* @param {string} selector
|
||||
*/
|
||||
addSelector: function (selector) {
|
||||
filters.push(function (element) {
|
||||
return element.matches(selector);
|
||||
});
|
||||
},
|
||||
|
||||
reject: {
|
||||
|
||||
/**
|
||||
* Adds a new filter for the elements of `highlightAll` and `highlightAllUnder` such that only elements for
|
||||
* which the given function returns `false` will be highlighted.
|
||||
*
|
||||
* @param {(value: { element: HTMLElement, language: string }) => boolean} condition
|
||||
*/
|
||||
add: function (condition) {
|
||||
filters.push(function (element) {
|
||||
return !condition({
|
||||
element: element,
|
||||
language: Prism.util.getLanguage(element)
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a new filter for the elements of `highlightAll` and `highlightAllUnder` such that only elements that do
|
||||
* not match the given CSS selection will be highlighted.
|
||||
*
|
||||
* @param {string} selector
|
||||
*/
|
||||
addSelector: function (selector) {
|
||||
filters.push(function (element) {
|
||||
return !element.matches(selector);
|
||||
});
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Filters the elements of `highlightAll` and `highlightAllUnder` such that only elements with a known language
|
||||
* will be highlighted. All elements with an unset or unknown language will be ignored.
|
||||
*
|
||||
* __Note:__ This will effectively disable the AutoLoader plugin.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
filterKnown: !!script && script.hasAttribute('data-filter-known')
|
||||
};
|
||||
|
||||
config.add(function filterKnown(env) {
|
||||
return !config.filterKnown || typeof Prism.languages[env.language] === 'object';
|
||||
});
|
||||
|
||||
if (script) {
|
||||
var attr;
|
||||
if (attr = script.getAttribute('data-filter-selector')) {
|
||||
config.addSelector(attr);
|
||||
}
|
||||
if (attr = script.getAttribute('data-reject-selector')) {
|
||||
config.reject.addSelector(attr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies all filters to the given element and returns true if and only if every filter returned true on the
|
||||
* given element.
|
||||
*
|
||||
* @param {HTMLElement} element
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function combinedFilter(element) {
|
||||
for (var i = 0, l = filters.length; i < l; i++) {
|
||||
if (!filters[i](element)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Prism.hooks.add('before-all-elements-highlight', function (env) {
|
||||
env.elements = env.elements.filter(combinedFilter);
|
||||
});
|
||||
|
||||
}());
|
|
@ -0,0 +1 @@
|
|||
!function(){if("undefined"==typeof self||self.Prism){Element.prototype.matches||(Element.prototype.matches=Element.prototype.msMatchesSelector||Element.prototype.webkitMatchesSelector);var e,t=Prism.util.currentScript(),r=[],n=Prism.plugins.filterHighlightAll={add:function(t){r.push(function(e){return t({element:e,language:Prism.util.getLanguage(e)})})},addSelector:function(t){r.push(function(e){return e.matches(t)})},reject:{add:function(t){r.push(function(e){return!t({element:e,language:Prism.util.getLanguage(e)})})},addSelector:function(t){r.push(function(e){return!e.matches(t)})}},filterKnown:!!t&&t.hasAttribute("data-filter-known")};if(n.add(function(e){return!n.filterKnown||"object"==typeof Prism.languages[e.language]}),t)(e=t.getAttribute("data-filter-selector"))&&n.addSelector(e),(e=t.getAttribute("data-reject-selector"))&&n.reject.addSelector(e);Prism.hooks.add("before-all-elements-highlight",function(e){e.elements=e.elements.filter(i)})}function i(e){for(var t=0,n=r.length;t<n;t++)if(!r[t](e))return!1;return!0}}();
|
45
prism.js
45
prism.js
|
@ -23,24 +23,6 @@ var Prism = (function (_self){
|
|||
var lang = /\blang(?:uage)?-([\w-]+)\b/i;
|
||||
var uniqueId = 0;
|
||||
|
||||
/**
|
||||
* Returns the Prism language of the given element set by a `language-xxxx` or `lang-xxxx` class.
|
||||
*
|
||||
* If no language is set for the element or the element is `null` or `undefined`, `none` will be returned.
|
||||
*
|
||||
* @param {Element} element
|
||||
* @returns {string}
|
||||
*/
|
||||
function getLanguage(element) {
|
||||
while (element && !lang.test(element.className)) {
|
||||
element = element.parentNode;
|
||||
}
|
||||
if (element) {
|
||||
return (element.className.match(lang) || [, 'none'])[1].toLowerCase();
|
||||
}
|
||||
return 'none';
|
||||
}
|
||||
|
||||
|
||||
var _ = {
|
||||
manual: _self.Prism && _self.Prism.manual,
|
||||
|
@ -108,6 +90,24 @@ var _ = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the Prism language of the given element set by a `language-xxxx` or `lang-xxxx` class.
|
||||
*
|
||||
* If no language is set for the element or the element is `null` or `undefined`, `none` will be returned.
|
||||
*
|
||||
* @param {Element} element
|
||||
* @returns {string}
|
||||
*/
|
||||
getLanguage: function (element) {
|
||||
while (element && !lang.test(element.className)) {
|
||||
element = element.parentElement;
|
||||
}
|
||||
if (element) {
|
||||
return (element.className.match(lang) || [, 'none'])[1].toLowerCase();
|
||||
}
|
||||
return 'none';
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the script element that is currently executing.
|
||||
*
|
||||
|
@ -241,21 +241,24 @@ var _ = {
|
|||
highlightAllUnder: function(container, async, callback) {
|
||||
var env = {
|
||||
callback: callback,
|
||||
container: container,
|
||||
selector: 'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'
|
||||
};
|
||||
|
||||
_.hooks.run('before-highlightall', env);
|
||||
|
||||
var elements = container.querySelectorAll(env.selector);
|
||||
env.elements = Array.prototype.slice.apply(env.container.querySelectorAll(env.selector));
|
||||
|
||||
for (var i=0, element; element = elements[i++];) {
|
||||
_.hooks.run('before-all-elements-highlight', env);
|
||||
|
||||
for (var i = 0, element; element = env.elements[i++];) {
|
||||
_.highlightElement(element, async === true, env.callback);
|
||||
}
|
||||
},
|
||||
|
||||
highlightElement: function(element, async, callback) {
|
||||
// Find language
|
||||
var language = getLanguage(element);
|
||||
var language = _.util.getLanguage(element);
|
||||
var grammar = _.languages[language];
|
||||
|
||||
// Set language on the element, if not present
|
||||
|
|
Loading…
Reference in New Issue