diff --git a/.gitignore b/.gitignore index 843da762..d48cb46e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ # Ignore the build target build/ +Autopod_firefox_extension_* \ No newline at end of file diff --git a/.gitpod.yml b/.gitpod.yml index 4fcba032..3e22c268 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -1,2 +1,5 @@ image: - file: gitpod/debian.Dockerfile \ No newline at end of file + file: gitpod/debian.Dockerfile +vscode: + extensions: + - streetsidesoftware.code-spell-checker@1.8.0:pOcw5Mko+D583rMKG2b1PQ== \ No newline at end of file diff --git a/.theia/settings.json b/.theia/settings.json new file mode 100644 index 00000000..4c577e2e --- /dev/null +++ b/.theia/settings.json @@ -0,0 +1,4 @@ +{ +// FIXME: File a bug to cSpell to allow `word's` + "cSpell.userWords": [ "gitpod", "Hrbek", "gitpod's", "Kreyren", "Kreyren's", "Krey", "Krey's", "Autopod" ] +} \ No newline at end of file diff --git a/Makefile b/Makefile index af31d0eb..ecfdbe0c 100644 --- a/Makefile +++ b/Makefile @@ -17,21 +17,29 @@ all: $(info The 'make' is configured to not work without arguments in $(NAME) project) @ exit 2 +build: build-userstyle build-firefox-extension + # FIXME-QA: Sanitize -build: build-firefox-extension - $(info Building autopod targets.. ) +build-userstyle: + $(info Building autopod targets ) @ mkdir build || true - @ m4 --prefix-builtins src/autopod.m4 > build/automail.js - @ date +"%s" | sed 's_^_//Automail built at _' >> build/automail.js - @ rm build/userModules.js - $(info Autopod has been sucessfully built) + $(info Generating javascript file ) + @ m4 --prefix-builtins src/autopod.m4 > build/autopod.js + $(info Appending time built ) + @ date +"%s" | sed 's_^_//Autopod built at _' >> build/autopod.js + $(info Autopod's userstyle has been sucessfully built) build-firefox-extension: - $(info Creating Firefox addon) + $(info Creating Firefox extension) @ cp -r icons/ build/icons - @ zip -r $(NAME)_firefox_extension_$(VERSION).$(PATCHLEVEL).$(SUBLEVEL).zip autopod.js icons/ src/manifest.json - @ mv $(NAME)_firefox_extension_$(VERSION).$(PATCHLEVEL).$(SUBLEVEL).zip $(NAME)_firefox_extension_$(VERSION).$(PATCHLEVEL).$(SUBLEVEL).xpi + $(info Packaging Firefox extension) + @ rm Autopod_firefox_extension* || true + @ cp src/manifest.json build/ + @ cd build && zip -r ../$(NAME)_firefox_extension_$(VERSION).$(PATCHLEVEL).$(SUBLEVEL).zip . + $(info Firefox extension has been successfully packaged in the root of the repository) +# FIXME-QA: Sanitize the Autopod_firefox_Extension removal clean: @ rm -r build || true + @ rm Autopod_firefox_extension* || true $(info Build target has been cleared successfully) \ No newline at end of file diff --git a/gitpod/debian.Dockerfile b/gitpod/debian.Dockerfile index 77095e41..1b2803f0 100644 --- a/gitpod/debian.Dockerfile +++ b/gitpod/debian.Dockerfile @@ -1,6 +1,8 @@ FROM debian:latest # FIXME: Requires novnc configuration +# FIXME: Get Firefox and chromium to test this + USER root # Get core packages diff --git a/src/autopod.m4 b/src/autopod.m4 index dd8614c9..c665dd99 100644 --- a/src/autopod.m4 +++ b/src/autopod.m4 @@ -4,11 +4,12 @@ m4_define(NAME,autopod) m4_define(VERSION,1.00) m4_divert(0)m4_dnl // ==UserScript== -// @name Autopod +// @name NAME // @namespace http://tampermonkey.net/ // @version VERSION // @description Various non-standard utilities for gitpod.io and gitpod-staging.com -// @author hoh +// @author hoh, kreyren +// @grant GM_xmlhttpRequest // @match https://gitpod.io/* // @license GPLv3 // ==/UserScript== @@ -29,12 +30,23 @@ const scriptInfo = { // A collection of non-standard utilities for gitpod.io /* GENERAL STRUCTURE: - 1. Settings + (1. Settings) 2. CSS - 3. tools and helper functions - 4. The modules, as individual callable functions - 5. The URL matcher, for making the modules run at the right sites - 6. Module descriptions + (3. The modules, as individual callable functions) */ +m4_include(src/core.js) +let style = document.createElement("style"); +style.id = "autopod-styles"; +style.type = "text/css"; +style.textContent = ` +m4_include(src/css/global.css) +`; +let documentHead = document.querySelector("head"); +if(documentHead){ + documentHead.appendChild(style) +} +else{ + return//xml documents or something. At least it's not a place where the script can run +} })() diff --git a/src/core.js b/src/core.js new file mode 100644 index 00000000..9bfda570 --- /dev/null +++ b/src/core.js @@ -0,0 +1,10 @@ +// Make sure that localStorage is available to us +// FIXME-QA: Peer-review required +try{ + localStorage.setItem("test","test"); + localStorage.removeItem("test"); +} +catch(e){ + alert("Error: LocalStorage not available."); + console.log("LocalStorage, required for saving settings, is not available. Terminating Autopod.") +} \ No newline at end of file diff --git a/src/utilities/colourPicker.js b/src/utilities/colourPicker.js deleted file mode 100644 index c0f1c613..00000000 --- a/src/utilities/colourPicker.js +++ /dev/null @@ -1,121 +0,0 @@ -if(useScripts.colourPicker && (!useScripts.mobileFriendly)){ - let colourStyle = create("style"); - colourStyle.id = "colour-picker-styles"; - colourStyle.type = "text/css"; - documentHead.appendChild(colourStyle); - const basicStyles = ` -.footer .links{ - margin-left: calc(0px + 1%); - transform: translate(0px,10px); -} -.hohColourPicker .hohCheckbox{ - margin-left: 10px; -} -`; - if(Array.isArray(useScripts.colourSettings)){//legacy styles - let newObjectStyle = {}; - useScripts.colourSettings.forEach( - colour => newObjectStyle[colour.colour] = { - initial: colour.initial, - dark: colour.dark, - contrast: colour.contrast - } - ); - useScripts.colourSettings = newObjectStyle; - useScripts.save() - } - let applyColourStyles = function(){ - colourStyle.textContent = basicStyles;//eh, fix later. - Object.keys(useScripts.colourSettings).forEach(key => { - let colour = useScripts.colourSettings[key]; - let hexToRgb = function(hex){ - let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); - return result ? [ - parseInt(result[1],16), - parseInt(result[2],16), - parseInt(result[3],16) - ] : null; - } - if(colour.initial){ - colourStyle.textContent += `:root{${key}:${hexToRgb(colour.initial).join(",")};}` - }; - if(colour.dark){ - colourStyle.textContent += `.site-theme-dark{${key}:${hexToRgb(colour.dark).join(",")};}` - }; - if(colour.contrast){ - colourStyle.textContent += `.site-theme-contrast{${key}:${hexToRgb(colour.contrast).join(",")};}` - } - }) - };applyColourStyles(); - let colourPickerLocation = document.querySelector("#app > .wrap > .footer > .container"); - if(colourPickerLocation){ - const supportedColours = [ - "--color-background", - "--color-foreground", - "--color-foreground-grey", - "--color-foreground-grey-dark", - "--color-foreground-blue", - "--color-foreground-blue-dark", - "--color-background-blue-dark", - "--color-overlay", - "--color-shadow", - "--color-shadow-dark", - "--color-text", - "--color-text-light", - "--color-text-lighter", - "--color-text-bright", - "--color-blue", - "--color-blue-dim", - "--color-white", - "--color-black", - "--color-red", - "--color-peach", - "--color-orange", - "--color-yellow", - "--color-green" - ]; - let colourChanger = function(){ - useScripts.colourSettings[cpSelector.value] = { - "initial" : (cpInitialBox.checked ? cpInput.value : false), - "dark" : (cpDarkBox.checked ? cpInput.value : false), - "contrast" : (cpContrastBox.checked ? cpInput.value : false) - } - applyColourStyles(); - useScripts.save() - }; - let cpContainer = create("div","hohColourPicker",false,colourPickerLocation); - let cpTitle = create("h2",false,"Adjust Colours",cpContainer); - let cpInput = create("input",false,false,cpContainer); - cpInput.type = "color"; - let cpSelector = create("select",false,false,cpContainer); - supportedColours.forEach(colour => { - let option = create("option",false,colour,cpSelector); - option.value = colour; - }); - let cpDomain = create("p",false,false,cpContainer); - let cpInitialBox = createCheckbox(cpDomain); - create("span",false,"default",cpDomain); - let cpDarkBox = createCheckbox(cpDomain); - create("span",false,"dark",cpDomain); - let cpContrastBox = createCheckbox(cpDomain); - create("span",false,"contrast",cpDomain); - let cpSelectorChanger = function(){ - if(useScripts.colourSettings[cpSelector.value]){ - cpInitialBox.checked = !!useScripts.colourSettings[cpSelector.value].initial; - cpDarkBox.checked = !!useScripts.colourSettings[cpSelector.value].dark; - cpContrastBox.checked = !!useScripts.colourSettings[cpSelector.value].contrast; - cpInput.value = useScripts.colourSettings[cpSelector.value].initial - } - cpInitialBox.checked = false; - cpDarkBox.checked = false; - cpContrastBox.checked = false; - }; - cpSelector.onchange = cpSelectorChanger; - cpInput.onchange = colourChanger; - cpInitialBox.onchange = colourChanger; - cpDarkBox.onchange = colourChanger; - cpContrastBox.onchange = colourChanger; - cpSelectorChanger() - } -} - diff --git a/src/utilities/displayBox.js b/src/utilities/displayBox.js deleted file mode 100644 index 90dc1177..00000000 --- a/src/utilities/displayBox.js +++ /dev/null @@ -1,54 +0,0 @@ -function createDisplayBox(cssProperties){ - let displayBox = create("div","hohDisplayBox",false,document.querySelector("#app"),cssProperties); - let mousePosition; - let offset = [0,0]; - let isDown = false; - let isDownResize = false; - let displayBoxClose = create("span","hohDisplayBoxClose",svgAssets.cross,displayBox); - displayBoxClose.onclick = function(){ - displayBox.remove(); - }; - let resizePearl = create("span","hohResizePearl",false,displayBox); - displayBox.addEventListener("mousedown",function(e){ - isDown = true; - offset = [ - displayBox.offsetLeft - e.clientX, - displayBox.offsetTop - e.clientY - ]; - },true); - resizePearl.addEventListener("mousedown",function(e){ - event.stopPropagation(); - event.preventDefault(); - isDownResize = true; - offset = [ - displayBox.offsetLeft, - displayBox.offsetTop - ]; - },true); - document.addEventListener("mouseup",function(){ - isDown = false; - isDownResize = false; - },true); - document.addEventListener("mousemove",function(event){ - event.preventDefault(); - if(isDownResize){ - mousePosition = { - x : event.clientX, - y : event.clientY - }; - displayBox.style.width = (mousePosition.x - offset[0] + 5) + "px"; - displayBox.style.height = (mousePosition.y - offset[1] + 5) + "px"; - return; - } - if(isDown){ - mousePosition = { - x : event.clientX, - y : event.clientY - }; - displayBox.style.left = (mousePosition.x + offset[0]) + "px"; - displayBox.style.top = (mousePosition.y + offset[1]) + "px"; - } - },true); - let innerSpace = create("div","scrollableContent",false,displayBox); - return innerSpace; -} diff --git a/src/utilities/levDist.js b/src/utilities/levDist.js deleted file mode 100644 index 6521d11b..00000000 --- a/src/utilities/levDist.js +++ /dev/null @@ -1,45 +0,0 @@ -function levDist(s,t){//https://stackoverflow.com/a/11958496/5697837 - // Step 1 - let n = s.length; - let m = t.length; - if(!n){ - return m - } - if(!m){ - return n - } - let d = []; //2d matrix - for(var i = n; i >= 0; i--) d[i] = []; - // Step 2 - for(var i = n; i >= 0; i--) d[i][0] = i; - for(var j = m; j >= 0; j--) d[0][j] = j; - // Step 3 - for(var i = 1; i <= n; i++){ - let s_i = s.charAt(i - 1); - // Step 4 - for(var j = 1; j <= m; j++){ - //Check the jagged ld total so far - if(i === j && d[i][j] > 4){ - return n - } - let t_j = t.charAt(j - 1); - let cost = (s_i === t_j) ? 0 : 1; // Step 5 - //Calculate the minimum - let mi = d[i - 1][j] + 1; - let b = d[i][j - 1] + 1; - let c = d[i - 1][j - 1] + cost; - if(b < mi){ - mi = b - } - if(c < mi){ - mi = c; - } - d[i][j] = mi; // Step 6 - //Damerau transposition - /*if (i > 1 && j > 1 && s_i === t.charAt(j - 2) && s.charAt(i - 2) === t_j) { - d[i][j] = Math.min(d[i][j], d[i - 2][j - 2] + cost); - }*/ - } - } - return d[n][m] -} diff --git a/src/utilities/parseListJSON.js b/src/utilities/parseListJSON.js deleted file mode 100644 index 8b6f7788..00000000 --- a/src/utilities/parseListJSON.js +++ /dev/null @@ -1,63 +0,0 @@ -function parseListJSON(listNote){ - if(!listNote){ - return null - }; - let commandMatches = listNote.match(/\$({.*})\$/); - if(commandMatches){ - try{ - let noteContent = JSON.parse(commandMatches[1]); - noteContent.adjustValue = noteContent.adjust || 0; - let rangeParser = function(thing){ - if(typeof thing === "number"){ - return 1 - } - else if(typeof thing === "string"){ - thing = thing.split(",").map(a => a.trim()) - }; - return thing.reduce(function(acc,item){ - if(typeof item === "number"){ - return acc + 1 - }; - let multiplierPresent = item.split("x").map(a => a.trim()); - let value = 1; - let rangePresent = multiplierPresent[0].split("-").map(a => a.trim()); - if(rangePresent.length === 2){//range - let minRange = parseFloat(rangePresent[0]); - let maxRange = parseFloat(rangePresent[1]); - if(minRange && maxRange){ - value = maxRange - minRange + 1 - } - } - if(multiplierPresent.length === 1){//no multiplier - return acc + value - } - if(multiplierPresent.length === 2){//possible multiplier - let multiplier = parseFloat(multiplierPresent[1]); - if(multiplier || multiplier === 0){ - return acc + value*multiplier - } - else{ - return acc + 1 - } - } - else{//unparsable - return acc + 1 - } - },0); - }; - if(noteContent.more){ - noteContent.adjustValue += rangeParser(noteContent.more) - }; - if(noteContent.skip){ - noteContent.adjustValue -= rangeParser(noteContent.skip) - }; - return noteContent; - } - catch(e){ - console.warn("Unable to parse JSON in list note",commandMatches) - } - } - else{ - return null - } -}; diff --git a/src/utilities/saveAs.js b/src/utilities/saveAs.js deleted file mode 100644 index 6f8c7851..00000000 --- a/src/utilities/saveAs.js +++ /dev/null @@ -1,13 +0,0 @@ -function saveAs(data,fileName,pureText){ - //todo: support for browsers without blobs? - let link = create("a"); - document.body.appendChild(link); - let json = pureText ? data : JSON.stringify(data); - let blob = new Blob([json],{type: "octet/stream"}); - let url = window.URL.createObjectURL(blob); - link.href = url; - link.download = fileName || "File from Anilist.co"; - link.click(); - window.URL.revokeObjectURL(url); - document.body.removeChild(link); -}