Skip to content

Commit

Permalink
Merge pull request #770 from Golmote/prism-keep-markup
Browse files Browse the repository at this point in the history
Keep Markup Plugin
  • Loading branch information
Golmote committed Sep 22, 2015
2 parents ed4ccfe + 391b440 commit bd3e9ea
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 0 deletions.
5 changes: 5 additions & 0 deletions components.js
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,11 @@ var components = {
"title": "Autoloader",
"owner": "Golmote",
"noCSS": true
},
"keep-markup": {
"title": "Keep Markup",
"owner": "Golmote",
"noCSS": true
}
}
};
80 changes: 80 additions & 0 deletions plugins/keep-markup/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<!DOCTYPE html>
<html lang="en">
<head>

<meta charset="utf-8" />
<link rel="shortcut icon" href="favicon.png" />
<title>Keep markup ▲ Prism plugins</title>
<base href="../.." />
<link rel="stylesheet" href="style.css" />
<link rel="stylesheet" href="themes/prism.css" data-noprefix />

<style type="text/css">
code[class*="language-"] mark,
pre[class*="language-"] mark {
display: inline-block;
color: inherit;
background: none;
border: 1px solid #000;
box-shadow: 0 0 2px #fff;
padding: 1px;
background: rgba(0,0,0,0.2);
}
</style>

<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>Keep markup</h2>
<p>Prevents custom markup from being dropped out during highlighting.</p>
</header>

<section>

<h1>How to use</h1>
<p>You have nothing to do. With this plugin loaded, all markup inside code will be kept.</p>

<h1>Examples</h1>

<p>The following source code</p>
<pre><code class="language-markup">&lt;pre>&lt;code class="language-css">
@media &lt;mark>screen&lt;/mark> {
div {
&lt;mark>text&lt;/mark>-decoration: &lt;mark>&lt;mark>under&lt;/mark>line&lt;/mark>;
back&lt;mark>ground: url&lt;/mark>('foo.png');
}
}&lt;/code>&lt;/pre></code></pre>

<p>would render like this:</p>
<pre><code class="language-css">
@media <mark>screen</mark> {
div {
<mark>text</mark>-decoration: <mark><mark>under</mark>line</mark>;
back<mark>ground: url</mark>('foo.png');
}
}</code></pre>

<p>
It also works for inline code:
<code class="language-javascript">v<mark>ar b</mark>ar = <mark>func</mark>tion () { <mark>/*</mark> foo <mark>*</mark>/ };</code>
</p>

</section>

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

<script src="prism.js"></script>
<script src="plugins/keep-markup/prism-keep-markup.js"></script>
<script src="utopia.js"></script>
<script src="components.js"></script>
<script src="code.js"></script>

</body>
</html>
97 changes: 97 additions & 0 deletions plugins/keep-markup/prism-keep-markup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
(function () {

if (typeof self === 'undefined' || !self.Prism || !self.document || !document.createRange) {
return;
}

Prism.hooks.add('before-highlight', function (env) {
var firstWhiteSpaces = false;
var pos = 0;
var data = [];
var f = function (elt, baseNode) {
var o = {};
if (!baseNode) {
// Clone the original tag to keep all attributes
o.clone = elt.cloneNode(false);
o.posOpen = pos;
data.push(o);
}
for (var i = 0, l = elt.childNodes.length; i < l; i++) {
var child = elt.childNodes[i];
if (child.nodeType === 1) { // element
f(child);
} else if(child.nodeType === 3) { // text
if(!firstWhiteSpaces) {
// We need to ignore the first white spaces in the code block
child.data = child.data.replace(/^(?:\r?\n|\r)/, '');
firstWhiteSpaces = true;
}
pos += child.data.length;
}
}
if (!baseNode) {
o.posClose = pos;
}
};
f(env.element, true);

if (data && data.length) {
// data is an array of all existing tags
env.keepMarkup = data;
}
});

Prism.hooks.add('after-highlight', function (env) {
if(env.keepMarkup && env.keepMarkup.length) {

var walk = function (elt, nodeState) {
for (var i = 0, l = elt.childNodes.length; i < l; i++) {

var child = elt.childNodes[i];

if (child.nodeType === 1) { // element
if (!walk(child, nodeState)) {
return false;
}

} else if (child.nodeType === 3) { // text
if(!nodeState.nodeStart && nodeState.pos + child.data.length > nodeState.node.posOpen) {
// We found the start position
nodeState.nodeStart = child;
nodeState.nodeStartPos = nodeState.node.posOpen - nodeState.pos;
}
if(nodeState.nodeStart && nodeState.pos + child.data.length >= nodeState.node.posClose) {
// We found the end position
nodeState.nodeEnd = child;
nodeState.nodeEndPos = nodeState.node.posClose - nodeState.pos;
}

nodeState.pos += child.data.length;
}

if (nodeState.nodeStart && nodeState.nodeEnd) {
// Select the range and wrap it with the clone
var range = document.createRange();
range.setStart(nodeState.nodeStart, nodeState.nodeStartPos);
range.setEnd(nodeState.nodeEnd, nodeState.nodeEndPos);
nodeState.node.clone.appendChild(range.extractContents());
range.insertNode(nodeState.node.clone);
range.detach();

// Process is over
return false;
}
}
return true;
};

// For each tag, we walk the DOM to reinsert it
env.keepMarkup.forEach(function (node) {
walk(env.element, {
node: node,
pos: 0
});
});
}
});
}());
1 change: 1 addition & 0 deletions plugins/keep-markup/prism-keep-markup.min.js

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

0 comments on commit bd3e9ea

Please sign in to comment.