diff --git a/plugins/command-line/prism-command-line.js b/plugins/command-line/prism-command-line.js index 0d1392ff8e..907fd36df6 100644 --- a/plugins/command-line/prism-command-line.js +++ b/plugins/command-line/prism-command-line.js @@ -1,140 +1,182 @@ -(function() { +(function () { -if (typeof self === 'undefined' || !self.Prism || !self.document) { - return; -} - -var clsReg = /(?:^|\s)command-line(?:\s|$)/; - -Prism.hooks.add('before-highlight', function (env) { - var vars = env.vars = env.vars || {}; - var commandLine = vars['command-line'] = vars['command-line'] || {}; - - if (commandLine.complete || !env.code) { - commandLine.complete = true; + if (typeof self === 'undefined' || !self.Prism || !self.document) { return; } - // Works only for wrapped inside
 (not inline).
-	var pre = env.element.parentNode;
-	if (!pre || !/pre/i.test(pre.nodeName) || // Abort only if neither the 
 nor the  have the class
-		(!clsReg.test(pre.className) && !clsReg.test(env.element.className))) {
-		commandLine.complete = true;
-		return;
+	var CLASS_PATTERN = /(?:^|\s)command-line(?:\s|$)/;
+	var PROMPT_CLASS = 'command-line-prompt';
+
+	/** @type {(str: string, prefix: string) => boolean} */
+	var startsWith = "".startsWith
+		? function (s, p) { return s.startsWith(p); }
+		: function (s, p) { return s.indexOf(p) === 0; };
+
+	/**
+	 * Repeats the given string some number of times.
+	 *
+	 * This is just a polyfill for `String.prototype.repeat`.
+	 *
+	 * @param {string} str
+	 * @param {number} times
+	 * @returns {string}
+	 */
+	function repeat(str, times) {
+		var s = "";
+		for (var i = 0; i < times; i++) {
+			s += str;
+		}
+		return s;
 	}
 
-	// The element might be highlighted multiple times, so we just remove the previous prompt
-	var existingPrompt = env.element.querySelector('.command-line-prompt');
-	if (existingPrompt) {
-		existingPrompt.remove();
+	/**
+	 * Returns the command line info object from the given hook environment.
+	 *
+	 * @param {any} env
+	 * @returns {CommandLineInfo}
+	 *
+	 * @typedef CommandLineInfo
+	 * @property {boolean} [complete]
+	 * @property {number} [numberOfLines]
+	 * @property {string[]} [outputLines]
+	 */
+	function getCommandLineInfo(env) {
+		var vars = env.vars = env.vars || {};
+		return vars['command-line'] = vars['command-line'] || {};
 	}
 
-	var codeLines = env.code.split('\n');
-	commandLine.numberOfLines = codeLines.length;
-	var outputLines = commandLine.outputLines = [];
-
-	var outputSections = pre.getAttribute('data-output');
-	var outputFilter = pre.getAttribute('data-filter-output');
-	if (outputSections || outputSections === '') { // The user specified the output lines. -- cwells
-		outputSections = outputSections.split(',');
-		for (var i = 0; i < outputSections.length; i++) { // Parse the output sections into start/end ranges. -- cwells
-			var range = outputSections[i].split('-');
-			var outputStart = parseInt(range[0], 10);
-			var outputEnd = (range.length === 2 ? parseInt(range[1], 10) : outputStart);
-
-			if (!isNaN(outputStart) && !isNaN(outputEnd)) {
-				if (outputStart < 1) {
-					outputStart = 1;
-				}
-				if (outputEnd > codeLines.length) {
-					outputEnd = codeLines.length;
+
+	Prism.hooks.add('before-highlight', function (env) {
+		var commandLine = getCommandLineInfo(env);
+
+		if (commandLine.complete || !env.code) {
+			commandLine.complete = true;
+			return;
+		}
+
+		// Works only for  wrapped inside 
 (not inline).
+		var pre = env.element.parentElement;
+		if (!pre || !/pre/i.test(pre.nodeName) || // Abort only if neither the 
 nor the  have the class
+			(!CLASS_PATTERN.test(pre.className) && !CLASS_PATTERN.test(env.element.className))) {
+			commandLine.complete = true;
+			return;
+		}
+
+		// The element might be highlighted multiple times, so we just remove the previous prompt
+		var existingPrompt = env.element.querySelector('.' + PROMPT_CLASS);
+		if (existingPrompt) {
+			existingPrompt.remove();
+		}
+
+		var codeLines = env.code.split('\n');
+		commandLine.numberOfLines = codeLines.length;
+		/** @type {string[]} */
+		var outputLines = commandLine.outputLines = [];
+
+		var outputSections = pre.getAttribute('data-output');
+		var outputFilter = pre.getAttribute('data-filter-output');
+		if (outputSections !== null) { // The user specified the output lines. -- cwells
+			outputSections.split(',').forEach(function (section) {
+				var range = section.split('-');
+				var outputStart = parseInt(range[0], 10);
+				var outputEnd = range.length === 2 ? parseInt(range[1], 10) : outputStart;
+
+				if (!isNaN(outputStart) && !isNaN(outputEnd)) {
+					if (outputStart < 1) {
+						outputStart = 1;
+					}
+					if (outputEnd > codeLines.length) {
+						outputEnd = codeLines.length;
+					}
+					// Convert start and end to 0-based to simplify the arrays. -- cwells
+					outputStart--;
+					outputEnd--;
+					// Save the output line in an array and clear it in the code so it's not highlighted. -- cwells
+					for (var j = outputStart; j <= outputEnd; j++) {
+						outputLines[j] = codeLines[j];
+						codeLines[j] = '';
+					}
 				}
-				// Convert start and end to 0-based to simplify the arrays. -- cwells
-				outputStart--;
-				outputEnd--;
-				// Save the output line in an array and clear it in the code so it's not highlighted. -- cwells
-				for (var j = outputStart; j <= outputEnd; j++) {
-					outputLines[j] = codeLines[j];
-					codeLines[j] = '';
+			});
+		} else if (outputFilter) { // Treat lines beginning with this string as output. -- cwells
+			for (var i = 0; i < codeLines.length; i++) {
+				if (startsWith(codeLines[i], outputFilter)) { // This line is output. -- cwells
+					outputLines[i] = codeLines[i].slice(outputFilter.length);
+					codeLines[i] = '';
 				}
 			}
 		}
-	} else if (outputFilter) { // Treat lines beginning with this string as output. -- cwells
-		for (var i = 0; i < codeLines.length; i++) {
-			if (codeLines[i].indexOf(outputFilter) === 0) { // This line is output. -- cwells
-				outputLines[i] = codeLines[i].slice(outputFilter.length);
-				codeLines[i] = '';
-			}
+
+		env.code = codeLines.join('\n');
+	});
+
+	Prism.hooks.add('before-insert', function (env) {
+		var commandLine = getCommandLineInfo(env);
+
+		if (commandLine.complete) {
+			return;
 		}
-	}
 
-	env.code = codeLines.join('\n');
-});
+		// Reinsert the output lines into the highlighted code. -- cwells
+		var codeLines = env.highlightedCode.split('\n');
+		var outputLines = commandLine.outputLines || [];
+		for (var i = 0, l = outputLines.length; i < l; i++) {
+			if (outputLines.hasOwnProperty(i)) {
+				codeLines[i] = outputLines[i];
+			}
+		}
+		env.highlightedCode = codeLines.join('\n');
+	});
 
-Prism.hooks.add('before-insert', function (env) {
-	var vars = env.vars = env.vars || {};
-	var commandLine = vars['command-line'] = vars['command-line'] || {};
-	if (commandLine.complete) {
-		return;
-	}
+	Prism.hooks.add('complete', function (env) {
+		var commandLine = getCommandLineInfo(env);
 
-	// Reinsert the output lines into the highlighted code. -- cwells
-	var codeLines = env.highlightedCode.split('\n');
-	for (var i = 0, l = (commandLine.outputLines || []).length; i < l; i++) {
-		if (commandLine.outputLines.hasOwnProperty(i)) {
-			codeLines[i] = commandLine.outputLines[i];
+		if (commandLine.complete) {
+			return;
 		}
-	}
-	env.highlightedCode = codeLines.join('\n');
-});
 
-Prism.hooks.add('complete', function (env) {
-	var vars = env.vars = env.vars || {};
-	var commandLine = vars['command-line'] = vars['command-line'] || {};
-	if (commandLine.complete) {
-		return;
-	}
+		var pre = env.element.parentElement;
+		if (CLASS_PATTERN.test(env.element.className)) { // Remove the class "command-line" from the 
+			env.element.className = env.element.className.replace(CLASS_PATTERN, ' ');
+		}
+		if (!CLASS_PATTERN.test(pre.className)) { // Add the class "command-line" to the 
+			pre.className += ' command-line';
+		}
 
-	var pre = env.element.parentNode;
-	if (clsReg.test(env.element.className)) { // Remove the class "command-line" from the 
-		env.element.className = env.element.className.replace(clsReg, ' ');
-	}
-	if (!clsReg.test(pre.className)) { // Add the class "command-line" to the 
-		pre.className += ' command-line';
-	}
+		function getAttribute(key, defaultValue) {
+			return (pre.getAttribute(key) || defaultValue).replace(/"/g, '"');
+		}
 
-	var getAttribute = function(key, defaultValue) {
-		return (pre.getAttribute(key) || defaultValue).replace(/"/g, '"');
-	};
-
-	// Create the "rows" that will become the command-line prompts. -- cwells
-	var promptLines = new Array((commandLine.numberOfLines || 0) + 1);
-	var promptText = getAttribute('data-prompt', '');
-	if (promptText !== '') {
-		promptLines = promptLines.join('');
-	} else {
-		var user = getAttribute('data-user', 'user');
-		var host = getAttribute('data-host', 'localhost');
-		promptLines = promptLines.join('');
-	}
+		// Create the "rows" that will become the command-line prompts. -- cwells
+		var promptLines;
+		var rowCount = commandLine.numberOfLines || 0;
+		var promptText = getAttribute('data-prompt', '');
+		if (promptText !== '') {
+			promptLines = repeat('', rowCount);
+		} else {
+			var user = getAttribute('data-user', 'user');
+			var host = getAttribute('data-host', 'localhost');
+			promptLines = repeat('', rowCount);
+		}
 
-	// Create the wrapper element. -- cwells
-	var prompt = document.createElement('span');
-	prompt.className = 'command-line-prompt';
-	prompt.innerHTML = promptLines;
-
-	// Remove the prompt from the output lines. -- cwells
-	for (var i = 0, l = (commandLine.outputLines || []).length; i < l; i++) {
-		if (commandLine.outputLines.hasOwnProperty(i)) {
-			var node = prompt.children[i];
-			node.removeAttribute('data-user');
-			node.removeAttribute('data-host');
-			node.removeAttribute('data-prompt');
+		// Create the wrapper element. -- cwells
+		var prompt = document.createElement('span');
+		prompt.className = PROMPT_CLASS;
+		prompt.innerHTML = promptLines;
+
+		// Remove the prompt from the output lines. -- cwells
+		var outputLines = commandLine.outputLines || [];
+		for (var i = 0, l = outputLines.length; i < l; i++) {
+			if (outputLines.hasOwnProperty(i)) {
+				var node = prompt.children[i];
+				node.removeAttribute('data-user');
+				node.removeAttribute('data-host');
+				node.removeAttribute('data-prompt');
+			}
 		}
-	}
 
-	env.element.insertBefore(prompt, env.element.firstChild);
-	commandLine.complete = true;
-});
+		env.element.insertBefore(prompt, env.element.firstChild);
+		commandLine.complete = true;
+	});
 
 }());
diff --git a/plugins/command-line/prism-command-line.min.js b/plugins/command-line/prism-command-line.min.js
index b0f6cd1557..8a3d34716e 100644
--- a/plugins/command-line/prism-command-line.min.js
+++ b/plugins/command-line/prism-command-line.min.js
@@ -1 +1 @@
-!function(){if("undefined"!=typeof self&&self.Prism&&self.document){var f=/(?:^|\s)command-line(?:\s|$)/;Prism.hooks.add("before-highlight",function(e){var t=e.vars=e.vars||{},a=t["command-line"]=t["command-line"]||{};if(!a.complete&&e.code){var n=e.element.parentNode;if(n&&/pre/i.test(n.nodeName)&&(f.test(n.className)||f.test(e.element.className))){var r=e.element.querySelector(".command-line-prompt");r&&r.remove();var s=e.code.split("\n");a.numberOfLines=s.length;var o=a.outputLines=[],i=n.getAttribute("data-output"),l=n.getAttribute("data-filter-output");if(i||""===i){i=i.split(",");for(var m=0;ms.length&&(c=s.length),c--;for(var u=--p;u<=c;u++)o[u]=s[u],s[u]=""}}}else if(l)for(m=0;m');else{var i=r("data-user","user"),l=r("data-host","localhost");s=s.join('')}var m=document.createElement("span");m.className="command-line-prompt",m.innerHTML=s;for(var d=0,p=(a.outputLines||[]).length;ds.length&&(a=s.length),a--;for(var r=--n;r<=a;r++)o[r]=s[r],s[r]=""}});else if(i)for(var l=0;l',r);else n=d('',r);var o=document.createElement("span");o.className=p,o.innerHTML=n;for(var i=t.outputLines||[],l=0,m=i.length;l