Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
"core-js": "3.44.0",
"diff-match-patch": "1.0.5",
"dmn-js": "10.3.0",
"dompurify": "^3.3.1",
"jodit": "4.7.9",
"jszip": "3.10.1",
"lodash": "4.17.23",
Expand Down Expand Up @@ -100,6 +101,7 @@
"@microsoft/eslint-formatter-sarif": "3.1.0",
"@stylistic/eslint-plugin": "4.4.1",
"@types/diff-match-patch": "^1.0.32",
"@types/dompurify": "^3.0.5",
"@types/jest": "27.5.2",
"@types/lodash": "^4.14.161",
"@types/marked": "^4.0.1",
Expand Down
6 changes: 3 additions & 3 deletions src/app/about/about.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@
<h2>
<span
*ngIf="!isLoadingContent"
[innerHTML]="applicationName | safe: 'html'"
[innerHTML]="applicationName | safe"
></span>
&nbsp;<span style="font-size: 14px">version {{ appVersion }}</span>
</h2>
<div
*ngIf="!isLoadingContent"
[innerHTML]="content | safe: 'html'"
[innerHTML]="content | safe"
class="clearfix"
></div>
<p *ngIf="!isLoadingContent" [innerHTML]="contactDetails | safe: 'html'"></p>
<p *ngIf="!isLoadingContent" [innerHTML]="contactDetails | safe"></p>
</div>
1 change: 1 addition & 0 deletions src/app/content/content-editor/content-editor.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ export class ContentEditorComponent implements OnInit {
return false;
}

// TODO: Revisit this regexp
const expression = /<([A-Z][A-Z0-9]*)\b[^>]*>(.*?)<\/\1>/gim;
return expression.test(this.content);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@
>
</ngx-jodit>
<div style="clear: both">
<span [innerHTML]="displayContent | safe: 'html'" *ngIf="!inEditMode"></span>
<span [innerHTML]="displayContent | safe" *ngIf="!inEditMode"></span>
</div>
14 changes: 11 additions & 3 deletions src/app/content/html/html-editor/html-editor.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,14 @@ export class HtmlEditorComponent implements OnInit, OnChanges {
buttonsSM: buttons,
buttonsXS: buttons,
sourceEditor: 'ace',
cleanHTML: {
// deny script tags; remove attributes like onerror
denyTags: 'script',
// if any element has error handlers, remove them
removeOnError: true,
// run cleaner inside an iframe sandbox (safer but slower)
useIframeSandbox: true
} as any
};
}

Expand All @@ -163,7 +171,7 @@ export class HtmlEditorComponent implements OnInit, OnChanges {
// Intercept the HTML content to render for display only so that certain parts can be altered
// The version or branch override will try to force all Mauro path links to work within the same context as
// the containing model the root element is in, if available
this.displayContent = this.htmlParser.parseAndModify(this.description, this.rootElement,{
this.displayContent = this.htmlParser.parseAndModify(this.description, this.rootElement, {
versionOrBranchOverride: this.getVersionOrBranchOverride()
});
}
Expand Down Expand Up @@ -218,8 +226,8 @@ export class HtmlEditorComponent implements OnInit, OnChanges {
if (!component.allowAutocompleteSearch) {
return;
}
const savedSelection = editor.selection.save();
const focusNode = editor.selection.sel.focusNode;
const savedSelection = editor.selection?.save();
const focusNode = editor.selection?.sel?.focusNode;

component.dialog
.openElementSearch(component.rootElement)
Expand Down
5 changes: 3 additions & 2 deletions src/app/content/markdown/markdown.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ SPDX-License-Identifier: Apache-2.0
import { Directive, Input, ElementRef, Renderer2, OnInit } from '@angular/core';
import { MarkdownParserService } from './markdown-parser/markdown-parser.service';
import { CatalogueItem } from '@maurodatamapper/mdm-resources';
import DOMPurify from 'dompurify';

@Directive({
selector: '[mdmMarkdown]',
Expand Down Expand Up @@ -67,9 +68,9 @@ export class MarkdownDirective implements OnInit {
if (this.markdown) {
let html = this.markdownParser.parse(this.markdown, this.renderType, this.rootElement);
if (this.renderType === 'text') {
html = `<p>${html}</p>`;
html = `<span>${html}</span>`;
}
this.renderer.setProperty(this.el.nativeElement, 'innerHTML', html);
this.renderer.setProperty(this.el.nativeElement, 'innerHTML', DOMPurify.sanitize(html, { RETURN_TRUSTED_TYPE: false }));
}
}
}
46 changes: 16 additions & 30 deletions src/app/content/safe.pipe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,39 +17,25 @@ SPDX-License-Identifier: Apache-2.0
*/

import { Pipe, PipeTransform } from '@angular/core';
import {
DomSanitizer,
SafeHtml,
SafeStyle,
SafeScript,
SafeUrl,
SafeResourceUrl
} from '@angular/platform-browser';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import DOMPurify from 'dompurify';

@Pipe({
name: 'safe',
standalone: true
name: 'safe',
standalone: true,
// Set pure: true for performance; if your code mutates the same string reference,
// set pure: false so pipe runs every change detection cycle.
pure: true
})
export class SafePipe implements PipeTransform {
constructor(protected sanitizer: DomSanitizer) {}

public transform(
value: string,
type: string
): SafeHtml | SafeStyle | SafeScript | SafeUrl | SafeResourceUrl {
switch (type) {
case 'html':
return this.sanitizer.bypassSecurityTrustHtml(value);
case 'style':
return this.sanitizer.bypassSecurityTrustStyle(value);
case 'script':
return this.sanitizer.bypassSecurityTrustScript(value);
case 'url':
return this.sanitizer.bypassSecurityTrustUrl(value);
case 'resourceUrl':
return this.sanitizer.bypassSecurityTrustResourceUrl(value);
default:
throw new Error(`Invalid safe type specified: ${type}`);
}
constructor(private sanitizer: DomSanitizer) {}

transform(unsafeHtml: string | null | undefined): SafeHtml | null {
if (!unsafeHtml) return null;

// DOMPurify defaults are safe; you can pass a config object here to allow certain tags/attributes.
const cleaned = DOMPurify.sanitize(unsafeHtml, { RETURN_TRUSTED_TYPE: false });
// Return SafeHtml so you can bind directly to [innerHTML].
return this.sanitizer.bypassSecurityTrustHtml(cleaned);
}
}
16 changes: 8 additions & 8 deletions src/app/home/home.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
<div>
<div
*ngIf="!isLoadingContent"
[innerHTML]="introLeftContent | safe: 'html'"
[innerHTML]="introLeftContent | safe"
></div>
<div *ngIf="!isLoggedIn && !isLoadingContent">
<button
Expand All @@ -55,14 +55,14 @@
</div>
<div
*ngIf="!isLoadingContent"
[innerHTML]="introRightContent | safe: 'html'"
[innerHTML]="introRightContent | safe"
></div>
</div>
<!-- <div flex fxLayout="row" fxLayout.sm="column" fxLayout.xs="column" fxLayoutAlign="space-between" class="flex-block">
<div fxFlex="50" fxFlex.md="100" fxFlex.sm="100" fxFlex.xs="100">
<div
*ngIf="!isLoadingContent"
[innerHTML]="introLeftContent | safe: 'html'"
[innerHTML]="introLeftContent | safe"
></div>

<div *ngIf="!isLoggedIn && !isLoadingContent">
Expand Down Expand Up @@ -102,7 +102,7 @@
<div fxFlex="50" fxFlex.sm="100" fxFlex.xs="100" fxHide.sm fxHide.xs>
<div
*ngIf="!isLoadingContent"
[innerHTML]="introRightContent | safe: 'html'"
[innerHTML]="introRightContent | safe"
></div>
</div>
</div>
Expand All @@ -115,7 +115,7 @@

<div
*ngIf="!isLoadingContent"
[innerHTML]="detailHeading | safe: 'html'"
[innerHTML]="detailHeading | safe"
></div>

<div
Expand All @@ -134,7 +134,7 @@
></ngx-skeleton-loader>
<div
*ngIf="!isLoadingContent"
[innerHTML]="detailColumn1 | safe: 'html'"
[innerHTML]="detailColumn1 | safe"
></div>
</div>
<div fxFlex="33" fxFlex.sm="100" fxFlex.xs="100">
Expand All @@ -144,7 +144,7 @@
></ngx-skeleton-loader>
<div
*ngIf="!isLoadingContent"
[innerHTML]="detailColumn2 | safe: 'html'"
[innerHTML]="detailColumn2 | safe"
></div>
</div>
<div fxFlex="33" fxFlex.sm="100" fxFlex.xs="100">
Expand All @@ -154,7 +154,7 @@
></ngx-skeleton-loader>
<div
*ngIf="!isLoadingContent"
[innerHTML]="detailColumn3 | safe: 'html'"
[innerHTML]="detailColumn3 | safe"
></div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ <h5>
<div
#sourceView
class="diff-view"
[innerHTML]="sourceText | safe: 'html'"
[innerHTML]="sourceText | safe"
></div>
</div>
<div class="target-view">
Expand All @@ -57,7 +57,7 @@ <h5>
<div
#targetView
class="diff-view"
[innerHTML]="targetText | safe: 'html'"
[innerHTML]="targetText | safe"
></div>
</div>
<div class="resolved-view">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ <h4>{{ source.branchName }}</h4>
<div
*ngIf="hasSourceValue"
class="diff-view"
[innerHTML]="sourceText | safe: 'html'"
[innerHTML]="sourceText | safe"
></div>
</div>
</div>
Expand All @@ -143,7 +143,7 @@ <h4 class="branchHeader">{{ target.branchName }}</h4>
<div
*ngIf="hasTargetValue"
class="diff-view"
[innerHTML]="targetText | safe: 'html'"
[innerHTML]="targetText | safe"
></div>
</div>
</div>
Expand All @@ -158,7 +158,7 @@ <h4 class="branchHeader">{{ sourceUsed }}</h4>
>
<div
class="diff-view"
[innerHTML]="committingContent | safe: 'html'"
[innerHTML]="committingContent | safe"
></div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ <h4 class="modal-title marginless">{{ modalTitle }}</h4>
</div>
<form [formGroup]="formGroup">
<div class="modal-body pxy-2">
<p *ngIf="message" [innerHtml]="message | safe: 'html'"></p>
<p *ngIf="message" [innerHtml]="message | safe"></p>
<div class="mdm--form-input">
<mat-form-field appearance="outline" required class="full-width">
<mat-label>Name</mat-label>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<h4 class="modal-title marginless">{{ modalTitle }}</h4>
</div>
<div class="modal-body pxy-2">
<p [innerHtml]="message | safe: 'html'"></p>
<p [innerHtml]="message | safe"></p>
<form [formGroup]="formGroup">
<div class="mdm--form-input">
<mat-form-field appearance="outline" class="full-width paddingless">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<h4 class="modal-title marginless">{{ title }}</h4>
</div>
<div class="modal-body">
<span [innerHtml]="message | safe: 'html'"></span>
<span [innerHtml]="message | safe"></span>
</div>
<div class="modal-footer" style="padding: 10px">
<button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ <h4 mat-dialog-title>
<mat-dialog-content class="mat-typography">
<div class="full-width">
<form role="form" class="mb-2">
<span [innerHtml]="message | safe: 'html'"></span>
<span [innerHtml]="message | safe"></span>
<mat-radio-group name="versionList" [(value)]="data.versionList" [(ngModel)]="data.versionList" (ngModelChange)="onVersionChange()" class="mb-0">

<mat-radio-button value="Major" [checked]="data.versionList == 'Major'">Major <small><em>(default)</em></small></mat-radio-button>
Expand Down
2 changes: 1 addition & 1 deletion src/app/modals/input-modal/input-modal.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<h4 class='modal-title marginless'>{{modalTitle}}</h4>
</div>
<div class="modal-body pxy-2">
<p [innerHtml]="message | safe: 'html'"></p>
<p [innerHtml]="message | safe"></p>
<div class="mdm--form-input">
<mat-form-field appearance="outline" class="full-width paddingless">
<mat-label>{{inputLabel}}</mat-label>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ <h4 mat-dialog-title>
<hr>
<mat-dialog-content class="mat-typography">
<div class="full-width">
<span [innerHtml]="data.content | safe: 'html'"></span>
<span [innerHtml]="data.content | safe"></span>
</div>
</mat-dialog-content>
<mat-dialog-actions align="end" class="pt-2 pb-2">
Expand Down
Loading
Loading