NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name WPorg-Dev // @namespace wordpress // @description A userscript to help developers access certain WordPress.org plugin information and pages a lot easier. // @include https://wordpress.org/plugins/* // @include https://*.wordpress.org/plugins/* // @version 2.0 // @copyright 2017 Armando Lüscher // @author Armando Lüscher // @oujs:author noplanman // @grant GM_addStyle // @require https://code.jquery.com/jquery-1.11.3.min.js // @homepageURL https://github.com/noplanman/WPorg-Dev-Userscript // @supportURL https://github.com/noplanman/WPorg-Dev-Userscript/issues // @updateURL https://github.com/noplanman/WPorg-Dev-Userscript/raw/master/WPorg-Dev.user.js // ==/UserScript== // The base URL of the WordPress plugins pages. var wpBaseURL = location.protocol + '//' + location.host; var pluginsBaseURL = wpBaseURL + '/plugins/'; var wodu = {}; /** * Extract the plugin slug from a URL. * @param {string} url URL to extract the plugin slug from. * @return {string} The extracted plugin slug. */ wodu.getSlug = function (url) { var p = url.indexOf(pluginsBaseURL); if (p >= 0) { return url.substring(p + pluginsBaseURL.length).split('/')[0]; } return ''; }; /** * Generate the failed message and the retry button. * * @param {jQuery} $el The error message panel gets appended to this jQuery object. * @param {Function} cb Callback function when clicking the "Retry" button. * @return {jQuery} The jQuery object containing the message and button. */ wodu.getFailedRetryButton = function ($el, cb) { $el.removeClass('wodu-loaded'); return $('<div class="wodu-failed error">Failed.</div>') .append($('<div class="alignright button button-primary button-small">Retry</div>').click(cb)) .appendTo($el); }; /** * Generate a dropdown menu with all the downloadable versions. * * When the selection changes, the selected version download begins. * * @param {jQuery} $devPage The page containing the links. * @return {jQuery} Dropdown menu with all the links. */ wodu.getDLLinkDropdown = function ($devPage) { var $select = $('<select class="wodu-dllink-dropdown"/>') .append('<option value="">' + $('#download-previous-link', $devPage).text() + '</option>') .click(function () { this.value = ''; }) .change(function () { if (this.value) location.href = this.value; }); // Force width of first entry. (https://stackoverflow.com/a/27442394) var $selectTmp = $select.clone().hide(); $selectTmp.appendTo($('body')); $select.width($selectTmp.width() + 10); $selectTmp.remove(); $('.previous-versions option', $devPage).each(function () { $select.append('<option value="' + $(this).attr('value') + '">' + $(this).text() + '</option>'); }); return $select; }; /** * Get the repository (and admin) links from the developers page. * * @param {string} slug Plugin slug. * @param {jQuery} $devPage The page containing the links. * @return {array} An array of the developer links. */ wodu.getDevLinks = function (slug, $devPage) { return [ '<a href="' + pluginsBaseURL + slug + '#developers">Developers</a>', '<a href="http://plugins.svn.wordpress.org/' + slug + '">SVN</a>', '<a href="http://plugins.trac.wordpress.org/browser/' + slug + '">Trac</a>', '<a href="http://plugins.trac.wordpress.org/log/' + slug + '">Log</a>' ]; }; /** * Load the extra plugin infos for a certain plugin. * * @param {jQuery} $card The plugin cart to load the infos for. */ wodu.loadPluginCardExtra = function ($card) { if ($card.hasClass('wodu-loaded')) { return; } $card.addClass('wodu-loaded'); var slug = wodu.getSlug($('.entry-title a', $card).attr('href')); // Get rid of any error message that may be there. var $panelInfo = $('.wodu-panel-info', $card).empty(); var $spinner = $('.wodu-spinner', $card).show(); $.get(pluginsBaseURL + slug + '/advanced', function (response) { // Get rid of all images first, no need to load those. var $devPage = $(response.replace(/<img[^>]*>/g, '')); var $meta = $('.plugin-meta', $devPage); // Remove languages section, no need for it. $('.languages', $meta).parent().remove(); $panelInfo.append($meta); var $panelDev = $('.wodu-panel-dev', $card) .append(wodu.getDevLinks(slug, $devPage).join(' - ')) .append(wodu.getDLLinkDropdown($devPage)); }) .fail(function () { wodu.getFailedRetryButton($panelInfo, function () { wodu.loadPluginCardExtra($card); }); }) .always(function () { $spinner.hide(); }); }; /** * Add extra plugin information to plugin cards. * * @param {jQuery} $pluginCards All the plugin cards displayed on the current page. */ wodu.setupPluginCardExtras = function ($pluginCards) { // Add the CSS. GM_addStyle( '.wodu-close { position: absolute; top: 4px; right: 4px; }' + '.wodu-plugin-card { position: relative; }' + '.wodu-title { font-size: 1.1em; }' + '.wodu-dllink-dropdown { float: right; padding: 3px 5px; }' + '.wodu-plugin-card-extras { box-sizing: border-box; overflow: auto; display: none; position: absolute; width: 100%; height: 100%; margin: -15px; border: 1px solid #ccc; padding: 4px 10px; background-color: rgba(255, 255, 255, 0.9); z-index: 1; }' + // Little triangle. '.wodu-plugin-card:before { content: ""; position: absolute; top: 0px; right: 0px; border-width: 36px 0 0 36px; border-style: solid; border-color: #ddd transparent; }' + '.wodu-extras-button { position: absolute; top: 4px; right: 4px; height: 16px; width: 16px; cursor: pointer; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAjElEQVQ4jdWSUQ2AMAxEn4RKQMIkIAEJSEHCHIAEnIATcAA/HYGyhoUvuL8l17vXdPAXdUD1drgBNkCejEGbrAZgNDTBmgRYnIAVaE/vqN6DSIBJm6w8/FFnJCHOGVMO/1w6A30yHWkP+FnqS1oBflrhQi3aFgvwo3pvwfaMHn4kc0ar4s/jqXbaP6gdQPwjtYbeRCAAAAAASUVORK5CYII=); }' ); $pluginCards.each(function () { var $card = $(this).addClass('wodu-plugin-card'); var $extrasButton = $('<div class="wodu-extras-button"/>') .click(function () { $extrasButton.hide(); $extras.show(); wodu.loadPluginCardExtra($card); }) .prependTo($card); // Prepare the extras. var $close = $('<div class="wodu-close"/>') .click(function () { $extras.hide(); $extrasButton.show(); }); var $extras = $('<div/>', {class: 'wodu-plugin-card-extras'}) .append($close) .append('<div class="wodu-spinner"/>') .append('<div class="wodu-title">' + $('.entry-title a', $card).parent().html() + '</div>') .append('<div class="wodu-panel-dev"/>') .append('<div class="wodu-panel-info"/>') .prependTo($card); }); }; /** * Start the party. */ wodu.init = function () { // Add the global CSS rules. GM_addStyle( '.wodu-spinner { position: absolute; left: 50%; top: 50%; height: 16px; width: 16px; background: no-repeat center center url(data:image/gif;base64,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) }' + '.wodu-close { height: 16px; width: 16px; cursor: pointer; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAhklEQVQ4jaWT0Q2AIAwFbyQ2kw3sCG6IG8AG+kFNSAUEIWnSlLyDPgrkdQABuAYjADuFeFRoQwDSAiCwIH7iVUiANzer1ZoAr944FSTN0b1PQCwEzuRxBGAhPXETkCqA1mt1xbaFaROjaWfYxM30XKt1PZgapJVRPiF/iL8AUW8Qpc2cLAA3TsPXvWkb2AIAAAAASUVORK5CYII=) }' + '.wodu-failed { margin: 0; }' + '.wodu-panel-info .plugin-meta { margin: 0; }' + '.wodu-panel-info .plugin-meta .tags { width: auto; }' + '.wodu-panel-info .plugin-meta li { padding: 0; }' ); var $pluginCards = $('.plugin-card'); if ($pluginCards.length) { wodu.setupPluginCardExtras($pluginCards); } }; // source: https://muffinresearch.co.uk/does-settimeout-solve-the-domcontentloaded-problem/ if (/(?!.*?compatible|.*?webkit)^mozilla|opera/i.test(navigator.userAgent)) { // Feeling dirty yet? document.addEventListener('DOMContentLoaded', wodu.init, false); } else { window.setTimeout(wodu.init, 0); }