Commit 837890622228f9ca38a4cd1de6ab6997f75e44a9

Chris Wells 2015-11-29T20:27:14

Add Command Line plugin.

diff --git a/components.js b/components.js
index 9d6e24d..e17a578 100644
--- a/components.js
+++ b/components.js
@@ -598,6 +598,10 @@ var components = {
 			"title": "Keep Markup",
 			"owner": "Golmote",
 			"noCSS": true
+		},
+		"command-line": {
+			"title": "Command Line",
+			"owner": "chriswells0"
 		}
 	}
 };
diff --git a/plugins/command-line/index.html b/plugins/command-line/index.html
new file mode 100644
index 0000000..146b5d7
--- /dev/null
+++ b/plugins/command-line/index.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+
+<meta charset="utf-8" />
+<link rel="shortcut icon" href="favicon.png" />
+<title>Command Line ▲ Prism plugins</title>
+<base href="../.." />
+<link rel="stylesheet" href="style.css" />
+<link rel="stylesheet" href="themes/prism.css" data-noprefix />
+<link rel="stylesheet" href="plugins/command-line/prism-command-line.css" data-noprefix />
+<script src="prefixfree.min.js"></script>
+
+<script>var _gaq = [['_setAccount', 'UA-33746269-1'], ['_trackPageview']];</script>
+<script src="http://www.google-analytics.com/ga.js" async></script>
+</head>
+<body>
+
+<header>
+	<div class="intro" data-src="templates/header-plugins.html" data-type="text/html"></div>
+
+	<h2>Command Line</h2>
+	<p>Display a command line with a prompt and, optionally, the output/response from the commands.</p>
+</header>
+
+<section class="language-markup">
+	<h1>How to use</h1>
+
+	<p>This is intended for code blocks (<code class="language-markup">&lt;pre>&lt;code></code>) and not for inline code.</p>
+
+	<p>Add class <strong>command-line</strong> to your <code class="language-markup">&lt;pre></code>. For a server command line, specify the user and host names using the <code class="language-markup">data-user</code> and <code class="language-markup">data-host</code> attributes. The resulting prompt displays a <strong>#</strong> for the root user and <strong>$</strong> for all other users. For any other command line, such as a Windows prompt, you may specify the entire prompt using the <code class="language-markup">data-prompt</code> attribute.</p>
+
+	<p>Optional: You may specify the lines to be presented as output (no prompt) through the <code class="language-markup">data-output</code> attribute on the <code class="language-markup">&lt;pre></code> element in the following simple format:</p>
+	<ul>
+		<li>A single number refers to the line with that number</li>
+		<li>Ranges are denoted by two numbers, separated with a hyphen (-)</li>
+		<li>Multiple line numbers or ranges are separated by commas.</li>
+		<li>Whitespace is allowed anywhere and will be stripped off.</li>
+	</ul>
+
+	<p>Examples:</p>
+	<dl>
+		<dt>5</dt>
+		<dd>The 5th line</dd>
+
+		<dt>1-5</dt>
+		<dd>Lines 1 through 5</dd>
+
+		<dt>1,4</dt>
+		<dd>Line 1 and line 4</dd>
+
+		<dt>1-2, 5, 9-20</dt>
+		<dd>Lines 1 through 2, line 5, lines 9 through 20</dd>
+	</dl>
+</section>
+
+<section>
+	<h1>Examples</h1>
+
+	<h2>Root User Without Output</h2>
+<pre class="command-line" data-user="root" data-host="localhost"><code class="language-bash">cd /usr/local/etc
+cp php.ini php.ini.bak
+vi php.ini</code></pre>
+
+	<h2>Non-Root User With Output</h2>
+<pre class="command-line" data-user="chris" data-host="remotehost" data-output="2, 4-8"><code class="language-bash">pwd
+/usr/home/chris/bin
+ls -la
+total 2
+drwxr-xr-x   2 chris  chris     11 Jan 10 16:48 .
+drwxr--r-x  45 chris  chris     92 Feb 14 11:10 ..
+-rwxr-xr-x   1 chris  chris    444 Aug 25  2013 backup
+-rwxr-xr-x   1 chris  chris    642 Jan 17 14:42 deploy</code></pre>
+
+	<h2>Windows PowerShell With Output</h2>
+<pre class="command-line" data-prompt="PS C:\Users\Chris>" data-output="2-19"><code class="language-powershell">dir
+
+
+    Directory: C:\Users\Chris
+
+
+Mode                LastWriteTime     Length Name
+----                -------------     ------ ----
+d-r--        10/14/2015   5:06 PM            Contacts
+d-r--        12/12/2015   1:47 PM            Desktop
+d-r--         11/4/2015   7:59 PM            Documents
+d-r--        10/14/2015   5:06 PM            Downloads
+d-r--        10/14/2015   5:06 PM            Favorites
+d-r--        10/14/2015   5:06 PM            Links
+d-r--        10/14/2015   5:06 PM            Music
+d-r--        10/14/2015   5:06 PM            Pictures
+d-r--        10/14/2015   5:06 PM            Saved Games
+d-r--        10/14/2015   5:06 PM            Searches
+d-r--        10/14/2015   5:06 PM            Videos</code></pre>
+
+</section>
+
+<footer data-src="templates/footer.html" data-type="text/html"></footer>
+
+<script src="prism.js"></script>
+<script src="plugins/command-line/prism-command-line.js"></script>
+<script src="utopia.js"></script>
+<script src="components.js"></script>
+<script src="code.js"></script>
+<script src="components/prism-bash.js"></script>
+<script src="components/prism-powershell.js"></script>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/plugins/command-line/prism-command-line.css b/plugins/command-line/prism-command-line.css
new file mode 100644
index 0000000..60ab996
--- /dev/null
+++ b/plugins/command-line/prism-command-line.css
@@ -0,0 +1,33 @@
+.command-line-prompt {
+	border-right: 1px solid #999;
+	display: block;
+	float: left;
+	font-size: 100%;
+	letter-spacing: -1px;
+	margin-right: 1em;
+	pointer-events: none;
+
+	-webkit-user-select: none;
+	-moz-user-select: none;
+	-ms-user-select: none;
+	user-select: none;
+}
+
+.command-line-prompt > span:before {
+	color: #999;
+	content: "[" attr(data-user) "@" attr(data-host) "] $";
+	display: block;
+	padding-right: 0.8em;
+}
+
+.command-line-prompt > span[data-user="root"]:before {
+	content: "[" attr(data-user) "@" attr(data-host) "] #";
+}
+
+.command-line-prompt > span[data-prompt]:before {
+	content: attr(data-prompt);
+}
+
+.command-line-prompt > span.output:before {
+	content: ' ';
+}
diff --git a/plugins/command-line/prism-command-line.js b/plugins/command-line/prism-command-line.js
new file mode 100644
index 0000000..cadc706
--- /dev/null
+++ b/plugins/command-line/prism-command-line.js
@@ -0,0 +1,74 @@
+(function() {
+
+if (typeof self === 'undefined' || !self.Prism || !self.document) {
+	return;
+}
+
+Prism.hooks.add('complete', function (env) {
+	if (!env.code) {
+		return;
+	}
+
+	// Works only for <code> wrapped inside <pre> (not inline).
+	var pre = env.element.parentNode;
+	var clsReg = /\s*\bcommand-line\b\s*/;
+	if (
+		!pre || !/pre/i.test(pre.nodeName) ||
+			// Abort only if neither the <pre> nor the <code> have the class
+		(!clsReg.test(pre.className) && !clsReg.test(env.element.className))
+	) {
+		return;
+	}
+
+	if (env.element.querySelector('.command-line-prompt')) {
+		// Abort if prompt already exists.
+		return;
+	}
+
+	if (clsReg.test(env.element.className)) {
+		// Remove the class "command-line" from the <code>
+		env.element.className = env.element.className.replace(clsReg, '');
+	}
+	if (!clsReg.test(pre.className)) {
+		// Add the class "command-line" to the <pre>
+		pre.className += ' command-line';
+	}
+
+	// Create the "rows" that will become the command-line prompts. -- cwells
+	var lines = new Array(1 + env.code.split('\n').length);
+	var promptText = pre.getAttribute('data-prompt') || '';
+	if (promptText !== '') {
+		lines = lines.join('<span data-prompt="' + promptText + '"></span>');
+	} else {
+		var user = pre.getAttribute('data-user') || 'user';
+		var host = pre.getAttribute('data-host') || 'localhost';
+		lines = lines.join('<span data-user="' + user + '" data-host="' + host + '"></span>');
+	}
+
+	// Create the wrapper element. -- cwells
+	var prompt = document.createElement('span');
+	prompt.className = 'command-line-prompt';
+	prompt.innerHTML = lines;
+
+	// Mark the output lines so they can be styled differently (no prompt). -- cwells
+	var outputSections = pre.getAttribute('data-output') || '';
+	outputSections = outputSections.split(',');
+	for (var i = 0; i < outputSections.length; i++) {
+		var outputRange = outputSections[i].split('-');
+		var outputStart = parseInt(outputRange[0]);
+		var outputEnd = outputStart; // Default: end at the first line when it's not an actual range. -- cwells
+		if (outputRange.length === 2) {
+			outputEnd = parseInt(outputRange[1]);
+		}
+
+		if (!isNaN(outputStart) && !isNaN(outputEnd)) {
+			for (var j = outputStart; j <= outputEnd && j <= prompt.children.length; j++) {
+				prompt.children[j - 1].className = 'output';
+			}
+		}
+	}
+
+	env.element.innerHTML = prompt.outerHTML + env.element.innerHTML;
+});
+
+}());