@@ -33,6 +33,11 @@ define(function (require, exports, module) {
3333 EditorManager = require ( "editor/EditorManager" ) ,
3434 WorkspaceManager = require ( "view/WorkspaceManager" ) ;
3535
36+ const TRACK_STYLES = {
37+ LINE : "line" ,
38+ ON_LEFT : "left"
39+ } ;
40+
3641 /**
3742 * Vertical space above/below the scrollbar (set per OS).
3843 * This remains global but applies to all editors.
@@ -57,24 +62,8 @@ define(function (require, exports, module) {
5762 * The (fixed) height of each individual tickmark.
5863 * @const
5964 */
60- const MARKER_HEIGHT = 2 ;
61-
62- /**
63- * Returns the vertical space above and below the scrollbar, which depends
64- * on OS or may be altered by other CSS/extension changes.
65- * @return {number }
66- */
67- function getScrollbarTrackOffset ( ) {
68- return scrollbarTrackOffset ;
69- }
70-
71- /**
72- * Sets how much vertical space there is above and below the scrollbar.
73- * @param {number } offset Value in pixels
74- */
75- function setScrollbarTrackOffset ( offset ) {
76- scrollbarTrackOffset = offset ;
77- }
65+ const MARKER_HEIGHT_LINE = 2 ;
66+ const MARKER_HEIGHT_LEFT = 5 ;
7867
7968 /**
8069 * Helper: get or create the scrollTrackMarker state object for an editor.
@@ -124,7 +113,7 @@ define(function (require, exports, module) {
124113
125114 var trackHeight = $sb [ 0 ] . offsetHeight ;
126115 if ( trackHeight > 0 ) {
127- markerState . trackOffset = getScrollbarTrackOffset ( ) ;
116+ markerState . trackOffset = scrollbarTrackOffset ;
128117 markerState . trackHt = trackHeight - markerState . trackOffset * 2 ;
129118 } else {
130119 // No scrollbar: use the height of the entire code content
@@ -166,7 +155,7 @@ define(function (require, exports, module) {
166155 /**
167156 * Renders the given list of positions as merged tickmarks in the scrollbar track.
168157 * @param {!Editor } editor
169- * @param {! Array.<{line: number, ch: number}> } posArray
158+ * @param {Array.<{line: number, ch: number}> } posArray
170159 */
171160 function _renderMarks ( editor , posArray ) {
172161 const cm = editor . _codeMirror ;
@@ -197,59 +186,113 @@ define(function (require, exports, module) {
197186 const ratio = editorHt ? ( y / editorHt ) : 0 ;
198187 const top = Math . round ( ratio * markerState . trackHt ) + markerState . trackOffset - 1 ;
199188 // default 2px height => from top..(top+2)
200- markPositions . push ( { top : top , bottom : top + MARKER_HEIGHT } ) ;
189+ let markerHeight = MARKER_HEIGHT_LINE , isLine = true ;
190+ if ( pos . options . trackStyle === TRACK_STYLES . ON_LEFT ) {
191+ markerHeight = MARKER_HEIGHT_LEFT ;
192+ isLine = false ;
193+ }
194+ markPositions . push ( { top : top , bottom : top + markerHeight , isLine,
195+ cssColorClass : pos . options . cssColorClass || "" } ) ;
201196 } ) ;
202197
203198 // Sort them by top coordinate
204199 markPositions . sort ( function ( a , b ) { return a . top - b . top ; } ) ;
205200
206201 // Merge nearby or overlapping segments
207- const mergedMarks = [ ] ;
208- markPositions . forEach ( function ( m ) {
202+ const mergedLineMarks = [ ] , mergedLeftMarks = [ ] ;
203+ markPositions . forEach ( function ( mark ) {
204+ const mergedMarks = mark . isLine ? mergedLineMarks : mergedLeftMarks ;
209205 if ( mergedMarks . length > 0 ) {
210206 const last = mergedMarks [ mergedMarks . length - 1 ] ;
211207 // If overlapping or adjacent, merge them
212- if ( m . top <= last . bottom + 1 ) {
213- last . bottom = Math . max ( last . bottom , m . bottom ) ;
208+ if ( mark . top <= last . bottom + 1 ) {
209+ last . bottom = Math . max ( last . bottom , mark . bottom ) ;
214210 last . height = last . bottom - last . top ;
215211 return ;
216212 }
217213 }
218- m . height = m . bottom - m . top ;
219- mergedMarks . push ( m ) ;
214+ mark . height = mark . bottom - mark . top ;
215+ mergedMarks . push ( mark ) ;
220216 } ) ;
221217
222- // Build HTML
223- const html = mergedMarks . map ( function ( m ) {
224- return "<div class='tickmark' style='top:" + m . top + "px; height:" + m . height + "px;'></div>" ;
218+ // Build HTML for horizontal marks
219+ let html = mergedLineMarks . map ( function ( m ) {
220+ return `<div class='tickmark ${ m . cssColorClass } ' style='top: ${ m . top } px; height: ${ m . height } px;'></div>` ;
221+ } ) . join ( "" ) ;
222+
223+ // Append to track
224+ $track . append ( $ ( html ) ) ;
225+
226+ // Build HTML for hertical marks
227+ html = mergedLeftMarks . map ( function ( m ) {
228+ return `<div class='tickmark tickmark-side ${
229+ m . cssColorClass } ' style='top: ${ m . top } px; height: ${ m . height } px;'></div>`;
225230 } ) . join ( "" ) ;
226231
227232 // Append to track
228233 $track . append ( $ ( html ) ) ;
229234 }
230235
231236 /**
232- * Clear any markers in the editor's tickmark track, leaving it visible if it was shown.
233- * Safe to call when the tickmark track is not visible also.
237+ * Clear tickmarks from the editor's tickmark track.
238+ * - If `markName` is provided, only clears marks with that name.
239+ * - If `markName` is omitted, clears **all unnamed marks** but leaves named marks.
240+ * - To **clear all marks**, including named ones, use `clearAll()`.
234241 * @param {!Editor } editor
242+ * @param {string } [markName] Optional. If given, only clears marks with that name.
235243 */
236- function clear ( editor ) {
237- if ( ! editor ) {
238- console . error ( "Calling ScrollTrackMarkers.clear without editor instance is deprecated." ) ;
244+ function clear ( editor , markName ) {
245+ if ( ! editor ) {
246+ console . error ( "Calling ScrollTrackMarkers.clear without an editor instance is deprecated." ) ;
239247 editor = EditorManager . getActiveEditor ( ) ;
240248 }
241249 const markerState = editor && editor . _scrollTrackMarker ;
242250 if ( ! markerState ) {
243251 return ;
244252 }
253+
254+ if ( markName ) {
255+ // Filter out only the named marks that match the given `markName`
256+ markerState . marks = markerState . marks . filter ( mark => mark . options && mark . options . name !== markName ) ;
257+ } else {
258+ // Remove only unnamed marks (marks where options.name is undefined or null)
259+ markerState . marks = markerState . marks . filter ( mark => mark . options && mark . options . name ) ;
260+ }
261+
262+ // Re-render the marks after clearing
245263 $ ( ".tickmark-track" , editor . getRootElement ( ) ) . empty ( ) ;
264+ _renderMarks ( editor , markerState . marks ) ;
265+
266+ if ( markerState . $markedTickmark && markName ) {
267+ markerState . $markedTickmark . remove ( ) ;
268+ markerState . $markedTickmark = null ;
269+ }
270+ }
271+
272+ /**
273+ * Clears all tickmarks from the editor's tickmark track, including named and unnamed marks.
274+ * @param {!Editor } editor
275+ */
276+ function clearAll ( editor ) {
277+ if ( ! editor ) {
278+ throw new Error ( "Called ScrollTrackMarkers.clearAll without an editor!" ) ;
279+ }
280+ const markerState = editor && editor . _scrollTrackMarker ;
281+ if ( ! markerState ) {
282+ return ;
283+ }
284+
285+ // Completely remove all tickmarks
246286 markerState . marks = [ ] ;
287+ $ ( ".tickmark-track" , editor . getRootElement ( ) ) . empty ( ) ;
288+
247289 if ( markerState . $markedTickmark ) {
248290 markerState . $markedTickmark . remove ( ) ;
249291 markerState . $markedTickmark = null ;
250292 }
251293 }
252294
295+
253296 /**
254297 * Shows or hides the tickmark track for the given editor.
255298 * @param {!Editor } editor
@@ -306,16 +349,22 @@ define(function (require, exports, module) {
306349 /**
307350 * Adds tickmarks for the given positions into the editor's tickmark track, if visible.
308351 * @param {!Editor } editor
309- * @param {!Array.<{line: number, ch: number}> } posArray
352+ * @param {Array.<{line: number, ch: number}> } posArray
353+ * @param {Object } [options]
354+ * @param {string } [options.name] you can assign a name to marks and then use this name to selectively
355+ * these clear marks.
356+ * @param {string } [options.trackStyle] one of TRACK_STYLES.*
357+ * @param {string } [options.cssColorClass] a css class that should only override the --mark-color css var.
310358 */
311- function addTickmarks ( editor , posArray ) {
359+ function addTickmarks ( editor , posArray , options = { } ) {
312360 const markerState = _getMarkerState ( editor ) ;
313361 if ( ! markerState . visible ) {
314362 return ;
315363 }
364+ const newPosArray = posArray . map ( pos => ( { ...pos , options } ) ) ;
316365 // Concat new positions
317- markerState . marks = markerState . marks . concat ( posArray ) ;
318- _renderMarks ( editor , posArray ) ;
366+ markerState . marks = markerState . marks . concat ( newPosArray ) ;
367+ _renderMarks ( editor , markerState . marks ) ;
319368 }
320369
321370 /**
@@ -340,7 +389,7 @@ define(function (require, exports, module) {
340389
341390 const top = _getTop ( editor , markerState . marks [ index ] ) ;
342391 const $tick = $ (
343- `<div class='tickmark tickmark-current' style='top: ${ top } px; height: ${ MARKER_HEIGHT } px;'></div>` ) ;
392+ `<div class='tickmark tickmark-current' style='top: ${ top } px; height: ${ MARKER_HEIGHT_LINE } px;'></div>` ) ;
344393
345394 $ ( ".tickmark-track" , editor . getRootElement ( ) ) . append ( $tick ) ;
346395 markerState . $markedTickmark = $tick ;
@@ -361,9 +410,9 @@ define(function (require, exports, module) {
361410
362411 // public API
363412 exports . clear = clear ;
413+ exports . clearAll = clearAll ;
364414 exports . setVisible = setVisible ;
365415 exports . addTickmarks = addTickmarks ;
366416 exports . markCurrent = markCurrent ;
367- exports . getScrollbarTrackOffset = getScrollbarTrackOffset ;
368- exports . setScrollbarTrackOffset = setScrollbarTrackOffset ;
417+ exports . TRACK_STYLES = TRACK_STYLES ;
369418} ) ;
0 commit comments