Fix the horrible whitespacing

This commit is contained in:
nazrin 2024-12-27 12:37:46 +00:00
parent d5518a164e
commit a9dd23a52c
17 changed files with 1311 additions and 1309 deletions

1
.gitignore vendored
View file

@ -1,3 +1,4 @@
.msc .msc
web-ext-artifacts/

View file

@ -1,72 +1,73 @@
let tabs = {}; let tabs = {};
function createTab(id){ function createTab(id){
return tabs[id] = { return tabs[id] = {
top: "", top: "",
scriptsIndex: {}, scriptsIndex: {},
scripts: [] scripts: []
}; };
} }
chrome.browserAction.setBadgeBackgroundColor({color:"#303030"}); chrome.browserAction.setBadgeBackgroundColor({color:"#303030"});
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
let rTabID = request.tabID; let rTabID = request.tabID;
let action = request.action; let action = request.action;
let value = request.value; let value = request.value;
if(sender.tab){ // Messages from tabs if(sender.tab){ // Messages from tabs
let tabID = sender.tab.id; let tabID = sender.tab.id;
if(!tabs[tabID]) createTab(tabID) if(!tabs[tabID]) createTab(tabID)
let tab = tabs[tabID]; let tab = tabs[tabID];
switch(action){ switch(action){
case "add-files": { case "add-files": {
value.forEach(info => { value.forEach(info => {
if(!tab.scriptsIndex[info.id]){ if(!tab.scriptsIndex[info.id]){
tab.scriptsIndex[info.id] = info; tab.scriptsIndex[info.id] = info;
tab.scripts.push(info); tab.scripts.push(info);
if(info.enabled) tab.badge++; if(info.enabled) tab.badge++;
let file = new File(info.id); let file = new File(info.id);
file.onChange = function(newInfo){ file.onChange = function(newInfo){
for(let index in newInfo){ for(let index in newInfo){
info[index] = newInfo[index]; info[index] = newInfo[index];
} }
} }
} }
}); });
if(tab.scripts.length>0) if(tab.scripts.length>0){
chrome.browserAction.setBadgeText({ chrome.browserAction.setBadgeText({
tabId: tabID, tabId: tabID,
text: String(tab.scripts.length) text: String(tab.scripts.length)
}); });
break; }
} break;
case "set-url": { }
tab = createTab(tabID); case "set-url": {
tab.top = value; tab = createTab(tabID);
break; tab.top = value;
} break;
} }
} else { // Messages from anywhere else }
let tab; } else { // Messages from anywhere else
if(rTabID){ let tab;
tab = tabs[rTabID]; if(rTabID){
if(!tab) return; tab = tabs[rTabID];
} if(!tab) return;
}
switch(action){
case "get-files": { switch(action){
sendResponse(tab.scripts); case "get-files": {
break; sendResponse(tab.scripts);
} break;
case "get-url": { }
sendResponse(tab.top); case "get-url": {
break; sendResponse(tab.top);
} break;
} }
} }
}); }
chrome.tabs.onRemoved.addListener((tabID, removeInfo) => { });
delete tabs[tabID]; chrome.tabs.onRemoved.addListener((tabID, removeInfo) => {
}); delete tabs[tabID];
});

View file

@ -1,46 +1,46 @@
let myHead = document.createElement("custom-web"); let myHead = document.createElement("custom-web");
document.documentElement.appendChild(myHead); document.documentElement.appendChild(myHead);
chrome.runtime.sendMessage({ chrome.runtime.sendMessage({
action: "set-url", action: "set-url",
value: window.location.href value: window.location.href
}); });
File.loadAll().then(files => { File.loadAll().then(files => {
let activeFiles = []; let activeFiles = [];
for(let i = 0; i < files.length; i++){ for(let i = 0; i < files.length; i++){
let info = files[i].info; let info = files[i].info;
if(info.links && info.links.length > 0) { if(info.links && info.links.length > 0) {
let found = false; let found = false;
for(let l = 0; l < info.links.length && !found; l++) { for(let l = 0; l < info.links.length && !found; l++) {
let regexp = new RegExp(info.links[l]); let regexp = new RegExp(info.links[l]);
found = window.location.href.match(regexp); found = window.location.href.match(regexp);
} }
if(!found) continue; if(!found) continue;
} }
activeFiles.push(info); activeFiles.push(info);
if(!info.enabled) continue; if(!info.enabled) continue;
if(info.type == "JS") { if(info.type == "JS") {
let jsContainer = document.createElement("script"); let jsContainer = document.createElement("script");
jsContainer.textContent = info.content; jsContainer.textContent = info.content;
myHead.appendChild(jsContainer); myHead.appendChild(jsContainer);
} else { } else {
let cssContainer = document.createElement("style"); let cssContainer = document.createElement("style");
cssContainer.textContent = info.content; cssContainer.textContent = info.content;
myHead.appendChild(cssContainer); myHead.appendChild(cssContainer);
} }
} }
let isTop = (window == window.top); let isTop = (window == window.top);
if(isTop){ // Only allow top to set URL if(isTop){ // Only allow top to set URL
chrome.runtime.sendMessage({ chrome.runtime.sendMessage({
action: "set-url", action: "set-url",
value: window.location.href value: window.location.href
}); });
} }
chrome.runtime.sendMessage({ chrome.runtime.sendMessage({
action: "add-files", action: "add-files",
value: activeFiles value: activeFiles
}); });
}); });

View file

@ -1,67 +1,67 @@
*{box-sizing:border-box;} *{box-sizing:border-box;}
:root{ :root{
--top: #212121; --top: #212121;
--background: #303030; --background: #303030;
--light: #424242; --light: #424242;
--lighter: #606060; --lighter: #606060;
--lightest: #848484; --lightest: #848484;
} }
html{ html{
height:100vh; height:100vh;
font-family: "Segoe UI", Tahoma, sans-serif; font-family: "Segoe UI", Tahoma, sans-serif;
} }
body{ body{
min-height:100%; min-height:100%;
margin: 0; margin: 0;
background-color: var(--background); background-color: var(--background);
} }
.check{ .check{
font-size:20px; font-size:20px;
display: inline-flex; display: inline-flex;
width:2em; width:2em;
height:1em; height:1em;
margin-right: 10px; margin-right: 10px;
} }
.check input{ .check input{
display:none; display:none;
} }
.check input + span{ .check input + span{
position:relative; position:relative;
display:inline-flex; display:inline-flex;
width:100%; width:100%;
height:100%; height:100%;
background: #000; background: #000;
border-radius:1000px; border-radius:1000px;
cursor:pointer; cursor:pointer;
transition: background 100ms ease-in-out; transition: background 100ms ease-in-out;
} }
.check input:checked + span{ .check input:checked + span{
background:#0a3; background:#0a3;
} }
.check input + span::before{ .check input + span::before{
content:""; content:"";
display:inline-block; display:inline-block;
width:1em; height:1em; width:1em; height:1em;
margin-left:1px; margin-left:1px;
border:0.15em solid transparent; border:0.15em solid transparent;
background-clip: padding-box; background-clip: padding-box;
box-sizing:border-box; box-sizing:border-box;
border-radius:100%; border-radius:100%;
background-color:white; background-color:white;
transition: all 100ms ease-in-out; transition: all 100ms ease-in-out;
} }
.check input:checked + span::before{ .check input:checked + span::before{
transform: translateX(100%); transform: translateX(100%);
margin-left:-1px; margin-left:-1px;
} }
.check.no-transition input + span, .check.no-transition input + span,
.check.no-transition input + span::before{ .check.no-transition input + span::before{
transition:none; transition:none;
} }
/* Small Check */ /* Small Check */
.check.small{ .check.small{
font-size:17px; font-size:17px;
} }

View file

@ -1,233 +1,233 @@
/* reset */ /* reset */
input { input {
padding: 0; padding: 0;
background-color: transparent; background-color: transparent;
outline: none; outline: none;
border: none; border: none;
} }
#editor { #editor {
margin: 0; margin: 0;
} }
* { box-sizing: border-box; } * { box-sizing: border-box; }
/* custom styles */ /* custom styles */
body { body {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
/* header */ /* header */
header { header {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: flex-end; justify-content: flex-end;
height: 50px; height: 50px;
flex-shrink: 0; flex-shrink: 0;
padding: 0 20px; padding: 0 20px;
box-sizing: border-box; box-sizing: border-box;
background-color: var(--top); background-color: var(--top);
} }
header .check { header .check {
margin-right: 10px; margin-right: 10px;
} }
header input { header input {
width: 50%; width: 50%;
height: 40px; height: 40px;
padding: 0 15px; padding: 0 15px;
margin-right: auto; margin-right: auto;
border-radius: 40px; border-radius: 40px;
background-color: var(--top); background-color: var(--top);
font-family: "Segoe UI", Tahoma, sans-serif; font-family: "Segoe UI", Tahoma, sans-serif;
font-size: 30px; font-size: 30px;
color: white; color: white;
cursor:pointer; cursor:pointer;
margin-right: auto; margin-right: auto;
transition: padding 100ms ease-in-out; transition: padding 100ms ease-in-out;
} }
header input:hover, header input:hover,
header input:focus { header input:focus {
background-color: var(--light); background-color: var(--light);
} }
header input:focus{ header input:focus{
cursor:auto; cursor:auto;
} }
header > span { header > span {
width: 40px; width: 40px;
height: 40px; height: 40px;
padding: 5px; padding: 5px;
margin-left: 5px; margin-left: 5px;
border-radius: 40px; border-radius: 40px;
cursor: pointer; cursor: pointer;
} }
header > span#download-btn { header > span#download-btn {
padding: 7px; padding: 7px;
} }
header > span:last-child { header > span:last-child {
margin-right: -5px; margin-right: -5px;
} }
header > span:hover { header > span:hover {
background-color: var(--light); background-color: var(--light);
} }
header > span svg { header > span svg {
width: 100%; width: 100%;
height: 100%; height: 100%;
fill: white; fill: white;
} }
#save-btn { #save-btn {
pointer-events: none; pointer-events: none;
} }
#save-btn.edited { #save-btn.edited {
pointer-events: all; pointer-events: all;
} }
#save-btn svg { #save-btn svg {
opacity: 0.25; opacity: 0.25;
transition: opacity 100ms ease-in-out; transition: opacity 100ms ease-in-out;
} }
#save-btn.edited svg { #save-btn.edited svg {
opacity: 1; opacity: 1;
} }
/* editor */ /* editor */
main { main {
flex-grow: 1; flex-grow: 1;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
#editor { #editor {
flex-grow: 1; flex-grow: 1;
} }
/* links popup */ /* links popup */
#links-popup { #links-popup {
display: none; /* flex */ display: none; /* flex */
flex-direction: column; flex-direction: column;
width: 100%; width: 100%;
max-width: 600px; max-width: 600px;
height: 500px; height: 500px;
border-radius: 20px; border-radius: 20px;
overflow: hidden; overflow: hidden;
position: absolute; position: absolute;
margin: auto; margin: auto;
top: 0; bottom: 0; top: 0; bottom: 0;
right: 0; left: 0; right: 0; left: 0;
z-index: 10; z-index: 10;
background-color: var(--light); background-color: var(--light);
box-shadow: 0 0 25px rgba(0, 0, 0, 0.5); box-shadow: 0 0 25px rgba(0, 0, 0, 0.5);
} }
#links-popup header { #links-popup header {
background: none; background: none;
background-color: var(--background); background-color: var(--background);
} }
#links-popup header h1 { #links-popup header h1 {
margin-right: auto; margin-right: auto;
font-family: "Segoe UI", Tahoma, sans-serif; font-family: "Segoe UI", Tahoma, sans-serif;
font-weight: normal; font-weight: normal;
font-size: 24px; font-size: 24px;
color: white; color: white;
} }
#links-popup header > span { #links-popup header > span {
width: 35px; width: 35px;
height: 35px; height: 35px;
} }
#links-popup main { #links-popup main {
align-items: center; align-items: center;
} }
#links-popup main #links-wrapper { #links-popup main #links-wrapper {
width: 100%; width: 100%;
height: 100%; height: 100%;
padding: 20px; padding: 20px;
overflow: auto; overflow: auto;
} }
#links-popup main #links-wrapper .link-entry { #links-popup main #links-wrapper .link-entry {
position: relative; position: relative;
width: 100%; width: 100%;
flex-shrink: 0; flex-shrink: 0;
margin-bottom: 6px; margin-bottom: 6px;
border-radius: 40px; border-radius: 40px;
overflow: hidden; overflow: hidden;
} }
#links-popup main #links-wrapper .link-entry input { #links-popup main #links-wrapper .link-entry input {
display: block; display: block;
height: 40px; height: 40px;
width: 100%; width: 100%;
border-radius: 40px; border-radius: 40px;
padding: 10px 15px; padding: 10px 15px;
padding-right: 40px; padding-right: 40px;
font-family: "Segoe UI", Tahoma, sans-serif; font-family: "Segoe UI", Tahoma, sans-serif;
font-weight: normal; font-weight: normal;
font-size: 16px; font-size: 16px;
color: rgb(235, 227, 227); color: rgb(235, 227, 227);
opacity: 1; opacity: 1;
cursor: pointer; cursor: pointer;
} }
#links-popup main #links-wrapper .link-entry:hover, #links-popup main #links-wrapper .link-entry:hover,
#links-popup main #links-wrapper .link-entry input:focus { #links-popup main #links-wrapper .link-entry input:focus {
background-color: var(--lighter); background-color: var(--lighter);
opacity: 1; opacity: 1;
} }
#links-popup main #links-wrapper .link-entry input:focus { #links-popup main #links-wrapper .link-entry input:focus {
cursor:auto; cursor:auto;
} }
#links-popup main #links-wrapper .link-entry svg { #links-popup main #links-wrapper .link-entry svg {
position: absolute; position: absolute;
top: 0; right: 0px; top: 0; right: 0px;
height: 40px; height: 40px;
width: 40px; width: 40px;
padding: 10px; padding: 10px;
border-radius: 100%; border-radius: 100%;
flex-shrink: 0; flex-shrink: 0;
fill: white; fill: white;
opacity: 0; opacity: 0;
cursor: pointer cursor: pointer
} }
#links-popup main #links-wrapper .link-entry:hover svg, #links-popup main #links-wrapper .link-entry:hover svg,
#links-popup main #links-wrapper .link-entry input:focus + svg { #links-popup main #links-wrapper .link-entry input:focus + svg {
opacity: 0.5; opacity: 0.5;
} }
#links-popup main #links-wrapper .link-entry svg:hover { #links-popup main #links-wrapper .link-entry svg:hover {
opacity: 1; opacity: 1;
} }
/* better monokai */ /* better monokai */
#editor.ace-monokai { #editor.ace-monokai {
background-color: var(--background); background-color: var(--background);
} }
#editor.ace-monokai .ace_gutter { #editor.ace-monokai .ace_gutter {
background-color: var(--light); background-color: var(--light);
} }
#editor.ace-monokai .ace_selection { #editor.ace-monokai .ace_selection {
background-color: var(--lighter); background-color: var(--lighter);
} }
#editor.ace-monokai .ace_marker-layer .ace_active-line { #editor.ace-monokai .ace_marker-layer .ace_active-line {
background-color: rgba(0, 0, 0, 0.2); background-color: rgba(0, 0, 0, 0.2);
} }

View file

@ -1,152 +1,152 @@
svg{ svg{
max-width:100%; max-width:100%;
max-height:100%; max-height:100%;
} }
body.drag-over{ body.drag-over{
background-color: var(--light); background-color: var(--light);
} }
header{ header{
width:100%; width:100%;
height:50px; height:50px;
display: flex; display: flex;
align-items:center; align-items:center;
padding:0px 20px; padding:0px 20px;
background-color: var(--top); background-color: var(--top);
color:white; color:white;
fill:white; fill:white;
font-size:30px; font-size:30px;
} }
header img{ header img{
width:36px; width:36px;
margin-right:10px; margin-right:10px;
} }
header img + span{ header img + span{
margin-right:auto; margin-right:auto;
} }
header #new-file { header #new-file {
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
width: 40px; width: 40px;
height: 40px; height: 40px;
border-radius: 40px; border-radius: 40px;
overflow: hidden; overflow: hidden;
align-items: center; align-items: center;
transition: width 100ms ease-in-out; transition: width 100ms ease-in-out;
} }
header #new-file:hover { header #new-file:hover {
width: 175px; width: 175px;
background-color: var(--light); background-color: var(--light);
} }
header #new-file span.btn { header #new-file span.btn {
display:flex; display:flex;
align-items:center; align-items:center;
justify-content:center; justify-content:center;
flex-grow: 1; flex-grow: 1;
flex-shrink: 1; flex-shrink: 1;
min-width: 30px; min-width: 30px;
height: 100%; height: 100%;
opacity:0.5; opacity:0.5;
text-align: center; text-align: center;
font-size: 14px; font-size: 14px;
cursor: pointer; cursor: pointer;
user-select: none; user-select: none;
} }
header #new-file span.btn:hover { header #new-file span.btn:hover {
opacity:1; opacity:1;
text-shadow: 0 0 0 rgba(255, 255, 255, 0.5); text-shadow: 0 0 0 rgba(255, 255, 255, 0.5);
} }
header #new-file .btn-svg { header #new-file .btn-svg {
flex-shrink: 0; flex-shrink: 0;
width: 40px; width: 40px;
height: 40px; height: 40px;
padding: 5px; padding: 5px;
} }
header #new-file .btn-svg svg { header #new-file .btn-svg svg {
display: block; display: block;
width: 100%; width: 100%;
height: 100%; height: 100%;
fill: white; fill: white;
} }
#files{ #files{
padding:10px 20px; padding:10px 20px;
} }
.file{ .file{
position:relative; position:relative;
color:white; color:white;
height:45px; height:45px;
padding:10px 15px; padding:10px 15px;
display:grid; display:grid;
grid-template-columns: 60px auto 50px 125px; grid-template-columns: 60px auto 50px 125px;
align-items:center; align-items:center;
font-size:16px; font-size:16px;
border-radius:45px; border-radius:45px;
cursor:pointer; cursor:pointer;
} }
.file:hover{ .file:hover{
background: var(--lighter); background: var(--lighter);
} }
.file .file-type{ .file .file-type{
justify-self: center; justify-self: center;
} }
.file .file-name, .file .file-name,
.file .file-type{ .file .file-type{
pointer-events:none; pointer-events:none;
} }
.file .file-icons{ .file .file-icons{
display:flex; display:flex;
pointer-events:none; pointer-events:none;
} }
.file .file-icons .file-icon{ .file .file-icons .file-icon{
display:flex; display:flex;
align-items:center; align-items:center;
border-radius:20px; border-radius:20px;
padding:2px 0px; padding:2px 0px;
transition: all 100ms ease-in-out; transition: all 100ms ease-in-out;
cursor:pointer; cursor:pointer;
pointer-events:all; pointer-events:all;
} }
.file .file-icons .file-icon svg{ .file .file-icons .file-icon svg{
width: 20px; width: 20px;
height: 20px; height: 20px;
fill: white; fill: white;
opacity:0.7; opacity:0.7;
} }
.file .file-icons .file-icon.icon-confirm svg, .file .file-icons .file-icon.icon-confirm svg,
.file .file-icons .file-icon svg:hover{ .file .file-icons .file-icon svg:hover{
opacity:1; opacity:1;
} }
.file .file-icons .file-icon.icon-confirm{ .file .file-icons .file-icon.icon-confirm{
background:#C00; background:#C00;
padding:2px 5px; padding:2px 5px;
} }
.file .file-icons .file-icon::before{ .file .file-icons .file-icon::before{
content:"DELETE"; content:"DELETE";
font-size: 12px; font-size: 12px;
width: 0px; width: 0px;
overflow:hidden; overflow:hidden;
text-align:center; text-align:center;
transition: width 100ms ease-in-out; transition: width 100ms ease-in-out;
} }
.file .file-icons .file-icon.icon-confirm::before{ .file .file-icons .file-icon.icon-confirm::before{
width:50px; width:50px;
} }
.file .file-icons .file-edit{ .file .file-icons .file-edit{
margin-left:auto; margin-left:auto;
margin-right:5px; margin-right:5px;
} }
.file-type[data-type="JS"]{ .file-type[data-type="JS"]{
color: #ffde24 color: #ffde24
} }
.file-type[data-type="CSS"]{ .file-type[data-type="CSS"]{
color: #15a0dc color: #15a0dc
} }

View file

@ -1,89 +1,89 @@
html{ html{
height:auto; height:auto;
} }
body{ body{
width:200px; width:200px;
color:white; color:white;
padding:3px 0px; padding:3px 0px;
font-size:12px; font-size:12px;
} }
img{ img{
height:22px; height:22px;
width:22px; width:22px;
justify-self:center; justify-self:center;
} }
.title{ .title{
font-size:16px; font-size:16px;
} }
.line{ .line{
display:grid; display:grid;
align-items:center; align-items:center;
grid-template-columns: 34px auto 25px; grid-template-columns: 34px auto 25px;
column-gap: 10px; column-gap: 10px;
height:30px; height:30px;
padding:0px 10px; padding:0px 10px;
} }
.line .check{ .line .check{
flex-shrink:0; flex-shrink:0;
} }
.line > .line-item{ .line > .line-item{
white-space: nowrap; white-space: nowrap;
max-width: 100%; max-width: 100%;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
pointer-events:none; pointer-events:none;
} }
.line > .line-item + .line-item{ .line > .line-item + .line-item{
opacity:0.5; opacity:0.5;
justify-self: center; justify-self: center;
} }
.btn{ .btn{
cursor:pointer; cursor:pointer;
} }
.btn:hover{ .btn:hover{
opacity:1; opacity:1;
background: var(--lighter); background: var(--lighter);
} }
#files:empty{ #files:empty{
display:none; display:none;
} }
section:not(:first-child){ section:not(:first-child){
margin-top:3px; margin-top:3px;
padding-top:3px; padding-top:3px;
border-top:1px solid var(--light); border-top:1px solid var(--light);
} }
section h2{ section h2{
margin: 0; margin: 0;
font-size: 10px; font-size: 10px;
font-weight:400; font-weight:400;
padding:0px 10px; padding:0px 10px;
color: var(--lighter) color: var(--lighter)
} }
section h2 span{ section h2 span{
max-width: 100%; max-width: 100%;
display: inline-block; display: inline-block;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
pointer-events:none; pointer-events:none;
} }
#add-new .line { #add-new .line {
grid-template-columns: 50% 50%; grid-template-columns: 50% 50%;
align-items: stretch; align-items: stretch;
column-gap:0; column-gap:0;
height:20px; height:20px;
} }
#add-new .line .btn{ #add-new .line .btn{
display:flex; display:flex;
align-items:center; align-items:center;
justify-content:center; justify-content:center;
opacity:0.7; opacity:0.7;
} }
#add-new .line .btn:hover{ #add-new .line .btn:hover{
opacity:1; opacity:1;
background:none; background:none;
} }

View file

@ -1,56 +1,56 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="utf-8"/> <meta charset="utf-8"/>
<title>Script Editor</title> <title>Script Editor</title>
<link rel="shortcut icon" type="image/png" href="img/icon48.png"> <link rel="shortcut icon" type="image/png" href="img/icon48.png">
<link rel="stylesheet" href="css/common.css"/> <link rel="stylesheet" href="css/common.css"/>
<link rel="stylesheet" href="css/editor.css"/> <link rel="stylesheet" href="css/editor.css"/>
</head> </head>
<body> <body>
<header> <header>
<label class="check" title="Enable or disable file"> <label class="check" title="Enable or disable file">
<input id="enable-input" type="checkbox"> <input id="enable-input" type="checkbox">
<span></span> <span></span>
</label> </label>
<input id="name-input" type="text" title="File name"/> <input id="name-input" type="text" title="File name"/>
<span id="download-btn" title="Export file"> <span id="download-btn" title="Export file">
<svg viewBox="0 0 24 24"> <svg viewBox="0 0 24 24">
<path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM17 13l-5 5-5-5h3V9h4v4h3z"/> <path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM17 13l-5 5-5-5h3V9h4v4h3z"/>
</svg> </svg>
</span> </span>
<span id="links-btn" title="Edit target websites"> <span id="links-btn" title="Edit target websites">
<svg viewBox="0 0 48 48"> <svg viewBox="0 0 48 48">
<path d="M7.8 24c0-3.42 2.78-6.2 6.2-6.2h8v-3.8h-8c-5.52 0-10 4.48-10 10s4.48 10 10 10h8v-3.8h-8c-3.42 0-6.2-2.78-6.2-6.2zm8.2 2h16v-4h-16v4zm18-12h-8v3.8h8c3.42 0 6.2 2.78 6.2 6.2s-2.78 6.2-6.2 6.2h-8v3.8h8c5.52 0 10-4.48 10-10s-4.48-10-10-10z"/> <path d="M7.8 24c0-3.42 2.78-6.2 6.2-6.2h8v-3.8h-8c-5.52 0-10 4.48-10 10s4.48 10 10 10h8v-3.8h-8c-3.42 0-6.2-2.78-6.2-6.2zm8.2 2h16v-4h-16v4zm18-12h-8v3.8h8c3.42 0 6.2 2.78 6.2 6.2s-2.78 6.2-6.2 6.2h-8v3.8h8c5.52 0 10-4.48 10-10s-4.48-10-10-10z"/>
</svg> </svg>
</span> </span>
<span id="save-btn" title="Save file"> <span id="save-btn" title="Save file">
<svg viewBox="0 0 48 48"> <svg viewBox="0 0 48 48">
<path d="M34 6h-24c-2.21 0-4 1.79-4 4v28c0 2.21 1.79 4 4 4h28c2.21 0 4-1.79 4-4v-24l-8-8zm-10 32c-3.31 0-6-2.69-6-6s2.69-6 6-6 6 2.69 6 6-2.69 6-6 6zm6-20h-20v-8h20v8z"/> <path d="M34 6h-24c-2.21 0-4 1.79-4 4v28c0 2.21 1.79 4 4 4h28c2.21 0 4-1.79 4-4v-24l-8-8zm-10 32c-3.31 0-6-2.69-6-6s2.69-6 6-6 6 2.69 6 6-2.69 6-6 6zm6-20h-20v-8h20v8z"/>
</svg> </svg>
</span> </span>
</header> </header>
<main> <main>
<pre id="editor"></pre> <pre id="editor"></pre>
</main> </main>
<div id="links-popup"> <div id="links-popup">
<header> <header>
<h1>Target Websites</h1> <h1>Target Websites</h1>
<span id="close-links-btn"> <span id="close-links-btn">
<svg viewBox="0 0 24 24"> <svg viewBox="0 0 24 24">
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"/> <path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"/>
</svg> </svg>
</span> </span>
</header> </header>
<main> <main>
<div id="links-wrapper"></div> <div id="links-wrapper"></div>
</main> </main>
</div> </div>
</body> </body>
<script src="js/ace/ace.js"></script> <script src="js/ace/ace.js"></script>
<script src="js/storage.js"></script> <script src="js/storage.js"></script>
<script src="js/file.js"></script> <script src="js/file.js"></script>
<script src="js/webdav.js"></script> <script src="js/webdav.js"></script>
<script src="js/settings.js"></script> <script src="js/settings.js"></script>
<script src="js/editor.js"></script> <script src="js/editor.js"></script>
</html> </html>

View file

@ -1,41 +1,41 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="utf-8"/> <meta charset="utf-8"/>
<title>Custom Web</title> <title>Custom Web</title>
<link rel="shortcut icon" type="image/png" href="img/icon48.png"> <link rel="shortcut icon" type="image/png" href="img/icon48.png">
<link rel="stylesheet" href="css/common.css"/> <link rel="stylesheet" href="css/common.css"/>
<link rel="stylesheet" href="css/index.css"/> <link rel="stylesheet" href="css/index.css"/>
</head> </head>
<body> <body>
<header> <header>
<img src="img/icon48.png"/> <img src="img/icon48.png"/>
<span> <span>
<span>Custom Web</span> <span>Custom Web</span>
<span class="btn-svg" id="settings-page"> <span class="btn-svg" id="settings-page">
<a href="settings.html"> <a href="settings.html">
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e8eaed"><path d="m370-80-16-128q-13-5-24.5-12T307-235l-119 50L78-375l103-78q-1-7-1-13.5v-27q0-6.5 1-13.5L78-585l110-190 119 50q11-8 23-15t24-12l16-128h220l16 128q13 5 24.5 12t22.5 15l119-50 110 190-103 78q1 7 1 13.5v27q0 6.5-2 13.5l103 78-110 190-118-50q-11 8-23 15t-24 12L590-80H370Zm70-80h79l14-106q31-8 57.5-23.5T639-327l99 41 39-68-86-65q5-14 7-29.5t2-31.5q0-16-2-31.5t-7-29.5l86-65-39-68-99 42q-22-23-48.5-38.5T533-694l-13-106h-79l-14 106q-31 8-57.5 23.5T321-633l-99-41-39 68 86 64q-5 15-7 30t-2 32q0 16 2 31t7 30l-86 65 39 68 99-42q22 23 48.5 38.5T427-266l13 106Zm42-180q58 0 99-41t41-99q0-58-41-99t-99-41q-59 0-99.5 41T342-480q0 58 40.5 99t99.5 41Zm-2-140Z"/></svg> <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e8eaed"><path d="m370-80-16-128q-13-5-24.5-12T307-235l-119 50L78-375l103-78q-1-7-1-13.5v-27q0-6.5 1-13.5L78-585l110-190 119 50q11-8 23-15t24-12l16-128h220l16 128q13 5 24.5 12t22.5 15l119-50 110 190-103 78q1 7 1 13.5v27q0 6.5-2 13.5l103 78-110 190-118-50q-11 8-23 15t-24 12L590-80H370Zm70-80h79l14-106q31-8 57.5-23.5T639-327l99 41 39-68-86-65q5-14 7-29.5t2-31.5q0-16-2-31.5t-7-29.5l86-65-39-68-99 42q-22-23-48.5-38.5T533-694l-13-106h-79l-14 106q-31 8-57.5 23.5T321-633l-99-41-39 68 86 64q-5 15-7 30t-2 32q0 16 2 31t7 30l-86 65 39 68 99-42q22 23 48.5 38.5T427-266l13 106Zm42-180q58 0 99-41t41-99q0-58-41-99t-99-41q-59 0-99.5 41T342-480q0 58 40.5 99t99.5 41Zm-2-140Z"/></svg>
</a> </a>
</span> </span>
</span> </span>
<span id="new-file"> <span id="new-file">
<span class="btn btn-svg" id="new-up" title="Upload file"> <span class="btn btn-svg" id="new-up" title="Upload file">
<svg viewBox="0 0 24 24"> <svg viewBox="0 0 24 24">
<path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z"/> <path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z"/>
</svg> </svg>
</span> </span>
<span class="btn" id="new-css" title="Create stylesheet">CSS</span> <span class="btn" id="new-css" title="Create stylesheet">CSS</span>
<span class="btn" id="new-js" title="Create script">JS</span> <span class="btn" id="new-js" title="Create script">JS</span>
<span class="btn-svg"> <span class="btn-svg">
<svg viewBox="0 0 48 48"> <svg viewBox="0 0 48 48">
<path d="M38 26h-12v12h-4v-12h-12v-4h12v-12h4v12h12v4z"/> <path d="M38 26h-12v12h-4v-12h-12v-4h12v-12h4v12h12v4z"/>
</svg> </svg>
</span> </span>
</span> </span>
</header> </header>
<section id="files"></section> <section id="files"></section>
</body> </body>
<script src="js/storage.js"></script> <script src="js/storage.js"></script>
<script src="js/file.js"></script> <script src="js/file.js"></script>
<script src="js/index.js"></script> <script src="js/index.js"></script>
</html> </html>

View file

@ -1,169 +1,169 @@
let fileId = window.location.hash.substr(1); let fileId = window.location.hash.substr(1);
let file = {}; let file = {};
let enableInput = document.getElementById("enable-input"); let enableInput = document.getElementById("enable-input");
let nameInput = document.getElementById("name-input"); let nameInput = document.getElementById("name-input");
let linksBtn = document.getElementById("links-btn"); let linksBtn = document.getElementById("links-btn");
let saveBtn = document.getElementById("save-btn"); let saveBtn = document.getElementById("save-btn");
let editor = ace.edit("editor"); let editor = ace.edit("editor");
editor.setTheme("ace/theme/monokai"); editor.setTheme("ace/theme/monokai");
File.load(fileId).then((f) => { File.load(fileId).then((f) => {
let info = (file = f).info; let info = (file = f).info;
enableInput.parentNode.classList.add("no-transition"); enableInput.parentNode.classList.add("no-transition");
enableInput.checked = info.enabled; enableInput.checked = info.enabled;
setTimeout(()=>{enableInput.parentNode.classList.remove("no-transition")}, 0); setTimeout(()=>{enableInput.parentNode.classList.remove("no-transition")}, 0);
nameInput.value = info.name; nameInput.value = info.name;
editor.setValue(info.content||"", -1); editor.setValue(info.content||"", -1);
if(info.type == "JS") { if(info.type == "JS") {
editor.session.setMode("ace/mode/javascript"); editor.session.setMode("ace/mode/javascript");
} else { } else {
editor.session.setMode("ace/mode/css"); editor.session.setMode("ace/mode/css");
} }
if(info.links) { if(info.links) {
info.links.forEach((link) => { info.links.forEach((link) => {
createLinkEntry(link); createLinkEntry(link);
}); });
createLinkEntry(); createLinkEntry();
} }
f.onChange = function(info){ f.onChange = function(info){
enableInput.checked = info.enabled; enableInput.checked = info.enabled;
nameInput.value = info.name; nameInput.value = info.name;
} }
enableInput.addEventListener("input", editorSetEdited); enableInput.addEventListener("input", editorSetEdited);
nameInput.addEventListener("input", editorSetEdited); nameInput.addEventListener("input", editorSetEdited);
editor.session.on("change", editorSetEdited); editor.session.on("change", editorSetEdited);
}); });
function editorSetEdited() { function editorSetEdited() {
saveBtn.classList.add("edited"); saveBtn.classList.add("edited");
} }
/* export */ /* export */
let downloadLink = document.createElement("a"); let downloadLink = document.createElement("a");
downloadLink.style.display = "none"; downloadLink.style.display = "none";
document.body.appendChild(downloadLink); document.body.appendChild(downloadLink);
let downloadBtn = document.getElementById("download-btn"); let downloadBtn = document.getElementById("download-btn");
downloadBtn.addEventListener("click", () => { downloadBtn.addEventListener("click", () => {
save(); save();
let info = file.info; let info = file.info;
delete info.id; delete info.id;
downloadLink.href = "data:text/json;charset=utf-8," + downloadLink.href = "data:text/json;charset=utf-8," +
encodeURIComponent(JSON.stringify(info)); encodeURIComponent(JSON.stringify(info));
downloadLink.download = info.name + ".json"; downloadLink.download = info.name + ".json";
downloadLink.click(); downloadLink.click();
}); });
/* links */ /* links */
let popupActive = false; let popupActive = false;
let popup = document.getElementById("links-popup"); let popup = document.getElementById("links-popup");
let linksWrapper = document.getElementById("links-wrapper"); let linksWrapper = document.getElementById("links-wrapper");
linksBtn.addEventListener("click", (e) => { linksBtn.addEventListener("click", (e) => {
e.stopPropagation(); e.stopPropagation();
if(popupActive) { if(popupActive) {
popup.style.display = "none"; popup.style.display = "none";
popupActive = false; popupActive = false;
} else { } else {
popup.style.display = "flex"; popup.style.display = "flex";
popupActive = true; popupActive = true;
} }
}); });
function linksClose() { function linksClose() {
if(popupActive) { if(popupActive) {
popup.style.display = "none"; popup.style.display = "none";
popupActive = false; popupActive = false;
save(); save();
} }
} }
document.getElementById("close-links-btn"). document.getElementById("close-links-btn").
addEventListener("click", linksClose); addEventListener("click", linksClose);
document.addEventListener("mousedown", linksClose); document.addEventListener("mousedown", linksClose);
window.addEventListener("keydown", (e) => { window.addEventListener("keydown", (e) => {
if(e.key === "Escape") { linksClose(); } if(e.key === "Escape") { linksClose(); }
}); });
popup.addEventListener("mousedown", (e) => { popup.addEventListener("mousedown", (e) => {
e.stopPropagation(); e.stopPropagation();
}); });
function createLinkEntry(link = "") { function createLinkEntry(link = "") {
let empty = link == ""; let empty = link == "";
let entry = document.createElement("div"); let entry = document.createElement("div");
entry.className = "link-entry"; entry.className = "link-entry";
entry.innerHTML = ` entry.innerHTML = `
<input type="text" value="${link}" placeholder="Add a target website"/> <input type="text" value="${link}" placeholder="Add a target website"/>
<svg viewBox="0 0 24 24" title="Delete entry"> <svg viewBox="0 0 24 24" title="Delete entry">
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"/> <path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"/>
</svg> </svg>
`; `;
let entryInput = entry.querySelector("input"); let entryInput = entry.querySelector("input");
entryInput.addEventListener("input", () => { entryInput.addEventListener("input", () => {
if(empty) { if(empty) {
entrySvg.style.display = ""; entrySvg.style.display = "";
empty = false; empty = false;
createLinkEntry(); createLinkEntry();
} }
editorSetEdited(); editorSetEdited();
}); });
entryInput.addEventListener("blur", () => { entryInput.addEventListener("blur", () => {
if(entryInput.value == "" && !empty) { if(entryInput.value == "" && !empty) {
entry.remove(); entry.remove();
} }
}); });
let entrySvg = entry.querySelector("svg"); let entrySvg = entry.querySelector("svg");
if(empty) { entrySvg.style.display = "none"; } if(empty) { entrySvg.style.display = "none"; }
entrySvg.addEventListener("click", () => { entrySvg.addEventListener("click", () => {
if(!empty) { if(!empty) {
entry.remove(); entry.remove();
editorSetEdited(); editorSetEdited();
} }
}); });
linksWrapper.appendChild(entry); linksWrapper.appendChild(entry);
} }
/* save */ /* save */
enableInput.addEventListener("change", save); enableInput.addEventListener("change", save);
function save() { function save() {
let info = file.info; let info = file.info;
info.enabled = enableInput.checked; info.enabled = enableInput.checked;
info.name = nameInput.value; info.name = nameInput.value;
info.content = editor.getValue(); info.content = editor.getValue();
let links = []; let links = [];
let inputs = linksWrapper.querySelectorAll("input"); let inputs = linksWrapper.querySelectorAll("input");
if(inputs) { if(inputs) {
inputs.forEach((input) => { inputs.forEach((input) => {
if(input.value != "") { if(input.value != "") {
links.push(input.value); links.push(input.value);
} }
}); });
} }
info.links = links; info.links = links;
file.touch(); file.touch();
file.save(); file.save();
WebDAV.putFile(file.info); WebDAV.putFile(file.info);
saveBtn.classList.remove("edited"); saveBtn.classList.remove("edited");
} }
saveBtn.addEventListener("click", save); saveBtn.addEventListener("click", save);
window.addEventListener("keydown", (e) => { window.addEventListener("keydown", (e) => {
if(e.ctrlKey && e.key=="s") { if(e.ctrlKey && e.key=="s") {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
save(); save();
} }
}, true); }, true);

View file

@ -1,99 +1,99 @@
function File(id){ function File(id){
let _this = this; let _this = this;
if(!id) id = File.uuid(); if(!id) id = File.uuid();
let info = this.info = {id, enabled:true}; let info = this.info = {id, enabled:true};
this.changeInfo = function(i){ this.changeInfo = function(i){
for(let _i in i){ for(let _i in i){
info[_i] = i[_i]; info[_i] = i[_i];
} }
}; };
this.touch = function(){ this.touch = function(){
info.lastModified = ((new Date()).getTime() / 1000)|0; info.lastModified = ((new Date()).getTime() / 1000)|0;
} }
this.save = function(){ this.save = function(){
return new Promise(function(succ, err){ return new Promise(function(succ, err){
Storage.save({[File.PREFIX+info.id]:info}).then(_ => { Storage.save({[File.PREFIX+info.id]:info}).then(_ => {
File.saveIndex(info.id, info.enabled).then(succ); File.saveIndex(info.id, info.enabled).then(succ);
}); });
}); });
}; };
this.onChange = function(info){}; //Placeholder function this.onChange = function(info){}; //Placeholder function
Storage.onChange(File.PREFIX+id, newInfo => { Storage.onChange(File.PREFIX+id, newInfo => {
_this.changeInfo(newInfo); _this.changeInfo(newInfo);
_this.onChange(newInfo); _this.onChange(newInfo);
}); });
return this; return this;
} }
File.PREFIX = "FILE-"; File.PREFIX = "FILE-";
File.saveIndex = function(id, enabled){ File.saveIndex = function(id, enabled){
return new Promise((succ, err) => { return new Promise((succ, err) => {
File.loadIndex().then((index) => { File.loadIndex().then((index) => {
index[id] = enabled; index[id] = enabled;
Storage.save({"INDEX":index}).then(succ); Storage.save({"INDEX":index}).then(succ);
}); });
}); });
}; };
File.loadIndex = function(){ File.loadIndex = function(){
return new Promise((succ, err) => { return new Promise((succ, err) => {
Storage.load(["INDEX"]).then((result) => { Storage.load(["INDEX"]).then((result) => {
let index = result["INDEX"] || {}; let index = result["INDEX"] || {};
succ(index); succ(index);
}); });
}); });
}; };
File.uuid = function(){ File.uuid = function(){
return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c => return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16) (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
) )
}; };
File.remove = function(id){ File.remove = function(id){
return new Promise((succ, err) => { return new Promise((succ, err) => {
File.loadIndex().then((index) => { File.loadIndex().then((index) => {
delete index[id]; delete index[id];
Storage.save({"INDEX":index}).then(_ => { Storage.save({"INDEX":index}).then(_ => {
Storage.remove([File.PREFIX+id]).then(succ); Storage.remove([File.PREFIX+id]).then(succ);
}); });
}); });
}); });
}; };
File.load = function(id){ File.load = function(id){
return new Promise((succ, err) => { return new Promise((succ, err) => {
let innerID = File.PREFIX+id; let innerID = File.PREFIX+id;
Storage.load([innerID]).then(result => { Storage.load([innerID]).then(result => {
if(!result[innerID]) err(); if(!result[innerID]) err();
let file = new File(id); let file = new File(id);
file.changeInfo(result[innerID]); file.changeInfo(result[innerID]);
succ(file); succ(file);
}); });
}); });
}; };
File.loadAll = function(){ File.loadAll = function(){
return new Promise((succ, err) => { return new Promise((succ, err) => {
let files = []; let files = [];
File.loadIndex().then((index) => { File.loadIndex().then((index) => {
for(let id in index){ for(let id in index){
files.push(File.load(id)); files.push(File.load(id));
} }
Promise.all(files).then((files) => { Promise.all(files).then((files) => {
succ(files); succ(files);
}); });
}); });
}); });
}; };
File.loadEnabled = function(){ File.loadEnabled = function(){
return new Promise((succ, err) => { return new Promise((succ, err) => {
let files = []; let files = [];
File.loadIndex().then((index) => { File.loadIndex().then((index) => {
for(let id in index){ for(let id in index){
if(index[id]) files.push(File.load(id)); if(index[id]) files.push(File.load(id));
} }
Promise.all(files).then((files) => { Promise.all(files).then((files) => {
succ(files); succ(files);
}) })
}); });
}); });
}; };

View file

@ -1,149 +1,149 @@
function createFileEntry(fileObject, element){ function createFileEntry(fileObject, element){
let info = fileObject.info; let info = fileObject.info;
let file = document.createElement("div"); let file = document.createElement("div");
file.className = "file"; file.className = "file";
file.innerHTML = ` file.innerHTML = `
<label class="check" title="Enable or disable file"><input type="checkbox" ${info.enabled?"checked='true'":""}><span></span></label> <label class="check" title="Enable or disable file"><input type="checkbox" ${info.enabled?"checked='true'":""}><span></span></label>
<span class="file-name">${info.name}</span> <span class="file-name">${info.name}</span>
<span class="file-type" data-type="${info.type}">${info.type}</span> <span class="file-type" data-type="${info.type}">${info.type}</span>
<div class="file-icons"> <div class="file-icons">
<span class="file-icon file-edit" title="Edit file"> <span class="file-icon file-edit" title="Edit file">
<svg viewBox="0 0 48 48"> <svg viewBox="0 0 48 48">
<path d="M6 34.5v7.5h7.5l22.13-22.13-7.5-7.5-22.13 22.13zm35.41-20.41c.78-.78.78-2.05 0-2.83l-4.67-4.67c-.78-.78-2.05-.78-2.83 0l-3.66 3.66 7.5 7.5 3.66-3.66z"/> <path d="M6 34.5v7.5h7.5l22.13-22.13-7.5-7.5-22.13 22.13zm35.41-20.41c.78-.78.78-2.05 0-2.83l-4.67-4.67c-.78-.78-2.05-.78-2.83 0l-3.66 3.66 7.5 7.5 3.66-3.66z"/>
</svg> </svg>
</span> </span>
<span class="file-icon file-delete" title="Delete file"> <span class="file-icon file-delete" title="Delete file">
<svg viewBox="0 0 48 48"> <svg viewBox="0 0 48 48">
<path d="M12 38c0 2.21 1.79 4 4 4h16c2.21 0 4-1.79 4-4v-24h-24v24zm26-30h-7l-2-2h-10l-2 2h-7v4h28v-4z"/> <path d="M12 38c0 2.21 1.79 4 4 4h16c2.21 0 4-1.79 4-4v-24h-24v24zm26-30h-7l-2-2h-10l-2 2h-7v4h28v-4z"/>
</svg> </svg>
</span> </span>
</div> </div>
`; `;
let fileName = file.querySelector(".file-name"); let fileName = file.querySelector(".file-name");
let fileType = file.querySelector(".file-type"); let fileType = file.querySelector(".file-type");
let fileEnable = file.querySelector("input"); let fileEnable = file.querySelector("input");
fileEnable.addEventListener("change", function(){ fileEnable.addEventListener("change", function(){
info.enabled = this.checked; info.enabled = this.checked;
fileObject.save(); fileObject.save();
}); });
let fileEdit = file.querySelector(".file-icon.file-edit"); let fileEdit = file.querySelector(".file-icon.file-edit");
fileEdit.addEventListener("click", edit); fileEdit.addEventListener("click", edit);
let fileDelete = file.querySelector(".file-icon.file-delete"); let fileDelete = file.querySelector(".file-icon.file-delete");
fileDelete.addEventListener("click", function(){ fileDelete.addEventListener("click", function(){
if(fileDelete.classList.contains("icon-confirm")){ if(fileDelete.classList.contains("icon-confirm")){
File.remove(info.id).then(function(){ File.remove(info.id).then(function(){
file.remove(); file.remove();
}); });
}else{ }else{
fileDelete.classList.add("icon-confirm"); fileDelete.classList.add("icon-confirm");
setTimeout(function(){ setTimeout(function(){
fileDelete.classList.remove("icon-confirm"); fileDelete.classList.remove("icon-confirm");
}, 1000); }, 1000);
} }
}); });
file.addEventListener("click", e => { file.addEventListener("click", e => {
if(e.target.className=="file") edit(); if(e.target.className=="file") edit();
}); });
element.appendChild(file); element.appendChild(file);
fileObject.onChange = function(info){ fileObject.onChange = function(info){
fileEnable.checked = info.enabled; fileEnable.checked = info.enabled;
fileName.textContent = info.name; fileName.textContent = info.name;
} }
function edit(){ function edit(){
chrome.tabs.create({url: chrome.runtime.getURL("editor.html#"+info.id)}); chrome.tabs.create({url: chrome.runtime.getURL("editor.html#"+info.id)});
} }
} }
let filesElement = document.getElementById("files"); let filesElement = document.getElementById("files");
File.loadAll().then(function(files){ File.loadAll().then(function(files){
files = files.sort((a, b) => { files = files.sort((a, b) => {
if(a.info.name < b.info.name) return -1; if(a.info.name < b.info.name) return -1;
if(a.info.name > b.info.name) return 1; if(a.info.name > b.info.name) return 1;
return 0; return 0;
}); });
for(let i=0;i<files.length;i++){ for(let i=0;i<files.length;i++){
createFileEntry(files[i], filesElement); createFileEntry(files[i], filesElement);
} }
}); });
let newFileJS = document.getElementById("new-js"); let newFileJS = document.getElementById("new-js");
newFileJS.addEventListener("click", () => { newFileJS.addEventListener("click", () => {
let f = new File(); let f = new File();
f.changeInfo({type: "JS", name: "New Script"}); f.changeInfo({type: "JS", name: "New Script"});
f.save().then(() => { f.save().then(() => {
createFileEntry(f, filesElement); createFileEntry(f, filesElement);
}); });
}); });
let newFileCSS = document.getElementById("new-css"); let newFileCSS = document.getElementById("new-css");
newFileCSS.addEventListener("click", () => { newFileCSS.addEventListener("click", () => {
let f = new File(); let f = new File();
f.changeInfo({type: "CSS", name: "New Stylesheet"}); f.changeInfo({type: "CSS", name: "New Stylesheet"});
f.save().then(() => { f.save().then(() => {
createFileEntry(f, filesElement); createFileEntry(f, filesElement);
}); });
}); });
/* file input */ /* file input */
function newFromFile(inFile) { function newFromFile(inFile) {
let info = {}; let info = {};
if(inFile.type == "text/javascript") { if(inFile.type == "text/javascript") {
info.type = "JS"; info.type = "JS";
info.name = inFile.name.match(/(.*)\..*$/); info.name = inFile.name.match(/(.*)\..*$/);
} else if(inFile.type == "text/css") { } else if(inFile.type == "text/css") {
info.type = "CSS"; info.type = "CSS";
info.name = inFile.name.match(/(.*)\..*$/); info.name = inFile.name.match(/(.*)\..*$/);
} else if(inFile.type == "application/json") { } else if(inFile.type == "application/json") {
} else { } else {
alert("Unsupported file type"); alert("Unsupported file type");
return; return;
} }
let reader = new FileReader(); let reader = new FileReader();
reader.addEventListener("load", () => { reader.addEventListener("load", () => {
if(inFile.type == "application/json") { if(inFile.type == "application/json") {
try { try {
info = JSON.parse(reader.result); info = JSON.parse(reader.result);
} catch(e) { alert("The uploaded json file is not valid"); } } catch(e) { alert("The uploaded json file is not valid"); }
} else { } else {
info.content = reader.result; info.content = reader.result;
} }
let f = new File(); let f = new File();
f.changeInfo(info); f.changeInfo(info);
f.save().then(() => { f.save().then(() => {
createFileEntry(f, filesElement); createFileEntry(f, filesElement);
}); });
}); });
reader.readAsText(inFile); reader.readAsText(inFile);
} }
document.body.addEventListener("dragover", (e) => { document.body.addEventListener("dragover", (e) => {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
document.body.classList.add("drag-over"); document.body.classList.add("drag-over");
}); });
document.body.addEventListener("dragleave", (e) => { document.body.addEventListener("dragleave", (e) => {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
document.body.classList.remove("drag-over"); document.body.classList.remove("drag-over");
}); });
document.body.addEventListener("drop", (e) => { document.body.addEventListener("drop", (e) => {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
document.body.classList.remove("drag-over"); document.body.classList.remove("drag-over");
newFromFile(e.dataTransfer.files[0]); newFromFile(e.dataTransfer.files[0]);
}); });
let inputFile = document.createElement("input"); let inputFile = document.createElement("input");
inputFile.type = "file"; inputFile.type = "file";
inputFile.addEventListener("change", () => { inputFile.addEventListener("change", () => {
newFromFile(inputFile.files[0]); newFromFile(inputFile.files[0]);
}); });
let newFileUp = document.getElementById("new-up"); let newFileUp = document.getElementById("new-up");
newFileUp.addEventListener("click", () => { inputFile.click(); }); newFileUp.addEventListener("click", () => { inputFile.click(); });

View file

@ -1,81 +1,81 @@
let addNew = document.getElementById("add-new"); let addNew = document.getElementById("add-new");
let section = document.getElementById("files"); let section = document.getElementById("files");
let manage = document.getElementById("manage"); let manage = document.getElementById("manage");
manage.addEventListener("click", e => { manage.addEventListener("click", e => {
chrome.tabs.create({ url: chrome.runtime.getURL("index.html") }); chrome.tabs.create({ url: chrome.runtime.getURL("index.html") });
window.close(); window.close();
}); });
chrome.tabs.query({active: true, currentWindow: true}, tabs => { chrome.tabs.query({active: true, currentWindow: true}, tabs => {
let tabID = tabs[0].id; let tabID = tabs[0].id;
// Query file list // Query file list
chrome.runtime.sendMessage({tabID, action: "get-files"}, files => { chrome.runtime.sendMessage({tabID, action: "get-files"}, files => {
if(!files || !files.length) return; if(!files || !files.length) return;
files.forEach(info => { files.forEach(info => {
let file = new File(info.id); let file = new File(info.id);
file.changeInfo(info); file.changeInfo(info);
info = file.info; info = file.info;
let span = document.createElement("span"); let span = document.createElement("span");
span.className = "line btn"; span.className = "line btn";
span.addEventListener("click", e => { span.addEventListener("click", e => {
if(e.target.classList.contains("btn")){ if(e.target.classList.contains("btn")){
chrome.tabs.create({ url: chrome.runtime.getURL("editor.html#"+info.id)}); chrome.tabs.create({ url: chrome.runtime.getURL("editor.html#"+info.id)});
window.close(); window.close();
} }
}); });
let enable = document.createElement("label"); let enable = document.createElement("label");
enable.className = "check small"; enable.className = "check small";
enable.innerHTML = ` enable.innerHTML = `
<input id="enable-input" type="checkbox"> <input id="enable-input" type="checkbox">
<span><span></span></span> <span><span></span></span>
`; `;
let input = enable.children[0]; let input = enable.children[0];
input.checked = info.enabled; input.checked = info.enabled;
input.addEventListener("change", e => { input.addEventListener("change", e => {
file.info.enabled = input.checked; file.info.enabled = input.checked;
file.save(); file.save();
}); });
span.appendChild(enable); span.appendChild(enable);
let name = document.createElement("span"); let name = document.createElement("span");
name.className = "line-item"; name.className = "line-item";
name.textContent = info.name; name.textContent = info.name;
span.appendChild(name); span.appendChild(name);
let type = document.createElement("span"); let type = document.createElement("span");
type.className = "line-item"; type.className = "line-item";
type.textContent = info.type; type.textContent = info.type;
span.appendChild(type); span.appendChild(type);
file.onChange = function(info){ file.onChange = function(info){
input.checked = info.enabled; input.checked = info.enabled;
name.textContent = info.name; name.textContent = info.name;
} }
section.appendChild(span); section.appendChild(span);
}); });
}); });
// Query URL // Query URL
addNew.style.display = "none"; addNew.style.display = "none";
chrome.runtime.sendMessage({tabID, action: "get-url"}, url => { chrome.runtime.sendMessage({tabID, action: "get-url"}, url => {
if(!url) return; if(!url) return;
addNew.style.display = ""; addNew.style.display = "";
let addJS = document.getElementById("add-js"); let addJS = document.getElementById("add-js");
let addCSS = document.getElementById("add-css"); let addCSS = document.getElementById("add-css");
addJS.addEventListener("click", e =>{add("JS")}); addJS.addEventListener("click", e =>{add("JS")});
addCSS.addEventListener("click", e =>{add("CSS")}); addCSS.addEventListener("click", e =>{add("CSS")});
function add(type){ function add(type){
let f = new File(); let f = new File();
f.changeInfo({type, name: "New "+(type=="CSS"?"Stylesheet":"Script"), links:[url]}); f.changeInfo({type, name: "New "+(type=="CSS"?"Stylesheet":"Script"), links:[url]});
f.save().then(_ => { f.save().then(_ => {
chrome.tabs.create({ url: chrome.runtime.getURL("editor.html#"+f.info.id)}); chrome.tabs.create({ url: chrome.runtime.getURL("editor.html#"+f.info.id)});
window.close(); window.close();
}); });
} }
}); });
}); });

View file

@ -1,29 +1,29 @@
let Storage = {}; let Storage = {};
Storage.save = browser.storage.local.set; Storage.save = browser.storage.local.set;
Storage.load = browser.storage.local.get; Storage.load = browser.storage.local.get;
Storage.remove = browser.storage.local.remove; Storage.remove = browser.storage.local.remove;
Storage.saveSync = browser.storage.sync.set; Storage.saveSync = browser.storage.sync.set;
Storage.loadSync = browser.storage.sync.get; Storage.loadSync = browser.storage.sync.get;
Storage.removeSync = browser.storage.sync.remove; Storage.removeSync = browser.storage.sync.remove;
Storage.callbacks = {}; Storage.callbacks = {};
Storage.onChange = function(key, fn){ Storage.onChange = function(key, fn){
if(!Storage.callbacks[key]) Storage.callbacks[key] = []; if(!Storage.callbacks[key]) Storage.callbacks[key] = [];
Storage.callbacks[key].push(fn); Storage.callbacks[key].push(fn);
} }
Storage.emit = function(key, newValue){ Storage.emit = function(key, newValue){
if(!Storage.callbacks[key]) return; if(!Storage.callbacks[key]) return;
Storage.callbacks[key].forEach(x => { Storage.callbacks[key].forEach(x => {
x(newValue); x(newValue);
}); });
} }
chrome.storage.onChanged.addListener(function(objects, area){ chrome.storage.onChanged.addListener(function(objects, area){
if(area!="local") return; if(area!="local") return;
for(let id in objects){ for(let id in objects){
let newValue = objects[id].newValue; let newValue = objects[id].newValue;
if(newValue) { Storage.emit(id, newValue); } if(newValue) { Storage.emit(id, newValue); }
} }
}); });

View file

@ -28,7 +28,7 @@ WebDAV.propfind = async (path, opts) => {
let res = await WebDAV.req(path, "PROPFIND", opts); let res = await WebDAV.req(path, "PROPFIND", opts);
let xmlText = await res.text(); let xmlText = await res.text();
let parser = new DOMParser(); let parser = new DOMParser();
let xmlDoc = parser.parseFromString(xmlText, "text/xml"); let xmlDoc = parser.parseFromString(xmlText, "text/xml");
let responses = xmlDoc.getElementsByTagName("D:response"); let responses = xmlDoc.getElementsByTagName("D:response");

View file

@ -1,24 +1,24 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="utf-8"/> <meta charset="utf-8"/>
<link rel="stylesheet" href="css/common.css"/> <link rel="stylesheet" href="css/common.css"/>
<link rel="stylesheet" href="css/popup.css"/> <link rel="stylesheet" href="css/popup.css"/>
<title>Custom Web Popup</title> <title>Custom Web Popup</title>
</head> </head>
<body> <body>
<section> <section>
<span id="manage" class="line btn"><img src="img/icon48.png"/><span>Manage Files</span></span> <span id="manage" class="line btn"><img src="img/icon48.png"/><span>Manage Files</span></span>
</section> </section>
<section id="add-new"> <section id="add-new">
<div class="line"> <div class="line">
<span id="add-js" class="btn">Add Script</span> <span id="add-js" class="btn">Add Script</span>
<span id="add-css" class="btn">Add Style</span> <span id="add-css" class="btn">Add Style</span>
</div> </div>
</section> </section>
<section id="files"></section> <section id="files"></section>
<script src="js/storage.js"></script> <script src="js/storage.js"></script>
<script src="js/file.js"></script> <script src="js/file.js"></script>
<script src="js/popup.js"></script> <script src="js/popup.js"></script>
</body> </body>
</html> </html>

View file

@ -1,6 +1,6 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="utf-8"/> <meta charset="utf-8"/>
<title>Custom Web - Settings</title> <title>Custom Web - Settings</title>
<link rel="shortcut icon" type="image/png" href="img/icon48.png"> <link rel="shortcut icon" type="image/png" href="img/icon48.png">