BigW Consortium Gitlab
Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
gitlab-ce
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Forest Godfrey
gitlab-ce
Commits
36a917e1
Commit
36a917e1
authored
Sep 22, 2017
by
Fatih Acet
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
RepoEditor: Implement line and range linking.
parent
92173ac5
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
151 additions
and
146 deletions
+151
-146
line_highlighter.js
app/assets/javascripts/line_highlighter.js
+142
-141
repo_preview.vue
app/assets/javascripts/repo/components/repo_preview.vue
+9
-5
No files found.
app/assets/javascripts/line_highlighter.js
View file @
36a917e1
...
...
@@ -28,148 +28,149 @@
// </div>
// </div>
//
(
function
()
{
this
.
LineHighlighter
=
(
function
()
{
// CSS class applied to highlighted lines
LineHighlighter
.
prototype
.
highlightClass
=
'hll'
;
// Internal copy of location.hash so we're not dependent on `location` in tests
LineHighlighter
.
prototype
.
_hash
=
''
;
function
LineHighlighter
(
hash
)
{
if
(
hash
==
null
)
{
// Initialize a LineHighlighter object
//
// hash - String URL hash for dependency injection in tests
hash
=
location
.
hash
;
}
this
.
setHash
=
this
.
setHash
.
bind
(
this
);
this
.
highlightLine
=
this
.
highlightLine
.
bind
(
this
);
this
.
clickHandler
=
this
.
clickHandler
.
bind
(
this
);
this
.
highlightHash
=
this
.
highlightHash
.
bind
(
this
);
this
.
_hash
=
hash
;
this
.
bindEvents
();
this
.
highlightHash
();
}
LineHighlighter
.
prototype
.
bindEvents
=
function
()
{
const
$fileHolder
=
$
(
'.file-holder'
);
$fileHolder
.
on
(
'click'
,
'a[data-line-number]'
,
this
.
clickHandler
);
$fileHolder
.
on
(
'highlight:line'
,
this
.
highlightHash
);
};
LineHighlighter
.
prototype
.
highlightHash
=
function
()
{
var
range
;
if
(
this
.
_hash
!==
''
)
{
range
=
this
.
hashToRange
(
this
.
_hash
);
if
(
range
[
0
])
{
this
.
highlightRange
(
range
);
$
.
scrollTo
(
"#L"
+
range
[
0
],
{
// Scroll to the first highlighted line on initial load
// Offset -50 for the sticky top bar, and another -100 for some context
offset
:
-
150
});
}
}
};
LineHighlighter
.
prototype
.
clickHandler
=
function
(
event
)
{
var
current
,
lineNumber
,
range
;
event
.
preventDefault
();
this
.
clearHighlight
();
lineNumber
=
$
(
event
.
target
).
closest
(
'a'
).
data
(
'line-number'
);
current
=
this
.
hashToRange
(
this
.
_hash
);
if
(
!
(
current
[
0
]
&&
event
.
shiftKey
))
{
// If there's no current selection, or there is but Shift wasn't held,
// treat this like a single-line selection.
this
.
setHash
(
lineNumber
);
return
this
.
highlightLine
(
lineNumber
);
}
else
if
(
event
.
shiftKey
)
{
if
(
lineNumber
<
current
[
0
])
{
range
=
[
lineNumber
,
current
[
0
]];
}
else
{
range
=
[
current
[
0
],
lineNumber
];
}
this
.
setHash
(
range
[
0
],
range
[
1
]);
return
this
.
highlightRange
(
range
);
}
};
LineHighlighter
.
prototype
.
clearHighlight
=
function
()
{
return
$
(
"."
+
this
.
highlightClass
).
removeClass
(
this
.
highlightClass
);
// Unhighlight previously highlighted lines
};
// Convert a URL hash String into line numbers
//
// hash - Hash String
//
// Examples:
//
// hashToRange('#L5') # => [5, null]
// hashToRange('#L5-15') # => [5, 15]
// hashToRange('#foo') # => [null, null]
//
// Returns an Array
LineHighlighter
.
prototype
.
hashToRange
=
function
(
hash
)
{
var
first
,
last
,
matches
;
// ?L(\d+)(?:-(\d+))?$/)
matches
=
hash
.
match
(
/^#
?
L
(\d
+
)(?:
-
(\d
+
))?
$/
);
if
(
matches
&&
matches
.
length
)
{
first
=
parseInt
(
matches
[
1
],
10
);
last
=
matches
[
2
]
?
parseInt
(
matches
[
2
],
10
)
:
null
;
return
[
first
,
last
];
}
else
{
return
[
null
,
null
];
}
};
// Highlight a single line
//
// lineNumber - Line number to highlight
LineHighlighter
.
prototype
.
highlightLine
=
function
(
lineNumber
)
{
return
$
(
"#LC"
+
lineNumber
).
addClass
(
this
.
highlightClass
);
};
// Highlight all lines within a range
//
// range - Array containing the starting and ending line numbers
LineHighlighter
.
prototype
.
highlightRange
=
function
(
range
)
{
var
i
,
lineNumber
,
ref
,
ref1
,
results
;
if
(
range
[
1
])
{
results
=
[];
for
(
lineNumber
=
i
=
ref
=
range
[
0
],
ref1
=
range
[
1
];
ref
<=
ref1
?
i
<=
ref1
:
i
>=
ref1
;
lineNumber
=
ref
<=
ref1
?
(
i
+=
1
)
:
(
i
-=
1
))
{
results
.
push
(
this
.
highlightLine
(
lineNumber
));
}
return
results
;
}
else
{
return
this
.
highlightLine
(
range
[
0
]);
}
};
const
LineHighlighter
=
function
(
options
=
{})
{
options
.
highlightLineClass
=
options
.
highlightLineClass
||
'hll'
;
options
.
fileHolderSelector
=
options
.
fileHolderSelector
||
'.file-holder'
;
options
.
scrollFileHolder
=
options
.
scrollFileHolder
||
false
;
options
.
hash
=
options
.
hash
||
location
.
hash
;
// Set the URL hash string
LineHighlighter
.
prototype
.
setHash
=
function
(
firstLineNumber
,
lastLineNumber
)
{
var
hash
;
if
(
lastLineNumber
)
{
hash
=
"#L"
+
firstLineNumber
+
"-"
+
lastLineNumber
;
this
.
options
=
options
;
this
.
_hash
=
options
.
hash
;
this
.
highlightLineClass
=
options
.
highlightLineClass
;
this
.
setHash
=
this
.
setHash
.
bind
(
this
);
this
.
highlightLine
=
this
.
highlightLine
.
bind
(
this
);
this
.
clickHandler
=
this
.
clickHandler
.
bind
(
this
);
this
.
highlightHash
=
this
.
highlightHash
.
bind
(
this
);
this
.
bindEvents
();
this
.
highlightHash
();
};
LineHighlighter
.
prototype
.
bindEvents
=
function
()
{
const
$fileHolder
=
$
(
this
.
options
.
fileHolderSelector
);
$fileHolder
.
on
(
'click'
,
'a[data-line-number]'
,
this
.
clickHandler
);
$fileHolder
.
on
(
'highlight:line'
,
this
.
highlightHash
);
};
LineHighlighter
.
prototype
.
highlightHash
=
function
()
{
var
range
;
if
(
this
.
_hash
!==
''
)
{
range
=
this
.
hashToRange
(
this
.
_hash
);
if
(
range
[
0
])
{
this
.
highlightRange
(
range
);
const
lineSelector
=
`#L
${
range
[
0
]}
`
;
const
scrollOptions
=
{
// Scroll to the first highlighted line on initial load
// Offset -50 for the sticky top bar, and another -100 for some context
offset
:
-
150
};
if
(
this
.
options
.
scrollFileHolder
)
{
$
(
this
.
options
.
fileHolderSelector
).
scrollTo
(
lineSelector
,
scrollOptions
);
}
else
{
hash
=
"#L"
+
firstLineNumber
;
$
.
scrollTo
(
lineSelector
,
scrollOptions
)
;
}
this
.
_hash
=
hash
;
return
this
.
__setLocationHash__
(
hash
);
};
// Make the actual hash change in the browser
//
// This method is stubbed in tests.
LineHighlighter
.
prototype
.
__setLocationHash__
=
function
(
value
)
{
return
history
.
pushState
({
url
:
value
// We're using pushState instead of assigning location.hash directly to
// prevent the page from scrolling on the hashchange event
},
document
.
title
,
value
);
};
return
LineHighlighter
;
})();
}).
call
(
window
);
}
}
};
LineHighlighter
.
prototype
.
clickHandler
=
function
(
event
)
{
var
current
,
lineNumber
,
range
;
event
.
preventDefault
();
this
.
clearHighlight
();
lineNumber
=
$
(
event
.
target
).
closest
(
'a'
).
data
(
'line-number'
);
current
=
this
.
hashToRange
(
this
.
_hash
);
if
(
!
(
current
[
0
]
&&
event
.
shiftKey
))
{
// If there's no current selection, or there is but Shift wasn't held,
// treat this like a single-line selection.
this
.
setHash
(
lineNumber
);
return
this
.
highlightLine
(
lineNumber
);
}
else
if
(
event
.
shiftKey
)
{
if
(
lineNumber
<
current
[
0
])
{
range
=
[
lineNumber
,
current
[
0
]];
}
else
{
range
=
[
current
[
0
],
lineNumber
];
}
this
.
setHash
(
range
[
0
],
range
[
1
]);
return
this
.
highlightRange
(
range
);
}
};
LineHighlighter
.
prototype
.
clearHighlight
=
function
()
{
return
$
(
"."
+
this
.
highlightLineClass
).
removeClass
(
this
.
highlightLineClass
);
};
// Convert a URL hash String into line numbers
//
// hash - Hash String
//
// Examples:
//
// hashToRange('#L5') # => [5, null]
// hashToRange('#L5-15') # => [5, 15]
// hashToRange('#foo') # => [null, null]
//
// Returns an Array
LineHighlighter
.
prototype
.
hashToRange
=
function
(
hash
)
{
var
first
,
last
,
matches
;
// ?L(\d+)(?:-(\d+))?$/)
matches
=
hash
.
match
(
/^#
?
L
(\d
+
)(?:
-
(\d
+
))?
$/
);
if
(
matches
&&
matches
.
length
)
{
first
=
parseInt
(
matches
[
1
],
10
);
last
=
matches
[
2
]
?
parseInt
(
matches
[
2
],
10
)
:
null
;
return
[
first
,
last
];
}
else
{
return
[
null
,
null
];
}
};
// Highlight a single line
//
// lineNumber - Line number to highlight
LineHighlighter
.
prototype
.
highlightLine
=
function
(
lineNumber
)
{
return
$
(
"#LC"
+
lineNumber
).
addClass
(
this
.
highlightLineClass
);
};
// Highlight all lines within a range
//
// range - Array containing the starting and ending line numbers
LineHighlighter
.
prototype
.
highlightRange
=
function
(
range
)
{
var
i
,
lineNumber
,
ref
,
ref1
,
results
;
if
(
range
[
1
])
{
results
=
[];
for
(
lineNumber
=
i
=
ref
=
range
[
0
],
ref1
=
range
[
1
];
ref
<=
ref1
?
i
<=
ref1
:
i
>=
ref1
;
lineNumber
=
ref
<=
ref1
?
(
i
+=
1
)
:
(
i
-=
1
))
{
results
.
push
(
this
.
highlightLine
(
lineNumber
));
}
return
results
;
}
else
{
return
this
.
highlightLine
(
range
[
0
]);
}
};
// Set the URL hash string
LineHighlighter
.
prototype
.
setHash
=
function
(
firstLineNumber
,
lastLineNumber
)
{
var
hash
;
if
(
lastLineNumber
)
{
hash
=
"#L"
+
firstLineNumber
+
"-"
+
lastLineNumber
;
}
else
{
hash
=
"#L"
+
firstLineNumber
;
}
this
.
_hash
=
hash
;
return
this
.
__setLocationHash__
(
hash
);
};
// Make the actual hash change in the browser
//
// This method is stubbed in tests.
LineHighlighter
.
prototype
.
__setLocationHash__
=
function
(
value
)
{
return
history
.
pushState
({
url
:
value
// We're using pushState instead of assigning location.hash directly to
// prevent the page from scrolling on the hashchange event
},
document
.
title
,
value
);
};
window
.
LineHighlighter
=
LineHighlighter
;
app/assets/javascripts/repo/components/repo_preview.vue
View file @
36a917e1
<
script
>
/* global LineHighlighter */
import
Store
from
'../stores/repo_store'
;
export
default
{
data
:
()
=>
Store
,
mounted
()
{
this
.
highlightFile
();
},
computed
:
{
html
()
{
return
this
.
activeFile
.
html
;
},
},
methods
:
{
highlightFile
()
{
$
(
this
.
$el
).
find
(
'.file-content'
).
syntaxHighlight
();
},
},
mounted
()
{
this
.
highlightFile
();
this
.
lineHighlighter
=
new
LineHighlighter
({
fileHolderSelector
:
'.blob-viewer-container'
,
scrollFileHolder
:
true
,
});
},
watch
:
{
html
()
{
this
.
$nextTick
(()
=>
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment