fix/vue-quill-xss_CVE-2021-3163 #114
3 changed files with 187 additions and 29 deletions
105
package-lock.json
generated
105
package-lock.json
generated
|
@ -38,6 +38,7 @@
|
||||||
"pwacompat": "^2.0.17",
|
"pwacompat": "^2.0.17",
|
||||||
"qrcode": "^1.5.4",
|
"qrcode": "^1.5.4",
|
||||||
"qs": "^6.14.0",
|
"qs": "^6.14.0",
|
||||||
|
"quill": "^2.0.3",
|
||||||
"socket.io-client": "^4.8.1",
|
"socket.io-client": "^4.8.1",
|
||||||
"unplugin-vue-markdown": "^29.1.0",
|
"unplugin-vue-markdown": "^29.1.0",
|
||||||
"uuid": "^11.1.0",
|
"uuid": "^11.1.0",
|
||||||
|
@ -4652,6 +4653,52 @@
|
||||||
"vue": "^3.2.41"
|
"vue": "^3.2.41"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@vueup/vue-quill/node_modules/eventemitter3": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@vueup/vue-quill/node_modules/fast-diff": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig==",
|
||||||
|
"license": "Apache-2.0"
|
||||||
|
},
|
||||||
|
"node_modules/@vueup/vue-quill/node_modules/parchment": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/parchment/-/parchment-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg==",
|
||||||
|
"license": "BSD-3-Clause"
|
||||||
|
},
|
||||||
|
"node_modules/@vueup/vue-quill/node_modules/quill": {
|
||||||
|
"version": "1.3.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/quill/-/quill-1.3.7.tgz",
|
||||||
|
"integrity": "sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g==",
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"clone": "^2.1.1",
|
||||||
|
"deep-equal": "^1.0.1",
|
||||||
|
"eventemitter3": "^2.0.3",
|
||||||
|
"extend": "^3.0.2",
|
||||||
|
"parchment": "^1.1.4",
|
||||||
|
"quill-delta": "^3.6.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@vueup/vue-quill/node_modules/quill/node_modules/quill-delta": {
|
||||||
|
"version": "3.6.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-3.6.3.tgz",
|
||||||
|
"integrity": "sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"deep-equal": "^1.0.1",
|
||||||
|
"extend": "^3.0.2",
|
||||||
|
"fast-diff": "1.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/acorn": {
|
"node_modules/acorn": {
|
||||||
"version": "8.15.0",
|
"version": "8.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
||||||
|
@ -6219,9 +6266,9 @@
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/eventemitter3": {
|
"node_modules/eventemitter3": {
|
||||||
"version": "2.0.3",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
|
||||||
"integrity": "sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg==",
|
"integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/execa": {
|
"node_modules/execa": {
|
||||||
|
@ -6280,7 +6327,6 @@
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
|
||||||
"integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
|
"integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
|
||||||
"dev": true,
|
|
||||||
"license": "Apache-2.0"
|
"license": "Apache-2.0"
|
||||||
},
|
},
|
||||||
"node_modules/fast-glob": {
|
"node_modules/fast-glob": {
|
||||||
|
@ -8129,6 +8175,12 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/lodash-es": {
|
||||||
|
"version": "4.17.21",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
|
||||||
|
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/lodash.clonedeep": {
|
"node_modules/lodash.clonedeep": {
|
||||||
"version": "4.5.0",
|
"version": "4.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
|
||||||
|
@ -8710,9 +8762,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/parchment": {
|
"node_modules/parchment": {
|
||||||
"version": "1.1.4",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/parchment/-/parchment-1.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/parchment/-/parchment-3.0.0.tgz",
|
||||||
"integrity": "sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg==",
|
"integrity": "sha512-HUrJFQ/StvgmXRcQ1ftY6VEZUq3jA2t9ncFN4F84J/vN0/FPpQF+8FKXb3l6fLces6q0uOHj6NJn+2xvZnxO6A==",
|
||||||
"license": "BSD-3-Clause"
|
"license": "BSD-3-Clause"
|
||||||
},
|
},
|
||||||
"node_modules/parent-module": {
|
"node_modules/parent-module": {
|
||||||
|
@ -9111,17 +9163,18 @@
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/quill": {
|
"node_modules/quill": {
|
||||||
"version": "1.3.7",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/quill/-/quill-1.3.7.tgz",
|
"resolved": "https://registry.npmjs.org/quill/-/quill-2.0.3.tgz",
|
||||||
"integrity": "sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g==",
|
"integrity": "sha512-xEYQBqfYx/sfb33VJiKnSJp8ehloavImQ2A6564GAbqG55PGw1dAWUn1MUbQB62t0azawUS2CZZhWCjO8gRvTw==",
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"clone": "^2.1.1",
|
"eventemitter3": "^5.0.1",
|
||||||
"deep-equal": "^1.0.1",
|
"lodash-es": "^4.17.21",
|
||||||
"eventemitter3": "^2.0.3",
|
"parchment": "^3.0.0",
|
||||||
"extend": "^3.0.2",
|
"quill-delta": "^5.1.0"
|
||||||
"parchment": "^1.1.4",
|
},
|
||||||
"quill-delta": "^3.6.2"
|
"engines": {
|
||||||
|
"npm": ">=8.2.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/quill-delta": {
|
"node_modules/quill-delta": {
|
||||||
|
@ -9141,24 +9194,18 @@
|
||||||
"integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
|
"integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
|
||||||
"license": "Apache-2.0"
|
"license": "Apache-2.0"
|
||||||
},
|
},
|
||||||
"node_modules/quill/node_modules/fast-diff": {
|
|
||||||
"version": "1.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.1.2.tgz",
|
|
||||||
"integrity": "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig==",
|
|
||||||
"license": "Apache-2.0"
|
|
||||||
},
|
|
||||||
"node_modules/quill/node_modules/quill-delta": {
|
"node_modules/quill/node_modules/quill-delta": {
|
||||||
"version": "3.6.3",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-3.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-5.1.0.tgz",
|
||||||
"integrity": "sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg==",
|
"integrity": "sha512-X74oCeRI4/p0ucjb5Ma8adTXd9Scumz367kkMK5V/IatcX6A0vlgLgKbzXWy5nZmCGeNJm2oQX0d2Eqj+ZIlCA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"deep-equal": "^1.0.1",
|
"fast-diff": "^1.3.0",
|
||||||
"extend": "^3.0.2",
|
"lodash.clonedeep": "^4.5.0",
|
||||||
"fast-diff": "1.1.2"
|
"lodash.isequal": "^4.5.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10"
|
"node": ">= 12.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/randombytes": {
|
"node_modules/randombytes": {
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
"pwacompat": "^2.0.17",
|
"pwacompat": "^2.0.17",
|
||||||
"qrcode": "^1.5.4",
|
"qrcode": "^1.5.4",
|
||||||
"qs": "^6.14.0",
|
"qs": "^6.14.0",
|
||||||
|
"quill": "^2.0.3",
|
||||||
"socket.io-client": "^4.8.1",
|
"socket.io-client": "^4.8.1",
|
||||||
"unplugin-vue-markdown": "^29.1.0",
|
"unplugin-vue-markdown": "^29.1.0",
|
||||||
"uuid": "^11.1.0",
|
"uuid": "^11.1.0",
|
||||||
|
|
110
src/components/QuillEditor.vue
Normal file
110
src/components/QuillEditor.vue
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
<template>
|
||||||
|
<div ref="quill"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { defineComponent, type PropType } from "vue";
|
||||||
|
import Quill, { Delta } from "quill";
|
||||||
|
import "quill/dist/quill.core.css";
|
||||||
|
import "quill/dist/quill.snow.css";
|
||||||
|
|
||||||
|
type RangeStatic = { index: number; length: number };
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export default defineComponent({
|
||||||
|
props: {
|
||||||
|
toolbar: {
|
||||||
|
type: [String, Array, Object],
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
modules: {
|
||||||
|
type: Object as PropType<Record<string, unknown>>,
|
||||||
|
default: {},
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
type: [String, Object] as PropType<string | Delta>,
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
contentType: {
|
||||||
|
type: String as PropType<"delta" | "html" | "text">,
|
||||||
|
default: "text",
|
||||||
|
},
|
||||||
|
readonly: { type: Boolean, default: false },
|
||||||
|
placeholder: String,
|
||||||
|
},
|
||||||
|
emits: {
|
||||||
|
"update:content": (content: Delta | string) => true,
|
||||||
|
textChange: (tc: { delta: Delta; oldDelta: Delta; source: string }) => true,
|
||||||
|
selectionChange: (sc: { range: RangeStatic; oldRange: RangeStatic; source: string }) => true,
|
||||||
|
focus: () => true,
|
||||||
|
blur: () => true,
|
||||||
|
ready: (quill: Quill) => true,
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
conent(val, oldVal) {
|
||||||
|
this.setContent(val);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
instance: undefined as undefined | Quill,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.instance = new Quill(this.$refs.quill as HTMLElement, {
|
||||||
|
theme: "snow",
|
||||||
|
modules: {
|
||||||
|
toolbar: this.toolbar,
|
||||||
|
},
|
||||||
|
placeholder: this.placeholder,
|
||||||
|
readOnly: this.readonly,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.instance.on("selection-change", (range, oldRange, source) => {
|
||||||
|
if (!range) {
|
||||||
|
this.$emit("blur");
|
||||||
|
} else {
|
||||||
|
this.$emit("focus");
|
||||||
|
}
|
||||||
|
this.$emit("selectionChange", { range, oldRange, source });
|
||||||
|
});
|
||||||
|
this.instance.on("text-change", (delta, oldDelta, source) => {
|
||||||
|
this.$emit("update:content", this.getContent());
|
||||||
|
this.$emit("textChange", { delta, oldDelta, source });
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$emit("ready", this.instance as Quill);
|
||||||
|
this.setContent(this.content);
|
||||||
|
},
|
||||||
|
beforeUnmount() {
|
||||||
|
this.instance = undefined;
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getContent(): string | Delta {
|
||||||
|
if (this.contentType === "delta") {
|
||||||
|
return (this.instance?.getContents() ?? {}) as Delta;
|
||||||
|
} else if (this.contentType === "html") {
|
||||||
|
return this.instance?.getSemanticHTML() ?? "";
|
||||||
|
} else {
|
||||||
|
return this.instance?.getText() ?? "";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setContent(content: Delta | string) {
|
||||||
|
if (this.contentType === "delta") {
|
||||||
|
if (typeof content !== "string") {
|
||||||
|
this.instance?.setContents(content);
|
||||||
|
}
|
||||||
|
} else if (this.contentType === "html") {
|
||||||
|
if (typeof content === "string" && this.instance) {
|
||||||
|
this.instance.root.innerHTML = content;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (typeof content === "string") {
|
||||||
|
this.instance?.setText(content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
Loading…
Add table
Add a link
Reference in a new issue