Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve/fix #4435

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
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
4 changes: 2 additions & 2 deletions packages/quill/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "quill",
"version": "2.0.2",
"name": "hoavm-quill",
"version": "2.0.2-alpha1.20",
"description": "Your powerful, rich text editor",
"author": "Jason Chen <[email protected]>",
"homepage": "https://quilljs.com",
Expand Down
9 changes: 8 additions & 1 deletion packages/quill/src/formats/font.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@ import { ClassAttributor, Scope, StyleAttributor } from 'parchment';

const config = {
scope: Scope.INLINE,
whitelist: ['serif', 'monospace'],
whitelist: [
'arial',
'comic-sans',
'courier-new',
'georgia',
'helvetica',
'lucida',
],
};

const FontClass = new ClassAttributor('font', 'ql-font', config);
Expand Down
48 changes: 39 additions & 9 deletions packages/quill/src/formats/image.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,44 @@
import { EmbedBlot } from 'parchment';
import { sanitize } from './link.js';
// import { sanitize } from './link.js';

const ATTRIBUTES = ['alt', 'height', 'width'];
const ATTRIBUTES = [
'alt',
'height',
'width',
'src',
'srcset',
'sizes',
'crossorigin',
'usemap',
'ismap',
'loading',
'referrerpolicy',
'decoding',
'longdesc',
'title',
'class',
'id',
'style',
'tabindex',
'draggable',
'align',
'border',
'hspace',
'vspace',
'accesskey',
];

class Image extends EmbedBlot {
static blotName = 'image';
static tagName = 'IMG';

static create(value: string) {
const node = super.create(value) as Element;
if (typeof value === 'string') {
node.setAttribute('src', this.sanitize(value));
}
static create(value: any) {
const node = document.createElement('img');
ATTRIBUTES.forEach((attr) => {
if (value[attr]) {
node.setAttribute(attr, value[attr]);
}
});
return node;
}

Expand All @@ -32,11 +59,14 @@ class Image extends EmbedBlot {
}

static sanitize(url: string) {
return sanitize(url, ['http', 'https', 'data']) ? url : '//:0';
return url;
}

static value(domNode: Element) {
return domNode.getAttribute('src');
return ATTRIBUTES.reduce((acc: any, attr) => {
acc[attr] = domNode.getAttribute(attr);
return acc;
}, {});
}

domNode: HTMLImageElement;
Expand Down
54 changes: 45 additions & 9 deletions packages/quill/src/formats/link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,65 @@ class Link extends Inline {
static PROTOCOL_WHITELIST = ['http', 'https', 'mailto', 'tel', 'sms'];

static create(value: string) {
const node = super.create(value) as HTMLElement;
node.setAttribute('href', this.sanitize(value));
node.setAttribute('rel', 'noopener noreferrer');
node.setAttribute('target', '_blank');
const node = super.create();
let newValue;
if (isStringified(value)) {
newValue = JSON.parse(value);
} else {
newValue = value;
}

if (typeof newValue !== 'string') {
['href', 'target', 'title'].forEach((attr) => {
if (newValue[attr]) node.setAttribute(attr, newValue[attr]);
});
return node;
}

node.setAttribute('href', newValue);
return node;
}

static formats(domNode: HTMLElement) {
return domNode.getAttribute('href');
return JSON.stringify({
href: domNode.getAttribute('href'),
target: domNode.getAttribute('target'),
title: domNode.getAttribute('title'),
});
}

static sanitize(url: string) {
return sanitize(url, this.PROTOCOL_WHITELIST) ? url : this.SANITIZED_URL;
}

format(name: string, value: unknown) {
format(name: string, value: any) {
if (name !== this.statics.blotName || !value) {
super.format(name, value);
return super.format(name, value);
}
let newValue;
if (isStringified(value)) {
newValue = JSON.parse(value);
} else {
// @ts-expect-error
this.domNode.setAttribute('href', this.constructor.sanitize(value));
newValue = value;
}

if (typeof newValue !== 'string') {
this.domNode.setAttribute('href', newValue.href);
this.domNode.setAttribute('target', newValue.target);
this.domNode.setAttribute('title', newValue.title);
} else {
this.domNode.setAttribute('href', newValue);
}
}
}

function isStringified(value: any) {
try {
JSON.parse(value);
} catch (e) {
return false;
}
return true;
}

function sanitize(url: string, protocols: string[]) {
Expand Down
8 changes: 8 additions & 0 deletions packages/quill/src/formats/scriptTag.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Embed from '../blots/embed.js';

class ScriptTag extends Embed {
static blotName = 'script';
static tagName = 'SCRIPT';
}

export default ScriptTag;
2 changes: 1 addition & 1 deletion packages/quill/src/formats/size.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { ClassAttributor, Scope, StyleAttributor } from 'parchment';

const SizeClass = new ClassAttributor('size', 'ql-size', {
scope: Scope.INLINE,
whitelist: ['small', 'large', 'huge'],
whitelist: ['extra-small', 'small', 'medium', 'large'],
});
const SizeStyle = new StyleAttributor('size', 'font-size', {
scope: Scope.INLINE,
Expand Down
42 changes: 33 additions & 9 deletions packages/quill/src/formats/video.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,40 @@
import { BlockEmbed } from '../blots/block.js';
import Link from './link.js';

const ATTRIBUTES = ['height', 'width'];
const ATTRIBUTES = [
'src',
'srcdoc',
'name',
'width',
'height',
'frameborder',
'allow',
'allowfullscreen',
'sandbox',
'referrerpolicy',
'loading',
'longdesc',
'title',
'class',
'id',
'style',
'tabindex',
'draggable',
'scrolling',
];

class Video extends BlockEmbed {
static blotName = 'video';
static className = 'ql-video';
static tagName = 'IFRAME';

static create(value: string) {
const node = super.create(value) as Element;
node.setAttribute('frameborder', '0');
node.setAttribute('allowfullscreen', 'true');
node.setAttribute('src', this.sanitize(value));
static create(value: any) {
const node = document.createElement('iframe');
ATTRIBUTES.forEach((attr) => {
if (value[attr]) {
node.setAttribute(attr, value[attr]);
}
});
return node;
}

Expand All @@ -33,7 +55,10 @@ class Video extends BlockEmbed {
}

static value(domNode: Element) {
return domNode.getAttribute('src');
return ATTRIBUTES.reduce((acc: any, attr) => {
acc[attr] = domNode.getAttribute(attr);
return acc;
}, {});
}

domNode: HTMLVideoElement;
Expand All @@ -51,8 +76,7 @@ class Video extends BlockEmbed {
}

html() {
const { video } = this.value();
return `<a href="${video}">${video}</a>`;
return Video.create(this.value().video).outerHTML;
}
}

Expand Down
15 changes: 5 additions & 10 deletions packages/quill/src/quill.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Quill from './core.js';
import Quill, { Parchment, Range } from './core.js';
import type {
Bounds,
DebugLevel,
Expand Down Expand Up @@ -30,6 +30,7 @@ import Link from './formats/link.js';
import Script from './formats/script.js';
import Strike from './formats/strike.js';
import Underline from './formats/underline.js';
import ScriptTag from './formats/scriptTag.js';

import Formula from './formats/formula.js';
import Image from './formats/image.js';
Expand Down Expand Up @@ -98,6 +99,7 @@ Quill.register(
'formats/formula': Formula,
'formats/image': Image,
'formats/video': Video,
'formats/scriptTag': ScriptTag,

'modules/syntax': Syntax,
'modules/table': Table,
Expand All @@ -115,21 +117,14 @@ Quill.register(
true,
);

export {
AttributeMap,
Delta,
Module,
Op,
OpIterator,
Parchment,
Range,
} from './core.js';
export { Module } from './core.js';
export type {
Bounds,
DebugLevel,
EmitterSource,
ExpandedQuillOptions,
QuillOptions,
};
export { Parchment, Range };

export default Quill;
3 changes: 2 additions & 1 deletion packages/quill/test/types/quill.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { assertType, expectTypeOf } from 'vitest';
import Quill, { Delta } from '../../src/quill.js';
import Quill from '../../src/quill.js';
import type { EmitterSource, Parchment, Range } from '../../src/quill.js';
import Delta from 'quill-delta';
import type { default as Block, BlockEmbed } from '../../src/blots/block.js';
import SnowTheme from '../../src/themes/snow.js';
import { LeafBlot } from 'parchment';
Expand Down