codemirror-foldable-indentation-guides 1.0.3 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +210 -147
- package/dist/index.js +210 -147
- package/package.json +1 -1
- package/src/build-indentation-decorations.ts +14 -10
- package/src/indentation-view-plugin.ts +187 -124
- package/src/map.ts +44 -19
package/dist/index.cjs
CHANGED
|
@@ -354,6 +354,57 @@ class ClickableIndentationGuideWidget extends view.WidgetType {
|
|
|
354
354
|
}
|
|
355
355
|
}
|
|
356
356
|
|
|
357
|
+
function buildIndentationDecorations(view$1, indentationMap, visibleLines) {
|
|
358
|
+
var _a;
|
|
359
|
+
const state = view$1.state;
|
|
360
|
+
const widgets = [];
|
|
361
|
+
const indentWidth = language.getIndentUnit(state);
|
|
362
|
+
const { thickness, activeThickness, hoverThickness, additionalPadding, foldBlockOnClick, highlightActiveBlockBackground, hideFirstIndent, } = state.facet(indentationGuidesConfig);
|
|
363
|
+
const lineLevels = new Map();
|
|
364
|
+
for (const line of visibleLines) {
|
|
365
|
+
const entry = indentationMap.get(line.number);
|
|
366
|
+
const level = (_a = entry === null || entry === void 0 ? void 0 : entry.level) !== null && _a !== void 0 ? _a : 0;
|
|
367
|
+
lineLevels.set(line.number, level);
|
|
368
|
+
if (!entry) {
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
371
|
+
/** Workaround for folded empty lines in python and similar languages.
|
|
372
|
+
* Without this check, unwanted indentation guides will be drawn after foldPlaceholder
|
|
373
|
+
*/
|
|
374
|
+
const foldedAndEmpty = isLineFolded(view$1, entry.line.number) &&
|
|
375
|
+
isLineEmpty(view$1, entry.line.number);
|
|
376
|
+
if (!level || foldedAndEmpty) {
|
|
377
|
+
continue;
|
|
378
|
+
}
|
|
379
|
+
const deco = view.Decoration.widget({
|
|
380
|
+
widget: new ClickableIndentationGuideWidget(indentWidth, level, line.number, {
|
|
381
|
+
thickness,
|
|
382
|
+
activeThickness,
|
|
383
|
+
hoverThickness,
|
|
384
|
+
additionalPadding,
|
|
385
|
+
foldOnClick: foldBlockOnClick,
|
|
386
|
+
highlightBackground: highlightActiveBlockBackground,
|
|
387
|
+
hideFirstIndent,
|
|
388
|
+
}),
|
|
389
|
+
side: 0,
|
|
390
|
+
});
|
|
391
|
+
widgets.push(deco.range(line.from));
|
|
392
|
+
}
|
|
393
|
+
return {
|
|
394
|
+
decoSet: view.Decoration.set(widgets),
|
|
395
|
+
lineLevels,
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
400
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
401
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
402
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
403
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
404
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
405
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
406
|
+
});
|
|
407
|
+
};
|
|
357
408
|
/**
|
|
358
409
|
* Indentation map for a set of lines.
|
|
359
410
|
*
|
|
@@ -371,15 +422,40 @@ class IndentationMap {
|
|
|
371
422
|
* @param markerType - The type of indentation to use (terminate at end of scope vs last line of code in scope)
|
|
372
423
|
*/
|
|
373
424
|
constructor(lines, state, unitWidth, markerType) {
|
|
374
|
-
this.
|
|
425
|
+
this.terminated = false;
|
|
375
426
|
this.state = state;
|
|
376
427
|
this.map = new Map();
|
|
377
428
|
this.unitWidth = unitWidth;
|
|
378
429
|
this.markerType = markerType;
|
|
379
|
-
for (const line of
|
|
430
|
+
for (const line of lines) {
|
|
380
431
|
this.add(line);
|
|
381
432
|
}
|
|
382
433
|
}
|
|
434
|
+
initLinesSync(lines) {
|
|
435
|
+
const linesArr = [...lines];
|
|
436
|
+
for (let i = 0; i < linesArr.length; i++) {
|
|
437
|
+
const line = linesArr[i];
|
|
438
|
+
this.add(line);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
initLinesAsync(lines) {
|
|
442
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
443
|
+
const linesArr = [...lines];
|
|
444
|
+
for (let i = 0; i < linesArr.length; i++) {
|
|
445
|
+
if (this.terminated) {
|
|
446
|
+
break;
|
|
447
|
+
}
|
|
448
|
+
const line = linesArr[i];
|
|
449
|
+
this.add(line);
|
|
450
|
+
if (i % 100 === 0) {
|
|
451
|
+
yield new Promise((resolve) => setTimeout(resolve));
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
terminate() {
|
|
457
|
+
this.terminated = true;
|
|
458
|
+
}
|
|
383
459
|
/**
|
|
384
460
|
* Checks if the indentation map has an entry for the given line.
|
|
385
461
|
*
|
|
@@ -397,9 +473,6 @@ class IndentationMap {
|
|
|
397
473
|
*/
|
|
398
474
|
get(line) {
|
|
399
475
|
const entry = this.map.get(typeof line === 'number' ? line : line.number);
|
|
400
|
-
if (!entry) {
|
|
401
|
-
throw new Error('Line not found in indentation map');
|
|
402
|
-
}
|
|
403
476
|
return entry;
|
|
404
477
|
}
|
|
405
478
|
/**
|
|
@@ -421,6 +494,7 @@ class IndentationMap {
|
|
|
421
494
|
* @param line - The {@link Line} to add to the map.
|
|
422
495
|
*/
|
|
423
496
|
add(line) {
|
|
497
|
+
var _a;
|
|
424
498
|
if (this.has(line)) {
|
|
425
499
|
return this.get(line);
|
|
426
500
|
}
|
|
@@ -433,10 +507,13 @@ class IndentationMap {
|
|
|
433
507
|
// if we're at the end, we'll just use the previous line's indentation
|
|
434
508
|
if (line.number === this.state.doc.lines) {
|
|
435
509
|
const prev = this.closestNonEmpty(line, -1);
|
|
436
|
-
return this.set(line, 0, prev.level);
|
|
510
|
+
return this.set(line, 0, (_a = prev === null || prev === void 0 ? void 0 : prev.level) !== null && _a !== void 0 ? _a : 0);
|
|
437
511
|
}
|
|
438
512
|
const prev = this.closestNonEmpty(line, -1);
|
|
439
513
|
const next = this.closestNonEmpty(line, 1);
|
|
514
|
+
if (!prev || !next) {
|
|
515
|
+
return this.set(line, 0, 0);
|
|
516
|
+
}
|
|
440
517
|
// if the next line ends the block and the marker type is not set to codeOnly,
|
|
441
518
|
// we'll just use the previous line's indentation
|
|
442
519
|
if (prev.level >= next.level && this.markerType !== 'codeOnly') {
|
|
@@ -470,7 +547,7 @@ class IndentationMap {
|
|
|
470
547
|
while (dir === -1 ? lineNo >= 1 : lineNo <= this.state.doc.lines) {
|
|
471
548
|
if (this.has(lineNo)) {
|
|
472
549
|
const entry = this.get(lineNo);
|
|
473
|
-
if (!entry.empty) {
|
|
550
|
+
if (!(entry === null || entry === void 0 ? void 0 : entry.empty)) {
|
|
474
551
|
return entry;
|
|
475
552
|
}
|
|
476
553
|
}
|
|
@@ -500,6 +577,9 @@ class IndentationMap {
|
|
|
500
577
|
return;
|
|
501
578
|
}
|
|
502
579
|
let current = this.get(currentLine);
|
|
580
|
+
if (!current) {
|
|
581
|
+
return;
|
|
582
|
+
}
|
|
503
583
|
// check if the current line is starting a new block, if yes, we want to
|
|
504
584
|
// start from inside the block.
|
|
505
585
|
if (this.has(current.line.number + 1)) {
|
|
@@ -528,7 +608,7 @@ class IndentationMap {
|
|
|
528
608
|
continue;
|
|
529
609
|
}
|
|
530
610
|
const prev = this.get(start - 1);
|
|
531
|
-
if (prev.level < current.level) {
|
|
611
|
+
if (!prev || prev.level < current.level) {
|
|
532
612
|
break;
|
|
533
613
|
}
|
|
534
614
|
prev.active = current.level;
|
|
@@ -540,7 +620,7 @@ class IndentationMap {
|
|
|
540
620
|
continue;
|
|
541
621
|
}
|
|
542
622
|
const next = this.get(end + 1);
|
|
543
|
-
if (next.level < current.level) {
|
|
623
|
+
if (!next || next.level < current.level) {
|
|
544
624
|
break;
|
|
545
625
|
}
|
|
546
626
|
next.active = current.level;
|
|
@@ -556,48 +636,6 @@ function getNewIndentationMap(state, lines) {
|
|
|
556
636
|
return new IndentationMap(lines, state, indentWidth, markerType);
|
|
557
637
|
}
|
|
558
638
|
|
|
559
|
-
function buildIndentationDecorations(view$1) {
|
|
560
|
-
var _a;
|
|
561
|
-
const state = view$1.state;
|
|
562
|
-
const widgets = [];
|
|
563
|
-
const lines = getVisibleLines(view$1);
|
|
564
|
-
const indentWidth = language.getIndentUnit(state);
|
|
565
|
-
const { thickness, activeThickness, hoverThickness, additionalPadding, foldBlockOnClick, highlightActiveBlockBackground, hideFirstIndent, } = state.facet(indentationGuidesConfig);
|
|
566
|
-
const map = getNewIndentationMap(state, lines);
|
|
567
|
-
const lineLevels = new Map();
|
|
568
|
-
for (const line of lines) {
|
|
569
|
-
const entry = map.get(line.number);
|
|
570
|
-
const level = (_a = entry === null || entry === void 0 ? void 0 : entry.level) !== null && _a !== void 0 ? _a : 0;
|
|
571
|
-
lineLevels.set(line.number, level);
|
|
572
|
-
/** Workaround for folded empty lines in python and similar languages.
|
|
573
|
-
* Without this check, unwanted indentation guides will be drawn after foldPlaceholder
|
|
574
|
-
*/
|
|
575
|
-
const foldedAndEmpty = isLineFolded(view$1, entry.line.number) &&
|
|
576
|
-
isLineEmpty(view$1, entry.line.number);
|
|
577
|
-
if (!level || foldedAndEmpty) {
|
|
578
|
-
continue;
|
|
579
|
-
}
|
|
580
|
-
const deco = view.Decoration.widget({
|
|
581
|
-
widget: new ClickableIndentationGuideWidget(indentWidth, level, line.number, {
|
|
582
|
-
thickness,
|
|
583
|
-
activeThickness,
|
|
584
|
-
hoverThickness,
|
|
585
|
-
additionalPadding,
|
|
586
|
-
foldOnClick: foldBlockOnClick,
|
|
587
|
-
highlightBackground: highlightActiveBlockBackground,
|
|
588
|
-
hideFirstIndent,
|
|
589
|
-
}),
|
|
590
|
-
side: 0,
|
|
591
|
-
});
|
|
592
|
-
widgets.push(deco.range(line.from));
|
|
593
|
-
}
|
|
594
|
-
return {
|
|
595
|
-
indentationMap: map,
|
|
596
|
-
decoSet: view.Decoration.set(widgets),
|
|
597
|
-
lineLevels,
|
|
598
|
-
};
|
|
599
|
-
}
|
|
600
|
-
|
|
601
639
|
function handleGuideHover(guideElement, plugin) {
|
|
602
640
|
var _a, _b, _c, _d, _e;
|
|
603
641
|
if (!guideElement || !plugin) {
|
|
@@ -622,28 +660,42 @@ function handleGuideHover(guideElement, plugin) {
|
|
|
622
660
|
plugin.applyHoverClasses(start, end, col);
|
|
623
661
|
}
|
|
624
662
|
|
|
663
|
+
const DEBOUNCE_DELAY_MS = 500;
|
|
625
664
|
class IndentationViewPlugin {
|
|
626
665
|
constructor(view) {
|
|
627
666
|
var _a, _b;
|
|
628
667
|
this.hoveredGuide = null;
|
|
629
|
-
|
|
668
|
+
this.lastCursorPos = null;
|
|
669
|
+
this.allStateDebounceId = null;
|
|
670
|
+
const visibleLines = getVisibleLines(view);
|
|
671
|
+
this.indentationMap = this.updateIndentationMap(view, visibleLines);
|
|
672
|
+
const built = buildIndentationDecorations(view, this.indentationMap, visibleLines);
|
|
630
673
|
this.highlightHoveredGuide = false;
|
|
631
674
|
this.highlightHoveredBlock = false;
|
|
632
|
-
this.activeColEdges = [];
|
|
633
|
-
this.activeCol = 0;
|
|
634
675
|
this.view = view;
|
|
635
|
-
this.viewContentWidth =
|
|
636
|
-
|
|
637
|
-
this.contentElement = view.dom.querySelector('.cm-content');
|
|
676
|
+
this.viewContentWidth = (_b = (_a = view.contentDOM) === null || _a === void 0 ? void 0 : _a.clientWidth) !== null && _b !== void 0 ? _b : 0;
|
|
677
|
+
this.contentElement = view.contentDOM;
|
|
638
678
|
this.decorations = built.decoSet;
|
|
639
679
|
this.lineLevels = built.lineLevels;
|
|
640
|
-
this.indentationMap = built.indentationMap;
|
|
641
680
|
this.unitWidth = language.getIndentUnit(view.state);
|
|
642
681
|
this.currentLineNumber = getCurrentLine(view.state).number;
|
|
643
682
|
}
|
|
683
|
+
updateIndentationMap(view, visibleLines) {
|
|
684
|
+
var _a;
|
|
685
|
+
if (this.allStateDebounceId) {
|
|
686
|
+
clearTimeout(this.allStateDebounceId);
|
|
687
|
+
}
|
|
688
|
+
(_a = this.indentationMap) === null || _a === void 0 ? void 0 : _a.terminate();
|
|
689
|
+
this.indentationMap = getNewIndentationMap(view.state, visibleLines);
|
|
690
|
+
this.allStateDebounceId = setTimeout(() => {
|
|
691
|
+
const allLines = getAllLines(view);
|
|
692
|
+
this.indentationMap.initLinesAsync(allLines);
|
|
693
|
+
}, DEBOUNCE_DELAY_MS);
|
|
694
|
+
return this.indentationMap;
|
|
695
|
+
}
|
|
644
696
|
update(update) {
|
|
645
697
|
var _a, _b, _c;
|
|
646
|
-
(_a = this.contentElement) !== null && _a !== void 0 ? _a : (this.contentElement = update.view.
|
|
698
|
+
(_a = this.contentElement) !== null && _a !== void 0 ? _a : (this.contentElement = update.view.contentDOM);
|
|
647
699
|
const unitWidth = language.getIndentUnit(update.state);
|
|
648
700
|
const unitWidthChanged = unitWidth !== this.unitWidth;
|
|
649
701
|
if (unitWidthChanged) {
|
|
@@ -661,11 +713,25 @@ class IndentationViewPlugin {
|
|
|
661
713
|
update.viewportChanged ||
|
|
662
714
|
viewContentWidth !== this.viewContentWidth;
|
|
663
715
|
const activeBlockUpdateRequired = isHighlightActive && viewChanged;
|
|
664
|
-
|
|
665
|
-
|
|
716
|
+
const visibleLines = update.docChanged ||
|
|
717
|
+
update.viewportChanged ||
|
|
718
|
+
unitWidthChanged ||
|
|
719
|
+
activeBlockUpdateRequired
|
|
720
|
+
? getVisibleLines(update.view)
|
|
721
|
+
: null;
|
|
722
|
+
if (!visibleLines) {
|
|
723
|
+
return;
|
|
724
|
+
}
|
|
725
|
+
if (update.docChanged || unitWidthChanged) {
|
|
726
|
+
this.updateIndentationMap(update.view, visibleLines);
|
|
727
|
+
}
|
|
728
|
+
if (update.viewportChanged || unitWidthChanged) {
|
|
729
|
+
if (!update.docChanged) {
|
|
730
|
+
this.indentationMap.initLinesSync(visibleLines);
|
|
731
|
+
}
|
|
732
|
+
const built = buildIndentationDecorations(update.view, this.indentationMap, visibleLines);
|
|
666
733
|
this.decorations = built.decoSet;
|
|
667
734
|
this.lineLevels = built.lineLevels;
|
|
668
|
-
this.indentationMap = built.indentationMap;
|
|
669
735
|
this.clearHoverClasses();
|
|
670
736
|
}
|
|
671
737
|
if (activeBlockUpdateRequired) {
|
|
@@ -675,46 +741,20 @@ class IndentationViewPlugin {
|
|
|
675
741
|
}
|
|
676
742
|
updateActiveColumns(lineNumber, highlightActiveMarker, highlightActiveBlockBackground) {
|
|
677
743
|
requestAnimationFrame(() => {
|
|
678
|
-
var _a
|
|
744
|
+
var _a;
|
|
679
745
|
this.clearActiveClasses();
|
|
680
|
-
const
|
|
681
|
-
|
|
682
|
-
if (lines) {
|
|
683
|
-
lines.forEach(line => {
|
|
684
|
-
const { active: activeCol } = line;
|
|
685
|
-
const lineNumber = line.line.number;
|
|
686
|
-
if (highlightActiveMarker) {
|
|
687
|
-
this.applyActiveMarker(lineNumber, activeCol !== null && activeCol !== void 0 ? activeCol : 0);
|
|
688
|
-
}
|
|
689
|
-
if (highlightActiveBlockBackground) {
|
|
690
|
-
this.applyBackgroundHighlight(lineNumber, activeCol !== null && activeCol !== void 0 ? activeCol : 0, 'active');
|
|
691
|
-
}
|
|
692
|
-
});
|
|
693
|
-
this.activeColEdges = [
|
|
694
|
-
lines[0].line.number,
|
|
695
|
-
lines[lines.length - 1].line.number,
|
|
696
|
-
];
|
|
697
|
-
this.activeCol = (_b = lines[0].active) !== null && _b !== void 0 ? _b : 0;
|
|
746
|
+
const activeLines = (_a = this.indentationMap) === null || _a === void 0 ? void 0 : _a.getActiveLinesNumbers(lineNumber);
|
|
747
|
+
if (!(activeLines === null || activeLines === void 0 ? void 0 : activeLines.length) || activeLines[0].active === undefined) {
|
|
698
748
|
return;
|
|
699
749
|
}
|
|
700
|
-
|
|
701
|
-
|
|
750
|
+
const minLineNumber = activeLines.reduce((acc, line) => Math.min(acc, line.line.number), Infinity) - 1;
|
|
751
|
+
const maxLineNumber = activeLines.reduce((acc, line) => Math.max(acc, line.line.number), -Infinity) + 1;
|
|
752
|
+
if (highlightActiveMarker) {
|
|
753
|
+
this.applyActiveMarker(minLineNumber, maxLineNumber, activeLines[0].active);
|
|
754
|
+
}
|
|
755
|
+
if (highlightActiveBlockBackground) {
|
|
756
|
+
this.applyBackgroundHighlight(minLineNumber, maxLineNumber, activeLines[0].active, 'active');
|
|
702
757
|
}
|
|
703
|
-
/** If current line is outside computed indentation map lines,
|
|
704
|
-
* compute active block lines from active column points */
|
|
705
|
-
const ranges = this.activeColEdges.map(edge => this.computeBlockRange(edge, this.activeCol));
|
|
706
|
-
ranges.forEach(range => {
|
|
707
|
-
for (let i = range.start; i <= range.end; i++) {
|
|
708
|
-
if (highlightActiveMarker) {
|
|
709
|
-
this.applyActiveMarker(lineNumber, this.activeCol);
|
|
710
|
-
}
|
|
711
|
-
if (highlightActiveBlockBackground) {
|
|
712
|
-
this.applyBackgroundHighlight(lineNumber, this.activeCol, 'active');
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
this.activeColEdges.push(range.start, range.end);
|
|
716
|
-
});
|
|
717
|
-
this.activeColEdges = Array.from(new Set(this.activeColEdges));
|
|
718
758
|
});
|
|
719
759
|
}
|
|
720
760
|
/** compute block (inclusive line numbers) for a given clicked line and column (0-based) */
|
|
@@ -746,29 +786,37 @@ class IndentationViewPlugin {
|
|
|
746
786
|
return { start, end };
|
|
747
787
|
}
|
|
748
788
|
clearActiveClasses() {
|
|
749
|
-
const dom = this.view.
|
|
789
|
+
const dom = this.view.contentDOM;
|
|
750
790
|
dom
|
|
751
791
|
.querySelectorAll('.cm-indentation-guide-button_active')
|
|
752
|
-
.forEach(el => el.classList.remove('cm-indentation-guide-button_active'));
|
|
792
|
+
.forEach((el) => el.classList.remove('cm-indentation-guide-button_active'));
|
|
753
793
|
dom
|
|
754
794
|
.querySelectorAll('.cm-indentation-guide-background-highlight_active')
|
|
755
|
-
.forEach(el => {
|
|
795
|
+
.forEach((el) => {
|
|
756
796
|
el.classList.remove('cm-indentation-guide-background-highlight_active');
|
|
757
797
|
});
|
|
758
798
|
}
|
|
759
|
-
applyActiveMarker(
|
|
760
|
-
const root = this.view.
|
|
761
|
-
const selector = `.cm-indentation-guide
|
|
762
|
-
root.querySelectorAll(selector).forEach(btn => {
|
|
763
|
-
|
|
799
|
+
applyActiveMarker(start, end, col) {
|
|
800
|
+
const root = this.view.contentDOM;
|
|
801
|
+
const selector = `.cm-indentation-guide-button[data-col="${col}"]`;
|
|
802
|
+
root.querySelectorAll(selector).forEach((btn) => {
|
|
803
|
+
var _a;
|
|
804
|
+
const lineAttr = (_a = btn.parentElement) === null || _a === void 0 ? void 0 : _a.dataset.line;
|
|
805
|
+
if (!lineAttr) {
|
|
806
|
+
return;
|
|
807
|
+
}
|
|
808
|
+
const ln = Number(lineAttr);
|
|
809
|
+
if (ln >= start && ln <= end) {
|
|
810
|
+
btn.classList.add('cm-indentation-guide-button_active');
|
|
811
|
+
}
|
|
764
812
|
});
|
|
765
813
|
}
|
|
766
814
|
/** highlight DOM buttons in column `col` for lines in [start, end] */
|
|
767
815
|
applyHoverClasses(start, end, col) {
|
|
768
816
|
this.clearHoverClasses();
|
|
769
|
-
const root = this.view.
|
|
817
|
+
const root = this.view.contentDOM;
|
|
770
818
|
const selector = `.cm-indentation-guide-button[data-col="${col}"]`;
|
|
771
|
-
root.querySelectorAll(selector).forEach(btn => {
|
|
819
|
+
root.querySelectorAll(selector).forEach((btn) => {
|
|
772
820
|
var _a;
|
|
773
821
|
const lineAttr = (_a = btn.parentElement) === null || _a === void 0 ? void 0 : _a.dataset.line;
|
|
774
822
|
if (!lineAttr) {
|
|
@@ -780,68 +828,88 @@ class IndentationViewPlugin {
|
|
|
780
828
|
btn.classList.add('cm-indentation-guide-button_hover');
|
|
781
829
|
}
|
|
782
830
|
if (this.highlightHoveredBlock) {
|
|
783
|
-
this.applyBackgroundHighlight(
|
|
831
|
+
this.applyBackgroundHighlight(start, end, col, 'hover');
|
|
784
832
|
}
|
|
785
833
|
}
|
|
786
834
|
});
|
|
787
835
|
this.hoveredGuide = { col, start, end };
|
|
788
836
|
}
|
|
789
|
-
applyBackgroundHighlight(
|
|
790
|
-
const root = this.view.
|
|
791
|
-
const selector = `.cm-indentation-guide
|
|
792
|
-
const
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
837
|
+
applyBackgroundHighlight(start, end, col, type) {
|
|
838
|
+
const root = this.view.contentDOM;
|
|
839
|
+
const selector = `.cm-indentation-guide-button[data-col="${col}"]`;
|
|
840
|
+
const highlightBackgroundSelector = `.cm-indentation-guide-background-highlight`;
|
|
841
|
+
root.querySelectorAll(selector).forEach((button) => {
|
|
842
|
+
var _a, _b;
|
|
843
|
+
const lineAttr = (_a = button.parentElement) === null || _a === void 0 ? void 0 : _a.dataset.line;
|
|
844
|
+
if (!lineAttr) {
|
|
845
|
+
return;
|
|
846
|
+
}
|
|
847
|
+
const ln = Number(lineAttr);
|
|
848
|
+
if (ln < start || ln > end) {
|
|
849
|
+
return;
|
|
850
|
+
}
|
|
851
|
+
const backgroundDiv = (_b = button.parentElement) === null || _b === void 0 ? void 0 : _b.querySelector(highlightBackgroundSelector);
|
|
852
|
+
if (!backgroundDiv) {
|
|
853
|
+
return;
|
|
854
|
+
}
|
|
855
|
+
let highlightLeft = button.offsetLeft;
|
|
856
|
+
let btnWidth = button.offsetWidth;
|
|
857
|
+
backgroundDiv.style.setProperty(`--indentation-guide-background-highlight-${type}-left`, `${highlightLeft}px`);
|
|
858
|
+
backgroundDiv.style.setProperty(`--indentation-guide-background-highlight-${type}-width`, `${this.viewContentWidth - (highlightLeft !== null && highlightLeft !== void 0 ? highlightLeft : 0) - (btnWidth !== null && btnWidth !== void 0 ? btnWidth : 0) / 2}px`);
|
|
859
|
+
backgroundDiv.classList.add(`cm-indentation-guide-background-highlight_${type}`);
|
|
860
|
+
});
|
|
806
861
|
}
|
|
807
862
|
clearHoverClasses() {
|
|
808
863
|
var _a;
|
|
809
864
|
if (((_a = this.hoveredGuide) === null || _a === void 0 ? void 0 : _a.col) === null) {
|
|
810
865
|
return;
|
|
811
866
|
}
|
|
812
|
-
const dom = this.view.
|
|
867
|
+
const dom = this.view.contentDOM;
|
|
813
868
|
dom
|
|
814
869
|
.querySelectorAll('.cm-indentation-guide-button_hover')
|
|
815
|
-
.forEach(el => el.classList.remove('cm-indentation-guide-button_hover'));
|
|
870
|
+
.forEach((el) => el.classList.remove('cm-indentation-guide-button_hover'));
|
|
816
871
|
this.hoveredGuide = null;
|
|
817
872
|
dom
|
|
818
873
|
.querySelectorAll('.cm-indentation-guide-background-highlight')
|
|
819
|
-
.forEach(el => {
|
|
874
|
+
.forEach((el) => {
|
|
820
875
|
el.classList.remove('cm-indentation-guide-background-highlight_hover');
|
|
821
876
|
});
|
|
822
877
|
}
|
|
823
878
|
}
|
|
824
879
|
const indentationGuidesPlugin = view.ViewPlugin.fromClass(IndentationViewPlugin, {
|
|
825
|
-
decorations: v => v.decorations,
|
|
880
|
+
decorations: (v) => v.decorations,
|
|
826
881
|
eventHandlers: {
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
if (!
|
|
882
|
+
scroll() {
|
|
883
|
+
var _a;
|
|
884
|
+
if (!this.lastCursorPos) {
|
|
830
885
|
return;
|
|
831
886
|
}
|
|
832
|
-
const
|
|
833
|
-
|
|
887
|
+
const target = (_a = document
|
|
888
|
+
.elementFromPoint(this.lastCursorPos.x, this.lastCursorPos.y)) === null || _a === void 0 ? void 0 : _a.closest('.cm-indentation-guide-button');
|
|
889
|
+
if (target) {
|
|
890
|
+
handleGuideHover(target, this);
|
|
891
|
+
}
|
|
892
|
+
return;
|
|
893
|
+
},
|
|
894
|
+
mousemove(e, view) {
|
|
895
|
+
const { highlightHoveredMarker, highlightHoveredBlockBackground } = view.state.facet(indentationGuidesConfig);
|
|
896
|
+
if (!highlightHoveredMarker && !highlightHoveredBlockBackground) {
|
|
834
897
|
return;
|
|
835
898
|
}
|
|
836
899
|
const target = e.target.closest('.cm-indentation-guide-button');
|
|
837
900
|
if (target) {
|
|
838
|
-
handleGuideHover(target,
|
|
901
|
+
handleGuideHover(target, this);
|
|
902
|
+
this.lastCursorPos = {
|
|
903
|
+
x: e.clientX,
|
|
904
|
+
y: e.clientY,
|
|
905
|
+
};
|
|
839
906
|
}
|
|
840
907
|
else {
|
|
841
|
-
|
|
908
|
+
this.clearHoverClasses();
|
|
909
|
+
this.lastCursorPos = null;
|
|
842
910
|
}
|
|
843
911
|
},
|
|
844
|
-
mouseout
|
|
912
|
+
mouseout(e, view) {
|
|
845
913
|
const { highlightHoveredMarker, highlightHoveredBlockBackground } = view.state.facet(indentationGuidesConfig);
|
|
846
914
|
if (!highlightHoveredMarker && !highlightHoveredBlockBackground) {
|
|
847
915
|
return;
|
|
@@ -851,11 +919,10 @@ const indentationGuidesPlugin = view.ViewPlugin.fromClass(IndentationViewPlugin,
|
|
|
851
919
|
if (!related ||
|
|
852
920
|
!related.closest ||
|
|
853
921
|
!related.closest('.cm-indentation-guide')) {
|
|
854
|
-
|
|
855
|
-
plugin === null || plugin === void 0 ? void 0 : plugin.clearHoverClasses();
|
|
922
|
+
this.clearHoverClasses();
|
|
856
923
|
}
|
|
857
924
|
},
|
|
858
|
-
mousedown
|
|
925
|
+
mousedown(e, view) {
|
|
859
926
|
var _a, _b;
|
|
860
927
|
const { foldBlockOnClick } = view.state.facet(indentationGuidesConfig);
|
|
861
928
|
if (!foldBlockOnClick) {
|
|
@@ -871,10 +938,6 @@ const indentationGuidesPlugin = view.ViewPlugin.fromClass(IndentationViewPlugin,
|
|
|
871
938
|
if (!lineAttr || !colAttr) {
|
|
872
939
|
return false;
|
|
873
940
|
}
|
|
874
|
-
const plugin = view.plugin(indentationGuidesPlugin);
|
|
875
|
-
if (!plugin) {
|
|
876
|
-
return false;
|
|
877
|
-
}
|
|
878
941
|
const lineNumber = Number(lineAttr);
|
|
879
942
|
const col = Number(colAttr);
|
|
880
943
|
const lines = getAllLines(view);
|
|
@@ -885,8 +948,8 @@ const indentationGuidesPlugin = view.ViewPlugin.fromClass(IndentationViewPlugin,
|
|
|
885
948
|
const level = (_b = entry === null || entry === void 0 ? void 0 : entry.level) !== null && _b !== void 0 ? _b : 0;
|
|
886
949
|
lineLevels.set(line.number, level);
|
|
887
950
|
}
|
|
888
|
-
|
|
889
|
-
const { start } =
|
|
951
|
+
this.lineLevels = lineLevels;
|
|
952
|
+
const { start } = this.computeBlockRange(lineNumber, col);
|
|
890
953
|
const range = getNearestFoldRange(view, start - 1);
|
|
891
954
|
if (!range) {
|
|
892
955
|
return;
|