@hmcts/media-viewer 4.2.38-innerhtml-security-update → 4.2.39-redact

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.
Binary file
@@ -2065,8 +2065,8 @@ class HighlightCreateDirective {
2065
2065
  }
2066
2066
  this.setPageProperties(page);
2067
2067
  const range = selection.getRangeAt(0).cloneRange();
2068
- const clientRects = range.getClientRects();
2069
- if (!clientRects || clientRects.length === 0) {
2068
+ const selectionRects = this.getSelectionRectangles(range);
2069
+ if (!selectionRects || selectionRects.length === 0) {
2070
2070
  return [];
2071
2071
  }
2072
2072
  let textLayerElement = range.startContainer;
@@ -2078,7 +2078,7 @@ class HighlightCreateDirective {
2078
2078
  return [];
2079
2079
  }
2080
2080
  this.removeEnhancedTextModeStyling(textLayerElement);
2081
- return this.processClientRects(clientRects, textLayer);
2081
+ return this.processClientRects(selectionRects, textLayer);
2082
2082
  }
2083
2083
  onPdfViewerClick(event) {
2084
2084
  this.store.dispatch(new SelectedAnnotation({
@@ -2096,14 +2096,23 @@ class HighlightCreateDirective {
2096
2096
  this.removeEnhancedTextModeStyling(localElement);
2097
2097
  if (selection.rangeCount && !selection.isCollapsed) {
2098
2098
  const range = selection.getRangeAt(0).cloneRange();
2099
- const clientRects = range.getClientRects();
2100
- if (clientRects) {
2099
+ const selectionRects = this.getSelectionRectangles(range);
2100
+ if (selectionRects) {
2101
2101
  const textLayer = localElement.closest(".textLayer");
2102
- return this.processClientRects(clientRects, textLayer);
2102
+ return this.processClientRects(selectionRects, textLayer);
2103
2103
  }
2104
2104
  }
2105
2105
  }
2106
2106
  }
2107
+ getSelectionRectangles(range) {
2108
+ if (this.toolbarEvents.redactionMode.getValue()) {
2109
+ const boundingRect = range.getBoundingClientRect();
2110
+ if (boundingRect && boundingRect.width > 0 && boundingRect.height > 0) {
2111
+ return [boundingRect];
2112
+ }
2113
+ }
2114
+ return range.getClientRects();
2115
+ }
2107
2116
  createTextRectangle(rect, parentRect) {
2108
2117
  const height = rect.bottom - rect.top;
2109
2118
  const width = rect.right - rect.left;
@@ -3353,55 +3362,26 @@ class TextHighlightDirective {
3353
3362
  highlightInputText(textToHighlight) {
3354
3363
  this.resetHighlight();
3355
3364
  this.textToHighlight = textToHighlight;
3356
- const searchPattern = new RegExp(this.escapeRegExp(textToHighlight), 'gi');
3365
+ const searchPattern = new RegExp(textToHighlight, 'gi');
3357
3366
  const hostElement = this.element.nativeElement;
3358
- this.highlightTextNodes(hostElement, searchPattern);
3367
+ if (hostElement.innerHTML.match(searchPattern)) {
3368
+ hostElement.innerHTML = hostElement.innerHTML
3369
+ .replace(searchPattern, this.highlightPattern('$&'));
3370
+ }
3359
3371
  this.textToHighlight = undefined;
3360
3372
  }
3361
3373
  resetHighlight() {
3362
3374
  const hostElement = this.element.nativeElement;
3363
- Array.from(hostElement.querySelectorAll('span.mvTextHighlight')).forEach((highlightElement) => {
3364
- highlightElement.replaceWith(document.createTextNode(highlightElement.textContent || ''));
3365
- });
3366
- hostElement.normalize();
3367
- }
3368
- highlightTextNodes(hostElement, searchPattern) {
3369
- const walker = document.createTreeWalker(hostElement, NodeFilter.SHOW_TEXT);
3370
- const textNodes = [];
3371
- let currentNode = walker.nextNode();
3372
- while (currentNode) {
3373
- textNodes.push(currentNode);
3374
- currentNode = walker.nextNode();
3375
- }
3376
- textNodes.forEach((textNode) => this.highlightTextNode(textNode, searchPattern));
3377
- }
3378
- highlightTextNode(textNode, searchPattern) {
3379
- const text = textNode.textContent || '';
3380
- const matches = Array.from(text.matchAll(searchPattern));
3381
- if (matches.length === 0) {
3382
- return;
3383
- }
3384
- const fragment = document.createDocumentFragment();
3385
- let currentIndex = 0;
3386
- matches.forEach((match) => {
3387
- const matchIndex = match.index || 0;
3388
- const matchText = match[0];
3389
- if (matchIndex > currentIndex) {
3390
- fragment.appendChild(document.createTextNode(text.slice(currentIndex, matchIndex)));
3375
+ const searchPattern = new RegExp(this.highlightPattern('(.*?)'), 'gi');
3376
+ while (hostElement.innerHTML.match(searchPattern)) {
3377
+ const matchGroups = searchPattern.exec(hostElement.innerHTML);
3378
+ if (matchGroups) {
3379
+ hostElement.innerHTML = hostElement.innerHTML.replace(matchGroups[0], matchGroups[1]);
3391
3380
  }
3392
- const highlightElement = document.createElement('span');
3393
- highlightElement.className = 'mvTextHighlight';
3394
- highlightElement.textContent = matchText;
3395
- fragment.appendChild(highlightElement);
3396
- currentIndex = matchIndex + matchText.length;
3397
- });
3398
- if (currentIndex < text.length) {
3399
- fragment.appendChild(document.createTextNode(text.slice(currentIndex)));
3400
3381
  }
3401
- textNode.replaceWith(fragment);
3402
3382
  }
3403
- escapeRegExp(value) {
3404
- return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
3383
+ highlightPattern(dynamicText) {
3384
+ return '<span class="mvTextHighlight">' + dynamicText + '</span>';
3405
3385
  }
3406
3386
  /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.26", ngImport: i0, type: TextHighlightDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
3407
3387
  /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.26", type: TextHighlightDirective, isStandalone: false, selector: "[mvTextHighlight]", inputs: { textToHighlight: "textToHighlight" }, ngImport: i0 }); }
@@ -7972,14 +7952,12 @@ class GovUkLabelComponent {
7972
7952
  /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.26", ngImport: i0, type: GovUkLabelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
7973
7953
  /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.26", type: GovUkLabelComponent, isStandalone: false, selector: "mv-gov-label", inputs: { config: "config" }, ngImport: i0, template: `<h1 *ngIf="config.isPageHeading else noHeading">
7974
7954
  <label *ngIf="config.label" [class]="config.classes + ' govuk-label'"
7975
- [for]="config.id">
7976
- {{ config.label }}
7955
+ [for]="config.id" [innerHTML]="config.label">
7977
7956
  </label>
7978
7957
  </h1>
7979
7958
  <ng-template #noHeading>
7980
7959
  <label *ngIf="config.label" [class]="config.classes + ' govuk-label'"
7981
- [for]="config.id">
7982
- {{ config.label }}
7960
+ [for]="config.id" [innerHTML]="config.label">
7983
7961
  </label>
7984
7962
  </ng-template>
7985
7963
  `, isInline: true, dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); }
@@ -7990,14 +7968,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.26", ngImpo
7990
7968
  selector: 'mv-gov-label',
7991
7969
  template: `<h1 *ngIf="config.isPageHeading else noHeading">
7992
7970
  <label *ngIf="config.label" [class]="config.classes + ' govuk-label'"
7993
- [for]="config.id">
7994
- {{ config.label }}
7971
+ [for]="config.id" [innerHTML]="config.label">
7995
7972
  </label>
7996
7973
  </h1>
7997
7974
  <ng-template #noHeading>
7998
7975
  <label *ngIf="config.label" [class]="config.classes + ' govuk-label'"
7999
- [for]="config.id">
8000
- {{ config.label }}
7976
+ [for]="config.id" [innerHTML]="config.label">
8001
7977
  </label>
8002
7978
  </ng-template>
8003
7979
  `,