diff --git a/components.js b/components.js
index b422f92273..80110d348a 100644
--- a/components.js
+++ b/components.js
@@ -610,6 +610,11 @@ var components = {
"command-line": {
"title": "Command Line",
"owner": "chriswells0"
+ },
+ "normalize-whitespace": {
+ "title": "Normalize Whitespace",
+ "owner": "zeitgeist87",
+ "noCSS": true
}
}
};
diff --git a/plugins/normalize-whitespace/demo.html b/plugins/normalize-whitespace/demo.html
new file mode 100644
index 0000000000..34e06f47c3
--- /dev/null
+++ b/plugins/normalize-whitespace/demo.html
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+ var example = {
+ foo: true,
+
+ bar: false
+ };
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/normalize-whitespace/index.html b/plugins/normalize-whitespace/index.html
new file mode 100644
index 0000000000..02a000f180
--- /dev/null
+++ b/plugins/normalize-whitespace/index.html
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+ Normalize Whitespace ▲ Prism plugins
+
+
+
+
+
+
+
+
+
+
+
+
+
+ How to use
+
+ Obviously, this is supposed to work only for code blocks (<pre><code>
) and not for inline code.
+ By default the plugin trims all leading and trailing whitespace of every code block.
+ It also removes extra indents and trailing whitespace on every line.
+
+ The plugin uses the Parse Settings plugin to get its settings.
+ The default settings can be overridden with the setDefaults()
method
+ like so:
+
+
+Prism.plugins.NormalizeWhitespace.setDefaults({
+ 'remove-trailing': true,
+ 'remove-indent': true,
+ 'left-trim': true,
+ 'right-trim': true,
+ /*'indent': 2,
+ 'remove-initial-line-feed': false,
+ 'tabs-to-spaces': 4,
+ 'spaces-to-tabs': 4*/
+});
+
+
+ It is also possible to change the default settings with data-*
-attributes.
+
+ <code data-left-trim="false">...</code>
+
+ The class no-whitespace-normalization
or the corresponding
+ data-attribute can be used to disable the normalization for a particular
+ code block.
+
+ <code class="no-whitespace-normalization"
+ data-whitespace-normalization="false">
+...
+</code>
+
+
+
+ Examples
+
+ The following example shows some of the possible ways of configuring this plugin:
+
+
+
+ The result looks like this:
+
+
+
+
+
+
+ var example = {
+ foo: true,
+
+ bar: false
+ };
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/plugins/normalize-whitespace/prism-normalize-whitespace.js b/plugins/normalize-whitespace/prism-normalize-whitespace.js
new file mode 100644
index 0000000000..f2df35f638
--- /dev/null
+++ b/plugins/normalize-whitespace/prism-normalize-whitespace.js
@@ -0,0 +1,162 @@
+(function() {
+
+if (typeof self === 'undefined' || !self.Prism || !self.document) {
+ return;
+}
+
+var assign = Object.assign || function (obj1, obj2) {
+ for (var name in obj2) {
+ if (obj2.hasOwnProperty(name))
+ obj1[name] = obj2[name];
+ }
+ return obj1;
+}
+
+function NormalizeWhitespace(defaults) {
+ this.defaults = assign({}, defaults);
+}
+
+function toCamelCase(value) {
+ return value.replace(/-(\w)/g, function(match, firstChar) {
+ return firstChar.toUpperCase();
+ });
+}
+
+function tabLen(str) {
+ var res = 0;
+ for (var i = 0; i < str.length; ++i) {
+ if (str.charCodeAt(i) == '\t'.charCodeAt(0))
+ res += 3;
+ }
+ return str.length + res;
+}
+
+NormalizeWhitespace.prototype = {
+ setDefaults: function (defaults) {
+ this.defaults = assign(this.defaults, defaults);
+ },
+ normalize: function (input, settings) {
+ settings = assign(this.defaults, settings);
+
+ for (var name in settings) {
+ var methodName = toCamelCase(name);
+ if (name !== "normalize" && methodName !== 'setDefaults' &&
+ settings[name] && this[methodName]) {
+ input = this[methodName].call(this, input, settings[name]);
+ }
+ }
+
+ return input;
+ },
+
+ /*
+ * Normalization methods
+ */
+ leftTrim: function (input) {
+ return input.replace(/^\s+/, '');
+ },
+ rightTrim: function (input) {
+ return input.replace(/\s+$/, '');
+ },
+ tabsToSpaces: function (input, spaces) {
+ spaces = spaces|0 || 4;
+ return input.replace(/\t/g, new Array(++spaces).join(' '));
+ },
+ spacesToTabs: function (input, spaces) {
+ spaces = spaces|0 || 4;
+ return input.replace(new RegExp(' {' + spaces + '}', 'g'), '\t');
+ },
+ removeTrailing: function (input) {
+ return input.replace(/\s*?$/gm, '');
+ },
+ // Support for deprecated plugin remove-initial-line-feed
+ removeInitialLineFeed: function (input) {
+ return input.replace(/^(?:\r?\n|\r)/, '');
+ },
+ removeIndent: function (input) {
+ var indents = input.match(/^[^\S\n\r]*(?=\S)/gm);
+
+ if (!indents || !indents[0].length)
+ return input;
+
+ indents.sort(function(a, b){return a.length - b.length; });
+
+ if (!indents[0].length)
+ return input;
+
+ return input.replace(new RegExp('^' + indents[0], 'gm'), '');
+ },
+ indent: function (input, tabs) {
+ return input.replace(/^[^\S\n\r]*(?=\S)/gm, new Array(++tabs).join('\t') + '$&');
+ },
+ breakLines: function (input, characters) {
+ characters = (characters === true) ? 80 : characters|0 || 80;
+
+ var lines = input.split('\n');
+ for (var i = 0; i < lines.length; ++i) {
+ if (tabLen(lines[i]) <= characters)
+ continue;
+
+ var line = lines[i].split(/(\s+)/g),
+ len = 0;
+
+ for (var j = 0; j < line.length; ++j) {
+ var tl = tabLen(line[j]);
+ len += tl;
+ if (len > characters) {
+ line[j] = '\n' + line[j];
+ len = tl;
+ }
+ }
+ lines[i] = line.join('');
+ }
+ return lines.join('\n');
+ }
+};
+
+Prism.plugins.NormalizeWhitespace = new NormalizeWhitespace({
+ 'remove-trailing': true,
+ 'remove-indent': true,
+ 'left-trim': true,
+ 'right-trim': true,
+ /*'break-lines': 80,
+ 'indent': 2,
+ 'remove-initial-line-feed': false,
+ 'tabs-to-spaces': 4,
+ 'spaces-to-tabs': 4*/
+});
+
+Prism.hooks.add('before-highlight', function (env) {
+ var pre = env.element.parentNode;
+ if (!env.code || !pre || pre.nodeName.toLowerCase() !== 'pre' ||
+ (env.settings && env.settings['whitespace-normalization'] === false))
+ return;
+
+ var children = pre.childNodes,
+ before = '',
+ after = '',
+ codeFound = false;
+
+ // Move surrounding whitespace from the tag into the tag
+ for (var i = 0; i < children.length; ++i) {
+ var node = children[i];
+
+ if (node == env.element) {
+ codeFound = true;
+ } else if (node.nodeName === "#text") {
+ if (codeFound) {
+ after += node.nodeValue;
+ } else {
+ before += node.nodeValue;
+ }
+
+ pre.removeChild(node);
+ --i;
+ }
+ }
+ env.code = before + env.code + after;
+
+ env.code = Prism.plugins.NormalizeWhitespace.normalize(env.code, env.settings);
+});
+
+}());
\ No newline at end of file
diff --git a/plugins/normalize-whitespace/prism-normalize-whitespace.min.js b/plugins/normalize-whitespace/prism-normalize-whitespace.min.js
new file mode 100644
index 0000000000..11669d7dd8
--- /dev/null
+++ b/plugins/normalize-whitespace/prism-normalize-whitespace.min.js
@@ -0,0 +1 @@
+!function(){function e(e){this.defaults=t({},e)}function n(e){return e.replace(/-(\w)/g,function(e,n){return n.toUpperCase()})}function r(e){for(var n=0,r=0;rn&&(o[s]="\n"+o[s],a=l)}t[i]=o.join("")}return t.join("\n")}},Prism.plugins.NormalizeWhitespace=new e({"remove-trailing":!0,"remove-indent":!0,"left-trim":!0,"right-trim":!0}),Prism.hooks.add("before-highlight",function(e){var n=e.element.parentNode;if(e.code&&n&&"pre"===n.nodeName.toLowerCase()&&(!e.settings||e.settings["whitespace-normalization"]!==!1)){for(var r=n.childNodes,t="",i="",o=!1,a=0;aRemove initial line feed
- How to use
+ How to use (DEPRECATED)
+ This plugin will be removed in the future. Please use the general purpose Normalize Whitespace plugin instead.
Obviously, this is supposed to work only for code blocks (<pre><code>
) and not for inline code.
With this plugin included, any initial line feed will be removed by default.
To bypass this behaviour, you may add the class keep-initial-line-feed to your desired <pre>
.