// ==UserScript== // @name jira-confluence // @namespace caichinger.com // @description Sanity for JIRA and Confluence // @include https://wiki.appcelerator.org/* // @include https://jira.appcelerator.org/* // @require http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js // @version 1 // @grant none // ==/UserScript== function run_userscript(jQuery) { "use strict"; document.styleSheets[0].insertRule( '#navigation {' + ' border-radius: 5px 5px 5px 5px;' + ' background-color: #F1F1F1;' + ' display: inline;' + ' padding: 5px;' + ' position: fixed;' + ' right: 15px;' + ' z-index: 10000;' + '}', 0); document.styleSheets[0].insertRule( '#navigation > *:first-child {' + ' padding:0px !important; ' + '}', 0); document.styleSheets[0].insertRule( '#wysiwyg > .cell, .wiki-edit-content {' + ' position: relative;' + ' display: block;' + '}', 0); document.styleSheets[0].insertRule( '.markdown-editor {' + ' top: 0px;' + ' height: 100%;' + ' width: 75%;' + ' left: 25%;' + ' position: absolute;' + ' pointer-events: none;' + '}', 0); document.styleSheets[0].insertRule( '.markdown-editor-container {' + ' width: 100%;' + ' height: calc(100% - 15px);' + ' position: relative;' + ' pointer-events: initial;' + '}', 0); document.styleSheets[0].insertRule( '#wysiwyg .markdown-editor-container {' + ' height: 100%;' + '}', 0); document.styleSheets[0].insertRule( '.markdown-editor-text {' + ' box-sizing: border-box;' + ' width: 100%;' + ' height: 100%;' + ' resize: none;' + '}', 0); document.styleSheets[0].insertRule( '.markdown-editor-paste {' + ' box-sizing: border-box;' + ' position: absolute;' + ' bottom: 0px;' + ' right: 0px;' + '}', 0); document.styleSheets[0].insertRule( '.aui-toolbar2 span.icon-markdown {' + ' background: url(data:image/png;base64,' + 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAASklEQVQ4y2NgGAWDBBQUFLwrKCh4' + 'R4w4uhgTuiQ2Nj7Ags1WUlyP4oIJEyYIYWOT5AJcGrGFBYYL8AFsBk+YMEGIiRT/kuPFIQAA+5cl' + 'CTYaywMAAAAASUVORK5CYII=' + ') no-repeat center;' + '}', 0); document.styleSheets[0].insertRule( '.aui-toolbar2 span.icon-dod {' + ' background: url(data:image/png;base64,' + 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAWUlEQVQ4y2NgGAUUA8aCgoJ3MM6E' + 'CROE8CnGppYJlwJCAKaWCd1EYgxBVstEaRgwEXImIRcx4dM8YcIEoQkTJgjhM4QJPVAIxQS6WhZs' + 'gQNj4zOUGIuGCAAAPcQyUGN6UfMAAAAASUVORK5CYII=' + ') no-repeat center;' + '}', 0); // Constants //////////// var DOD = '*DOD:*\n' + '\n' + '(?) Release Notes\n' + '(?) The change must be committed in git and it has to be pushed (all submodules!)\n' + '(?) The documentation has to be updated to contain the information to this change.\n' + '(?) There must be some sort of test in order to easily check that the feature actually work.\n' + '(?) The feature must be packaged.\n' + '(?) There need to be admin tickets in order to deploy the change.\n' + '(?) UBIALERT Label if it is a task that relates to the severe weather warning\n' + '(?) reviewed by …\n'; // JQuery insertAtCaret extension ///////////////////////////////// jQuery.fn.extend({ insertAtCaret: function(myValue){ return this.each(function(i) { if (document.selection) { //For browsers like Internet Explorer this.focus(); var sel = document.selection.createRange(); sel.text = myValue; this.focus(); } else if (this.selectionStart || this.selectionStart == '0') { //For browsers like Firefox and Webkit based var startPos = this.selectionStart; var endPos = this.selectionEnd; var scrollTop = this.scrollTop; this.value = this.value.substring(0, startPos)+myValue+this.value.substring(endPos,this.value.length); this.focus(); this.selectionStart = startPos + myValue.length; this.selectionEnd = startPos + myValue.length; this.scrollTop = scrollTop; } else { this.value += myValue; this.focus(); } }); } }); // J2M / M2J functions ////////////////////// function toM(converted) { converted = converted.replace(/^h([0-6])\.(.*)$/gm, function (match,level,content) { return Array(parseInt(level) + 1).join('#') + content; }); converted = converted.replace(/([*_])(.*)\1/g, function (match,wrapper,content) { var to = (wrapper === '*') ? '**' : '*'; return to + content + to; }); converted = converted.replace(/\{\{([^}]+)\}\}/g, '`$1`'); converted = converted.replace(/\?\?((?:.[^?]|[^?].)+)\?\?/g, '$1'); converted = converted.replace(/\+([^+]*)\+/g, '$1'); converted = converted.replace(/\^([^^]*)\^/g, '$1'); converted = converted.replace(/~([^~]*)~/g, '$1'); converted = converted.replace(/-([^-]*)-/g, '~~$1~~'); converted = converted.replace(/\{code(:([a-z]+))?\}([^]*)\{code\}/gm, '```$2$3```'); converted = converted.replace(/\[(.+?)\|(.+)\]/g, '[$1]($2)'); converted = converted.replace(/\[(.+?)\]([^\(]*)/g, '<$1>$2'); converted = converted.replace(/{noformat}/g, '```'); return converted; } function toJ(converted) { converted = converted.replace(/^(.*?)\n([=-])+$/gm, function (match,content,level) { return 'h' + (level[0] === '=' ? 1 : 2) + '. ' + content; }); converted = converted.replace(/^([#]+)(.*?)$/gm, function (match,level,content) { return 'h' + level.length + '.' + content; }); converted = converted.replace(/([*_]+)(.*?)\1/g, function (match,wrapper,content) { var to = (wrapper.length === 1) ? '_' : '*'; return to + content + to; }); var map = { cite: '??', del: '-', ins: '+', sup: '^', sub: '~' }; var regex = new RegExp('<(' + Object.keys(map).join('|') + ')>(.*?)<\/\\1>', 'g'); converted = converted.replace(regex, function (match,from,content) { console.log(from); var to = map[from]; return to + content + to; }); converted = converted.replace(/~~(.*?)~~/g, '-$1-'); converted = converted.replace(/`{3,}(\w+)?((?:\n|[^`])+)`{3,}/g, function(match, synt, content) { var code = '{code'; if (synt) { code += ':' + synt; } code += '}' + content + '{code}'; return code; }); converted = converted.replace(/`([^`]+)`/g, '{{$1}}'); converted = converted.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '[$1|$2]'); converted = converted.replace(/<([^>]+)>/g, '[$1]'); return converted; } // Floating edit buttons in Confluence ////////////////////////////////////// function floatConfluenceEditButton() { var nav = jQuery("#navigation"); if (nav.length) { var navDefaultTop = nav.offset().top; var navOldTop = null; jQuery(window).scroll(function (evt) { var scrollTop = jQuery(window).scrollTop(); var newTop = navDefaultTop - scrollTop; if (newTop < 15) { newTop = 15; } if (newTop !== navOldTop) { nav.css("top", "" + newTop + "px"); navOldTop = newTop; } }); } } // Editor enhancements ////////////////////// function isPlaintext() { return window['tinyMCE'] === undefined; } function hasNot(selector) { function hasNotSelector() { return jQuery(selector, this).length === 0; } return hasNotSelector; } function registerClickOnce(selector, fun) { var clsName = 'has-evt-handler-' + selector.replace(/[.#]/g, '').replace(/-/g, '_'); jQuery(selector) .not('.' + clsName) .addClass(clsName) .click(fun); } function addEditorButtons() { var editorButtons = jQuery.parseHTML( '
')[0]; if (!isPlaintext()) { if (jQuery(".aui-toolbar2-secondary").length !== 0) { jQuery(".aui-toolbar2-secondary") .filter(hasNot('.insert-mkd-btn')) .prepend(editorButtons); return; } } else { if (jQuery(".aui-toolbar2-primary").length !== 0) { jQuery(".aui-toolbar2-primary") .filter(hasNot('.insert-mkd-btn')) .append(editorButtons); jQuery(".wiki-edit-toolbar-last").hide(); return; } } console.log("unable to find element"); } function addMarkdownEditor() { var markdownEditor = jQuery.parseHTML( ' ')[0]; jQuery("#wysiwyg > .cell, .wiki-edit-content") .filter(hasNot('.markdown-editor')) .append(markdownEditor); } function addEventHandlers() { function insertDODClick(evt) { if (isPlaintext()) { var editor = jQuery(this).closest('.wiki-edit'); editor.find('.wiki-textfield').insertAtCaret(DOD); } else { var dod = DOD.replace(/\n/g, '