Commit 1090b2535ac247203e2537d6b3d3a05238254f35

Michael Schmidt 2019-01-23T04:45:07

Show invisibles inside tokens (#1610) This PR fixes #1608. The patterns for invisible characters (ICs) are now also recursively added to the `inside` of every pattern. I also had to change the color of ICs because in #1607 I changed the color to `inherit` which causes the ICs to have different colors depending on which token they are inside of. So, to make everything consistent, I changed the color to grey (`rgb(128, 128, 128)`) and made it half transparent so it would blend in. Looks really similar to #1607. --- Most of the code is just traversing the language definition, handling the different kinds of tokens (simple regex, array, pattern object), and trying not to fall because of the added tokens for ICs and the `rest` property.

diff --git a/plugins/show-invisibles/prism-show-invisibles.css b/plugins/show-invisibles/prism-show-invisibles.css
index c57be58..6b39a32 100644
--- a/plugins/show-invisibles/prism-show-invisibles.css
+++ b/plugins/show-invisibles/prism-show-invisibles.css
@@ -9,8 +9,8 @@
 .token.cr:before,
 .token.lf:before,
 .token.space:before {
-	color: inherit;
-	opacity: 0.4;
+	color: #808080;
+	opacity: 0.6;
 	position: absolute;
 }
 
diff --git a/plugins/show-invisibles/prism-show-invisibles.js b/plugins/show-invisibles/prism-show-invisibles.js
index f3d120a..809bde2 100644
--- a/plugins/show-invisibles/prism-show-invisibles.js
+++ b/plugins/show-invisibles/prism-show-invisibles.js
@@ -1,21 +1,84 @@
-(function(){
-
-if (
-	typeof self !== 'undefined' && !self.Prism ||
-	typeof global !== 'undefined' && !global.Prism
-) {
-	return;
-}
-
-Prism.hooks.add('before-highlight', function(env) {
-	var tokens = env.grammar;
-
-	if (!tokens) return;
-
-	tokens.tab = /\t/g;
-	tokens.crlf = /\r\n/g;
-	tokens.lf = /\n/g;
-	tokens.cr = /\r/g;
-	tokens.space = / /g;
-});
+(function () {
+
+	if (
+		typeof self !== 'undefined' && !self.Prism ||
+		typeof global !== 'undefined' && !global.Prism
+	) {
+		return;
+	}
+
+
+	var invisibles = {
+		'tab': /\t/,
+		'crlf': /\r\n/,
+		'lf': /\n/,
+		'cr': /\r/,
+		'space': / /
+	};
+
+
+	/**
+	 * Handles the recursive calling of `addInvisibles` for one token.
+	 *
+	 * @param {Object|Array} tokens The grammar or array which contains the token.
+	 * @param {string|number} name The name or index of the token in `tokens`.
+	 */
+	function handleToken(tokens, name) {
+		var value = tokens[name];
+
+		var type = Prism.util.type(value);
+		switch (type) {
+			case 'RegExp':
+				var inside = {};
+				tokens[name] = {
+					pattern: value,
+					inside: inside
+				};
+				addInvisibles(inside);
+				break;
+
+			case 'Array':
+				for (var i = 0, l = value.length; i < l; i++) {
+					handleToken(value, i);
+				}
+				break;
+
+			default: // 'Object'
+				var inside = value.inside || (value.inside = {});
+				addInvisibles(inside);
+				break;
+		}
+	}
+
+	/**
+	 * Recursively adds patterns to match invisible characters to the given grammar (if not added already).
+	 *
+	 * @param {Object} grammar
+	 */
+	function addInvisibles(grammar) {
+		if (!grammar || grammar['tab']) {
+			return;
+		}
+
+		// assign invisibles here to "mark" the grammar in case of self references
+		for (var name in invisibles) {
+			if (invisibles.hasOwnProperty(name)) {
+				grammar[name] = invisibles[name];
+			}
+		}
+
+		for (var name in grammar) {
+			if (grammar.hasOwnProperty(name) && !invisibles[name]) {
+				if (name === 'rest') {
+					addInvisibles(grammar['rest']);
+				} else {
+					handleToken(grammar, name);
+				}
+			}
+		}
+	}
+
+	Prism.hooks.add('before-highlight', function (env) {
+		addInvisibles(env.grammar);
+	});
 })();
diff --git a/plugins/show-invisibles/prism-show-invisibles.min.js b/plugins/show-invisibles/prism-show-invisibles.min.js
index 9df7258..32de8f2 100644
--- a/plugins/show-invisibles/prism-show-invisibles.min.js
+++ b/plugins/show-invisibles/prism-show-invisibles.min.js
@@ -1 +1 @@
-!function(){"undefined"!=typeof self&&!self.Prism||"undefined"!=typeof global&&!global.Prism||Prism.hooks.add("before-highlight",function(e){var f=e.grammar;f&&(f.tab=/\t/g,f.crlf=/\r\n/g,f.lf=/\n/g,f.cr=/\r/g,f.space=/ /g)})}();
\ No newline at end of file
+!function(){function r(a,i){var n=a[i],t=Prism.util.type(n);switch(t){case"RegExp":var f={};a[i]={pattern:n,inside:f},e(f);break;case"Array":for(var s=0,o=n.length;o>s;s++)r(n,s);break;default:var f=n.inside||(n.inside={});e(f)}}function e(i){if(i&&!i.tab){for(var n in a)a.hasOwnProperty(n)&&(i[n]=a[n]);for(var n in i)i.hasOwnProperty(n)&&!a[n]&&("rest"===n?e(i.rest):r(i,n))}}if(("undefined"==typeof self||self.Prism)&&("undefined"==typeof global||global.Prism)){var a={tab:/\t/,crlf:/\r\n/,lf:/\n/,cr:/\r/,space:/ /};Prism.hooks.add("before-highlight",function(r){e(r.grammar)})}}();
\ No newline at end of file