tag-browser: use separate <code-block> module for style preview
This commit is contained in:
@@ -38,7 +38,7 @@ function fetchWithType(url){
|
||||
.then((obj) => resolve({file:url,content:obj}));
|
||||
}else{
|
||||
response.text()
|
||||
.then((text) => resolve({file:url,content:text}))
|
||||
.then((text) => resolve({file:url,content:text,name:url}))
|
||||
|
||||
}
|
||||
},except => reject(except))
|
||||
@@ -103,14 +103,6 @@ function getSecondaryCategories(list){
|
||||
return ret
|
||||
}
|
||||
|
||||
function clearCodeBlock(){
|
||||
const pre = document.getElementById("previewBox");
|
||||
for(let el of Array.from(pre.childNodes)){
|
||||
pre.removeChild(el)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
function showMatchingTargets(fileNames,setSelected = false){
|
||||
let bonus = 0;
|
||||
for(let c of Array.from(document.querySelectorAll(".target"))){
|
||||
@@ -152,13 +144,27 @@ function onCategoryClicked(categoryNode,isSecondary = false){
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
async function onTargetClicked(target,append = false){
|
||||
const text = typeof target === "string"
|
||||
? target
|
||||
: getText(target);
|
||||
|
||||
fetchWithType(`chrome/${text}`)
|
||||
.then(obj => Highlighter.parse(obj,append))
|
||||
.then(obj => {
|
||||
let box = document.getElementById("previewBox");
|
||||
if(append){
|
||||
if(obj.file.endsWith("window_control_placeholder_support.css")){
|
||||
obj.insertMode = box.InsertModes.Prepend;
|
||||
box.insertContent(obj);
|
||||
}else{
|
||||
obj.insertMode = box.InsertModes.AppendLines;
|
||||
box.insertContent(obj);
|
||||
}
|
||||
}else{
|
||||
box.value = obj
|
||||
}
|
||||
})
|
||||
.catch(e => console.log(e))
|
||||
}
|
||||
|
||||
@@ -178,7 +184,8 @@ function onFilenameClicked(box,ctrlKey){
|
||||
}else{
|
||||
if(ctrlKey){
|
||||
selectedTarget.deselect(box);
|
||||
let preview = document.querySelector(`[data-filename="chrome/${box.getAttribute("title")}.css"]`);
|
||||
let previewbox = document.getElementById("previewBox");
|
||||
let preview = previewbox.getNamedSection(`chrome/${box.getAttribute("title")}.css`);
|
||||
if(preview){
|
||||
preview.remove();
|
||||
}
|
||||
@@ -309,260 +316,6 @@ function createCategories(){
|
||||
|
||||
}
|
||||
|
||||
const Highlighter = new(function(){
|
||||
|
||||
const state = new (function(){
|
||||
let current = 0;
|
||||
let previous = 0;
|
||||
this.now = ()=>current;
|
||||
this.previous = ()=>previous;
|
||||
this.set = function(a){ previous = current; current = a; return}
|
||||
})();
|
||||
|
||||
|
||||
|
||||
let pointer = 0;
|
||||
let token = "";
|
||||
|
||||
const selectorToClassMap = new Map([
|
||||
[":","pseudo"],
|
||||
["#","id"],
|
||||
[".","class"],
|
||||
["[","attribute"]]);
|
||||
|
||||
this.parse = function(info,appendMode){
|
||||
|
||||
const targetNode = document.getElementById("previewBox");
|
||||
|
||||
!appendMode && clearCodeBlock();
|
||||
|
||||
let node = document.createElement("div");
|
||||
node.setAttribute("data-filename",info.file);
|
||||
|
||||
function createNewRuleset(){
|
||||
let ruleset = document.createElement("span");
|
||||
ruleset.className = "ruleset";
|
||||
node.appendChild(ruleset);
|
||||
return ruleset
|
||||
}
|
||||
|
||||
let rulesetUnderConstruction = createNewRuleset();
|
||||
|
||||
function createElementFromToken(type,c){
|
||||
if(token.length === 0 && !c){
|
||||
return
|
||||
}
|
||||
let n = document.createElement("span");
|
||||
|
||||
switch(type){
|
||||
case "selector":
|
||||
// This isn't exactly correct, but it works because parser treats \r\n sequences that follow a closed comment as "selector"
|
||||
rulesetUnderConstruction = createNewRuleset();
|
||||
let parts = token.split(/([\.#:\[]\w[\w-_"'=\]]*|\s\w[\w-_"'=\]]*)/);
|
||||
|
||||
for(let part of parts){
|
||||
if(part.length === 0){
|
||||
continue
|
||||
}
|
||||
let c = part[0];
|
||||
switch (c){
|
||||
case ":":
|
||||
case "#":
|
||||
case "[":
|
||||
case ".":
|
||||
let p = n.appendChild(document.createElement("span"));
|
||||
p.className = selectorToClassMap.get(c);
|
||||
p.textContent = part;
|
||||
break;
|
||||
default:
|
||||
n.append(part);
|
||||
}
|
||||
}
|
||||
break
|
||||
case "comment":
|
||||
let linksToFile = token.match(/[\w-\.]+\.css/g);
|
||||
if(linksToFile && linksToFile.length){
|
||||
let linkIdx = 0;
|
||||
let fromIdx = 0;
|
||||
while(linkIdx < linksToFile.length){
|
||||
let part = linksToFile[linkIdx++];
|
||||
let idx = token.indexOf(part);
|
||||
n.append(token.substring(fromIdx,idx));
|
||||
let link = document.createElement("a");
|
||||
link.textContent = part;
|
||||
link.href = `https://github.com/MrOtherGuy/firefox-csshacks/tree/master/chrome/${part}`;
|
||||
link.target = "_blank";
|
||||
n.appendChild(link);
|
||||
fromIdx = idx + part.length;
|
||||
}
|
||||
n.append(token.substring(fromIdx));
|
||||
}else{
|
||||
n.textContent = c || token;
|
||||
}
|
||||
break;
|
||||
case "value":
|
||||
let startImportant = token.indexOf("!");
|
||||
if(startImportant === -1){
|
||||
n.textContent = c || token;
|
||||
}else{
|
||||
n.textContent = token.substr(0,startImportant);
|
||||
let importantTag = document.createElement("span");
|
||||
importantTag.className = "important-tag";
|
||||
importantTag.textContent = "!important";
|
||||
n.appendChild(importantTag);
|
||||
if(token.length > (9 + startImportant)){
|
||||
n.append(";")
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "function":
|
||||
n.textContent = c || token.slice(0,-1);
|
||||
break
|
||||
default:
|
||||
n.textContent = c || token;
|
||||
}
|
||||
|
||||
n.className = (`token ${type}`);
|
||||
token = "";
|
||||
rulesetUnderConstruction.appendChild(n);
|
||||
return
|
||||
}
|
||||
|
||||
let c;
|
||||
let functionValueLevel = 0;
|
||||
let curly = false;
|
||||
|
||||
while(pointer < info.content.length){
|
||||
c = info.content[pointer];
|
||||
|
||||
const currentState = state.now();
|
||||
curly = currentState != 2 && (c === "{" || c === "}");
|
||||
if(!curly){
|
||||
token+=c;
|
||||
}
|
||||
switch(currentState){
|
||||
|
||||
case 0:
|
||||
switch(c){
|
||||
case "/":
|
||||
if(info.content[pointer+1] === "*"){
|
||||
state.set(2);
|
||||
if(token.length > 1){
|
||||
token = token.slice(0,-1);
|
||||
createElementFromToken("selector");
|
||||
token += "/"
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "{":
|
||||
state.set(3);
|
||||
createElementFromToken("selector");
|
||||
break;
|
||||
case "}":
|
||||
createElementFromToken("text");
|
||||
break;
|
||||
case "@":
|
||||
state.set(5);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 2:
|
||||
switch(c){
|
||||
case "*":
|
||||
if(info.content[pointer+1] === "/"){
|
||||
token += "/";
|
||||
pointer++;
|
||||
state.set(state.previous());
|
||||
createElementFromToken("comment");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
switch(c){
|
||||
case "/":
|
||||
if(info.content[pointer+1] === "*"){
|
||||
state.set(2);
|
||||
}
|
||||
break;
|
||||
case ":":
|
||||
createElementFromToken("property");
|
||||
state.set(4);
|
||||
break;
|
||||
case "}":
|
||||
createElementFromToken("text");
|
||||
state.set(0);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
switch(c){
|
||||
case ";":
|
||||
createElementFromToken("value");
|
||||
state.set(3);
|
||||
break;
|
||||
case "}":
|
||||
createElementFromToken("value");
|
||||
state.set(0);
|
||||
break;
|
||||
case "(":
|
||||
createElementFromToken("value");
|
||||
functionValueLevel++;
|
||||
state.set(7);
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
switch(c){
|
||||
case " ":
|
||||
createElementFromToken("atrule");
|
||||
state.set(6);
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
switch(c){
|
||||
case ";":
|
||||
case "{":
|
||||
createElementFromToken("atvalue");
|
||||
state.set(0);
|
||||
}
|
||||
break
|
||||
case 7:
|
||||
switch(c){
|
||||
case ")":
|
||||
functionValueLevel--;
|
||||
if(functionValueLevel === 0){
|
||||
createElementFromToken("function");
|
||||
token = ")";
|
||||
state.set(4);
|
||||
}
|
||||
break;
|
||||
case "}":
|
||||
functionValueLevel = 0;
|
||||
state.set(0)
|
||||
}
|
||||
default:
|
||||
false
|
||||
}
|
||||
|
||||
curly && createElementFromToken("curly",c);
|
||||
|
||||
pointer++
|
||||
}
|
||||
createElementFromToken("text");
|
||||
token = "";
|
||||
state.set(0);
|
||||
pointer = 0;
|
||||
|
||||
if(info.file.endsWith("support.css")){
|
||||
targetNode.prepend(node);
|
||||
}else{
|
||||
targetNode.appendChild(node);
|
||||
}
|
||||
return
|
||||
}
|
||||
return this
|
||||
})();
|
||||
|
||||
async function handleSearchQuery(){
|
||||
let params = (new URL(document.location)).searchParams;
|
||||
let param = params.get("tag");
|
||||
@@ -579,7 +332,7 @@ async function handleSearchQuery(){
|
||||
param = params.get("file");
|
||||
if(param){
|
||||
let files = param.split(",").filter(a => DB.keys.includes(a));
|
||||
|
||||
let box = document.getElementById("previewBox");
|
||||
if(files.length === 0 ){
|
||||
return
|
||||
}
|
||||
@@ -589,7 +342,10 @@ async function handleSearchQuery(){
|
||||
Promise.all(promises)
|
||||
.then(responses => {
|
||||
showMatchingTargets(files,true);
|
||||
responses.forEach(Highlighter.parse)
|
||||
responses.forEach((res)=>{
|
||||
res.insertMode = res.file.endsWith("window_control_placeholder_support.css") ? box.InsertModes.Prepend : box.InsertModes.AppendLines;
|
||||
box.insertContent(res)
|
||||
})
|
||||
});
|
||||
|
||||
}
|
||||
@@ -611,8 +367,8 @@ document.onreadystatechange = (function () {
|
||||
|
||||
if (document.readyState === "complete") {
|
||||
function linkClicked(ev){
|
||||
if(ev.target instanceof HTMLAnchorElement){
|
||||
let ref = ev.target.href;
|
||||
if(ev.originalTarget instanceof HTMLAnchorElement){
|
||||
let ref = ev.originalTarget.href;
|
||||
if(!ref){
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user