diff --git a/app/components/CodeIntelStatusIndicator.tsx b/app/components/CodeIntelStatusIndicator.tsx index cc140e10..15d98211 100644 --- a/app/components/CodeIntelStatusIndicator.tsx +++ b/app/components/CodeIntelStatusIndicator.tsx @@ -213,7 +213,7 @@ export class CodeIntelStatusIndicator extends React.Component< <>
- Manage + + Manage +
)} {this.state.langServerOrError.issuesURL && ( )}
caught))
),
makeRepoURI
diff --git a/app/repo/index.tsx b/app/repo/index.tsx
index 05a901a4..b52f2789 100644
--- a/app/repo/index.tsx
+++ b/app/repo/index.tsx
@@ -300,6 +300,25 @@ export function makeRepoURI(parsed: ParsedRepoURI): RepoURI {
return uri
}
+export function normalizeRepoPath(origin: string): string {
+ let repoPath = origin
+ repoPath = repoPath.replace('\\', '')
+ if (origin.startsWith('git@')) {
+ repoPath = origin.substr('git@'.length)
+ repoPath = repoPath.replace(':', '/')
+ } else if (origin.startsWith('git://')) {
+ repoPath = origin.substr('git://'.length)
+ } else if (origin.startsWith('https://')) {
+ repoPath = origin.substr('https://'.length)
+ } else if (origin.includes('@')) {
+ // Assume the origin looks like `username@host:repo/path`
+ const split = origin.split('@')
+ repoPath = split[1]
+ repoPath = repoPath.replace(':', '/')
+ }
+ return repoPath.replace(/.git$/, '')
+}
+
/**
* A file at an exact commit of a known programming language
*/
diff --git a/app/review-board/backend/fetch.ts b/app/review-board/backend/fetch.ts
new file mode 100644
index 00000000..ac7bbf4a
--- /dev/null
+++ b/app/review-board/backend/fetch.ts
@@ -0,0 +1,19 @@
+import { from, Observable } from 'rxjs'
+import { ReviewBoardRepository } from '../util'
+
+function getRepository(repoID: number): Promise` element for a target that contains the code
+ */
+const getCodeCellFromTarget = (target: HTMLElement): HTMLElement | null => {
+ if (target.nodeName === 'PRE') {
+ return null
+ }
+ const pre = target.closest('pre') as HTMLElement
+ if (!pre) {
+ return null
+ }
+ if (target.innerText.trim().length === 0) {
+ return null
+ }
+ const closest = (target.closest('.l') || target.closest('.r')) as HTMLElement
+ if (!closest.classList.contains('trimmed') && closest.classList.contains('annotated')) {
+ const firstChild = closest.firstElementChild
+ if (
+ firstChild &&
+ firstChild.nodeName === 'SPAN' &&
+ firstChild.textContent &&
+ firstChild.innerHTML.trim().length === 0
+ ) {
+ const newElement = document.createElement('span')
+ newElement.innerHTML = ' '
+ closest.replaceChild(newElement, firstChild)
+ }
+ closest.classList.add('trimmed')
+ }
+ return closest
+}
+
+const getBlobCodeInner = (codeCell: HTMLElement) => {
+ if (codeCell.classList.contains('l') || codeCell.classList.contains('r')) {
+ return codeCell
+ }
+ return (codeCell.closest('.l') || codeCell.closest('.r')) as HTMLElement
+}
+
+/**
+ * Gets the line number for a given code element on unified diff, split diff and blob views
+ */
+const getLineNumberFromCodeElement = (codeElement: HTMLElement): number => {
+ // In diff views, the code element is the `` inside the cell
+ // On blob views, the code element is the ` ` itself, so `closest()` will simply return it
+ // Walk all previous sibling cells until we find one with the line number
+ let cell = codeElement.closest('td') as HTMLElement
+ while (cell) {
+ if (cell.nodeName === 'TH') {
+ return parseInt(cell.innerText, 10)
+ }
+ cell = cell.previousElementSibling as HTMLTableRowElement
+ }
+
+ cell = codeElement.closest('tr')! as HTMLTableRowElement
+ if (cell.getAttribute('line')) {
+ return parseInt(cell.getAttribute('line')!, 10)
+ }
+ throw new Error('Could not find a line number in any cell')
+}
+
+/**
+ * getDeltaFileName returns the path of the file container. Reviewboard will always be a diff.
+ */
+export function getDeltaFileName(container: HTMLElement): { headFilePath: string; baseFilePath: string } {
+ const info = container.querySelector('.filename-row') as HTMLElement
+ if (!info) {
+ throw new Error(`Unable to getDeltaFileName for container: ${container}`)
+ }
+ return { headFilePath: info.innerText, baseFilePath: info.innerText }
+}
+
+const getDiffCodePart = (codeElement: HTMLElement): DiffPart => {
+ const td = codeElement.closest('td')!
+ // If there are more cells on the right, this is the base, otherwise the head
+ return td.classList.contains('l') ? 'base' : 'head'
+}
+
+/**
+ * Implementations of the DOM functions for diff code views
+ */
+export const diffDomFunctions: DOMFunctions = {
+ getCodeElementFromTarget: target => {
+ const codeCell = getCodeCellFromTarget(target)
+ return codeCell && getBlobCodeInner(codeCell)
+ },
+ getCodeElementFromLineNumber: () => null,
+ getLineNumberFromCodeElement,
+ getDiffCodePart,
+}
+
+/**
+ * createBlobAnnotatorMount creates a