Skip to content

Commit c7e2160

Browse files
committed
Add whitespace-normalizer plugin
This plugin normalizes whitespace in code blocks. It can perform various operations. The user can configure them through the plugin object located at Prism.plugins.NormalizeWhitespace. Prism.plugins.NormalizeWhitespace.setSettings({ 'rem-trailing-whitespace': true, 'rem-extra-indent': true, 'left-trim': true, 'right-trim': true, 'rem-initial-line-feed': false, 'tabs-to-spaces': false, 'spaces-to-tabs': false, }); The plugin can be disabled for certain code blocks, by adding the class "no-whitespace-normalization" to it. There is also a HTML-interface using the parse-settings plugin.
1 parent 374c616 commit c7e2160

File tree

5 files changed

+265
-1
lines changed

5 files changed

+265
-1
lines changed

components.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,12 @@ var components = {
612612
"title": "Parse Settings",
613613
"owner": "zeitgeist87",
614614
"noCSS": true
615+
},
616+
"normalize-whitespace": {
617+
"title": "Normalize Whitespace",
618+
"require": "parse-settings",
619+
"owner": "zeitgeist87",
620+
"noCSS": true
615621
}
616622
}
617623
};
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
5+
<meta charset="utf-8" />
6+
<link rel="shortcut icon" href="favicon.png" />
7+
<title>Normalize Whitespace ▲ Prism plugins</title>
8+
<base href="../.." />
9+
<link rel="stylesheet" href="style.css" />
10+
<link rel="stylesheet" href="themes/prism.css" data-noprefix />
11+
<script src="prefixfree.min.js"></script>
12+
13+
<script>var _gaq = [['_setAccount', 'UA-33746269-1'], ['_trackPageview']];</script>
14+
<script src="http://www.google-analytics.com/ga.js" async></script>
15+
</head>
16+
<body>
17+
18+
<header>
19+
<div class="intro" data-src="templates/header-plugins.html" data-type="text/html"></div>
20+
21+
<h2>Normalize Whitespace</h2>
22+
<p>Supports multiple operations to normalize whitespace in code blocks.</p>
23+
</header>
24+
25+
<section class="language-markup">
26+
<h1>How to use</h1>
27+
28+
<p>Obviously, this is supposed to work only for code blocks (<code>&lt;pre>&lt;code></code>) and not for inline code.</p>
29+
<p>By default the plugin will trim all leading and trailing whitespace of every code block.</p>
30+
31+
<p>The plugin uses the <a href="plugins/parse-settings/">Parse Settings</a> plugin to get its settings.
32+
The default settings can be overridden with the <code class="language-javascript">setSettings()</code> method
33+
like so:</p>
34+
35+
<pre class="language-javascript"><code>
36+
Prism.plugins.NormalizeWhitespace.setSettings({
37+
'rem-trailing-whitespace': true,
38+
'rem-extra-indent': true,
39+
'left-trim': true,
40+
'right-trim': true,
41+
'rem-initial-line-feed': false,
42+
'tabs-to-spaces': false,
43+
'spaces-to-tabs': false,
44+
});
45+
</code></pre>
46+
47+
<p>It is also possible to change the default settings with <code>data-*</code>-attributes.</p>
48+
49+
<pre><code>&lt;code data-left-trim="false">...&lt;/code></code></pre>
50+
51+
<p>The class <code>no-whitespace-normalization</code> or the corresponding
52+
data-attribute can be used to disable the normalization for a particular
53+
code block.</p>
54+
55+
<pre><code>&lt;code class="no-whitespace-normalization"
56+
data-whitespace-normalization="false">
57+
...
58+
&lt;/code></code></pre>
59+
</section>
60+
61+
<section class="language-markup">
62+
<h1>Examples</h1>
63+
64+
<p>The following example shows some of the possible ways of configuring this plugin:</p>
65+
66+
<pre><code>
67+
&lt;body data-prism data-rem-trailing-whitespace="true">
68+
&lt;section id="main" class="language-javascript" data-right-trim="true">
69+
70+
&lt;pre>
71+
72+
&lt;code data-left-trim="true">
73+
74+
75+
var example = {
76+
foo: true,
77+
bar: false
78+
};
79+
80+
81+
&lt;/code>
82+
83+
&lt;/pre>
84+
85+
&lt;/section>
86+
&lt;script src="plugins/normalize-whitespace/prism-normalize-whitespace.js">&lt;/script>
87+
&lt;script type="text/javascript">
88+
Prism.plugins.NormalizeWhitespace.setSettings({
89+
'rem-trailing-whitespace': false,
90+
'left-trim': false,
91+
'right-trim': false
92+
});
93+
&lt;/script>
94+
&lt;/body>
95+
</code></pre>
96+
97+
<p>The result looks like this:</p>
98+
99+
<pre class="language-javascript">
100+
101+
<code>
102+
103+
104+
var example = {
105+
foo: true,
106+
bar: false
107+
};
108+
109+
110+
</code>
111+
112+
</pre>
113+
114+
</section>
115+
116+
<footer data-src="templates/footer.html" data-type="text/html"></footer>
117+
118+
<script src="prism.js"></script>
119+
<script src="plugins/parse-settings/prism-parse-settings.js"></script>
120+
<script src="plugins/normalize-whitespace/prism-normalize-whitespace.js"></script>
121+
<script src="utopia.js"></script>
122+
<script src="components.js"></script>
123+
<script src="code.js"></script>
124+
125+
126+
</body>
127+
</html>
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
(function() {
2+
3+
if (typeof self === 'undefined' || !self.Prism || !self.document || !Prism.plugins.Settings) {
4+
return;
5+
}
6+
7+
var Settings = Prism.plugins.Settings,
8+
merge = Settings.prototype.merge;
9+
10+
function NormalizeWhitespace(settings) {
11+
Settings.call(this, settings);
12+
}
13+
14+
NormalizeWhitespace.prototype = Object.create(Settings.prototype);
15+
NormalizeWhitespace.prototype.constructor = NormalizeWhitespace;
16+
17+
function toCamelCase(value) {
18+
return value.replace(/-(\w)/g, function(match, firstChar) {
19+
return firstChar.toUpperCase();
20+
});
21+
}
22+
23+
NormalizeWhitespace.prototype = merge(NormalizeWhitespace.prototype, {
24+
normalize: function(input, settings) {
25+
settings = (settings) ? merge(this.settings, settings) : this.settings;
26+
27+
for (var name in settings) {
28+
var methodName = toCamelCase(name);
29+
if (name !== "normalize" && methodName !== "setSettings" &&
30+
name !== "settings" && settings[name] && this[methodName]) {
31+
input = this[methodName].call(this, input, settings[name]);
32+
}
33+
}
34+
35+
return input;
36+
},
37+
38+
/*
39+
* Normalization methods
40+
*/
41+
leftTrim: function(input) {
42+
return input.replace(/^\s+/, '');
43+
},
44+
rightTrim: function(input) {
45+
return input.replace(/\s+$/, '');
46+
},
47+
tabsToSpaces: function(input, numberOfSpaces) {
48+
numberOfSpaces = numberOfSpaces || 4;
49+
var spaces = '';
50+
for (var i = 0; i < numberOfSpaces; ++i) {
51+
spaces += ' ';
52+
}
53+
return input.replace(/\t/g, spaces);
54+
},
55+
spacesToTabs: function(input, numberOfSpaces) {
56+
numberOfSpaces = parseInt(numberOfSpaces, 10) || 4;
57+
var regex = new RegExp(' {' + numberOfSpaces + '}', 'g');
58+
return input.replace(regex, '\t');
59+
},
60+
remTrailingWhitespace: function(input) {
61+
return input.replace(/\s*?$/gm, '');
62+
},
63+
remInitialLineFeed: function (input) {
64+
return input.replace(/^(?:\r?\n|\r)/, '');
65+
},
66+
remExtraIndent: function(input) {
67+
var shortestIndent = null;
68+
var indents = input.match(/^\s*(?=\S)/gm);
69+
70+
for (var i = 0; i < indents.length; ++i) {
71+
if (shortestIndent === null || shortestIndent > indents[i].length)
72+
shortestIndent = indents[i].length;
73+
}
74+
75+
if (!shortestIndent)
76+
return input;
77+
78+
return input.replace(/^\s*(?=\S)/gm, function(indent) {
79+
return indent.substring(shortestIndent);
80+
});
81+
}
82+
});
83+
84+
85+
Prism.plugins.NormalizeWhitespace = new NormalizeWhitespace({
86+
'rem-trailing-whitespace': true,
87+
'rem-extra-indent': true,
88+
'left-trim': true,
89+
'right-trim': true,
90+
'rem-initial-line-feed': false,
91+
'tabs-to-spaces': false,
92+
'spaces-to-tabs': false
93+
});
94+
95+
Prism.hooks.add('before-highlight', function (env) {
96+
var pre = env.element.parentNode;
97+
if (!env.code || !pre || pre.nodeName.toLowerCase() !== 'pre' ||
98+
env.settings['whitespace-normalization'] === false)
99+
return;
100+
101+
var children = pre.childNodes,
102+
before = '',
103+
after = '',
104+
codeFound = false;
105+
106+
// Move surrounding whitespace from the <pre> tag into the <code> tag
107+
for (var i = 0; i < children.length; ++i) {
108+
var node = children[i];
109+
110+
if (node == env.element) {
111+
codeFound = true;
112+
} else if (node.nodeName === "#text") {
113+
if (codeFound) {
114+
after += node.nodeValue;
115+
} else {
116+
before += node.nodeValue;
117+
}
118+
119+
pre.removeChild(node);
120+
// Cause the DOM API is crazy
121+
--i;
122+
}
123+
}
124+
env.code = before + env.code + after;
125+
126+
env.code = Prism.plugins.NormalizeWhitespace.normalize(env.code, env.settings);
127+
});
128+
129+
}());

plugins/normalize-whitespace/prism-normalize-whitespace.min.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

plugins/remove-initial-line-feed/index.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ <h2>Remove initial line feed</h2>
2323
</header>
2424

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

28+
<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>
2829
<p>Obviously, this is supposed to work only for code blocks (<code>&lt;pre>&lt;code></code>) and not for inline code.</p>
2930
<p>With this plugin included, any initial line feed will be removed by default.</p>
3031
<p>To bypass this behaviour, you may add the class <strong>keep-initial-line-feed</strong> to your desired <code>&lt;pre></code>.</p>

0 commit comments

Comments
 (0)