Skip to content
This repository was archived by the owner on Nov 25, 2021. It is now read-only.

Commit 2658b95

Browse files
committed
fix: conditionally tokenize code views (continued) (#144)
1 parent 494e3b7 commit 2658b95

File tree

3 files changed

+60
-11
lines changed

3 files changed

+60
-11
lines changed

src/hoverifier.ts

+13-5
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ export interface HoverifierOptions<C extends object, D, A> {
8787
* Whether or not hover tooltips can be pinned.
8888
*/
8989
pinningEnabled: boolean
90+
91+
/**
92+
* Whether or not code views need to be tokenized. Defaults to true.
93+
*/
94+
tokenize?: boolean
9095
}
9196

9297
/**
@@ -349,6 +354,7 @@ export function createHoverifier<C extends object, D, A>({
349354
getHover,
350355
getActions,
351356
pinningEnabled,
357+
tokenize = true,
352358
}: HoverifierOptions<C, D, A>): Hoverifier<C, D, A> {
353359
// Internal state that is not exposed to the caller
354360
// Shared between all hoverified code views
@@ -502,7 +508,7 @@ export function createHoverifier<C extends object, D, A>({
502508
if (isPosition(position)) {
503509
cell = dom.getCodeElementFromLineNumber(codeView, position.line, position.part)
504510
if (cell) {
505-
target = findElementWithOffset(cell, position.character)
511+
target = findElementWithOffset(cell, position.character, tokenize)
506512
if (target) {
507513
part = dom.getDiffCodePart && dom.getDiffCodePart(target)
508514
} else {
@@ -573,7 +579,7 @@ export function createHoverifier<C extends object, D, A>({
573579
// placed in the middle of a token.
574580
target:
575581
position && isPosition(position)
576-
? getTokenAtPosition(codeView, position, dom, position.part)
582+
? getTokenAtPosition(codeView, position, dom, position.part, tokenize)
577583
: target,
578584
...rest,
579585
})),
@@ -734,7 +740,7 @@ export function createHoverifier<C extends object, D, A>({
734740
container.update({ hoveredTokenElement: undefined })
735741
return
736742
}
737-
const token = getTokenAtPosition(codeView, highlightedRange.start, dom, part)
743+
const token = getTokenAtPosition(codeView, highlightedRange.start, dom, part, tokenize)
738744
container.update({ hoveredTokenElement: token })
739745
if (!token) {
740746
return
@@ -838,8 +844,10 @@ export function createHoverifier<C extends object, D, A>({
838844
selectedPosition: position,
839845
})
840846
const codeElements = getCodeElementsInRange({ codeView, position, getCodeElementFromLineNumber })
841-
for (const { element } of codeElements) {
842-
convertNode(element)
847+
if (tokenize) {
848+
for (const { element } of codeElements) {
849+
convertNode(element)
850+
}
843851
}
844852
// Scroll into view
845853
if (codeElements.length > 0) {

src/token_position.test.ts

+35-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ describe('token_positions', () => {
8989
})
9090

9191
describe('findElementWithOffset()', () => {
92-
it('finds the correct token', () => {
92+
it('finds the correct token (with tokenization)', () => {
9393
const content = `${tabChar}if rv := contextGet(r, routeKey); rv != nil {`
9494

9595
const elems = [
@@ -122,6 +122,40 @@ describe('token_positions', () => {
122122
}
123123
})
124124

125+
it('finds the correct token (without tokenization)', () => {
126+
const content = `<span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text=" "> </span><span class="cm-keyword">if</span> <span class="cm-variable">rv</span> :<span class="cm-operator">=</span> <span class="cm-variable">contextGet</span>(<span class="cm-variable">r</span>, <span class="cm-variable">varsKey</span>); <span class="cm-variable">rv</span> <span class="cm-operator">!=</span> <span class="cm-atom">nil</span> {</span>`
127+
128+
// Each offset is 3 more than the corresponding offset in the
129+
// tokenized test above because this test case comes from Bitbucket
130+
// where tabs are converted to spaces.
131+
//
132+
// The '(' and ' ' tokens are absent from this test because, on
133+
// Bitbucket, punctuation characters are not wrapped in tags and the
134+
// current offset-finding logic can't determine the offset for such
135+
// tokens. One way to fix that is to use the CodeMirror API
136+
// directly.
137+
const elems = [
138+
{
139+
offset: 14,
140+
token: 'contextGet',
141+
},
142+
{
143+
offset: 5,
144+
token: 'if',
145+
},
146+
]
147+
148+
const elem = dom.createElementFromString(content)
149+
150+
for (const { offset, token } of elems) {
151+
const tokenElem = findElementWithOffset(elem, offset, false)
152+
153+
expect(tokenElem).to.not.equal(undefined)
154+
155+
expect(tokenElem!.textContent).to.equal(token)
156+
}
157+
})
158+
125159
it('returns undefined for invalid offsets', () => {
126160
const content = 'Hello, World!'
127161

src/token_position.ts

+12-5
Original file line numberDiff line numberDiff line change
@@ -252,9 +252,15 @@ export const getTextNodes = (node: Node): Node[] => {
252252
* @param codeElement the element containing syntax highlighted code
253253
* @param offset character offset (1-indexed)
254254
*/
255-
export function findElementWithOffset(codeElement: HTMLElement, offset: number): HTMLElement | undefined {
256-
// Without being converted first, finding the position is inaccurate
257-
convertCodeElementIdempotent(codeElement)
255+
export function findElementWithOffset(
256+
codeElement: HTMLElement,
257+
offset: number,
258+
tokenize = true
259+
): HTMLElement | undefined {
260+
if (tokenize) {
261+
// Without being converted first, finding the position is inaccurate
262+
convertCodeElementIdempotent(codeElement)
263+
}
258264

259265
const textNodes = getTextNodes(codeElement)
260266

@@ -475,7 +481,8 @@ export const getTokenAtPosition = (
475481
getCodeElementFromLineNumber,
476482
isFirstCharacterDiffIndicator,
477483
}: Pick<DOMFunctions, 'getCodeElementFromLineNumber' | 'isFirstCharacterDiffIndicator'>,
478-
part?: DiffPart
484+
part?: DiffPart,
485+
tokenize = true,
479486
): HTMLElement | undefined => {
480487
const codeElement = getCodeElementFromLineNumber(codeView, line, part)
481488
if (!codeElement) {
@@ -486,5 +493,5 @@ export const getTokenAtPosition = (
486493
character++
487494
}
488495

489-
return findElementWithOffset(codeElement, character)
496+
return findElementWithOffset(codeElement, character, tokenize)
490497
}

0 commit comments

Comments
 (0)