├── .gitignore ├── LICENSE ├── background.js ├── icons ├── icon128.png ├── icon128_proper.png ├── icon16.png └── icon32.png └── manifest.json /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | codopen.zip 3 | 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016-2019, David Smith 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /background.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2019, David Smith 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3. Neither the name of the copyright holder nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | function makeRule(urlRegex) { 33 | return { 34 | conditions: [ 35 | new chrome.declarativeContent.PageStateMatcher({ 36 | pageUrl: { urlMatches: urlRegex } 37 | }) 38 | ], 39 | actions: [new chrome.declarativeContent.ShowPageAction()] 40 | }; 41 | } 42 | 43 | // Enable action if we're on a codepen page 44 | chrome.runtime.onInstalled.addListener(function(details) { 45 | chrome.declarativeContent.onPageChanged.removeRules(undefined, function() { 46 | chrome.declarativeContent.onPageChanged.addRules([ 47 | makeRule(".+://codepen.io/.+/pen/.+"), 48 | makeRule(".+://cdpn.io/.+/debug/.+") 49 | ]); 50 | }); 51 | }); 52 | 53 | // Given a codepen URL, convert from pen<->debug 54 | function invertUrl(url) { 55 | // Strip off any query parameters 56 | url = url.split(/[?#]/)[0]; 57 | if (url.includes("/pen/")) { 58 | return url.replace("/pen/", "/debug/") 59 | .replace("/codepen.io/", "/cdpn.io/"); 60 | } else { 61 | // On debug URLs, strip last element of the path off 62 | url = url.slice(0, url.lastIndexOf("/")) 63 | return url.replace("/debug/", "/pen/") 64 | .replace("/cdpn.io/", "/codepen.io/"); 65 | } 66 | } 67 | 68 | // Determine if a codepen URL is debug view 69 | function isDebugUrl(url) { 70 | return url.includes("/debug/"); 71 | } 72 | 73 | function toggleDebug(tab) { 74 | // Extract the URL from the tab 75 | var invertedUrl = invertUrl(tab.url); 76 | 77 | chrome.tabs.query({url: invertedUrl + "*"}, function(tabs) { 78 | if (tabs.length > 0) { 79 | // Activate the URL 80 | chrome.tabs.update(tabs[0].id, {"active": true}); 81 | 82 | // If this is a debug URL, go ahead and reload the tab 83 | if (isDebugUrl(invertedUrl)){ 84 | chrome.tabs.reload(tabs[0].id); 85 | } 86 | } else { 87 | chrome.tabs.create({"url": invertedUrl}); 88 | } 89 | }); 90 | } 91 | 92 | 93 | chrome.runtime.onUpdateAvailable.addListener(function() { 94 | ga('send', 'event', 'action', 'updated', '') 95 | chrome.runtime.restart(); 96 | }); 97 | 98 | chrome.pageAction.onClicked.addListener(function(tab) { 99 | // Toggle the debugger; declarativeContent rules ensure 100 | // the active tab is a codepen 101 | ga('send', 'event', 'action', 'toggle', 'button'); 102 | toggleDebug(tab); 103 | }); 104 | 105 | 106 | chrome.commands.onCommand.addListener(function(cmd) { 107 | if (cmd == "toggle-codepen-dbg") { 108 | // If the active tab is a codepen.io, toggle it 109 | chrome.tabs.query({active:true, 110 | url: ["*://codepen.io/*/pen/*", 111 | "*://cdpn.io/*/debug/*"]}, 112 | function(tabs) { 113 | if (tabs.length > 0) { 114 | ga('send', 'event', 'action', 'toggle', 'keyboard'); 115 | toggleDebug(tabs[0]); 116 | } 117 | }); 118 | } 119 | }); 120 | 121 | // Setup analytics 122 | if (!window.ga) { 123 | (function(){ 124 | window.ga = function() { 125 | (window.ga.q = window.ga.q || []).push(arguments); 126 | }, window.ga.l = 1 * new Date(); 127 | 128 | var tag = 'script'; 129 | var a = document.createElement(tag); 130 | var m = document.getElementsByTagName(tag)[0]; 131 | 132 | a.async = 1; 133 | a.src = 'https://www.google-analytics.com/analytics.js'; 134 | m.parentNode.insertBefore(a, m); 135 | })(); 136 | 137 | ga('create', 'UA-44410703-2', 'auto'); 138 | ga('set', 'checkProtocolTask', null); 139 | } 140 | -------------------------------------------------------------------------------- /icons/icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dizzyd/codopen/ce7ed096e7a4afe98cf8532591f21ede0212c902/icons/icon128.png -------------------------------------------------------------------------------- /icons/icon128_proper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dizzyd/codopen/ce7ed096e7a4afe98cf8532591f21ede0212c902/icons/icon128_proper.png -------------------------------------------------------------------------------- /icons/icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dizzyd/codopen/ce7ed096e7a4afe98cf8532591f21ede0212c902/icons/icon16.png -------------------------------------------------------------------------------- /icons/icon32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dizzyd/codopen/ce7ed096e7a4afe98cf8532591f21ede0212c902/icons/icon32.png -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Codopen", 3 | "version": "1.0.3", 4 | "manifest_version": 2, 5 | "description": "Easy-peasy debugging of all your codepen codepens!", 6 | 7 | "background": { 8 | "scripts": ["background.js"], 9 | "persistent": false 10 | }, 11 | 12 | "page_action": { 13 | "default_icon": { 14 | "16": "icons/icon16.png", 15 | "32": "icons/icon32.png" 16 | } 17 | }, 18 | 19 | "commands": { 20 | "toggle-codepen-dbg": { 21 | "description": "Toggle CodePen Debugging Mode", 22 | "suggested_key": { 23 | "default": "Ctrl+Shift+I" 24 | } 25 | } 26 | }, 27 | 28 | "permissions": [ 29 | "activeTab", 30 | "declarativeContent", 31 | "tabs" 32 | ], 33 | 34 | "content_security_policy": "script-src 'self' https://www.google-analytics.com; object-src 'self'" 35 | } 36 | --------------------------------------------------------------------------------