diff --git a/src/HtmlUtils.js b/src/HtmlUtils.js
index 8af1894c79..5e8cfc3755 100644
--- a/src/HtmlUtils.js
+++ b/src/HtmlUtils.js
@@ -345,6 +345,7 @@ export function bodyToHtml(content, highlights, opts) {
}
safeBody = sanitizeHtml(body, sanitizeHtmlParams);
safeBody = unicodeToImage(safeBody);
+ safeBody = addCodeCopyButton(safeBody);
}
finally {
delete sanitizeHtmlParams.textFilter;
@@ -363,6 +364,18 @@ export function bodyToHtml(content, highlights, opts) {
return ;
}
+function addCodeCopyButton(safeBody) {
+ const el = document.createElement("div");
+ el.innerHTML = safeBody;
+ const codeBlocks = Array.from(el.getElementsByTagName("pre"));
+ codeBlocks.forEach(p => {
+ const button = document.createElement("span");
+ button.className = "mx_EventTile_copyButton";
+ p.appendChild(button);
+ });
+ return el.innerHTML;
+}
+
export function emojifyText(text) {
return {
__html: unicodeToImage(escape(text)),
diff --git a/src/components/views/messages/TextualBody.js b/src/components/views/messages/TextualBody.js
index 9595c2b850..45fca566b9 100644
--- a/src/components/views/messages/TextualBody.js
+++ b/src/components/views/messages/TextualBody.js
@@ -63,6 +63,19 @@ module.exports = React.createClass({
};
},
+ copyToClipboard: function(text) {
+ const textArea = document.createElement("textarea");
+ textArea.value = text;
+ document.body.appendChild(textArea);
+ textArea.select();
+ try {
+ const successful = document.execCommand('copy');
+ } catch (err) {
+ console.log('Unable to copy');
+ }
+ document.body.removeChild(textArea);
+ },
+
componentDidMount: function() {
this._unmounted = false;
@@ -81,6 +94,15 @@ module.exports = React.createClass({
}
}, 10);
}
+ const buttons = ReactDOM.findDOMNode(this).getElementsByClassName("mx_EventTile_copyButton");
+ if (buttons.length > 0) {
+ for (let i = 0; i < buttons.length; i++) {
+ buttons[i].onclick = (e) => {
+ const copyCode = buttons[i].parentNode.getElementsByTagName("code")[0];
+ this.copyToClipboard(copyCode.textContent);
+ };
+ }
+ }
}
},