Skip to content

Commit

Permalink
feat(kit): fix intersecting ranges
Browse files Browse the repository at this point in the history
  • Loading branch information
MillerSvt authored and splincode committed Nov 14, 2023
1 parent 4e8fc5e commit 30d1178
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import {encapsulation} from '@demo/emulate/encapsulation';
selector: 'tui-highlight-example-4',
templateUrl: './index.html',
styleUrls: ['./index.less'],
changeDetection,
encapsulation,
changeDetection,
})
export class TuiHighlightExample4 {
readonly rows = [
Expand Down
95 changes: 75 additions & 20 deletions projects/kit/directives/highlight/highlight.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ import {
tuiToArray,
} from '@taiga-ui/cdk';
import {TuiToRegexpPipe} from '@taiga-ui/kit/pipes';
import {Observable, Subject} from 'rxjs';
import {mergeAll, switchMap, takeUntil} from 'rxjs/operators';
import {merge, Observable, Subject} from 'rxjs';
import {switchMap, takeUntil} from 'rxjs/operators';

import {TuiHighlightComponent} from './highlight.component';

Expand All @@ -45,9 +45,7 @@ export class TuiHighlightDirective implements OnChanges {
svgNodeFilter,
);

private readonly clearHighlights$ = new Subject<void>();

private readonly addHighlight$ = new Subject<Observable<never>>();
private readonly highlight$ = new Subject<ReadonlyArray<Observable<never>>>();

private readonly cf: ComponentFactory<TuiHighlightComponent>;

Expand Down Expand Up @@ -76,9 +74,9 @@ export class TuiHighlightDirective implements OnChanges {
this.updateHighlights();
});

this.clearHighlights$
this.highlight$
.pipe(
switchMap(() => this.addHighlight$.pipe(mergeAll())),
switchMap(highlights => merge(...highlights)),
takeUntil(destroy$),
)
.subscribe();
Expand Down Expand Up @@ -117,33 +115,90 @@ export class TuiHighlightDirective implements OnChanges {
}

private updateHighlights(): void {
this.clearHighlights$.next();

if (!this.match) {
return;
}

this.highlight$.next(this.createHighlights());
}

private createHighlights(): ReadonlyArray<Observable<never>> {
const hostRect = this.el.nativeElement.getBoundingClientRect();

const highlights: Array<Observable<never>> = [];

for (const node of this.getNodes()) {
const occurrences: TuiHighlightOccurrence[] = [];

for (const occurrence of this.getOccurrences(node.nodeValue)) {
const range = this.createRange(node, occurrence);
if (!this.tuiHighlightMultiOccurrences) {
return [
this.createHighlight(
hostRect,
this.createRange(node, occurrence),
),
];
}

this.addHighlight$.next(
this.createHighlight(hostRect, range.getBoundingClientRect()),
);
occurrences[occurrence.index] = occurrence;
}

if (!this.tuiHighlightMultiOccurrences) {
return;
if (!occurrences.length) {
continue;
}

const mergedOccurrences: TuiHighlightOccurrence[] = [];

for (const occurrence of occurrences) {
if (!occurrence) {
continue;
}

const lastMergedOccurrence = mergedOccurrences.at(-1);

if (
lastMergedOccurrence &&
occurrence.index <=
lastMergedOccurrence.index + lastMergedOccurrence.length
) {
const end = Math.max(
lastMergedOccurrence.index + lastMergedOccurrence.length,
occurrence.index + occurrence.length,
);

lastMergedOccurrence.length = end - lastMergedOccurrence.index;
} else {
mergedOccurrences.push(occurrence);

if (lastMergedOccurrence) {
highlights.push(
this.createHighlight(
hostRect,
this.createRange(node, lastMergedOccurrence),
),
);
}
}
}

const lastMergedOccurrence = mergedOccurrences.at(-1);

if (lastMergedOccurrence) {
highlights.push(
this.createHighlight(
hostRect,
this.createRange(node, lastMergedOccurrence),
),
);
}
}

return highlights;
}

private createHighlight(
hostRect: DOMRect,
{left, top, width, height}: DOMRect,
): Observable<never> {
private createHighlight(hostRect: DOMRect, range: Range): Observable<never> {
const {left, top, width, height} = range.getBoundingClientRect();

return new Observable<never>(() => {
const ref = this.vcr.createComponent(this.cf);
const {instance} = ref;
Expand Down Expand Up @@ -177,7 +232,7 @@ export class TuiHighlightDirective implements OnChanges {

for (const item of this.patterns) {

Check failure on line 233 in projects/kit/directives/highlight/highlight.directive.ts

View workflow job for this annotation

GitHub Actions / Lint

Don't use simple "for-of" instead of "forEach"
for (const match of source.matchAll(item)) {

Check failure on line 234 in projects/kit/directives/highlight/highlight.directive.ts

View workflow job for this annotation

GitHub Actions / Lint

Don't use simple "for-of" instead of "forEach"
if (tuiIsNumber(match.index) && match.length) {
if (tuiIsNumber(match.index) && match[0].length) {
yield {
index: match.index,
length: match[0].length,
Expand Down

0 comments on commit 30d1178

Please sign in to comment.