Skip to content

Commit

Permalink
fix: prevent fetch resources in contenteditable
Browse files Browse the repository at this point in the history
  • Loading branch information
splincode committed Jul 1, 2024
1 parent 2c3a42f commit 10433f4
Show file tree
Hide file tree
Showing 17 changed files with 240 additions and 18 deletions.
12 changes: 9 additions & 3 deletions projects/demo/src/app/app.pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ export const DEMO_PAGES: TuiDocRoutePages = [
'editor, setup, starter kit, wysiwyg, редактор, текст, html, rich, text',
},
{
section: `Documentation`,
title: `Tokens`,
section: 'Documentation',
title: 'Tokens',
route: `${TuiDemoPath.StarterKit}/Options`,
keywords: `TUI_EDITOR_OPTIONS, TUI_ATTACH_FILES_LOADER`,
keywords: 'TUI_EDITOR_OPTIONS, TUI_ATTACH_FILES_LOADER',
},
{
section: 'Documentation',
Expand Down Expand Up @@ -217,6 +217,12 @@ export const DEMO_PAGES: TuiDocRoutePages = [
'editor, embed, video player, audio player, html5, wysiwyg, редактор, плеер, html, rich, text',
route: `/${TuiDemoPath.EmbedHtml5}`,
},
{
section: 'Documentation',
title: 'PDF',
keywords: 'editor, embed, pdf',
route: `/${TuiDemoPath.EmbedPDF}`,
},
],
},
{
Expand Down
5 changes: 5 additions & 0 deletions projects/demo/src/app/app.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,11 @@ export const routes: Routes = [
loadComponent: async () => import('./pages/embed/html5'),
title: 'Editor — HTML5',
}),
route({
path: TuiDemoPath.EmbedPDF,
loadComponent: async () => import('./pages/embed/pdf'),
title: 'Editor — PDF',
}),
route({
path: TuiDemoPath.ToolbarBottom,
loadComponent: async () => import('./pages/toolbar/bottom'),
Expand Down
5 changes: 2 additions & 3 deletions projects/demo/src/app/pages/embed/iframe/examples/1/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ import {ExampleTuiEmbedTool} from './embed-tool/embed-tool.component';
deps: [Injector],
useFactory: (injector: Injector) => [
import('@taiga-ui/editor').then(({TuiStarterKit}) => TuiStarterKit),
import('@taiga-ui/editor').then(({tuiCreateImageEditorExtension}) =>
tuiCreateImageEditorExtension({injector}),
import('@taiga-ui/editor').then(({tuiCreateIframeEditorExtension}) =>
tuiCreateIframeEditorExtension({injector}),
),
],
},
Expand All @@ -32,7 +32,6 @@ export default class Example {
private readonly isE2E = inject(TUI_IS_E2E);

protected readonly builtInTools = [TuiEditorTool.Undo];

protected readonly control = new FormControl(
`
<p>Here is an online IDE:</p>
Expand Down
12 changes: 12 additions & 0 deletions projects/demo/src/app/pages/embed/pdf/examples/1/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<tui-editor
class="editor"
[formControl]="control"
[tools]="builtInTools"
(fileAttached)="attach($event)"
/>

<h4>HTML:</h4>
<div [innerHTML]="safe(control.value)"></div>

<h4>Text:</h4>
<p>{{ control.value }}</p>
19 changes: 19 additions & 0 deletions projects/demo/src/app/pages/embed/pdf/examples/1/index.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.editor {
min-height: 700px;
}

:host {
&._e2e ::ng-deep {
//noinspection CssInvalidPseudoSelector
video::-webkit-media-controls-current-time-display,
video::-webkit-media-controls-time-remaining-display,
audio::-webkit-media-controls-current-time-display,
audio::-webkit-media-controls-time-remaining-display {
display: none;
}
}

::ng-deep iframe {
border: 1px solid var(--tui-background-accent-1);
}
}
137 changes: 137 additions & 0 deletions projects/demo/src/app/pages/embed/pdf/examples/1/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import type {Injector} from '@angular/core';
import {
ChangeDetectionStrategy,
Component,
inject,
INJECTOR,
ViewChild,
} from '@angular/core';
import {FormControl, ReactiveFormsModule, Validators} from '@angular/forms';
import type {SafeHtml} from '@angular/platform-browser';
import {DomSanitizer} from '@angular/platform-browser';
import {TUI_IS_E2E, tuiPure, tuiTypedFromEvent} from '@taiga-ui/cdk';
import type {TuiEditorAttachedFile} from '@taiga-ui/editor';
import {
TUI_ATTACH_FILES_LOADER,
TUI_ATTACH_FILES_OPTIONS,
TUI_EDITOR_EXTENSIONS,
TuiEditor,
TuiEditorTool,
} from '@taiga-ui/editor';
import type {Observable} from 'rxjs';
import {map} from 'rxjs';

@Component({
standalone: true,
imports: [ReactiveFormsModule, TuiEditor],
templateUrl: './index.html',
styleUrls: ['./index.less'],
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [
{
provide: TUI_EDITOR_EXTENSIONS,
deps: [INJECTOR],
useFactory: (injector: Injector) => [
import('@taiga-ui/editor').then(({TuiStarterKit}) => TuiStarterKit),
import('@tiptap/extension-text-style').then(({TextStyle}) => TextStyle),
import('@taiga-ui/editor').then(({TuiLink}) => TuiLink),
import('@taiga-ui/editor').then(({TuiFileLink}) => TuiFileLink),
import('@taiga-ui/editor').then(({tuiCreateIframeEditorExtension}) =>
tuiCreateIframeEditorExtension({injector}),
),
],
},
{
provide: TUI_ATTACH_FILES_LOADER,
useFactory:
() =>
([file]: File[]): Observable<
Array<TuiEditorAttachedFile<{type: string}>>
> => {
const fileReader = new FileReader();

// For example, instead of uploading to a file server,
// we convert the result immediately into content to base64
fileReader.readAsDataURL(file);

return tuiTypedFromEvent(fileReader, 'load').pipe(
map(() => [
{
name: file.name,

/* base64 or link to the file on your server */
link: String(fileReader.result),

attrs: {
type: file.type,
},
},
]),
);
},
},
{
provide: TUI_ATTACH_FILES_OPTIONS,
useValue: {
accept: 'application/pdf',
multiple: false,
},
},
],
host: {
class: 'html5-editor-example',
'[class._e2e]': 'isE2E',
},
})
export default class Example {
@ViewChild(TuiEditor)
private readonly editor?: TuiEditor;

private readonly sanitizer = inject(DomSanitizer);

protected readonly isE2E = inject(TUI_IS_E2E);

protected readonly builtInTools = [
TuiEditorTool.Undo,
TuiEditorTool.Link,
TuiEditorTool.Attach,
];

protected readonly control = new FormControl(
`
<p>sample.pdf</p>
<iframe
data-type="iframe-editor"
src="https://mozilla.github.io/pdf.js/web/viewer.html?url=https://pdfobject.com/pdf/sample.pdf"
width="100%"
height="300"
></iframe>
<p>Hello world</p>
`,
Validators.required,
);

@tuiPure
protected safe(content: string | null): SafeHtml {
return this.sanitizer.bypassSecurityTrustHtml(content ?? '');
}

protected attach([file]: Array<TuiEditorAttachedFile<{type: string}>>): void {
this.editor?.editorService
?.getOriginTiptapEditor()
?.chain()
.focus('end')
.createParagraphNear()
.insertContent(file.name)
.run();

this.editor?.editorService?.setIframe({
allowfullscreen: false,
frameborder: null,
// For example, src: `https://mozilla.github.io/pdf.js/web/viewer.html?url${file.link}`,
src: `data:application/pdf;base64${file.link}`,
width: '100%',
height: 300,
});
}
}
11 changes: 11 additions & 0 deletions projects/demo/src/app/pages/embed/pdf/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<tui-doc-page
header="Editor"
type="components"
>
<tui-doc-example
id="pdf"
heading="PDF"
[component]="component1"
[content]="example1"
/>
</tui-doc-page>
25 changes: 25 additions & 0 deletions projects/demo/src/app/pages/embed/pdf/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {ChangeDetectionStrategy, Component} from '@angular/core';
import {RouterLink} from '@angular/router';
import {TuiAddonDoc} from '@taiga-ui/addon-doc';
import {TuiLink} from '@taiga-ui/core';
import {TUI_EDITOR_DEFAULT_EXTENSIONS, TUI_EDITOR_EXTENSIONS} from '@taiga-ui/editor';

@Component({
standalone: true,
imports: [TuiAddonDoc, TuiLink, RouterLink],
templateUrl: './index.html',
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [
{
provide: TUI_EDITOR_EXTENSIONS,
useValue: TUI_EDITOR_DEFAULT_EXTENSIONS,
},
],
})
export default class Example {
protected readonly component1 = import('./examples/1');
protected readonly example1 = {
HTML: import('./examples/1/index.html?raw'),
TypeScript: import('./examples/1/index.ts?raw'),
};
}
4 changes: 2 additions & 2 deletions projects/demo/src/app/pages/starter/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ <h4>Text:</h4>
id="options"
heading="TUI_EDITOR_OPTIONS"
>
<tui-doc-code [code]="exampleOptions"></tui-doc-code>
<tui-doc-code [code]="exampleOptions" />

<p>
<strong>Description of the available configurations:</strong>
Expand Down Expand Up @@ -259,7 +259,7 @@ <h4>Text:</h4>
id="attach-files"
heading="TUI_ATTACH_FILES_LOADER / TUI_ATTACH_FILES_OPTIONS"
>
<tui-doc-code [code]="exampleFileAttach"></tui-doc-code>
<tui-doc-code [code]="exampleFileAttach" />
</tui-doc-example>
</ng-template>
</tui-doc-page>
2 changes: 1 addition & 1 deletion projects/demo/src/app/pages/starter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {ChangeDetectionStrategy, Component, inject} from '@angular/core';
import {FormControl, ReactiveFormsModule} from '@angular/forms';
import {TuiAddonDoc} from '@taiga-ui/addon-doc';
import {TUI_IS_E2E, TuiAutoFocus} from '@taiga-ui/cdk';
import {TuiLink} from '@taiga-ui/core';
import {
TUI_EDITOR_DEFAULT_EXTENSIONS,
TUI_EDITOR_DEFAULT_TOOLS,
Expand All @@ -10,7 +11,6 @@ import {
TuiEditorSocket,
TuiEditorTool,
} from '@taiga-ui/editor';
import {TuiLink} from "@taiga-ui/core";

@Component({
standalone: true,
Expand Down
1 change: 1 addition & 0 deletions projects/demo/src/app/shared/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export const TuiDemoPath = {
Checkbox: 'checkbox',
ColorPickerTool: 'custom-tool/color-picker',
EmbedHtml5: 'embed/html5',
EmbedPDF: 'embed/pdf',
EmbedIframe: 'embed/iframe',
EmbedYoutube: 'embed/youtube',
Focus: 'focus',
Expand Down
2 changes: 1 addition & 1 deletion projects/demo/src/styles.less
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@import '@taiga-ui/styles/taiga-ui-global.less';
@import '@taiga-ui/legacy/styles/taiga-ui-theme.less'; // TODO: check affected styles
@import '@taiga-ui/core/styles/taiga-ui-theme.less';
@import '~highlight.js/styles/github.css';

body {
Expand Down
5 changes: 4 additions & 1 deletion projects/editor/src/components/toolbar/toolbar.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,10 @@ export class TuiToolbar {
}

ngDevMode &&
console.info(!!this.filesLoader, 'Please provide TUI_ATTACH_FILES_LOADER');
console.assert(
!!this.filesLoader,
'Please provide TUI_ATTACH_FILES_LOADER, more: https://taiga-family.github.io/editor/starter-kit/Options',
);

this.filesLoader?.(files)
.pipe(take(1), takeUntilDestroyed(this.destroyRef))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {ChangeDetectionStrategy, Component, ElementRef, inject} from '@angular/core';
import type {SafeResourceUrl} from '@angular/platform-browser';
import {DomSanitizer} from '@angular/platform-browser';
import {tuiPure} from '@taiga-ui/cdk';

import {AbstractTuiEditorResizable} from '../../components/editor-resizable/editor-resizable.abstract';
import {TuiEditorResizable} from '../../components/editor-resizable/editor-resizable.component';
Expand Down Expand Up @@ -40,6 +41,7 @@ export class TuiIframeEditor extends AbstractTuiEditorResizable<TuiEditableIfram
);
}

@tuiPure
protected get src(): SafeResourceUrl {
return this.sanitizer.bypassSecurityTrustResourceUrl(this.attrs.src ?? '');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ declare module '@tiptap/core' {
}
}

export const createIframeEditorExtension = (injector: Injector): Node =>
export const tuiCreateIframeEditorExtension = ({injector}: {injector: Injector}): Node =>
Node.create({
name: 'iframe',
group: 'block',
atom: true,
draggable: false,

parseHTML(): NodeSpec['parseDOM'] {
return [{tag: 'iframe[data-type="iframe-editor"]'}];
return [{tag: 'iframe'}];
},

addAttributes(): Record<keyof TuiEditableIframe, Attribute> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
import type {SafeResourceUrl} from '@angular/platform-browser';
import {DomSanitizer} from '@angular/platform-browser';
import {WINDOW} from '@ng-web-apis/common';
import {tuiPure} from '@taiga-ui/cdk';

import {AbstractTuiEditorResizable} from '../../components/editor-resizable/editor-resizable.abstract';
import {TuiEditorResizable} from '../../components/editor-resizable/editor-resizable.component';
Expand Down Expand Up @@ -62,6 +63,11 @@ export class TuiImageEditor extends AbstractTuiEditorResizable<TuiEditableImage>
return this.attrs.draggable ?? null;
}

@tuiPure
protected get src(): SafeResourceUrl {
return this.sanitizer.bypassSecurityTrustResourceUrl(this.attrs.src);
}

protected get alt(): string {
return this.attrs.alt || '';
}
Expand All @@ -70,10 +76,6 @@ export class TuiImageEditor extends AbstractTuiEditorResizable<TuiEditableImage>
return this.attrs.title || '';
}

protected get src(): SafeResourceUrl {
return this.sanitizer.bypassSecurityTrustResourceUrl(this.attrs.src);
}

@HostListener('document:click.silent', ['$event.target'])
protected currentTargetIsFocused(node: Node): void {
this.focused = this.el.nativeElement.contains(node);
Expand Down
2 changes: 1 addition & 1 deletion taiga-ui
Submodule taiga-ui updated 221 files

0 comments on commit 10433f4

Please sign in to comment.