Skip to content

Commit

Permalink
Plugins: Toolbar & Copy to Clipboard (#891)
Browse files Browse the repository at this point in the history
* Add prism-toolbar plugin

This plugin exposes a `registerButton` method, which other
plugins can use to add buttons to the toolbar. Comes with
styles.

* Add demo file for toolbar plugin

Registers a "Hello World!" tag with the toolbar.

* Make `toolbar.registerButton` polymorphic

This allows developers to provide either a callback or an object
with a `text` string and an optional `onClick` function to create
a new button.

* Add Toolbar & Copy to Clipboard to components.js

* Add Copy to Clipboard plugin

* Switch `innerHTML` to `textContent`

This ensures additional HTML can't be passed to the toolbar
via the `text` property, ensuring a consistent display for the
buttons.

* Use `call` to bind `this` to the `onClick` method

This provides access to the clicked element, which is what `this`
is usually bound to on event listeners.

* Add hover animation to toolbar

* Add drop shadow to toolbar buttons

* Add `clipboard` to `optionalDependencies`

This will install Clipboard.js when installing from `npm`, but
won't fail the build if the installation of Clipboard.js fails.

* Load Clipboard.js from CDN if not present

* Display plugin code using data-src

* Recompile prism-toolbar

* Update Show Languages to be a Toolbar button

Show Languages now registers a callback with the toolbar
plugin to return an element with the language in it.

* Add basic HTML API & documentation

The Toolbar will now be able to read a `data-label` attribute
and add it to the code snippet.

* Switch a -> button when only providing onClick

Also adds a `url` property which creats an anchor tag and sets
the href. Adds some styles to override the button defaults.

* Add support for data-url to create anchor tag

This allows the HTML API to create links in the Toolbar.

* Update toolbar to allow order controlled via HTML

Uses a data-attribute on the `body` tag to update the order,
should the user choose to do so.

* Allow template element to provide content to label

This provides one of several options a user can implement in order to
get a custom button.

Also fixes some bugs in the documentation.

* Fix bug when combined with the autoloader plugin

The autoloader will rehighlight the element after the language arrives.
This means the complete hook can run multiple times. Without a check,
multiple toolbars can get added to an element.
  • Loading branch information
mAAdhaTTah authored and Golmote committed Nov 9, 2016
1 parent 25cdd3f commit 07b81ac
Show file tree
Hide file tree
Showing 13 changed files with 480 additions and 51 deletions.
14 changes: 13 additions & 1 deletion components.js
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,9 @@ var components = {
},
"show-language": {
"title": "Show Language",
"owner": "nauzilus"
"owner": "nauzilus",
"noCSS": true,
"require": "toolbar"
},
"jsonp-highlight": {
"title": "JSONP Highlight",
Expand Down Expand Up @@ -659,6 +661,16 @@ var components = {
"title": "Data-URI Highlight",
"owner": "Golmote",
"noCSS": true
},
"toolbar": {
"title": "Toolbar",
"owner": "mAAdhaTTah"
},
"copy-to-clipboard": {
"title": "Copy to Clipboard Button",
"owner": "mAAdhaTTah",
"require": "toolbar",
"noCSS": true
}
}
};
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
"author": "Lea Verou",
"license": "MIT",
"readmeFilename": "README.md",
"optionalDependencies": {
"clipboard": "^1.5.5"
},
"devDependencies": {
"chai": "^2.3.0",
"gulp": "^3.8.6",
Expand Down
48 changes: 48 additions & 0 deletions plugins/copy-to-clipboard/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<!DOCTYPE html>
<html lang="en">
<head>

<meta charset="utf-8" />
<link rel="shortcut icon" href="favicon.png" />
<title>Copy to Clipboard ▲ 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/toolbar/prism-toolbar.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 class="language-markup">

<header>
<div class="intro" data-src="templates/header-plugins.html" data-type="text/html"></div>

<h2>Copy to Clipboard</h2>
<p>Add a button that copies the code block to the clipboard when clicked.</p>
</header>

<section>
<h1>How to use</h1>
<p>In addition to including the plugin file with your PrismJS build, ensure <a href="https://clipboardjs.com/">Clipboard.js</a> is loaded before the plugin.</p>

<p>The simplest way to include Clipboard.js is to use any of the
<a href="https://github.com/zenorocha/clipboard.js/wiki/CDN-Providers">recommended CDNs</a>. If you're using Browserify, Clipboard.js will be loaded auotmatically
if it's included in your <code>package.json</code>.
If you don't load Clipboard.js yourself, the plugin will load it from a CDN for you.</p>

<pre data-src="plugins/copy-to-clipboard/prism-copy-to-clipboard.js"></pre>
</section>

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

<script src="prism.js"></script>
<script src="plugins/toolbar/prism-toolbar.js"></script>
<script src="plugins/copy-to-clipboard/prism-copy-to-clipboard.js"></script>
<script src="utopia.js"></script>
<script src="components.js"></script>
<script src="code.js"></script>

</body>
</html>
75 changes: 75 additions & 0 deletions plugins/copy-to-clipboard/prism-copy-to-clipboard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
(function(){
if (typeof self === 'undefined' || !self.Prism || !self.document) {
return;
}

if (!Prism.plugins.toolbar) {
console.warn('Copy to Clipboard plugin loaded before Toolbar plugin.');

return;
}

var Clipboard = window.Clipboard || undefined;

if (!Clipboard && typeof require === 'function') {
Clipboard = require('clipboard');
}

var callbacks = [];

if (!Clipboard) {
var script = document.createElement('script');
var head = document.querySelector('head');

script.onload = function() {
Clipboard = window.Clipboard;

if (Clipboard) {
while (callbacks.length) {
callbacks.pop()();
}
}
};

script.src = 'https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.5.8/clipboard.min.js';
head.appendChild(script);
}

Prism.plugins.toolbar.registerButton('copy-to-clipboard', function (env) {
var linkCopy = document.createElement('a');
linkCopy.textContent = 'Copy';

if (!Clipboard) {
callbacks.push(registerClipboard);
} else {
registerClipboard();
}

return linkCopy;

function registerClipboard() {
var clip = new Clipboard(linkCopy, {
'text': function () {
return env.code;
}
});

clip.on('success', function() {
linkCopy.textContent = 'Copied!';

resetText();
});
clip.on('error', function () {
linkCopy.textContent = 'Press Ctrl+C to copy';

resetText();
});
}

function resetText() {
setTimeout(function () {
linkCopy.textContent = 'Copy';
}, 5000);
}
});
})();
1 change: 1 addition & 0 deletions plugins/copy-to-clipboard/prism-copy-to-clipboard.min.js

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

5 changes: 3 additions & 2 deletions plugins/show-language/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<base href="../.." />
<link rel="stylesheet" href="style.css" />
<link rel="stylesheet" href="themes/prism.css" data-noprefix />
<link rel="stylesheet" href="plugins/show-language/prism-show-language.css" data-noprefix />
<link rel="stylesheet" href="plugins/toolbar/prism-toolbar.css" data-noprefix />
<script src="prefixfree.min.js"></script>

<script>var _gaq = [['_setAccount', 'UA-33746269-1'], ['_trackPageview']];</script>
Expand All @@ -25,7 +25,7 @@ <h2>Show Language</h2>

<section>
<h1>Examples</h1>

<h2>JavaScript</h2>
<pre data-src="plugins/show-language/prism-show-language.js"></pre>

Expand All @@ -43,6 +43,7 @@ <h2>SVG</h2>
<footer data-src="templates/footer.html" data-type="text/html"></footer>

<script src="prism.js"></script>
<script src="plugins/toolbar/prism-toolbar.js"></script>
<script src="plugins/show-language/prism-show-language.js"></script>
<script src="utopia.js"></script>
<script src="components.js"></script>
Expand Down
27 changes: 0 additions & 27 deletions plugins/show-language/prism-show-language.css

This file was deleted.

30 changes: 10 additions & 20 deletions plugins/show-language/prism-show-language.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,25 @@ if (typeof self === 'undefined' || !self.Prism || !self.document) {
return;
}

if (!Prism.plugins.toolbar) {
console.warn('Show Languages plugin loaded before Toolbar plugin.');

return;
}

// The languages map is built automatically with gulp
var Languages = /*languages_placeholder[*/{"html":"HTML","xml":"XML","svg":"SVG","mathml":"MathML","css":"CSS","clike":"C-like","javascript":"JavaScript","abap":"ABAP","actionscript":"ActionScript","apacheconf":"Apache Configuration","apl":"APL","applescript":"AppleScript","asciidoc":"AsciiDoc","aspnet":"ASP.NET (C#)","autoit":"AutoIt","autohotkey":"AutoHotkey","basic":"BASIC","csharp":"C#","cpp":"C++","coffeescript":"CoffeeScript","css-extras":"CSS Extras","fsharp":"F#","glsl":"GLSL","graphql":"GraphQL","http":"HTTP","inform7":"Inform 7","json":"JSON","latex":"LaTeX","livescript":"LiveScript","lolcode":"LOLCODE","matlab":"MATLAB","mel":"MEL","nasm":"NASM","nginx":"nginx","nsis":"NSIS","objectivec":"Objective-C","ocaml":"OCaml","parigp":"PARI/GP","php":"PHP","php-extras":"PHP Extras","powershell":"PowerShell","properties":".properties","protobuf":"Protocol Buffers","jsx":"React JSX","rest":"reST (reStructuredText)","sas":"SAS","sass":"Sass (Sass)","scss":"Sass (Scss)","sql":"SQL","typescript":"TypeScript","vhdl":"VHDL","vim":"vim","wiki":"Wiki markup","xojo":"Xojo (REALbasic)","yaml":"YAML"}/*]*/;
Prism.hooks.add('before-highlight', function(env) {
Prism.plugins.toolbar.registerButton('show-language', function(env) {
var pre = env.element.parentNode;
if (!pre || !/pre/i.test(pre.nodeName)) {
return;
}
var language = pre.getAttribute('data-language') || Languages[env.language] || (env.language.substring(0, 1).toUpperCase() + env.language.substring(1));

/* check if the divs already exist */
var sib = pre.previousSibling;
var div, div2;
if (sib && /\s*\bprism-show-language\b\s*/.test(sib.className) &&
sib.firstChild &&
/\s*\bprism-show-language-label\b\s*/.test(sib.firstChild.className)) {
div2 = sib.firstChild;
} else {
div = document.createElement('div');
div2 = document.createElement('div');
var element = document.createElement('span');
element.innerHTML = language;

div2.className = 'prism-show-language-label';

div.className = 'prism-show-language';
div.appendChild(div2);

pre.parentNode.insertBefore(div, pre);
}

div2.innerHTML = language;
return element;
});

})();
2 changes: 1 addition & 1 deletion plugins/show-language/prism-show-language.min.js

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

Loading

0 comments on commit 07b81ac

Please sign in to comment.