Now a bitbucket addon.

Performs some simple UI enhancements.
This commit is contained in:
Sage Vaillancourt 2023-02-02 14:36:40 -05:00
parent 577073326a
commit 92fc3dd021
9 changed files with 260 additions and 42 deletions

View File

@ -1,5 +1,5 @@
old-reddit-redirect.zip: *.json *.js img/* *.md *.txt
zip -r old-reddit-redirect.zip * -x .git/* -x img/screenshot.png -x .gitignore -x Makefile
bitbucket-fork-redirect.zip: *.json *.js img/* *.md *.txt
zip -r bitbucket-fork-redirect.zip * -x .git/* -x img/screenshot.png -x .gitignore -x Makefile
clean:
rm *.zip

View File

@ -1,36 +1,14 @@
const oldReddit = "https://old.reddit.com";
const excludedPaths = [
"/poll",
"/rpan",
"/settings",
"/topics",
"/community-points",
];
chrome.webRequest.onBeforeRequest.addListener(details => {
const url = new URL(details.url)
chrome.webRequest.onBeforeRequest.addListener(
function (details) {
const url = new URL(details.url);
if (url.hostname !== "git.add123.com") return
if (!url.pathname.endsWith("plugins/servlet/search")) return
if (details.url.includes("fork:") || details.url.includes("fork%3A")) return
if (url.hostname === "old.reddit.com") return;
for (const path of excludedPaths) {
if (url.pathname.indexOf(path) === 0) return;
}
if (url.pathname.indexOf("/gallery") === 0) {
return { redirectUrl: oldReddit + '/comments' + url.pathname.slice("/gallery".length) };
}
return { redirectUrl: oldReddit + url.pathname + url.search + url.hash };
return { redirectUrl: `${details.url}%20fork%3Afalse` }
},
{
urls: [
"*://reddit.com/*",
"*://www.reddit.com/*",
"*://np.reddit.com/*",
"*://amp.reddit.com/*",
"*://i.reddit.com/*",
],
urls: [ "https://git.add123.com/*" ],
types: [
"main_frame",
"sub_frame",
@ -43,4 +21,4 @@ chrome.webRequest.onBeforeRequest.addListener(
],
},
["blocking"]
);
)

107
backtick-comments.js Normal file
View File

@ -0,0 +1,107 @@
const jsKeywords = new Set([
"abstract", "arguments", "await*", "boolean", "break", "byte", "case",
"catch", "char", "class*", "const", "continue", "debugger", "default",
"delete", "do", "double", "else", "enum*", "eval", "export*", "extends*",
"false", "final", "finally", "float", "for", "function", "goto", "if",
"implements", "import*", "in", "instanceof", "int", "interface", "let*",
"long", "native", "new", "null", "package", "private", "protected", "public",
"return", "short", "static", "super*", "switch", "synchronized", "this",
"throw", "throws", "transient", "true", "try", "typeof", "var", "void",
"volatile", "while", "with", "yield"
])
const csKeywords = new Set([
"abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char",
"checked", "class", "const", "continue", "decimal", "default", "delegate",
"do", "double", "else", "enum", "event", "explicit", "extern", "false",
"finally", "fixed", "float", "for", "foreach", "goto", "if", "implicit",
"in", "int", "interface", "internal", "is", "lock", "long", "namespace",
"new", "null", "object", "operator", "out", "override", "params", "private",
"protected", "public", "readonly", "ref", "return", "sbyte", "sealed",
"short", "sizeof", "stackalloc", "static", "string", "struct", "switch",
"this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked",
"unsafe", "ushort", "using", "virtual", "void", "volatile", "while",
])
const javaKeywords = new Set([
"abstract", "continue", "for", "new", "switch", "assert", "default",
"goto", "package", "synchronized", "boolean", "do", "if", "private",
"this", "break", "double", "implements", "protected", "throw", "byte",
"else", "import", "public", "throws", "case", "enum", "instanceof",
"return", "transient", "catch", "extends", "int", "short", "try", "char",
"final", "interface", "static", "void", "class", "finally", "long",
"strictfp", "volatile", "const", "float", "native", "super", "while",
])
const keywordMap = {
js: jsKeywords,
mjs: jsKeywords,
java: javaKeywords,
cs: csKeywords,
none: new Set()
}
const bookendedWith = (text, bookend) => text.startsWith(bookend) && text.endsWith(bookend)
const getClass = (text, keywords) => {
if (keywords.has(text)) {
return 'hl-keyword'
}
if (bookendedWith(text, '"')) {
return 'hl-string'
}
return 'hl-variable'
}
const getKeywords = () => keywordMap[getFileName().replace(/.*\./g, '')] || keywordMap.none
const commentSpan = innerText => {
const span = document.createElement('span')
span.innerText = innerText
span.classList.add('hl-comment')
return span
}
const colorCodeInComment = (codeStart = '`', codeEnd) => {
codeEnd ??= codeStart
const processed = new Set()
const keywords = getKeywords()
getClassNameElementsArray('hl-comment').forEach(element => {
if (!element.innerText?.startsWith(codeStart) || processed.has(element)) {
return
}
const codeStartElement = commentSpan(codeStart)
element.replaceWith(codeStartElement, element)
element.innerText = element.innerText.replace(codeStart, '')
while (element) {
if (!element.classList.contains('hl-comment')) {
break
}
processed.add(element)
element.classList.remove('hl-comment')
const text = element.innerText.replaceAll(codeStart, '').replaceAll(codeEnd, '')
element.classList.add(getClass(text, keywords))
const codeEndIndex = element.innerText.indexOf(codeEnd)
if (codeEndIndex > -1) {
const codeEndElement = commentSpan(element.innerText.substring(codeEndIndex))
element.innerText = element.innerText.substring(0, codeEndIndex)
element.replaceWith(element, codeEndElement)
break
}
element = element.nextElementSibling
}
})
}
const commentCodeFix = () => {
colorCodeInComment('`', '`')
colorCodeInComment('<code>', '</code>')
colorCodeInComment('<pre>', '</pre>')
colorCodeInComment('<tt>', '</tt>')
}
addFix(commentCodeFix)

17
csharp-quotes.js Normal file
View File

@ -0,0 +1,17 @@
const fixCSharpStrings = () => {
const hasCSharpFileName = getFileName().endsWith('.cs')
if (!hasCSharpFileName) {
return
}
getClassNameElementsArray('hl-string')
.filter(e => e.innerText.includes('@"') || e.innerText.includes('@$""'))
.forEach(e => {
const s = e.innerHTML
const firstQuote = s.indexOf('"') + 1
const spanned = s.substring(firstQuote, s.length - 1).replaceAll('""', '<span class="hl-def">""</span>')
e.innerHTML = s.substring(0, firstQuote) + spanned + '"'
})
}
addFix(fixCSharpStrings)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -1,27 +1,41 @@
{
"name": "Old Reddit Redirect",
"description": "Ensure Reddit always loads the old design",
"version": "1.6.1",
"name": "ADD Git NoFork",
"description": "Ensure searches don't include forks",
"version": "1.0.2",
"manifest_version": 2,
"background": { "scripts": ["background.js"] },
"browser_specific_settings": {
"gecko": {
"id": "svaillancourt@add123.com"
}
},
"background": {
"scripts": ["background.js"]
},
"icons": {
"48": "img/icon48.png",
"128": "img/icon128.png"
},
"content_scripts": [
{
"matches": ["*://old.reddit.com/*"],
"matches": ["*://git.add123.com/*"],
"css": ["styles.css"],
"run_at": "document_start"
},
{
"matches": ["*://git.add123.com/*"],
"js": [
"utils.js",
"csharp-quotes.js",
"backtick-comments.js",
"var-highlighter.js"
],
"run_at": "document_start"
}
],
"permissions": [
"activeTab",
"webRequest",
"webRequestBlocking",
"*://reddit.com/*",
"*://www.reddit.com/*",
"*://np.reddit.com/*",
"*://amp.reddit.com/*",
"*://i.reddit.com/*"
"*://git.add123.com/*"
]
}

13
utils.js Normal file
View File

@ -0,0 +1,13 @@
const NEW_PAGE_DELAY = 1000
const CURRENT_PAGE_DELAY = 300
const getClassNameElementsArray = className =>
Object.values(document.getElementsByClassName(className))
// Runs on "complete" load and when https://urlurl.url#this-hash-value changes
const addFix = fixFunc => {
window.addEventListener('load', () => setTimeout(fixFunc, NEW_PAGE_DELAY))
addEventListener('hashchange', () => setTimeout(fixFunc, CURRENT_PAGE_DELAY))
}
const getFileName = () => getClassNameElementsArray('file-breadcrumbs-segment-highlighted').map(e => e.innerText)[0]

89
var-highlighter.js Normal file
View File

@ -0,0 +1,89 @@
const getVarElements = () => [
...getClassNameElementsArray('hl-variable'),
...getClassNameElementsArray('hl-def'),
...getClassNameElementsArray('hl-type')
]
let currentSelected
const selectVar = varName => {
if (!varName) {
return
}
// Clear existing colors
getClassNameElementsArray(selectedClass)
.forEach(e => e.classList.remove(selectedClass))
// Color vars with matching text
getVarElements()
.filter(e => e.innerText === varName)
.forEach(e => e.classList.add(selectedClass))
currentSelected = varName
}
const selectedClass = 'sages-selected-variable'
const getTagMatching = (name, matcher) => {
const elements = Object.values(document.getElementsByTagName(name)).filter(matcher)
return elements.length ? elements[0] : null
}
const addVariableClickers = skipExpandos => {
const getSearchButton = () => getTagMatching(
'button', e => e.dataset?.testid === 'search-action-button')
const getSearchBox = () => getTagMatching('input', e => e.name === 'changes-search-input')
if (!skipExpandos) {
getClassNameElementsArray('expand-context-button').forEach(e => {
const currentOnClick = e.onclick
e.onclick = (...args) => {
currentOnClick && currentOnClick(...args)
setTimeout(() => {
selectVar(currentSelected)
addVariableClickers(true)
}, CURRENT_PAGE_DELAY)
}
})
}
getVarElements()
.forEach(e => {
e.onclick = () => selectVar(e.innerText)
e.ondblclick = () => {
let searchBox = getSearchBox()
if (!searchBox) {
getSearchButton()?.click()
searchBox = getSearchBox()
}
searchBox.value = e.innerText
searchBox.dispatchEvent(new window.Event('change', { bubbles: true }))
}
})
}
addFix(() => {
const styleSheet = document.createElement('style')
styleSheet.innerText = `
.${selectedClass} {
background: rgb(255, 253, 170) !important;
border-radius: 3px;
padding: 2px !important;
margin: -2px !important;
/*
padding-left: 2px !important;
padding-right: 2px !important;
margin-left: -2px !important;
margin-right: -2px !important;
*/
}`
document.head.appendChild(styleSheet)
addVariableClickers()
selectVar(currentSelected)
})