Skip to content

Commit

Permalink
Merge pull request #847 from zeitgeist87/WhitespaceNormalizer
Browse files Browse the repository at this point in the history
Whitespace normalizer plugin
  • Loading branch information
LeaVerou committed Feb 6, 2016
2 parents 97b0eb5 + 38b7b3b commit ef53322
Show file tree
Hide file tree
Showing 6 changed files with 300 additions and 1 deletion.
5 changes: 5 additions & 0 deletions components.js
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,11 @@ var components = {
"command-line": {
"title": "Command Line",
"owner": "chriswells0"
},
"normalize-whitespace": {
"title": "Normalize Whitespace",
"owner": "zeitgeist87",
"noCSS": true
}
}
};
29 changes: 29 additions & 0 deletions plugins/normalize-whitespace/demo.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<body data-prism data-remove-trailing="true">
<section id="main" class="language-javascript" data-right-trim="true">

<pre>

<code data-left-trim="true">


var example = {
foo: true,

bar: false
};


</code>

</pre>

</section>
<script src="plugins/normalize-whitespace/prism-normalize-whitespace.js"></script>
<script type="text/javascript">
Prism.plugins.NormalizeWhitespace.setDefaults({
'remove-trailing': false,
'left-trim': false,
'right-trim': false
});
</script>
</body>
101 changes: 101 additions & 0 deletions plugins/normalize-whitespace/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<!DOCTYPE html>
<html lang="en">
<head>

<meta charset="utf-8" />
<link rel="shortcut icon" href="favicon.png" />
<title>Normalize Whitespace ▲ Prism plugins</title>
<base href="../.." />
<link rel="stylesheet" href="style.css" />
<link rel="stylesheet" href="themes/prism.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>Normalize Whitespace</h2>
<p>Supports multiple operations to normalize whitespace in code blocks.</p>
</header>

<section class="language-markup">
<h1>How to use</h1>

<p>Obviously, this is supposed to work only for code blocks (<code>&lt;pre>&lt;code></code>) and not for inline code.</p>
<p>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.</p>

<p>The plugin uses the <a href="plugins/parse-settings/">Parse Settings</a> plugin to get its settings.
The default settings can be overridden with the <code class="language-javascript">setDefaults()</code> method
like so:</p>

<pre class="language-javascript"><code>
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*/
});
</code></pre>

<p>It is also possible to change the default settings with <code>data-*</code>-attributes.</p>

<pre><code>&lt;code data-left-trim="false">...&lt;/code></code></pre>

<p>The class <code>no-whitespace-normalization</code> or the corresponding
data-attribute can be used to disable the normalization for a particular
code block.</p>

<pre><code>&lt;code class="no-whitespace-normalization"
data-whitespace-normalization="false">
...
&lt;/code></code></pre>
</section>

<section class="language-markup">
<h1>Examples</h1>

<p>The following example shows some of the possible ways of configuring this plugin:</p>

<pre data-src="plugins/normalize-whitespace/demo.html"></pre>

<p>The result looks like this:</p>

<pre class="language-javascript">

<code>


var example = {
foo: true,

bar: false
};


</code>

</pre>

</section>

<footer data-src="templates/footer.html" data-type="text/html"></footer>

<script src="prism.js"></script>
<script src="plugins/parse-settings/prism-parse-settings.js"></script>
<script src="plugins/normalize-whitespace/prism-normalize-whitespace.js"></script>
<script src="utopia.js"></script>
<script src="components.js"></script>
<script src="code.js"></script>


</body>
</html>
162 changes: 162 additions & 0 deletions plugins/normalize-whitespace/prism-normalize-whitespace.js
Original file line number Diff line number Diff line change
@@ -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 <pre> tag into the <code> 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);
});

}());

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion plugins/remove-initial-line-feed/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ <h2>Remove initial line feed</h2>
</header>

<section class="language-markup">
<h1>How to use</h1>
<h1>How to use (DEPRECATED)</h1>

<p>This plugin will be removed in the future. Please use the general purpose <a href="plugins/normalize-whitespace/">Normalize Whitespace</a> plugin instead.</p>
<p>Obviously, this is supposed to work only for code blocks (<code>&lt;pre>&lt;code></code>) and not for inline code.</p>
<p>With this plugin included, any initial line feed will be removed by default.</p>
<p>To bypass this behaviour, you may add the class <strong>keep-initial-line-feed</strong> to your desired <code>&lt;pre></code>.</p>
Expand Down

0 comments on commit ef53322

Please sign in to comment.