Compare commits
10 Commits
92fc3dd021
...
f7276dcb3d
Author | SHA1 | Date |
---|---|---|
Sage Vaillancourt | f7276dcb3d | |
Sage Vaillancourt | de342265b1 | |
Sage Vaillancourt | 46b873e71d | |
Sage Vaillancourt | ab9f6641f4 | |
Sage Vaillancourt | e71e2fb699 | |
Sage Vaillancourt | 8cdcfac87d | |
Sage Vaillancourt | 62ade8de28 | |
Sage Vaillancourt | be9719be8c | |
Sage Vaillancourt | 22079471bc | |
Sage Vaillancourt | bee9f4e2b2 |
2
Makefile
2
Makefile
|
@ -1,4 +1,4 @@
|
||||||
bitbucket-fork-redirect.zip: *.json *.js img/* *.md *.txt
|
all: *.json *.js img/* *.md *.txt
|
||||||
zip -r bitbucket-fork-redirect.zip * -x .git/* -x img/screenshot.png -x .gitignore -x Makefile
|
zip -r bitbucket-fork-redirect.zip * -x .git/* -x img/screenshot.png -x .gitignore -x Makefile
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
|
|
@ -44,24 +44,24 @@ const keywordMap = {
|
||||||
|
|
||||||
const bookendedWith = (text, bookend) => text.startsWith(bookend) && text.endsWith(bookend)
|
const bookendedWith = (text, bookend) => text.startsWith(bookend) && text.endsWith(bookend)
|
||||||
|
|
||||||
const getClass = (text, keywords) => {
|
const getClass = (text, prefix, keywords) => {
|
||||||
if (keywords.has(text)) {
|
if (keywords.has(text)) {
|
||||||
return 'hl-keyword'
|
return prefix + 'keyword'
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bookendedWith(text, '"')) {
|
if (bookendedWith(text, '"')) {
|
||||||
return 'hl-string'
|
return prefix + 'string'
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'hl-variable'
|
return prefix + 'variable'
|
||||||
}
|
}
|
||||||
|
|
||||||
const getKeywords = () => keywordMap[getFileName().replace(/.*\./g, '')] || keywordMap.none
|
const getKeywords = () => keywordMap[getFileName()?.replace(/.*\./g, '')] || keywordMap.none
|
||||||
|
|
||||||
const commentSpan = innerText => {
|
const commentSpan = (innerText, prefix) => {
|
||||||
const span = document.createElement('span')
|
const span = document.createElement('span')
|
||||||
span.innerText = innerText
|
span.innerText = innerText
|
||||||
span.classList.add('hl-comment')
|
span.classList.add(prefix + 'comment')
|
||||||
return span
|
return span
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,24 +69,29 @@ const colorCodeInComment = (codeStart = '`', codeEnd) => {
|
||||||
codeEnd ??= codeStart
|
codeEnd ??= codeStart
|
||||||
const processed = new Set()
|
const processed = new Set()
|
||||||
const keywords = getKeywords()
|
const keywords = getKeywords()
|
||||||
getClassNameElementsArray('hl-comment').forEach(element => {
|
const comments = [...getClassNameElementsArray('hl-comment'), ...getClassNameElementsArray('cm-comment')]
|
||||||
if (!element.innerText?.startsWith(codeStart) || processed.has(element)) {
|
comments.forEach(element => {
|
||||||
|
const codeStartIndex = element.innerText?.indexOf(codeStart)
|
||||||
|
if (codeStartIndex === -1 || processed.has(element)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const codeStartElement = commentSpan(codeStart)
|
const prefix = element.classList.contains('hl-comment') ? 'hl-' : 'cm-'
|
||||||
|
const endOfCodeStart = codeStartIndex + codeStart.length
|
||||||
|
const codeStartText = element.innerText.substring(0, endOfCodeStart)
|
||||||
|
const codeStartElement = commentSpan(codeStartText, prefix)
|
||||||
|
element.innerText = element.innerText.substring(endOfCodeStart, element.innerText.length)
|
||||||
element.replaceWith(codeStartElement, element)
|
element.replaceWith(codeStartElement, element)
|
||||||
element.innerText = element.innerText.replace(codeStart, '')
|
|
||||||
while (element) {
|
while (element) {
|
||||||
if (!element.classList.contains('hl-comment')) {
|
if (!element.classList.contains('hl-comment') && !element.classList.contains('cm-comment')) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
processed.add(element)
|
processed.add(element)
|
||||||
element.classList.remove('hl-comment')
|
element.classList.remove(`${prefix}comment`)
|
||||||
const text = element.innerText.replaceAll(codeStart, '').replaceAll(codeEnd, '')
|
const text = element.innerText.replaceAll(codeStart, '').replaceAll(codeEnd, '')
|
||||||
element.classList.add(getClass(text, keywords))
|
element.classList.add(getClass(text, prefix, keywords))
|
||||||
const codeEndIndex = element.innerText.indexOf(codeEnd)
|
const codeEndIndex = element.innerText.indexOf(codeEnd)
|
||||||
if (codeEndIndex > -1) {
|
if (codeEndIndex > -1) {
|
||||||
const codeEndElement = commentSpan(element.innerText.substring(codeEndIndex))
|
const codeEndElement = commentSpan(element.innerText.substring(codeEndIndex), prefix)
|
||||||
element.innerText = element.innerText.substring(0, codeEndIndex)
|
element.innerText = element.innerText.substring(0, codeEndIndex)
|
||||||
element.replaceWith(element, codeEndElement)
|
element.replaceWith(element, codeEndElement)
|
||||||
break
|
break
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const fixCSharpStrings = () => {
|
const fixCSharpStrings = () => {
|
||||||
const hasCSharpFileName = getFileName().endsWith('.cs')
|
const hasCSharpFileName = getFileName()?.endsWith('.cs')
|
||||||
if (!hasCSharpFileName) {
|
if (!hasCSharpFileName) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
const getChangeHeader = () => getClassNameElementsArray('change-header')[0]
|
||||||
|
|
||||||
|
const getFileElements = () => querySelectorAllArray('.file,.icon-folder-closed')
|
||||||
|
|
||||||
|
const getSelectedFile = () => getClassNameElementsArray('file-selected')[0]
|
||||||
|
|
||||||
|
const addScrollHints = () => {
|
||||||
|
getClassNameElementsArray('sages-extra-breadcrumbs').forEach(e => e.parentNode.removeChild(e))
|
||||||
|
const buildHint = (fileElement, prefix, top) => {
|
||||||
|
const hint = document.createElement('div', {})
|
||||||
|
hint.classList.add('sages-extra-breadcrumbs')
|
||||||
|
if (fileElement.classList.contains('file-viewed')) {
|
||||||
|
hint.classList.add('sages-extra-breadcrumbs-viewed')
|
||||||
|
}
|
||||||
|
hint.innerText = `${prefix} ${decodeURIComponent(fileElement.firstElementChild?.href?.split('#')[1] || 'In Folder...')}`
|
||||||
|
if (top) {
|
||||||
|
hint.style.top = top
|
||||||
|
}
|
||||||
|
return hint;
|
||||||
|
}
|
||||||
|
const selectedFile = getSelectedFile()
|
||||||
|
const fileElements = getFileElements()
|
||||||
|
const index = fileElements.indexOf(selectedFile)
|
||||||
|
const breadcrumbs = Array.from(getChangeHeader().getElementsByTagName('h4'))[0]
|
||||||
|
console.log({ breadcrumbs })
|
||||||
|
if (index > 0) {
|
||||||
|
breadcrumbs.prepend(buildHint(fileElements[index - 1], 'Prev:', '1.4em'))
|
||||||
|
}
|
||||||
|
if (index < fileElements.length - 1) {
|
||||||
|
breadcrumbs.appendChild(buildHint(fileElements[index + 1], 'Next:'))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const changeFile = (e, noRecurse) => {
|
||||||
|
const selectedFile = getSelectedFile()
|
||||||
|
const fileElements = getFileElements()
|
||||||
|
|
||||||
|
const up = e.wheelDelta ? e.wheelDelta > 0 : e.deltaY < 0
|
||||||
|
const index = fileElements.indexOf(selectedFile)
|
||||||
|
const nextElement =
|
||||||
|
(up && index > 0) ? fileElements[index - 1] :
|
||||||
|
(!up && index < (fileElements.length - 1)) ? fileElements[index + 1] :
|
||||||
|
null
|
||||||
|
const isFolder = !nextElement?.firstElementChild
|
||||||
|
const toClick = nextElement?.firstElementChild ?? nextElement
|
||||||
|
toClick?.focus()
|
||||||
|
toClick?.click()
|
||||||
|
if (isFolder) {
|
||||||
|
changeFile(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let styled = false
|
||||||
|
addFix(() => {
|
||||||
|
const header = getChangeHeader()
|
||||||
|
header.onwheel = changeFile
|
||||||
|
styled || addStyle(`
|
||||||
|
.sages-extra-breadcrumbs {
|
||||||
|
color: rgba(0, 0, 0, 0) !important;
|
||||||
|
margin-top: -1.6em !important;
|
||||||
|
/*margin-bottom: -1em !important;*/
|
||||||
|
float: left !important;
|
||||||
|
position: absolute;
|
||||||
|
font-size: 11px;
|
||||||
|
margin-left: 20%;
|
||||||
|
}
|
||||||
|
.diff-meta:hover h4 .sages-extra-breadcrumbs {
|
||||||
|
color: rgba(0, 0, 0, 0.35) !important;
|
||||||
|
}
|
||||||
|
.diff-meta:hover h4 .sages-extra-breadcrumbs-viewed {
|
||||||
|
color: rgba(0, 0, 0, 0.2) !important;
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
styled = true
|
||||||
|
})
|
||||||
|
|
||||||
|
window.addEventListener('load', () => setTimeout(addScrollHints, NEW_PAGE_DELAY))
|
||||||
|
addEventListener('hashchange', () => setTimeout(addScrollHints, 200))
|
|
@ -1,11 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "ADD Git NoFork",
|
"name": "Sage's BitBucket Addon",
|
||||||
"description": "Ensure searches don't include forks",
|
"description": "Ensure searches don't include forks (and other enhancements)",
|
||||||
"version": "1.0.2",
|
"version": "1.0.13",
|
||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
"browser_specific_settings": {
|
"browser_specific_settings": {
|
||||||
"gecko": {
|
"gecko": {
|
||||||
"id": "svaillancourt@add123.com"
|
"id": "svaillancourt@add123.com",
|
||||||
|
"update_url": "https://bb-addon.sagev.space/updates.json"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"background": {
|
"background": {
|
||||||
|
@ -25,8 +26,11 @@
|
||||||
"matches": ["*://git.add123.com/*"],
|
"matches": ["*://git.add123.com/*"],
|
||||||
"js": [
|
"js": [
|
||||||
"utils.js",
|
"utils.js",
|
||||||
"csharp-quotes.js",
|
"all-ADD-repos.js",
|
||||||
"backtick-comments.js",
|
"backtick-comments.js",
|
||||||
|
"csharp-quotes.js",
|
||||||
|
"file-scroll.js",
|
||||||
|
"repo-search-sorter.js",
|
||||||
"var-highlighter.js"
|
"var-highlighter.js"
|
||||||
],
|
],
|
||||||
"run_at": "document_start"
|
"run_at": "document_start"
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
const compareResults = currentUser => (a, b) => {
|
||||||
|
return ['/projects/', currentUser]
|
||||||
|
.some(href => a.children[0].href.includes(href)) ? -1 : 1
|
||||||
|
}
|
||||||
|
|
||||||
|
const sortChildren = ol => {
|
||||||
|
const children = Array.from(ol.children)
|
||||||
|
children.forEach(child => ol.removeChild(child))
|
||||||
|
children
|
||||||
|
.sort(compareResults(getCurrentUser()))
|
||||||
|
.forEach(child => ol.appendChild(child))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Re-order the search results to list projects and the current user first
|
||||||
|
let claim = 0
|
||||||
|
const sortSearchResult = () => {
|
||||||
|
const searchBox = Array.from(document.getElementsByTagName('input'))
|
||||||
|
.filter(input => input.name === 'repository-search')[0]
|
||||||
|
if (!searchBox) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
searchBox.onkeyup = e => {
|
||||||
|
claim++
|
||||||
|
const myClaim = claim
|
||||||
|
setTimeout(() => {
|
||||||
|
if (claim !== myClaim) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const ol = getClassNameElementsArray('search-results')[0]?.firstChild
|
||||||
|
sortChildren(ol)
|
||||||
|
claim = 0
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addFix(sortSearchResult)
|
17
utils.js
17
utils.js
|
@ -2,12 +2,25 @@ const NEW_PAGE_DELAY = 1000
|
||||||
const CURRENT_PAGE_DELAY = 300
|
const CURRENT_PAGE_DELAY = 300
|
||||||
|
|
||||||
const getClassNameElementsArray = className =>
|
const getClassNameElementsArray = className =>
|
||||||
Object.values(document.getElementsByClassName(className))
|
Array.from(document.getElementsByClassName(className))
|
||||||
|
|
||||||
// Runs on "complete" load and when https://urlurl.url#this-hash-value changes
|
const querySelectorAllArray = selector =>
|
||||||
|
Array.from(document.querySelectorAll(selector))
|
||||||
|
|
||||||
|
/// Runs on "complete" load and when `https://website.tld#this-hash-value` changes
|
||||||
const addFix = fixFunc => {
|
const addFix = fixFunc => {
|
||||||
window.addEventListener('load', () => setTimeout(fixFunc, NEW_PAGE_DELAY))
|
window.addEventListener('load', () => setTimeout(fixFunc, NEW_PAGE_DELAY))
|
||||||
addEventListener('hashchange', () => setTimeout(fixFunc, CURRENT_PAGE_DELAY))
|
addEventListener('hashchange', () => setTimeout(fixFunc, CURRENT_PAGE_DELAY))
|
||||||
}
|
}
|
||||||
|
|
||||||
const getFileName = () => getClassNameElementsArray('file-breadcrumbs-segment-highlighted').map(e => e.innerText)[0]
|
const getFileName = () => getClassNameElementsArray('file-breadcrumbs-segment-highlighted').map(e => e.innerText)[0]
|
||||||
|
|
||||||
|
const getCurrentUser = () => {
|
||||||
|
return getClassNameElementsArray("user-dropdown-trigger")[0].title.replace(/(.*\()|\)/g, '')
|
||||||
|
}
|
||||||
|
|
||||||
|
const addStyle = css => {
|
||||||
|
const styleElement = document.createElement('style')
|
||||||
|
styleElement.innerText = css.replaceAll("\n", " ")
|
||||||
|
document.head.appendChild(styleElement)
|
||||||
|
}
|
||||||
|
|
|
@ -1,29 +1,44 @@
|
||||||
const getVarElements = () => [
|
const getVarElements = () => [
|
||||||
...getClassNameElementsArray('hl-variable'),
|
...getClassNameElementsArray('hl-variable'),
|
||||||
|
...getClassNameElementsArray('hl-variable-2'),
|
||||||
...getClassNameElementsArray('hl-def'),
|
...getClassNameElementsArray('hl-def'),
|
||||||
|
...getClassNameElementsArray('hl-attribute'),
|
||||||
|
...getClassNameElementsArray('hl-property'),
|
||||||
|
...getClassNameElementsArray('hl-tag'),
|
||||||
|
...getClassNameElementsArray('hl-string'),
|
||||||
|
...getClassNameElementsArray('hl-string-2'),
|
||||||
...getClassNameElementsArray('hl-type')
|
...getClassNameElementsArray('hl-type')
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const selectedClass = 'sages-selected-variable'
|
||||||
|
|
||||||
let currentSelected
|
let currentSelected
|
||||||
|
|
||||||
|
const cleanVarName = varName => {
|
||||||
|
if (varName.startsWith('/') && varName.endsWith('>')) {
|
||||||
|
varName = varName.substring(1, varName.length - 1)
|
||||||
|
}
|
||||||
|
varName = varName.replaceAll('"', "'")
|
||||||
|
return varName
|
||||||
|
}
|
||||||
|
|
||||||
const selectVar = varName => {
|
const selectVar = varName => {
|
||||||
if (!varName) {
|
if (!varName) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
varName = cleanVarName(varName)
|
||||||
// Clear existing colors
|
// Clear existing colors
|
||||||
getClassNameElementsArray(selectedClass)
|
getClassNameElementsArray(selectedClass)
|
||||||
.forEach(e => e.classList.remove(selectedClass))
|
.forEach(e => e.classList.remove(selectedClass))
|
||||||
|
|
||||||
// Color vars with matching text
|
// Color vars with matching text
|
||||||
getVarElements()
|
getVarElements()
|
||||||
.filter(e => e.innerText === varName)
|
.filter(e => cleanVarName(e.innerText) === varName)
|
||||||
.forEach(e => e.classList.add(selectedClass))
|
.forEach(e => e.classList.add(selectedClass))
|
||||||
|
|
||||||
currentSelected = varName
|
currentSelected = varName
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectedClass = 'sages-selected-variable'
|
|
||||||
|
|
||||||
const getTagMatching = (name, matcher) => {
|
const getTagMatching = (name, matcher) => {
|
||||||
const elements = Object.values(document.getElementsByTagName(name)).filter(matcher)
|
const elements = Object.values(document.getElementsByTagName(name)).filter(matcher)
|
||||||
return elements.length ? elements[0] : null
|
return elements.length ? elements[0] : null
|
||||||
|
|
Loading…
Reference in New Issue