Skip to content

Commit

Permalink
Support adding attributes when marking text
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexanderPrendota authored and marijnh committed Nov 20, 2018
1 parent 3619ae2 commit ce1f0cd
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 15 deletions.
7 changes: 3 additions & 4 deletions doc/manual.html
Expand Up @@ -1716,10 +1716,9 @@ <h3 id="api_marker">Text-marking methods</h3>
to <code>startStyle</code>, but for the rightmost span.</dd>
<dt id="mark_css"><code><strong>css</strong>: string</code></dt>
<dd>A string of CSS to be applied to the covered text. For example <code>"color: #fe3"</code>.</dd>
<dt id="mark_title"><code><strong>title</strong>:
string</code></dt><dd>When given, will give the nodes created
for this span a HTML <code>title</code> attribute with the
given value.</dd>
<dt id="mark_attributes"><code><strong>attributes</strong>:
object</code></dt><dd>When given, will give the nodes created
for this span a HTML <code>attributes</code> with the given value.</dd>
<dt id="mark_shared"><code><strong>shared</strong>: boolean</code></dt><dd>When the
target document is <a href="#linkedDoc">linked</a> to other
documents, you can set <code>shared</code> to true to make the
Expand Down
28 changes: 19 additions & 9 deletions src/line/line_data.js
Expand Up @@ -127,7 +127,7 @@ export function defaultSpecialCharPlaceholder(ch) {

// Build up the DOM representation for a single token, and add it to
// the line map. Takes care to render special characters separately.
function buildToken(builder, text, style, startStyle, endStyle, title, css) {
function buildToken(builder, text, style, startStyle, endStyle, css, attributes) {
if (!text) return
let displayText = builder.splitSpaces ? splitSpaces(text, builder.trailingSpace) : text
let special = builder.cm.state.specialChars, mustWrap = false
Expand Down Expand Up @@ -183,7 +183,13 @@ function buildToken(builder, text, style, startStyle, endStyle, title, css) {
if (startStyle) fullStyle += startStyle
if (endStyle) fullStyle += endStyle
let token = elt("span", [content], fullStyle, css)
if (title) token.title = title
if (attributes) {
for (let attr in attributes){
if (attributes.hasOwnProperty(attr) && attr !== "style" && attr !== "class") {
token.setAttribute(attr, attributes[attr])
}
}
}
return builder.content.appendChild(token)
}
builder.content.appendChild(content)
Expand All @@ -207,7 +213,7 @@ function splitSpaces(text, trailingBefore) {
// Work around nonsense dimensions being reported for stretches of
// right-to-left text.
function buildTokenBadBidi(inner, order) {
return (builder, text, style, startStyle, endStyle, title, css) => {
return (builder, text, style, startStyle, endStyle, css, attributes) => {
style = style ? style + " cm-force-border" : "cm-force-border"
let start = builder.pos, end = start + text.length
for (;;) {
Expand All @@ -217,8 +223,8 @@ function buildTokenBadBidi(inner, order) {
part = order[i]
if (part.to > start && part.from <= start) break
}
if (part.to >= end) return inner(builder, text, style, startStyle, endStyle, title, css)
inner(builder, text.slice(0, part.to - start), style, startStyle, null, title, css)
if (part.to >= end) return inner(builder, text, style, startStyle, endStyle, css, attributes)
inner(builder, text.slice(0, part.to - start), style, startStyle, null, css, attributes)
startStyle = null
text = text.slice(part.to - start)
start = part.to
Expand Down Expand Up @@ -253,10 +259,11 @@ function insertLineContent(line, builder, styles) {
}

let len = allText.length, pos = 0, i = 1, text = "", style, css
let nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed
let nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, collapsed, attributes
for (;;) {
if (nextChange == pos) { // Update current marker set
spanStyle = spanEndStyle = spanStartStyle = title = css = ""
spanStyle = spanEndStyle = spanStartStyle = css = ""
attributes = {}
collapsed = null; nextChange = Infinity
let foundBookmarks = [], endStyles
for (let j = 0; j < spans.length; ++j) {
Expand All @@ -272,7 +279,10 @@ function insertLineContent(line, builder, styles) {
if (m.css) css = (css ? css + ";" : "") + m.css
if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle
if (m.endStyle && sp.to == nextChange) (endStyles || (endStyles = [])).push(m.endStyle, sp.to)
if (m.title && !title) title = m.title
// support for the old title property
// https://github.com/codemirror/CodeMirror/pull/5673
if (m.title) {attributes.title = m.title}
if (m.attributes) { attributes = m.attributes }
if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0))
collapsed = sp
} else if (sp.from > pos && nextChange > sp.from) {
Expand Down Expand Up @@ -300,7 +310,7 @@ function insertLineContent(line, builder, styles) {
if (!collapsed) {
let tokenText = end > upto ? text.slice(0, upto - pos) : text
builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,
spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title, css)
spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", css, attributes)
}
if (end >= upto) {text = text.slice(upto - pos); pos = upto; break}
pos = end
Expand Down
2 changes: 1 addition & 1 deletion src/model/mark_text.js
Expand Up @@ -211,7 +211,7 @@ export function markText(doc, from, to, options, type) {
if (updateMaxLine) cm.curOp.updateMaxLine = true
if (marker.collapsed)
regChange(cm, from.line, to.line + 1)
else if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.css)
else if (marker.className || marker.startStyle || marker.endStyle || marker.css || marker.attributes )
for (let i = from.line; i <= to.line; i++) regLineChange(cm, i, "text")
if (marker.atomic) reCheckSelection(cm.doc)
signalLater(cm, "markerAdded", cm, marker)
Expand Down
13 changes: 12 additions & 1 deletion test/test.js
Expand Up @@ -549,13 +549,24 @@ testCM("markTextCSS", function(cm) {
function present() {
var spans = cm.display.lineDiv.getElementsByTagName("span");
for (var i = 0; i < spans.length; i++)
if (spans[i].style.color == "cyan" && span[i].textContent == "cdefg") return true;
if (spans[i].style.color == "cyan" && spans[i].textContent == "cdefg") return true;
}
var m = cm.markText(Pos(0, 2), Pos(0, 6), {css: "color: cyan"});
m.clear();
is(!present());
}, {value: "abcdefgh"});

testCM("markTextWithAttributes", function(cm) {
function present() {
var spans = cm.display.lineDiv.getElementsByTagName("span");
for (var i = 0; i < spans.length; i++)
if (spans[i].getAttribute('label') == "label" && span[i].textContent == "cdefg") return true;
}
var m = cm.markText(Pos(0, 2), Pos(0, 6), {attributes: {label: "label"}});
m.clear();
is(!present());
}, {value: "abcdefgh"});

testCM("bookmark", function(cm) {
function p(v) { return v && Pos(v[0], v[1]); }
forEach([{a: [1, 0], b: [1, 1], c: "", d: [1, 4]},
Expand Down

0 comments on commit ce1f0cd

Please sign in to comment.