I am currently utilizing CodeMirror () as a text editor with additional functionalities. One of these features includes highlighting specific words or groups of words based on their positions within the original string. I have an external structure that stores the list of substring positions that need to be highlighted. This structure is an Array where each element represents a line of text, containing arrays of objects with the positions of the substrings to be highlighted. For example, consider this text:
The moon
is pale and round
as is
also the sun
The words "moon", "pale", "round", and "sun" are to be highlighted. The structure for highlighting looks like this:
[
[ { iStart:4, iEnd:7 } ], // "moon"
[ { iStart:3, iEnd:6 }, { iStart:12, iEnd:16 } ], // "pale" and "round"
[],
[ { iStart:9, iEnd:11 } ] // "sun"
]
In my attempts to achieve this, I initially tried creating a custom language mode but faced challenges due to CodeMirror's usage of tokens instead of lines. I needed to determine the line corresponding to the current token in order to retrieve the correct data from the highlight structure.
Subsequently, I experimented with an external function that applies highlighting by manually adding SPAN tags like so:
function highlightText()
{
console.log( "highlightText()" );
// Obtain references to the text lines in the code editor
var codeLines = $("#editorContainer .CodeMirror-code pre>span" );
for( var i=0; i<colorSegments.length; i++ ){
// Check if there are elements to be highlighted in this line...
if( colorSegments[i] && colorSegments[i].length > 0 ){
// Retrieve the appropriate element and proceed with highlighting
var lineElement = codeLines[i];
highlightWordsInLine( lineElement, colorSegments[i] );
}
}
}
function highlightWordsInLine(element, positions) {
// Extract the raw text
var str = $( element ).text();
// Create a new string with highlighting tags.
// Start
var out = str.substr(0, positions[0].iStart);
for( var j=0; j<positions.length; j++ ){
var position = positions[j];
// Apply the highlighting tag
out += '<span class="cm-s-ambiance cm-relation">';
out += str.substr( position.iStart, position.iEnd - position.iStart + 1);
out += '</span>';
// Ensure inclusion of unhighlighted text in between
if( j < positions.length-1 ){
out += str.substr( position.iEnd - position.iStart + 1, positions[j+1].iStart );
}
}
// Complete end of line wrapping
out += str.substr( position.iEnd + 1);
// Update the html element value with applied highlight tags
element.innerHTML = out;
}
Although I acknowledge this method may not be optimal and has some limitations such as causing certain text to become unselectable, it has provided partial success in managing the highlighting process.
Hence, my inquiry pertains to the proper approach for achieving this task. Should I persist with the language-mode approach, and if so, how should I proceed?
I have also been advised to explore Ace (), but it appears to lack support for handling highlighting based on string positions rather than keyword lists or regexp rules.
Thank you in advance for your guidance.