Merged upstream master
|
@ -76,6 +76,8 @@ App.prototype.registerChefWorker = function() {
|
|||
|
||||
/**
|
||||
* Fires once all setup activities have completed.
|
||||
*
|
||||
* @fires Manager#apploaded
|
||||
*/
|
||||
App.prototype.loaded = function() {
|
||||
// Check that both the app and the worker have loaded successfully, and that
|
||||
|
@ -95,6 +97,8 @@ App.prototype.loaded = function() {
|
|||
|
||||
// Clear the loading message interval
|
||||
clearInterval(window.loadingMsgsInt);
|
||||
|
||||
document.dispatchEvent(this.manager.apploaded);
|
||||
};
|
||||
|
||||
|
||||
|
@ -459,7 +463,7 @@ App.prototype.loadURIParams = function() {
|
|||
// Read in recipe from URI params
|
||||
if (this.uriParams.recipe) {
|
||||
try {
|
||||
const recipeConfig = JSON.parse(this.uriParams.recipe);
|
||||
const recipeConfig = Utils.parseRecipeConfig(this.uriParams.recipe);
|
||||
this.setRecipeConfig(recipeConfig);
|
||||
} catch (err) {}
|
||||
} else if (this.uriParams.op) {
|
||||
|
@ -530,6 +534,7 @@ App.prototype.setRecipeConfig = function(recipeConfig) {
|
|||
// Populate arguments
|
||||
const args = item.querySelectorAll(".arg");
|
||||
for (let j = 0; j < args.length; j++) {
|
||||
if (recipeConfig[i].args[j] === undefined) continue;
|
||||
if (args[j].getAttribute("type") === "checkbox") {
|
||||
// checkbox
|
||||
args[j].checked = recipeConfig[i].args[j];
|
||||
|
@ -724,7 +729,14 @@ App.prototype.stateChange = function(e) {
|
|||
if (recipeConfig.length === 1) {
|
||||
title = `${recipeConfig[0].op} - ${title}`;
|
||||
} else if (recipeConfig.length > 1) {
|
||||
title = `${recipeConfig.length} operations - ${title}`;
|
||||
// See how long the full recipe is
|
||||
const ops = recipeConfig.map(op => op.op).join(", ");
|
||||
if (ops.length < 45) {
|
||||
title = `${ops} - ${title}`;
|
||||
} else {
|
||||
// If it's too long, just use the first one and say how many more there are
|
||||
title = `${recipeConfig[0].op}, ${recipeConfig.length - 1} more - ${title}`;
|
||||
}
|
||||
}
|
||||
document.title = title;
|
||||
|
||||
|
|
|
@ -168,7 +168,7 @@ ControlsWaiter.prototype.generateStateUrl = function(includeRecipe, includeInput
|
|||
const link = baseURL || window.location.protocol + "//" +
|
||||
window.location.host +
|
||||
window.location.pathname;
|
||||
const recipeStr = JSON.stringify(recipeConfig);
|
||||
const recipeStr = Utils.generatePrettyRecipe(recipeConfig);
|
||||
const inputStr = Utils.toBase64(this.app.getInput(), "A-Za-z0-9+/"); // B64 alphabet with no padding
|
||||
|
||||
includeRecipe = includeRecipe && (recipeConfig.length > 0);
|
||||
|
@ -182,7 +182,7 @@ ControlsWaiter.prototype.generateStateUrl = function(includeRecipe, includeInput
|
|||
|
||||
const hash = params
|
||||
.filter(v => v)
|
||||
.map(([key, value]) => `${key}=${encodeURIComponent(value)}`)
|
||||
.map(([key, value]) => `${key}=${Utils.encodeURIFragment(value)}`)
|
||||
.join("&");
|
||||
|
||||
if (hash) {
|
||||
|
@ -196,9 +196,9 @@ ControlsWaiter.prototype.generateStateUrl = function(includeRecipe, includeInput
|
|||
/**
|
||||
* Handler for changes made to the save dialog text area. Re-initialises the save link.
|
||||
*/
|
||||
ControlsWaiter.prototype.saveTextChange = function() {
|
||||
ControlsWaiter.prototype.saveTextChange = function(e) {
|
||||
try {
|
||||
const recipeConfig = JSON.parse(document.getElementById("save-text").value);
|
||||
const recipeConfig = Utils.parseRecipeConfig(e.target.value);
|
||||
this.initialiseSaveLink(recipeConfig);
|
||||
} catch (err) {}
|
||||
};
|
||||
|
@ -209,9 +209,16 @@ ControlsWaiter.prototype.saveTextChange = function() {
|
|||
*/
|
||||
ControlsWaiter.prototype.saveClick = function() {
|
||||
const recipeConfig = this.app.getRecipeConfig();
|
||||
const recipeStr = JSON.stringify(recipeConfig).replace(/},{/g, "},\n{");
|
||||
const recipeStr = JSON.stringify(recipeConfig);
|
||||
|
||||
document.getElementById("save-text").value = recipeStr;
|
||||
document.getElementById("save-text-chef").value = Utils.generatePrettyRecipe(recipeConfig, true);
|
||||
document.getElementById("save-text-clean").value = JSON.stringify(recipeConfig, null, 2)
|
||||
.replace(/{\n\s+"/g, "{ \"")
|
||||
.replace(/\[\n\s{3,}/g, "[")
|
||||
.replace(/\n\s{3,}]/g, "]")
|
||||
.replace(/\s*\n\s*}/g, " }")
|
||||
.replace(/\n\s{6,}/g, " ");
|
||||
document.getElementById("save-text-compact").value = recipeStr;
|
||||
|
||||
this.initialiseSaveLink(recipeConfig);
|
||||
$("#save-modal").modal();
|
||||
|
@ -248,7 +255,7 @@ ControlsWaiter.prototype.loadClick = function() {
|
|||
*/
|
||||
ControlsWaiter.prototype.saveButtonClick = function() {
|
||||
const recipeName = Utils.escapeHtml(document.getElementById("save-name").value);
|
||||
const recipeStr = document.getElementById("save-text").value;
|
||||
const recipeStr = document.querySelector("#save-texts .tab-pane.active textarea").value;
|
||||
|
||||
if (!recipeName) {
|
||||
this.app.alert("Please enter a recipe name", "danger", 2000);
|
||||
|
@ -337,7 +344,7 @@ ControlsWaiter.prototype.loadNameChange = function(e) {
|
|||
*/
|
||||
ControlsWaiter.prototype.loadButtonClick = function() {
|
||||
try {
|
||||
const recipeConfig = JSON.parse(document.getElementById("load-text").value);
|
||||
const recipeConfig = Utils.parseRecipeConfig(document.getElementById("load-text").value);
|
||||
this.app.setRecipeConfig(recipeConfig);
|
||||
|
||||
$("#rec-list [data-toggle=popover]").popover();
|
||||
|
|
|
@ -27,6 +27,10 @@ const Manager = function(app) {
|
|||
* @event Manager#appstart
|
||||
*/
|
||||
this.appstart = new CustomEvent("appstart", {bubbles: true});
|
||||
/**
|
||||
* @event Manager#apploaded
|
||||
*/
|
||||
this.apploaded = new CustomEvent("apploaded", {bubbles: true});
|
||||
/**
|
||||
* @event Manager#operationadd
|
||||
*/
|
||||
|
@ -98,7 +102,7 @@ Manager.prototype.initialiseEventListeners = function() {
|
|||
document.getElementById("load-name").addEventListener("change", this.controls.loadNameChange.bind(this.controls));
|
||||
document.getElementById("load-button").addEventListener("click", this.controls.loadButtonClick.bind(this.controls));
|
||||
document.getElementById("support").addEventListener("click", this.controls.supportButtonClick.bind(this.controls));
|
||||
this.addMultiEventListener("#save-text", "keyup paste", this.controls.saveTextChange, this.controls);
|
||||
this.addMultiEventListeners("#save-texts textarea", "keyup paste", this.controls.saveTextChange, this.controls);
|
||||
|
||||
// Operations
|
||||
this.addMultiEventListener("#search", "keyup paste search", this.ops.searchOperations, this.ops);
|
||||
|
@ -114,6 +118,7 @@ Manager.prototype.initialiseEventListeners = function() {
|
|||
// Recipe
|
||||
this.addDynamicListener(".arg", "keyup", this.recipe.ingChange, this.recipe);
|
||||
this.addDynamicListener(".arg", "change", this.recipe.ingChange, this.recipe);
|
||||
this.addDynamicListener(".arg", "input", this.recipe.ingChange, this.recipe);
|
||||
this.addDynamicListener(".disable-icon", "click", this.recipe.disableClick, this.recipe);
|
||||
this.addDynamicListener(".breakpoint", "click", this.recipe.breakpointClick, this.recipe);
|
||||
this.addDynamicListener("#rec-list li.operation", "dblclick", this.recipe.operationDblclick, this.recipe);
|
||||
|
|
|
@ -155,7 +155,35 @@ OperationsWaiter.prototype.getSelectedOp = function(ops) {
|
|||
*/
|
||||
OperationsWaiter.prototype.opListCreate = function(e) {
|
||||
this.manager.recipe.createSortableSeedList(e.target);
|
||||
$("[data-toggle=popover]").popover();
|
||||
this.enableOpsListPopovers(e.target);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets up popovers, allowing the popover itself to gain focus which enables scrolling
|
||||
* and other interactions.
|
||||
*
|
||||
* @param {Element} el - The element to start selecting from
|
||||
*/
|
||||
OperationsWaiter.prototype.enableOpsListPopovers = function(el) {
|
||||
$(el).find("[data-toggle=popover]").addBack("[data-toggle=popover]")
|
||||
.popover({trigger: "manual"})
|
||||
.on("mouseenter", function() {
|
||||
const _this = this;
|
||||
$(this).popover("show");
|
||||
$(".popover").on("mouseleave", function () {
|
||||
$(_this).popover("hide");
|
||||
});
|
||||
}).on("mouseleave", function () {
|
||||
const _this = this;
|
||||
setTimeout(function() {
|
||||
// Determine if the popover associated with this element is being hovered over
|
||||
if ($(_this).data("bs.popover") &&
|
||||
!$(_this).data("bs.popover").$tip.is(":hover")) {
|
||||
$(_this).popover("hide");
|
||||
}
|
||||
}, 50);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ RecipeWaiter.prototype.createSortableSeedList = function(listEl) {
|
|||
// Removes popover element and event bindings from the dragged operation but not the
|
||||
// event bindings from the one left in the operations list. Without manually removing
|
||||
// these bindings, we cannot re-initialise the popover on the stub operation.
|
||||
$(evt.item).popover("destroy");
|
||||
$(evt.item).popover("destroy").removeData("bs.popover").off("mouseenter").off("mouseleave");
|
||||
$(evt.clone).off(".popover").removeData("bs.popover");
|
||||
evt.item.setAttribute("data-toggle", "popover-disabled");
|
||||
},
|
||||
|
@ -120,8 +120,7 @@ RecipeWaiter.prototype.opSortEnd = function(evt) {
|
|||
|
||||
// Reinitialise the popover on the original element in the ops list because for some reason it
|
||||
// gets destroyed and recreated.
|
||||
$(evt.clone).popover();
|
||||
$(evt.clone).children("[data-toggle=popover]").popover();
|
||||
this.manager.ops.enableOpsListPopovers(evt.clone);
|
||||
|
||||
if (evt.item.parentNode.id !== "rec-list") {
|
||||
return;
|
||||
|
@ -296,6 +295,9 @@ RecipeWaiter.prototype.getConfig = function() {
|
|||
option: ingList[j].previousSibling.children[0].textContent.slice(0, -1),
|
||||
string: ingList[j].value
|
||||
};
|
||||
} else if (ingList[j].getAttribute("type") === "number") {
|
||||
// number
|
||||
ingredients[j] = parseFloat(ingList[j].value, 10);
|
||||
} else {
|
||||
// all others
|
||||
ingredients[j] = ingList[j].value;
|
||||
|
|
|
@ -46,10 +46,15 @@
|
|||
"Initialising Skynet...",
|
||||
"[REDACTED]",
|
||||
"Downloading more RAM...",
|
||||
"Loading more loading messages...",
|
||||
"Ordering 1s and 0s...",
|
||||
"Navigating neural network...",
|
||||
"Importing machine learning..."
|
||||
"Importing machine learning...",
|
||||
"Issuing Alice and Bob one-time pads...",
|
||||
"Mining bitcoin cash...",
|
||||
"Generating key material by trying to escape vim...",
|
||||
"for i in range(additional): Pylon()",
|
||||
"(creating unresolved tension...",
|
||||
"Symlinking emacs and vim to ed...",
|
||||
];
|
||||
|
||||
// Shuffle array using Durstenfeld algorithm
|
||||
|
@ -60,20 +65,20 @@
|
|||
loadingMsgs[j] = temp;
|
||||
}
|
||||
|
||||
// Show next loading message then move it to the end of the array
|
||||
// Show next loading message and move it to the end of the array
|
||||
function changeLoadingMsg() {
|
||||
const msg = loadingMsgs.shift();
|
||||
loadingMsgs.push(msg);
|
||||
try {
|
||||
const el = document.getElementById("preloader-msg");
|
||||
if (!el.classList.contains("loading"))
|
||||
el.classList.add("loading"); // Causes CSS transition on first message
|
||||
el.innerHTML = msg;
|
||||
} catch (err) {} // Ignore errors if DOM not yet ready
|
||||
loadingMsgs.push(msg);
|
||||
}
|
||||
|
||||
changeLoadingMsg();
|
||||
window.loadingMsgsInt = setInterval(changeLoadingMsg, (Math.random() * 1000) + 1000);
|
||||
window.loadingMsgsInt = setInterval(changeLoadingMsg, (Math.random() * 2000) + 1500);
|
||||
</script>
|
||||
<% if (!htmlWebpackPlugin.options.inline) { %>
|
||||
<script type="application/ld+json">
|
||||
|
@ -212,7 +217,22 @@
|
|||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label for="save-text">Save your recipe to local storage or copy the following string to load later</label>
|
||||
<textarea class="form-control" id="save-text" rows="5"></textarea>
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li role="presentation" class="active"><a href="#chef-format" role="tab" data-toggle="tab">Chef format</a></li>
|
||||
<li role="presentation"><a href="#clean-json" role="tab" data-toggle="tab">Clean JSON</a></li>
|
||||
<li role="presentation"><a href="#compact-json" role="tab" data-toggle="tab">Compact JSON</a></li>
|
||||
</ul>
|
||||
<div class="tab-content" id="save-texts">
|
||||
<div role="tabpanel" class="tab-pane active" id="chef-format">
|
||||
<textarea class="form-control" id="save-text-chef" rows="5"></textarea>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane" id="clean-json">
|
||||
<textarea class="form-control" id="save-text-clean" rows="5"></textarea>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane" id="compact-json">
|
||||
<textarea class="form-control" id="save-text-compact" rows="5"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="save-name">Recipe name</label>
|
||||
|
@ -277,6 +297,7 @@
|
|||
<select option="theme" id="theme">
|
||||
<option value="classic">Classic</option>
|
||||
<option value="dark">Dark</option>
|
||||
<option value="geocities">GeoCities</option>
|
||||
</select>
|
||||
<label for="theme"> Theme (only supported in modern browsers)</label>
|
||||
</div>
|
||||
|
@ -383,12 +404,12 @@
|
|||
<div class="collapse" id="faq-examples">
|
||||
<p>There are around 200 operations in CyberChef allowing you to carry out simple and complex tasks easily. Here are some examples:</p>
|
||||
<ul>
|
||||
<li><a href="#recipe=%5B%7B%22op%22%3A%22From%20Base64%22%2C%22args%22%3A%5B%22A-Za-z0-9%2B%2F%3D%22%2Ctrue%5D%7D%5D&input=VTI4Z2JHOXVaeUJoYm1RZ2RHaGhibXR6SUdadmNpQmhiR3dnZEdobElHWnBjMmd1">Decode a Base64-encoded string</a></li>
|
||||
<li><a href="#recipe=%5B%7B%22op%22%3A%22Translate%20DateTime%20Format%22%2C%22args%22%3A%5B%22Standard%20date%20and%20time%22%2C%22DD%2FMM%2FYYYY%20HH%3Amm%3Ass%22%2C%22UTC%22%2C%22dddd%20Do%20MMMM%20YYYY%20HH%3Amm%3Ass%20Z%20z%22%2C%22Australia%2FQueensland%22%5D%7D%5D&input=MTUvMDYvMjAxNSAyMDo0NTowMA">Convert a date and time to a different time zone</a></li>
|
||||
<li><a href="#recipe=%5B%7B%22op%22%3A%22Parse%20IPv6%20address%22%2C%22args%22%3A%5B%5D%7D%5D&input=MjAwMTowMDAwOjQxMzY6ZTM3ODo4MDAwOjYzYmY6M2ZmZjpmZGQy">Parse a Teredo IPv6 address</a></li>
|
||||
<li><a href="#recipe=%5B%7B%22op%22%3A%22From%20Hexdump%22%2C%22args%22%3A%5B%5D%7D%2C%7B%22op%22%3A%22Gunzip%22%2C%22args%22%3A%5B%5D%7D%5D&input=MDAwMDAwMDAgIDFmIDhiIDA4IDAwIDEyIGJjIGYzIDU3IDAwIGZmIDBkIGM3IGMxIDA5IDAwIDIwICB8Li4uLi6881cu%2Fy7HwS4uIHwKMDAwMDAwMTAgIDA4IDA1IGQwIDU1IGZlIDA0IDJkIGQzIDA0IDFmIGNhIDhjIDQ0IDIxIDViIGZmICB8Li7QVf4uLdMuLsouRCFb%2F3wKMDAwMDAwMjAgIDYwIGM3IGQ3IDAzIDE2IGJlIDQwIDFmIDc4IDRhIDNmIDA5IDg5IDBiIDlhIDdkICB8YMfXLi6%2BQC54Sj8uLi4ufXwKMDAwMDAwMzAgIDRlIGM4IDRlIDZkIDA1IDFlIDAxIDhiIDRjIDI0IDAwIDAwIDAwICAgICAgICAgICB8TshObS4uLi5MJC4uLnw">Convert data from a hexdump, then decompress</a></li>
|
||||
<li><a href="#recipe=%5B%7B%22op%22%3A%22Fork%22%2C%22args%22%3A%5B%22%5C%5Cn%22%2C%22%5C%5Cn%22%5D%7D%2C%7B%22op%22%3A%22From%20UNIX%20Timestamp%22%2C%22args%22%3A%5B%22Seconds%20(s)%22%5D%7D%5D&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA">Display multiple timestamps as full dates</a></li>
|
||||
<li><a href="#recipe=%5B%7B%22op%22%3A%22Fork%22%2C%22args%22%3A%5B%22%5C%5Cn%22%2C%22%5C%5Cn%22%5D%7D%2C%7B%22op%22%3A%22Conditional%20Jump%22%2C%22args%22%3A%5B%221%22%2C%222%22%2C%2210%22%5D%7D%2C%7B%22op%22%3A%22To%20Hex%22%2C%22args%22%3A%5B%22Space%22%5D%7D%2C%7B%22op%22%3A%22Return%22%2C%22args%22%3A%5B%5D%7D%2C%7B%22op%22%3A%22To%20Base64%22%2C%22args%22%3A%5B%22A-Za-z0-9%2B%2F%3D%22%5D%7D%5D&input=U29tZSBkYXRhIHdpdGggYSAxIGluIGl0ClNvbWUgZGF0YSB3aXRoIGEgMiBpbiBpdA">Carry out different operations on data of different types</a></li>
|
||||
<li><a href="#recipe=From_Base64('A-Za-z0-9%2B/%3D',true)&input=VTI4Z2JHOXVaeUJoYm1RZ2RHaGhibXR6SUdadmNpQmhiR3dnZEdobElHWnBjMmd1">Decode a Base64-encoded string</a></li>
|
||||
<li><a href="#recipe=Translate_DateTime_Format('Standard%20date%20and%20time','DD/MM/YYYY%20HH:mm:ss','UTC','dddd%20Do%20MMMM%20YYYY%20HH:mm:ss%20Z%20z','Australia/Queensland')&input=MTUvMDYvMjAxNSAyMDo0NTowMA">Convert a date and time to a different time zone</a></li>
|
||||
<li><a href="#recipe=Parse_IPv6_address()&input=MjAwMTowMDAwOjQxMzY6ZTM3ODo4MDAwOjYzYmY6M2ZmZjpmZGQy">Parse a Teredo IPv6 address</a></li>
|
||||
<li><a href="#recipe=From_Hexdump()Gunzip()&input=MDAwMDAwMDAgIDFmIDhiIDA4IDAwIDEyIGJjIGYzIDU3IDAwIGZmIDBkIGM3IGMxIDA5IDAwIDIwICB8Li4uLi6881cu/y7HwS4uIHwKMDAwMDAwMTAgIDA4IDA1IGQwIDU1IGZlIDA0IDJkIGQzIDA0IDFmIGNhIDhjIDQ0IDIxIDViIGZmICB8Li7QVf4uLdMuLsouRCFb/3wKMDAwMDAwMjAgIDYwIGM3IGQ3IDAzIDE2IGJlIDQwIDFmIDc4IDRhIDNmIDA5IDg5IDBiIDlhIDdkICB8YMfXLi6%2BQC54Sj8uLi4ufXwKMDAwMDAwMzAgIDRlIGM4IDRlIDZkIDA1IDFlIDAxIDhiIDRjIDI0IDAwIDAwIDAwICAgICAgICAgICB8TshObS4uLi5MJC4uLnw">Convert data from a hexdump, then decompress</a></li>
|
||||
<li><a href="#recipe=Fork('%5C%5Cn','%5C%5Cn',false)From_UNIX_Timestamp('Seconds%20(s)')&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA">Display multiple timestamps as full dates</a></li>
|
||||
<li><a href="#recipe=Fork('%5C%5Cn','%5C%5Cn',false)Conditional_Jump('1',2,10)To_Hex('Space')Return()To_Base64('A-Za-z0-9%2B/%3D')&input=U29tZSBkYXRhIHdpdGggYSAxIGluIGl0ClNvbWUgZGF0YSB3aXRoIGEgMiBpbiBpdA">Carry out different operations on data of different types</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<blockquote>
|
||||
|
@ -408,7 +429,7 @@
|
|||
<div class="collapse" id="faq-fork">
|
||||
<p>Maybe you have 10 timestamps that you want to parse or 16 encoded strings that all have the same key.</p>
|
||||
<p>The 'Fork' operation (found in the 'Flow control' category) splits up the input line by line and runs all subsequent operations on each line separately. Each output is then displayed on a separate line. These delimiters can be changed, so if your inputs are separated by commas, you can change the split delimiter to a comma instead.</p>
|
||||
<p><a href='#recipe=%5B%7B"op"%3A"Fork"%2C"args"%3A%5B"%5C%5Cn"%2C"%5C%5Cn"%5D%7D%2C%7B"op"%3A"From%20UNIX%20Timestamp"%2C"args"%3A%5B"Seconds%20(s)"%5D%7D%5D&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA%3D%3D'>Click here</a> for an example.</p>
|
||||
<p><a href="#recipe=Fork('%5C%5Cn','%5C%5Cn',false)From_UNIX_Timestamp('Seconds%20(s)')&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA">Click here</a> for an example.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane" id="report-bug">
|
||||
|
|
Before Width: | Height: | Size: 295 B After Width: | Height: | Size: 233 B |
Before Width: | Height: | Size: 773 B After Width: | Height: | Size: 672 B |
Before Width: | Height: | Size: 702 B After Width: | Height: | Size: 654 B |
Before Width: | Height: | Size: 796 B After Width: | Height: | Size: 762 B |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 419 B After Width: | Height: | Size: 245 B |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 746 B After Width: | Height: | Size: 426 B |
Before Width: | Height: | Size: 590 B After Width: | Height: | Size: 467 B |
Before Width: | Height: | Size: 905 B After Width: | Height: | Size: 764 B |
Before Width: | Height: | Size: 680 B After Width: | Height: | Size: 584 B |
Before Width: | Height: | Size: 491 B After Width: | Height: | Size: 351 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1 KiB |
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 843 B After Width: | Height: | Size: 764 B |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 513 B After Width: | Height: | Size: 385 B |
Before Width: | Height: | Size: 334 B After Width: | Height: | Size: 320 B |
Before Width: | Height: | Size: 463 B After Width: | Height: | Size: 346 B |
Before Width: | Height: | Size: 235 B After Width: | Height: | Size: 175 B |
Before Width: | Height: | Size: 474 B After Width: | Height: | Size: 446 B |
Before Width: | Height: | Size: 719 B After Width: | Height: | Size: 660 B |
Before Width: | Height: | Size: 585 B After Width: | Height: | Size: 564 B |
Before Width: | Height: | Size: 507 B After Width: | Height: | Size: 382 B |
Before Width: | Height: | Size: 245 B After Width: | Height: | Size: 179 B |
Before Width: | Height: | Size: 472 B After Width: | Height: | Size: 463 B |
Before Width: | Height: | Size: 695 B After Width: | Height: | Size: 680 B |
Before Width: | Height: | Size: 642 B After Width: | Height: | Size: 542 B |
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 798 B |
Before Width: | Height: | Size: 360 B After Width: | Height: | Size: 345 B |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 513 B |
Before Width: | Height: | Size: 575 B After Width: | Height: | Size: 534 B |
Before Width: | Height: | Size: 472 B After Width: | Height: | Size: 336 B |
Before Width: | Height: | Size: 769 B After Width: | Height: | Size: 662 B |
Before Width: | Height: | Size: 717 B After Width: | Height: | Size: 627 B |
Before Width: | Height: | Size: 553 B After Width: | Height: | Size: 445 B |
|
@ -9,6 +9,7 @@
|
|||
/* Themes */
|
||||
@import "./themes/_classic.css";
|
||||
@import "./themes/_dark.css";
|
||||
@import "./themes/_geocities.css";
|
||||
|
||||
/* Utilities */
|
||||
@import "./utils/_overrides.css";
|
||||
|
|
|
@ -78,7 +78,13 @@
|
|||
font-family: var(--primary-font-family);
|
||||
}
|
||||
|
||||
#save-text,
|
||||
#save-texts textarea,
|
||||
#load-text {
|
||||
font-family: var(--fixed-width-font-family);
|
||||
}
|
||||
|
||||
#save-texts textarea {
|
||||
border-top: none;
|
||||
box-shadow: none;
|
||||
height: 200px;
|
||||
}
|
||||
|
|
|
@ -61,8 +61,8 @@
|
|||
.loading-msg {
|
||||
display: block;
|
||||
position: relative;
|
||||
width: 300px;
|
||||
left: calc(50% - 150px);
|
||||
width: 400px;
|
||||
left: calc(50% - 200px);
|
||||
top: calc(50% + 50px);
|
||||
text-align: center;
|
||||
margin-top: 50px;
|
||||
|
|
115
src/web/stylesheets/themes/_geocities.css
Executable file
|
@ -0,0 +1,115 @@
|
|||
/**
|
||||
* GeoCities theme definitions
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
:root.geocities {
|
||||
--primary-font-family: "Comic Sans", "Comic Sans MS", "Chalkboard", "ChalkboardSE-Regular", "Marker Felt", "Purisa", "URW Chancery L", cursive, sans-serif;
|
||||
--primary-font-colour: black;
|
||||
--primary-font-size: 14px;
|
||||
--primary-line-height: 20px;
|
||||
|
||||
--fixed-width-font-family: "Courier New", Courier, monospace;
|
||||
--fixed-width-font-colour: yellow;
|
||||
--fixed-width-font-size: inherit;
|
||||
|
||||
--subtext-font-colour: darkgrey;
|
||||
--subtext-font-size: 13px;
|
||||
|
||||
--primary-background-colour: #00f;
|
||||
--secondary-background-colour: #f00;
|
||||
|
||||
--primary-border-colour: pink;
|
||||
--secondary-border-colour: springgreen;
|
||||
|
||||
--title-colour: red;
|
||||
--title-weight: bold;
|
||||
--title-background-colour: yellow;
|
||||
|
||||
--banner-font-colour: white;
|
||||
--banner-bg-colour: maroon;
|
||||
|
||||
|
||||
/* Operation colours */
|
||||
--op-list-operation-font-colour: blue;
|
||||
--op-list-operation-bg-colour: yellow;
|
||||
--op-list-operation-border-colour: green;
|
||||
|
||||
--rec-list-operation-font-colour: white;
|
||||
--rec-list-operation-bg-colour: purple;
|
||||
--rec-list-operation-border-colour: green;
|
||||
|
||||
--selected-operation-font-color: white;
|
||||
--selected-operation-bg-colour: pink;
|
||||
--selected-operation-border-colour: blue;
|
||||
|
||||
--breakpoint-font-colour: white;
|
||||
--breakpoint-bg-colour: red;
|
||||
--breakpoint-border-colour: blue;
|
||||
|
||||
--disabled-font-colour: grey;
|
||||
--disabled-bg-colour: black;
|
||||
--disabled-border-colour: grey;
|
||||
|
||||
--fc-operation-font-colour: sienna;
|
||||
--fc-operation-bg-colour: pink;
|
||||
--fc-operation-border-colour: yellow;
|
||||
|
||||
--fc-breakpoint-operation-font-colour: darkgrey;
|
||||
--fc-breakpoint-operation-bg-colour: deeppink;
|
||||
--fc-breakpoint-operation-border-colour: yellowgreen;
|
||||
|
||||
|
||||
/* Operation arguments */
|
||||
--arg-title-font-weight: bold;
|
||||
--arg-input-height: 34px;
|
||||
--arg-input-line-height: 20px;
|
||||
--arg-input-font-size: 15px;
|
||||
--arg-font-colour: white;
|
||||
--arg-background: black;
|
||||
--arg-border-colour: lime;
|
||||
--arg-disabled-background: grey;
|
||||
|
||||
|
||||
/* Buttons */
|
||||
--btn-default-font-colour: black;
|
||||
--btn-default-bg-colour: white;
|
||||
--btn-default-border-colour: grey;
|
||||
|
||||
--btn-default-hover-font-colour: black;
|
||||
--btn-default-hover-bg-colour: white;
|
||||
--btn-default-hover-border-colour: grey;
|
||||
|
||||
--btn-success-font-colour: white;
|
||||
--btn-success-bg-colour: lawngreen;
|
||||
--btn-success-border-colour: grey;
|
||||
|
||||
--btn-success-hover-font-colour: white;
|
||||
--btn-success-hover-bg-colour: lime;
|
||||
--btn-success-hover-border-colour: grey;
|
||||
|
||||
|
||||
/* Highlighter colours */
|
||||
--hl1: #fff000;
|
||||
--hl2: #95dfff;
|
||||
--hl3: #ffb6b6;
|
||||
--hl4: #fcf8e3;
|
||||
--hl5: #8de768;
|
||||
|
||||
|
||||
/* Scrollbar */
|
||||
--scrollbar-track: lightsteelblue;
|
||||
--scrollbar-thumb: lightslategrey;
|
||||
--scrollbar-hover: grey;
|
||||
|
||||
|
||||
/* Misc. */
|
||||
--drop-file-border-colour: purple;
|
||||
--popover-background: turquoise;
|
||||
--popover-border-colour: violet;
|
||||
--code-background: black;
|
||||
--code-font-colour: limegreen;
|
||||
}
|
|
@ -142,6 +142,10 @@ optgroup {
|
|||
border-color: var(--popover-border-colour);
|
||||
}
|
||||
|
||||
.popover-content {
|
||||
max-height: 90vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.popover.right>.arrow {
|
||||
border-right-color: var(--popover-border-colour);
|
||||
|
|