1add26278SSchplurtz le Déboulonné/* 2add26278SSchplurtz le Déboulonné * Copy2clipboard - copy <pre> text to clipboard. 3add26278SSchplurtz le Déboulonné * Copyright (C) 2020, 2021 Schplurtz le Déboulonné <Schplurtz@laposte.net> 4add26278SSchplurtz le Déboulonné * 5add26278SSchplurtz le Déboulonné * This program is free software; you can redistribute it and/or modify 6add26278SSchplurtz le Déboulonné * it under the terms of the CECILL 2.1 free license. See files 7add26278SSchplurtz le Déboulonné * LICENSE and LICENSE-fr for the details in the distribution directory or 8add26278SSchplurtz le Déboulonné * http://cecill.info/licences/Licence_CeCILL_V2.1-en.html 9add26278SSchplurtz le Déboulonné */ 104a476730SSchplurtz le DéboulonnéjQuery(function() { 114a476730SSchplurtz le Déboulonné if(!navigator.clipboard) 124a476730SSchplurtz le Déboulonné return; 13*1c306beaSSchplurtz le Déboulonné // messageBox( 'id', 'text' ); flash a message at top of screen 144a476730SSchplurtz le Déboulonné var messageBox=function( id, txt ) { 154a476730SSchplurtz le Déboulonné const body=document.getElementsByTagName('body')[0]; 164a476730SSchplurtz le Déboulonné const msg=document.createElement('div'); 174a476730SSchplurtz le Déboulonné msg.setAttribute('id', id ); 184a476730SSchplurtz le Déboulonné msg.classList.add('cp2clipmsg'); 194a476730SSchplurtz le Déboulonné const content = document.createTextNode(txt); 204a476730SSchplurtz le Déboulonné msg.appendChild(content); 214a476730SSchplurtz le Déboulonné body.appendChild(msg); 224a476730SSchplurtz le Déboulonné window.setTimeout(function() { 234a476730SSchplurtz le Déboulonné jQuery("#"+id).fadeTo(500, 0).slideUp(500, function(){ 244a476730SSchplurtz le Déboulonné jQuery(this).remove(); 254a476730SSchplurtz le Déboulonné }); 264a476730SSchplurtz le Déboulonné }, 1500); 2795208031SSchplurtz le Déboulonné }; 28*1c306beaSSchplurtz le Déboulonné // true on MS windows. used to set EOL 2986783ee6SSchplurtz le Déboulonné var iswin = (navigator.appVersion.indexOf("Win") != -1); 30*1c306beaSSchplurtz le Déboulonné // The async function that respond to click event 31eeae6715SSchplurtz le Déboulonné var response=async function(event) { 32eeae6715SSchplurtz le Déboulonné try { 33b16ffdaeSSchplurtz le Déboulonné let text=''; 3486783ee6SSchplurtz le Déboulonné // when line numbers are on, geshi uses <li> tag for each line 35*1c306beaSSchplurtz le Déboulonné let lis=event.target.previousSibling.getElementsByTagName('li'); 36eeae6715SSchplurtz le Déboulonné if( lis.length ) { 37eeae6715SSchplurtz le Déboulonné for( let li of lis ) { 38eeae6715SSchplurtz le Déboulonné text += li.textContent + '\n'; 39eeae6715SSchplurtz le Déboulonné } 40eeae6715SSchplurtz le Déboulonné } 4186783ee6SSchplurtz le Déboulonné // no line numbers, whole text is directely in <pre> tag 42eeae6715SSchplurtz le Déboulonné else { 43*1c306beaSSchplurtz le Déboulonné text = event.target.previousSibling.textContent; 4486783ee6SSchplurtz le Déboulonné text = text.replace( /\r\n/g, '\n' ); // can happen if page files are prepared on win and dropped in doku tree... 45eeae6715SSchplurtz le Déboulonné } 4686783ee6SSchplurtz le Déboulonné // Why replace \u00A0 ??? geshi adds an NBSP on each empty line. This is an issue 47eeae6715SSchplurtz le Déboulonné // with python, perl... when you want to run copied code, you get a 48eeae6715SSchplurtz le Déboulonné // syntax error "unexpected \xC2 character" or similar... So remove this 49eeae6715SSchplurtz le Déboulonné // crap. And yes it could remove a legitimate NBSP ; chances are low though. 50eeae6715SSchplurtz le Déboulonné text = text.replace(/^\u00A0$/gm, ""); 5186783ee6SSchplurtz le Déboulonné // if you paste \n separated lines with right button in powershell, the lines are 5286783ee6SSchplurtz le Déboulonné // fed in reverse order ! Most stupidly funny bug by MS ever. Anyway, just make sure 5386783ee6SSchplurtz le Déboulonné // we use \r\n separated lines under windows. It just makes sense. 5486783ee6SSchplurtz le Déboulonné // see powershell bugs https://github.com/PowerShell/PowerShell/issues/3816 and 5586783ee6SSchplurtz le Déboulonné // https://github.com/PowerShell/PSReadLine/issues/496 or 5686783ee6SSchplurtz le Déboulonné // https://github.com/PowerShell/PSReadLine/issues/579 , they're all the same... 5786783ee6SSchplurtz le Déboulonné if( iswin ) { 5886783ee6SSchplurtz le Déboulonné text=text.replace(/\n/g, '\r\n' ); 5986783ee6SSchplurtz le Déboulonné } 60eeae6715SSchplurtz le Déboulonné await navigator.clipboard.writeText(text); 61f20dc62bSSchplurtz le Déboulonné // console.log( "copié >>>" + text + "<<<" ); 62eeae6715SSchplurtz le Déboulonné messageBox('cp2clipok', LANG.plugins.copy2clipboard.copied); 63eeae6715SSchplurtz le Déboulonné } catch (err) { 64f20dc62bSSchplurtz le Déboulonné // console.error('Failed to copy!', err); 65eeae6715SSchplurtz le Déboulonné messageBox('cp2clipnok', LANG.plugins.copy2clipboard.error); 66eeae6715SSchplurtz le Déboulonné } 67eeae6715SSchplurtz le Déboulonné }; 68eeae6715SSchplurtz le Déboulonné 69*1c306beaSSchplurtz le Déboulonné // iterate over all <pre> node and create the needed structure. 70*1c306beaSSchplurtz le Déboulonné // <pre>...</pre> ==> <div class="cp2clipcont"><pre>...</pre><button /></div> 714a476730SSchplurtz le Déboulonné document.querySelectorAll('pre.code,pre.file').forEach(function(elem) { 72*1c306beaSSchplurtz le Déboulonné // wrap current node in a div. See https://stackoverflow.com/a/46595686/1831273 73*1c306beaSSchplurtz le Déboulonné let container=document.createElement('div'); 74*1c306beaSSchplurtz le Déboulonné container.classList.add('cp2clipcont'); 75*1c306beaSSchplurtz le Déboulonné elem.parentNode.insertBefore(container, elem); 76*1c306beaSSchplurtz le Déboulonné elem.previousElementSibling.appendChild(elem); 77*1c306beaSSchplurtz le Déboulonné 78*1c306beaSSchplurtz le Déboulonné let cpbutton = document.createElement('button'); 79*1c306beaSSchplurtz le Déboulonné cpbutton.setAttribute( 'title', LANG.plugins.copy2clipboard.title); 80*1c306beaSSchplurtz le Déboulonné //cpbutton.classList.add('cp2clip'); 81*1c306beaSSchplurtz le Déboulonné container.appendChild(cpbutton); 82*1c306beaSSchplurtz le Déboulonné cpbutton.addEventListener('click', response) 834a476730SSchplurtz le Déboulonné }) 8495208031SSchplurtz le Déboulonné}); 854a476730SSchplurtz le Déboulonné 86