Upgrade to QuillV2
This commit is contained in:
parent
fb04b1ede3
commit
7575bda35b
32 changed files with 910 additions and 1227 deletions
|
@ -226,6 +226,40 @@ Signal Desktop makes use of the following open source projects.
|
|||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
## @signalapp/quill-cjs
|
||||
|
||||
Copyright (c) 2017-2024, Slab
|
||||
Copyright (c) 2014, Jason Chen
|
||||
Copyright (c) 2013, salesforce.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
## @types/fabric
|
||||
|
||||
MIT License
|
||||
|
@ -1914,38 +1948,6 @@ Signal Desktop makes use of the following open source projects.
|
|||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
## parchment
|
||||
|
||||
Copyright (c) 2015, Jason Chen
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
## pify
|
||||
|
||||
MIT License
|
||||
|
@ -2053,63 +2055,6 @@ Signal Desktop makes use of the following open source projects.
|
|||
|
||||
License: MIT
|
||||
|
||||
## quill
|
||||
|
||||
Copyright (c) 2014, Jason Chen
|
||||
Copyright (c) 2013, salesforce.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
## quill-delta
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Jason Chen
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
## react
|
||||
|
||||
MIT License
|
||||
|
@ -2676,30 +2621,6 @@ Signal Desktop makes use of the following open source projects.
|
|||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
## react-quill
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020, zenoamaro <zenoamaro@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
## react-redux
|
||||
|
||||
The MIT License (MIT)
|
||||
|
|
|
@ -84,7 +84,7 @@
|
|||
type="text/css"
|
||||
/>
|
||||
<link
|
||||
href="node_modules/react-quill/dist/quill.core.css"
|
||||
href="node_modules/@signalapp/quill-cjs/dist/quill.core.css"
|
||||
rel="stylesheet"
|
||||
type="text/css"
|
||||
/>
|
||||
|
|
350
package-lock.json
generated
350
package-lock.json
generated
|
@ -23,6 +23,7 @@
|
|||
"@react-spring/web": "9.7.5",
|
||||
"@signalapp/better-sqlite3": "9.0.9",
|
||||
"@signalapp/libsignal-client": "0.65.4",
|
||||
"@signalapp/quill-cjs": "2.1.2",
|
||||
"@signalapp/ringrtc": "2.49.3",
|
||||
"@types/fabric": "4.5.3",
|
||||
"backbone": "1.6.0",
|
||||
|
@ -70,14 +71,11 @@
|
|||
"p-map": "2.1.0",
|
||||
"p-queue": "6.6.2",
|
||||
"p-timeout": "4.1.0",
|
||||
"parchment": "1.1.4",
|
||||
"pify": "3.0.0",
|
||||
"pino": "9.5.0",
|
||||
"protobufjs": "7.3.2",
|
||||
"proxy-agent": "6.4.0",
|
||||
"qrcode-generator": "1.4.4",
|
||||
"quill": "1.3.7",
|
||||
"quill-delta": "4.0.1",
|
||||
"react": "17.0.2",
|
||||
"react-aria": "3.35.1",
|
||||
"react-aria-components": "1.4.1",
|
||||
|
@ -88,7 +86,6 @@
|
|||
"react-hot-loader": "4.13.1",
|
||||
"react-intl": "6.8.7",
|
||||
"react-popper": "2.3.0",
|
||||
"react-quill": "2.0.0-beta.4",
|
||||
"react-redux": "8.1.3",
|
||||
"react-router-dom": "5.0.1",
|
||||
"react-textarea-autosize": "8.5.5",
|
||||
|
@ -165,7 +162,6 @@
|
|||
"@types/pify": "5.0.4",
|
||||
"@types/pixelmatch": "5.2.6",
|
||||
"@types/pngjs": "6.0.5",
|
||||
"@types/quill": "1.3.10",
|
||||
"@types/react": "17.0.45",
|
||||
"@types/react-dom": "17.0.17",
|
||||
"@types/react-redux": "7.1.34",
|
||||
|
@ -6561,6 +6557,33 @@
|
|||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/@signalapp/parchment-cjs": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@signalapp/parchment-cjs/-/parchment-cjs-3.0.1.tgz",
|
||||
"integrity": "sha512-hSBMQ1M7wE4GcC8ZeNtvpJF+DAJg3eIRRf1SiHS3I3Algav/sgJJNm6HIYm6muHuK7IJmuEjkL3ILSXgmu0RfQ==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@signalapp/quill-cjs": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@signalapp/quill-cjs/-/quill-cjs-2.1.2.tgz",
|
||||
"integrity": "sha512-y2sgqdivlrG41J4Zvt/82xtH/PZjDlgItqlD2g/Cv3ZbjlR6cGhTNXbfNygCJB8nXj+C7I28pjt1Zm3k0pv2mg==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@signalapp/parchment-cjs": "3.0.1",
|
||||
"eventemitter3": "^5.0.1",
|
||||
"lodash": "^4.17.21",
|
||||
"quill-delta": "^5.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"npm": ">=8.2.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@signalapp/quill-cjs/node_modules/eventemitter3": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
|
||||
"integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@signalapp/ringrtc": {
|
||||
"version": "2.49.3",
|
||||
"resolved": "https://registry.npmjs.org/@signalapp/ringrtc/-/ringrtc-2.49.3.tgz",
|
||||
|
@ -8725,14 +8748,6 @@
|
|||
"integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/quill": {
|
||||
"version": "1.3.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/quill/-/quill-1.3.10.tgz",
|
||||
"integrity": "sha512-IhW3fPW+bkt9MLNlycw8u8fWb7oO7W5URC9MfZYHBlA24rex9rs23D5DETChu1zvgVdc5ka64ICjJOgQMr6Shw==",
|
||||
"dependencies": {
|
||||
"parchment": "^1.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/range-parser": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz",
|
||||
|
@ -12363,16 +12378,47 @@
|
|||
}
|
||||
},
|
||||
"node_modules/call-bind": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
|
||||
"integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
|
||||
"integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.0",
|
||||
"es-define-property": "^1.0.0",
|
||||
"es-errors": "^1.3.0",
|
||||
"function-bind": "^1.1.2",
|
||||
"get-intrinsic": "^1.2.4",
|
||||
"set-function-length": "^1.2.1"
|
||||
"set-function-length": "^1.2.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/call-bind-apply-helpers": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz",
|
||||
"integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
"function-bind": "^1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/call-bound": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz",
|
||||
"integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.1",
|
||||
"get-intrinsic": "^1.2.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
|
@ -13004,14 +13050,6 @@
|
|||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/clone": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
|
||||
"integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==",
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/clone-deep": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
|
||||
|
@ -14239,11 +14277,6 @@
|
|||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/deep-equal": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
|
||||
"integrity": "sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw=="
|
||||
},
|
||||
"node_modules/deep-extend": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
|
||||
|
@ -14787,6 +14820,21 @@
|
|||
"url": "https://dotenvx.com"
|
||||
}
|
||||
},
|
||||
"node_modules/dunder-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.1",
|
||||
"es-errors": "^1.3.0",
|
||||
"gopd": "^1.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/duplexer2": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
|
||||
|
@ -15355,13 +15403,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/es-define-property": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
|
||||
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"get-intrinsic": "^1.2.4"
|
||||
},
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
|
@ -15381,6 +15427,19 @@
|
|||
"integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/es-object-atoms": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz",
|
||||
"integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-shim-unscopables": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz",
|
||||
|
@ -17086,7 +17145,8 @@
|
|||
"node_modules/extend": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
|
||||
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/extend-shallow": {
|
||||
"version": "2.0.1",
|
||||
|
@ -17149,11 +17209,6 @@
|
|||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||
"dev": true
|
||||
},
|
||||
"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=="
|
||||
},
|
||||
"node_modules/fast-glob": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
|
||||
|
@ -17944,16 +17999,22 @@
|
|||
}
|
||||
},
|
||||
"node_modules/get-intrinsic": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
|
||||
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
|
||||
"version": "1.2.7",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz",
|
||||
"integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.1",
|
||||
"es-define-property": "^1.0.1",
|
||||
"es-errors": "^1.3.0",
|
||||
"es-object-atoms": "^1.0.0",
|
||||
"function-bind": "^1.1.2",
|
||||
"has-proto": "^1.0.1",
|
||||
"has-symbols": "^1.0.3",
|
||||
"hasown": "^2.0.0"
|
||||
"get-proto": "^1.0.0",
|
||||
"gopd": "^1.2.0",
|
||||
"has-symbols": "^1.1.0",
|
||||
"hasown": "^2.0.2",
|
||||
"math-intrinsics": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
|
@ -17972,6 +18033,20 @@
|
|||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/get-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"dunder-proto": "^1.0.1",
|
||||
"es-object-atoms": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/get-stdin": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz",
|
||||
|
@ -18304,12 +18379,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/gopd": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
|
||||
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"get-intrinsic": "^1.1.3"
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
|
@ -18437,23 +18513,12 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/has-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/has-symbols": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
|
||||
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
||||
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
|
@ -18462,12 +18527,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/has-tostringtag": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
|
||||
"integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
||||
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"has-symbols": "^1.0.2"
|
||||
"has-symbols": "^1.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
|
@ -19412,12 +19478,20 @@
|
|||
}
|
||||
},
|
||||
"node_modules/is-date-object": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
|
||||
"integrity": "sha512-P5rExV1phPi42ppoMWy7V63N3i173RY921l4JJ7zonMSxK+OWGPj76GD+cUKUb68l4vQXcJp2SsG+r/A4ABVzg==",
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz",
|
||||
"integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bound": "^1.0.2",
|
||||
"has-tostringtag": "^1.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/is-decimal": {
|
||||
|
@ -21992,6 +22066,12 @@
|
|||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||
},
|
||||
"node_modules/lodash.clonedeep": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
|
||||
"integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.debounce": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
|
||||
|
@ -22032,6 +22112,12 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.isequal": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
|
||||
"integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.isinteger": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
|
||||
|
@ -22460,6 +22546,16 @@
|
|||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/math-intrinsics": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/mathml-tag-names": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz",
|
||||
|
@ -25078,11 +25174,6 @@
|
|||
"tslib": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/parchment": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/parchment/-/parchment-1.1.4.tgz",
|
||||
"integrity": "sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg=="
|
||||
},
|
||||
"node_modules/parent-module": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
||||
|
@ -26522,47 +26613,26 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"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==",
|
||||
"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/quill-delta": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-4.0.1.tgz",
|
||||
"integrity": "sha512-8MdJmDlsnkGTMP3VVqVb/S95l+X691/xY1iQ3tmDDBWkqUyqh72+tBnaEStxfEa5YqzozGeYWz8j2B3pni5Bew==",
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-5.1.0.tgz",
|
||||
"integrity": "sha512-X74oCeRI4/p0ucjb5Ma8adTXd9Scumz367kkMK5V/IatcX6A0vlgLgKbzXWy5nZmCGeNJm2oQX0d2Eqj+ZIlCA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"deep-equal": "^1.0.1",
|
||||
"extend": "^3.0.2",
|
||||
"fast-diff": "1.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/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=="
|
||||
},
|
||||
"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==",
|
||||
"dependencies": {
|
||||
"deep-equal": "^1.0.1",
|
||||
"extend": "^3.0.2",
|
||||
"fast-diff": "1.1.2"
|
||||
"fast-diff": "^1.3.0",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"lodash.isequal": "^4.5.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
"node": ">= 12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/quill-delta/node_modules/fast-diff": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
|
||||
"integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/rambda": {
|
||||
"version": "7.3.0",
|
||||
"resolved": "https://registry.npmjs.org/rambda/-/rambda-7.3.0.tgz",
|
||||
|
@ -27092,20 +27162,6 @@
|
|||
"react-dom": "^16.8.0 || ^17 || ^18"
|
||||
}
|
||||
},
|
||||
"node_modules/react-quill": {
|
||||
"version": "2.0.0-beta.4",
|
||||
"resolved": "https://registry.npmjs.org/react-quill/-/react-quill-2.0.0-beta.4.tgz",
|
||||
"integrity": "sha512-KyAHvAlPjP4xLElKZJefMth91Z6FbbXRvq9OSu6xN3KBaoasLP9p+3dcxg4Ywr4tBlpMGXcPszYSAgd5CpJ45Q==",
|
||||
"dependencies": {
|
||||
"@types/quill": "^1.3.10",
|
||||
"lodash": "^4.17.4",
|
||||
"quill": "^1.3.7"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16 || ^17",
|
||||
"react-dom": "^16 || ^17"
|
||||
}
|
||||
},
|
||||
"node_modules/react-redux": {
|
||||
"version": "8.1.3",
|
||||
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.1.3.tgz",
|
||||
|
@ -27489,14 +27545,18 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/regexp.prototype.flags": {
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
|
||||
"integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==",
|
||||
"version": "1.5.4",
|
||||
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
|
||||
"integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.2",
|
||||
"define-properties": "^1.1.3",
|
||||
"functions-have-names": "^1.2.2"
|
||||
"call-bind": "^1.0.8",
|
||||
"define-properties": "^1.2.1",
|
||||
"es-errors": "^1.3.0",
|
||||
"get-proto": "^1.0.1",
|
||||
"gopd": "^1.2.0",
|
||||
"set-function-name": "^2.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
|
@ -28461,6 +28521,22 @@
|
|||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/set-function-name": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
|
||||
"integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"define-data-property": "^1.1.4",
|
||||
"es-errors": "^1.3.0",
|
||||
"functions-have-names": "^1.2.3",
|
||||
"has-property-descriptors": "^1.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/setprototypeof": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
|
||||
|
|
|
@ -114,6 +114,7 @@
|
|||
"@react-spring/web": "9.7.5",
|
||||
"@signalapp/better-sqlite3": "9.0.9",
|
||||
"@signalapp/libsignal-client": "0.65.4",
|
||||
"@signalapp/quill-cjs": "2.1.2",
|
||||
"@signalapp/ringrtc": "2.49.3",
|
||||
"@types/fabric": "4.5.3",
|
||||
"backbone": "1.6.0",
|
||||
|
@ -161,14 +162,11 @@
|
|||
"p-map": "2.1.0",
|
||||
"p-queue": "6.6.2",
|
||||
"p-timeout": "4.1.0",
|
||||
"parchment": "1.1.4",
|
||||
"pify": "3.0.0",
|
||||
"pino": "9.5.0",
|
||||
"protobufjs": "7.3.2",
|
||||
"proxy-agent": "6.4.0",
|
||||
"qrcode-generator": "1.4.4",
|
||||
"quill": "1.3.7",
|
||||
"quill-delta": "4.0.1",
|
||||
"react": "17.0.2",
|
||||
"react-aria": "3.35.1",
|
||||
"react-aria-components": "1.4.1",
|
||||
|
@ -179,7 +177,6 @@
|
|||
"react-hot-loader": "4.13.1",
|
||||
"react-intl": "6.8.7",
|
||||
"react-popper": "2.3.0",
|
||||
"react-quill": "2.0.0-beta.4",
|
||||
"react-redux": "8.1.3",
|
||||
"react-router-dom": "5.0.1",
|
||||
"react-textarea-autosize": "8.5.5",
|
||||
|
@ -256,7 +253,6 @@
|
|||
"@types/pify": "5.0.4",
|
||||
"@types/pixelmatch": "5.2.6",
|
||||
"@types/pngjs": "6.0.5",
|
||||
"@types/quill": "1.3.10",
|
||||
"@types/react": "17.0.45",
|
||||
"@types/react-dom": "17.0.17",
|
||||
"@types/react-redux": "7.1.34",
|
||||
|
|
|
@ -1,185 +0,0 @@
|
|||
diff --git a/node_modules/quill/dist/quill.js b/node_modules/quill/dist/quill.js
|
||||
index 811b3d0..9243ab6 100644
|
||||
--- a/node_modules/quill/dist/quill.js
|
||||
+++ b/node_modules/quill/dist/quill.js
|
||||
@@ -4295,7 +4295,7 @@ var Scroll = function (_Parchment$Scroll) {
|
||||
value: function enable() {
|
||||
var enabled = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
||||
|
||||
- this.domNode.setAttribute('contenteditable', enabled);
|
||||
+ this.domNode.setAttribute('contenteditable', enabled ? 'plaintext-only' : false);
|
||||
}
|
||||
}, {
|
||||
key: 'formatAt',
|
||||
@@ -8896,7 +8896,8 @@ var debug = (0, _logger2.default)('quill:clipboard');
|
||||
|
||||
var DOM_KEY = '__ql-matcher';
|
||||
|
||||
-var CLIPBOARD_CONFIG = [[Node.TEXT_NODE, matchText], [Node.TEXT_NODE, matchNewline], ['br', matchBreak], [Node.ELEMENT_NODE, matchNewline], [Node.ELEMENT_NODE, matchBlot], [Node.ELEMENT_NODE, matchSpacing], [Node.ELEMENT_NODE, matchAttributor], [Node.ELEMENT_NODE, matchStyles], ['li', matchIndent], ['b', matchAlias.bind(matchAlias, 'bold')], ['i', matchAlias.bind(matchAlias, 'italic')], ['style', matchIgnore]];
|
||||
+// var CLIPBOARD_CONFIG = [[Node.TEXT_NODE, matchText], [Node.TEXT_NODE, matchNewline], ['br', matchBreak], [Node.ELEMENT_NODE, matchNewline], [Node.ELEMENT_NODE, matchBlot], [Node.ELEMENT_NODE, matchSpacing], [Node.ELEMENT_NODE, matchAttributor], [Node.ELEMENT_NODE, matchStyles], ['li', matchIndent], ['b', matchAlias.bind(matchAlias, 'bold')], ['i', matchAlias.bind(matchAlias, 'italic')], ['style', matchIgnore]];
|
||||
+var CLIPBOARD_CONFIG = [[Node.TEXT_NODE, matchText], [Node.TEXT_NODE, matchNewline], ['br', matchBreak], [Node.ELEMENT_NODE, matchNewline]];
|
||||
|
||||
var ATTRIBUTE_ATTRIBUTORS = [_align.AlignAttribute, _direction.DirectionAttribute].reduce(function (memo, attr) {
|
||||
memo[attr.keyName] = attr;
|
||||
@@ -8916,10 +8917,10 @@ var Clipboard = function (_Module) {
|
||||
|
||||
var _this = _possibleConstructorReturn(this, (Clipboard.__proto__ || Object.getPrototypeOf(Clipboard)).call(this, quill, options));
|
||||
|
||||
- _this.quill.root.addEventListener('paste', _this.onPaste.bind(_this));
|
||||
- _this.container = _this.quill.addContainer('ql-clipboard');
|
||||
- _this.container.setAttribute('contenteditable', true);
|
||||
- _this.container.setAttribute('tabindex', -1);
|
||||
+ // _this.quill.root.addEventListener('paste', _this.onPaste.bind(_this));
|
||||
+ // _this.container = _this.quill.addContainer('ql-clipboard');
|
||||
+ // _this.container.setAttribute('contenteditable', true);
|
||||
+ // _this.container.setAttribute('tabindex', -1);
|
||||
_this.matchers = [];
|
||||
CLIPBOARD_CONFIG.concat(_this.options.matchers).forEach(function (_ref) {
|
||||
var _ref2 = _slicedToArray(_ref, 2),
|
||||
@@ -8941,28 +8942,33 @@ var Clipboard = function (_Module) {
|
||||
key: 'convert',
|
||||
value: function convert(html) {
|
||||
if (typeof html === 'string') {
|
||||
- this.container.innerHTML = html.replace(/\>\r?\n +\</g, '><'); // Remove spaces between tags
|
||||
+ // this.container.innerHTML = html.replace(/\>\r?\n +\</g, '><'); // Remove spaces between tags
|
||||
+ var parser = new DOMParser();
|
||||
+ var htmlNoSpaces = html.replace(/\>\r?\n +\</g, '><'); // Remove spaces between tags
|
||||
+ this.container = parser.parseFromString(htmlNoSpaces, "text/html").body;
|
||||
return this.convert();
|
||||
}
|
||||
var formats = this.quill.getFormat(this.quill.selection.savedRange.index);
|
||||
- if (formats[_code2.default.blotName]) {
|
||||
- var text = this.container.innerText;
|
||||
- this.container.innerHTML = '';
|
||||
- return new _quillDelta2.default().insert(text, _defineProperty({}, _code2.default.blotName, formats[_code2.default.blotName]));
|
||||
- }
|
||||
+ // if (formats[_code2.default.blotName]) {
|
||||
+ // var text = this.container.innerText;
|
||||
+ // this.container.innerHTML = '';
|
||||
+ // return new _quillDelta2.default().insert(text, _defineProperty({}, _code2.default.blotName, formats[_code2.default.blotName]));
|
||||
+ // }
|
||||
|
||||
var _prepareMatching = this.prepareMatching(),
|
||||
_prepareMatching2 = _slicedToArray(_prepareMatching, 2),
|
||||
elementMatchers = _prepareMatching2[0],
|
||||
textMatchers = _prepareMatching2[1];
|
||||
|
||||
- var delta = traverse(this.container, elementMatchers, textMatchers);
|
||||
+ // var delta = traverse(this.container, elementMatchers, textMatchers);
|
||||
+ var delta = traverse(this.container, elementMatchers, textMatchers, formats);
|
||||
// Remove trailing newline
|
||||
if (deltaEndsWith(delta, '\n') && delta.ops[delta.ops.length - 1].attributes == null) {
|
||||
delta = delta.compose(new _quillDelta2.default().retain(delta.length() - 1).delete(1));
|
||||
}
|
||||
debug.log('convert', this.container.innerHTML, delta);
|
||||
- this.container.innerHTML = '';
|
||||
+ // this.container.innerHTML = '';
|
||||
+ this.container = null;
|
||||
return delta;
|
||||
}
|
||||
}, {
|
||||
@@ -9056,9 +9062,10 @@ function applyFormat(delta, format, value) {
|
||||
}
|
||||
|
||||
function computeStyle(node) {
|
||||
- if (node.nodeType !== Node.ELEMENT_NODE) return {};
|
||||
- var DOM_KEY = '__ql-computed-style';
|
||||
- return node[DOM_KEY] || (node[DOM_KEY] = window.getComputedStyle(node));
|
||||
+ // if (node.nodeType !== Node.ELEMENT_NODE) return {};
|
||||
+ // var DOM_KEY = '__ql-computed-style';
|
||||
+ // return node[DOM_KEY] || (node[DOM_KEY] = window.getComputedStyle(node));
|
||||
+ return node.style;
|
||||
}
|
||||
|
||||
function deltaEndsWith(delta, text) {
|
||||
@@ -9070,28 +9077,43 @@ function deltaEndsWith(delta, text) {
|
||||
}
|
||||
return endText.slice(-1 * text.length) === text;
|
||||
}
|
||||
+function deltaIs(delta, text) {
|
||||
+ var allText = "";
|
||||
+ for (var i = delta.ops.length - 1; i >= 0 && allText.length <= text.length; --i) {
|
||||
+ var op = delta.ops[i];
|
||||
+ if (typeof op.insert !== 'string') break;
|
||||
+ allText = op.insert + allText;
|
||||
+ }
|
||||
+ return allText === text;
|
||||
+}
|
||||
|
||||
function isLine(node) {
|
||||
if (node.childNodes.length === 0) return false; // Exclude embed blocks
|
||||
var style = computeStyle(node);
|
||||
- return ['block', 'list-item'].indexOf(style.display) > -1;
|
||||
+ // return ['block', 'list-item'].indexOf(style.display) > -1;
|
||||
+ return ['block', 'list-item'].indexOf(style.display) > -1 || node.nodeName === 'DIV' || node.nodeName === 'P' || node.nodeName === 'TIME';
|
||||
}
|
||||
|
||||
-function traverse(node, elementMatchers, textMatchers) {
|
||||
+// function traverse(node, elementMatchers, textMatchers) {
|
||||
+function traverse(node, elementMatchers, textMatchers, attributes) {
|
||||
// Post-order
|
||||
if (node.nodeType === node.TEXT_NODE) {
|
||||
return textMatchers.reduce(function (delta, matcher) {
|
||||
- return matcher(node, delta);
|
||||
+ // return matcher(node, delta);
|
||||
+ return matcher(node, delta, attributes);
|
||||
}, new _quillDelta2.default());
|
||||
} else if (node.nodeType === node.ELEMENT_NODE) {
|
||||
return [].reduce.call(node.childNodes || [], function (delta, childNode) {
|
||||
- var childrenDelta = traverse(childNode, elementMatchers, textMatchers);
|
||||
+ // var childrenDelta = traverse(childNode, elementMatchers, textMatchers);
|
||||
+ var childrenDelta = traverse(childNode, elementMatchers, textMatchers, attributes);
|
||||
if (childNode.nodeType === node.ELEMENT_NODE) {
|
||||
childrenDelta = elementMatchers.reduce(function (childrenDelta, matcher) {
|
||||
- return matcher(childNode, childrenDelta);
|
||||
+ // return matcher(childNode, childrenDelta);
|
||||
+ return matcher(childNode, childrenDelta, attributes);
|
||||
}, childrenDelta);
|
||||
childrenDelta = (childNode[DOM_KEY] || []).reduce(function (childrenDelta, matcher) {
|
||||
- return matcher(childNode, childrenDelta);
|
||||
+ // return matcher(childNode, childrenDelta);
|
||||
+ return matcher(childNode, childrenDelta, attributes);
|
||||
}, childrenDelta);
|
||||
}
|
||||
return delta.concat(childrenDelta);
|
||||
@@ -9177,8 +9199,10 @@ function matchIndent(node, delta) {
|
||||
}
|
||||
|
||||
function matchNewline(node, delta) {
|
||||
- if (!deltaEndsWith(delta, '\n')) {
|
||||
- if (isLine(node) || delta.length() > 0 && node.nextSibling && isLine(node.nextSibling)) {
|
||||
+ // if (!deltaEndsWith(delta, '\n')) {
|
||||
+ if (!deltaIs(delta, '\n') && !deltaEndsWith(delta, '\n\n')) {
|
||||
+ // if (isLine(node) || delta.length() > 0 && node.nextSibling && isLine(node.nextSibling)) {
|
||||
+ if (delta.length() > 0 && isLine(node)) {
|
||||
delta.insert('\n');
|
||||
}
|
||||
}
|
||||
@@ -9186,7 +9210,7 @@ function matchNewline(node, delta) {
|
||||
}
|
||||
|
||||
function matchSpacing(node, delta) {
|
||||
- if (isLine(node) && node.nextElementSibling != null && !deltaEndsWith(delta, '\n\n')) {
|
||||
+ if (isLine(node) && node.nextElementSibling != null && !deltaIs(delta, '\n') && !deltaEndsWith(delta, '\n\n')) {
|
||||
var nodeHeight = node.offsetHeight + parseFloat(computeStyle(node).marginTop) + parseFloat(computeStyle(node).marginBottom);
|
||||
if (node.nextElementSibling.offsetTop > node.offsetTop + nodeHeight * 1.5) {
|
||||
delta.insert('\n');
|
||||
@@ -9214,7 +9238,7 @@ function matchStyles(node, delta) {
|
||||
return delta;
|
||||
}
|
||||
|
||||
-function matchText(node, delta) {
|
||||
+function matchText(node, delta, attributes) {
|
||||
var text = node.data;
|
||||
// Word represents empty line with <o:p> </o:p>
|
||||
if (node.parentNode.tagName === 'O:P') {
|
||||
@@ -9238,7 +9262,7 @@ function matchText(node, delta) {
|
||||
text = text.replace(/\s+$/, replacer.bind(replacer, false));
|
||||
}
|
||||
}
|
||||
- return delta.insert(text);
|
||||
+ return delta.insert(text, attributes);
|
||||
}
|
||||
|
||||
exports.default = Clipboard;
|
||||
\ No newline at end of file
|
|
@ -136,6 +136,7 @@
|
|||
padding-block: 6px;
|
||||
padding-inline: 12px;
|
||||
border-radius: 8px;
|
||||
// This needs to be quite high to enable usage in popups like ForwardMessageModal
|
||||
z-index: variables.$z-index-above-popup;
|
||||
|
||||
display: flex;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import * as React from 'react';
|
||||
// @ts-expect-error -- no types
|
||||
import 'react-quill/dist/quill.core.css';
|
||||
import '@signalapp/quill-cjs/dist/quill.core.css';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import type { Meta } from '@storybook/react';
|
||||
import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation';
|
||||
|
|
|
@ -3,12 +3,15 @@
|
|||
|
||||
import * as React from 'react';
|
||||
|
||||
import Delta from 'quill-delta';
|
||||
import ReactQuill from 'react-quill';
|
||||
import Quill, { Delta } from '@signalapp/quill-cjs';
|
||||
import {
|
||||
matchText,
|
||||
matchNewline,
|
||||
matchBreak,
|
||||
} from '@signalapp/quill-cjs/modules/clipboard';
|
||||
import classNames from 'classnames';
|
||||
import { Manager, Reference } from 'react-popper';
|
||||
import type { DeltaStatic, KeyboardStatic, RangeStatic } from 'quill';
|
||||
import Quill from 'quill';
|
||||
import type { Range as RangeStatic } from '@signalapp/quill-cjs';
|
||||
|
||||
import { MentionCompletion } from '../quill/mentions/completion';
|
||||
import { FormattingMenu, QuillFormattingStyle } from '../quill/formatting/menu';
|
||||
|
@ -56,7 +59,6 @@ import { getClassNamesFor } from '../util/getClassNamesFor';
|
|||
import { isNotNil } from '../util/isNotNil';
|
||||
import * as log from '../logging/log';
|
||||
import * as Errors from '../types/errors';
|
||||
import { useRefMerger } from '../hooks/useRefMerger';
|
||||
import { useEmojiSearch } from '../hooks/useEmojiSearch';
|
||||
import type { LinkPreviewType } from '../types/message/LinkPreviews';
|
||||
import { StagedLinkPreview } from './conversation/StagedLinkPreview';
|
||||
|
@ -72,22 +74,23 @@ import {
|
|||
import { missingCaseError } from '../util/missingCaseError';
|
||||
import { AutoSubstituteAsciiEmojis } from '../quill/auto-substitute-ascii-emojis';
|
||||
import { dropNull } from '../util/dropNull';
|
||||
import { SimpleQuillWrapper } from './SimpleQuillWrapper';
|
||||
|
||||
Quill.register('formats/emoji', EmojiBlot);
|
||||
Quill.register('formats/mention', MentionBlot);
|
||||
Quill.register('formats/block', DirectionalBlot);
|
||||
Quill.register('formats/monospace', MonospaceBlot);
|
||||
Quill.register('formats/spoiler', SpoilerBlot);
|
||||
Quill.register('modules/autoSubstituteAsciiEmojis', AutoSubstituteAsciiEmojis);
|
||||
Quill.register('modules/emojiCompletion', EmojiCompletion);
|
||||
Quill.register('modules/mentionCompletion', MentionCompletion);
|
||||
Quill.register('modules/formattingMenu', FormattingMenu);
|
||||
Quill.register('modules/signalClipboard', SignalClipboard);
|
||||
|
||||
type HistoryStatic = {
|
||||
undo(): void;
|
||||
clear(): void;
|
||||
};
|
||||
Quill.register(
|
||||
{
|
||||
'formats/emoji': EmojiBlot,
|
||||
'formats/mention': MentionBlot,
|
||||
'formats/block': DirectionalBlot,
|
||||
'formats/monospace': MonospaceBlot,
|
||||
'formats/spoiler': SpoilerBlot,
|
||||
'modules/autoSubstituteAsciiEmojis': AutoSubstituteAsciiEmojis,
|
||||
'modules/emojiCompletion': EmojiCompletion,
|
||||
'modules/mentionCompletion': MentionCompletion,
|
||||
'modules/formattingMenu': FormattingMenu,
|
||||
'modules/signalClipboard': SignalClipboard,
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
export type InputApi = {
|
||||
focus: () => void;
|
||||
|
@ -120,7 +123,6 @@ export type Props = Readonly<{
|
|||
theme: ThemeType;
|
||||
placeholder?: string;
|
||||
sortedGroupMembers: ReadonlyArray<ConversationType> | null;
|
||||
scrollerRef?: React.RefObject<HTMLDivElement>;
|
||||
onDirtyChange?(dirty: boolean): unknown;
|
||||
onEditorStateChange(options: {
|
||||
bodyRanges: DraftBodyRanges;
|
||||
|
@ -185,8 +187,6 @@ export function CompositionInput(props: Props): React.ReactElement {
|
|||
theme,
|
||||
} = props;
|
||||
|
||||
const refMerger = useRefMerger();
|
||||
|
||||
const [emojiCompletionElement, setEmojiCompletionElement] =
|
||||
React.useState<JSX.Element>();
|
||||
const [formattingChooserElement, setFormattingChooserElement] =
|
||||
|
@ -200,8 +200,6 @@ export function CompositionInput(props: Props): React.ReactElement {
|
|||
const mentionCompletionRef = React.useRef<MentionCompletion>();
|
||||
const quillRef = React.useRef<Quill>();
|
||||
|
||||
const scrollerRefInner = React.useRef<HTMLDivElement>(null);
|
||||
|
||||
const propsRef = React.useRef<Props>(props);
|
||||
const canSendRef = React.useRef<boolean>(false);
|
||||
const memberRepositoryRef = React.useRef<MemberRepository>(
|
||||
|
@ -311,13 +309,7 @@ export function CompositionInput(props: Props): React.ReactElement {
|
|||
canSendRef.current = true;
|
||||
quill.setText('');
|
||||
|
||||
const historyModule = quill.getModule('history');
|
||||
|
||||
if (historyModule === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
historyModule.clear();
|
||||
quill.history.clear();
|
||||
};
|
||||
|
||||
const setContents = (
|
||||
|
@ -334,11 +326,7 @@ export function CompositionInput(props: Props): React.ReactElement {
|
|||
const delta = generateDelta(text || '', bodyRanges || []);
|
||||
|
||||
canSendRef.current = true;
|
||||
// We need to cast here because we use @types/quill@1.3.10 which has types
|
||||
// for quill-delta even though quill-delta is written in TS and has its own
|
||||
// types. @types/quill@2.0.0 fixes the issue but react-quill has a peer-dep
|
||||
// on the older quill types.
|
||||
quill.setContents(delta as unknown as DeltaStatic);
|
||||
quill.setContents(delta);
|
||||
if (cursorToEnd) {
|
||||
quill.setSelection(quill.getLength(), 0);
|
||||
}
|
||||
|
@ -410,11 +398,17 @@ export function CompositionInput(props: Props): React.ReactElement {
|
|||
const quill = quillRef.current;
|
||||
const changed = formattingChanged || mouseDownChanged;
|
||||
if (quill && changed) {
|
||||
quill.getModule('formattingMenu').updateOptions({
|
||||
const formattingMenu = quill.getModule('formattingMenu');
|
||||
if (!(formattingMenu instanceof FormattingMenu)) {
|
||||
throw new Error(
|
||||
'CompositionInput: formattingMenu module not properly initialized'
|
||||
);
|
||||
}
|
||||
|
||||
formattingMenu.updateOptions({
|
||||
isMenuEnabled: isFormattingEnabled,
|
||||
isMouseDown,
|
||||
});
|
||||
quill.options.formats = getQuillFormats();
|
||||
}
|
||||
}, [
|
||||
isFormattingEnabled,
|
||||
|
@ -424,7 +418,17 @@ export function CompositionInput(props: Props): React.ReactElement {
|
|||
]);
|
||||
|
||||
React.useEffect(() => {
|
||||
quillRef.current?.getModule('signalClipboard').updateOptions({
|
||||
const signalClipboard = quillRef.current?.getModule('signalClipboard');
|
||||
if (!signalClipboard) {
|
||||
return;
|
||||
}
|
||||
if (!(signalClipboard instanceof SignalClipboard)) {
|
||||
throw new Error(
|
||||
'CompositionInput: signalClipboard module not properly initialized'
|
||||
);
|
||||
}
|
||||
|
||||
signalClipboard.updateOptions({
|
||||
isDisabled: !isActive,
|
||||
});
|
||||
}, [isActive]);
|
||||
|
@ -527,6 +531,10 @@ export function CompositionInput(props: Props): React.ReactElement {
|
|||
}
|
||||
|
||||
const [blotToDelete] = quill.getLeaf(selection.index);
|
||||
if (!blotToDelete) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isMentionBlot(blotToDelete)) {
|
||||
const contents = quill.getContents(0, selection.index - 1);
|
||||
const restartDelta = getDeltaToRestartMention(contents.ops);
|
||||
|
@ -553,10 +561,18 @@ export function CompositionInput(props: Props): React.ReactElement {
|
|||
const { text, bodyRanges } = getTextAndRanges();
|
||||
|
||||
if (quill !== undefined) {
|
||||
const historyModule: HistoryStatic = quill.getModule('history');
|
||||
// This is pretty ugly, but it seems that Chromium tries to replicate the computed
|
||||
// style of removed DOM elements. 100% reproducible by selecting formatted lines and
|
||||
// typing new text. This code removes the style tags that we don't want there, and
|
||||
// quill doesn't know about. It can result formatting on the resultant message that
|
||||
// doesn't match the composer.
|
||||
const withStyles = quill.container.querySelectorAll('[style]');
|
||||
for (const node of withStyles) {
|
||||
node.attributes.removeNamedItem('style');
|
||||
}
|
||||
|
||||
if (text.length > MAX_LENGTH) {
|
||||
historyModule.undo();
|
||||
quill.history.undo();
|
||||
propsRef.current.onTextTooLong();
|
||||
return;
|
||||
}
|
||||
|
@ -722,7 +738,7 @@ export function CompositionInput(props: Props): React.ReactElement {
|
|||
const delta = generateDelta(draftText || '', draftBodyRanges || []);
|
||||
|
||||
return (
|
||||
<ReactQuill
|
||||
<SimpleQuillWrapper
|
||||
className={`${BASE_CLASS_NAME}__quill`}
|
||||
onChange={() => callbacksRef.current.onChange()}
|
||||
defaultValue={delta}
|
||||
|
@ -732,7 +748,13 @@ export function CompositionInput(props: Props): React.ReactElement {
|
|||
isDisabled: !isActive,
|
||||
},
|
||||
clipboard: {
|
||||
defaultMatchersOverride: [],
|
||||
disableDefaultListeners: true,
|
||||
matchers: [
|
||||
[Node.TEXT_NODE, matchText],
|
||||
[Node.TEXT_NODE, matchNewline],
|
||||
['br', matchBreak],
|
||||
[Node.ELEMENT_NODE, matchNewline],
|
||||
['IMG', matchEmojiImage],
|
||||
['IMG', matchEmojiBlot],
|
||||
['STRONG', matchBold],
|
||||
|
@ -746,23 +768,27 @@ export function CompositionInput(props: Props): React.ReactElement {
|
|||
},
|
||||
keyboard: {
|
||||
bindings: {
|
||||
onEnter: {
|
||||
key: 13,
|
||||
handler: () => callbacksRef.current.onEnter(),
|
||||
}, // 13 = Enter
|
||||
onShortKeyEnter: {
|
||||
key: 13, // 13 = Enter
|
||||
ShortEnter: {
|
||||
key: 'Enter',
|
||||
shortKey: true,
|
||||
handler: () => callbacksRef.current.onShortKeyEnter(),
|
||||
},
|
||||
onEscape: {
|
||||
key: 27,
|
||||
Enter: {
|
||||
key: 'Enter',
|
||||
handler: () => callbacksRef.current.onEnter(),
|
||||
},
|
||||
Escape: {
|
||||
key: 'Escape',
|
||||
handler: () => callbacksRef.current.onEscape(),
|
||||
}, // 27 = Escape
|
||||
onBackspace: {
|
||||
key: 8,
|
||||
},
|
||||
Backspace: {
|
||||
key: 'Backspace',
|
||||
handler: () => callbacksRef.current.onBackspace(),
|
||||
}, // 8 = Backspace
|
||||
},
|
||||
Tab: {
|
||||
key: 'Tab',
|
||||
handler: () => callbacksRef.current.onTab(),
|
||||
},
|
||||
},
|
||||
},
|
||||
emojiCompletion: {
|
||||
|
@ -795,27 +821,18 @@ export function CompositionInput(props: Props): React.ReactElement {
|
|||
readOnly={disabled}
|
||||
ref={element => {
|
||||
if (element) {
|
||||
const quill = element.getEditor();
|
||||
const keyboard = quill.getModule('keyboard') as KeyboardStatic;
|
||||
const quill = element.getQuill();
|
||||
if (!quill) {
|
||||
throw new Error(
|
||||
'CompositionInput: wrapper did not return quill!'
|
||||
);
|
||||
}
|
||||
|
||||
// force the tab handler to be prepended, otherwise it won't be
|
||||
// executed: https://github.com/quilljs/quill/issues/1967
|
||||
keyboard.bindings[9].unshift({
|
||||
key: 9,
|
||||
handler: () => callbacksRef.current.onTab(),
|
||||
}); // 9 = Tab
|
||||
// also, remove the default \t insertion binding
|
||||
keyboard.bindings[9].pop();
|
||||
quillRef.current = quill;
|
||||
|
||||
// When loading a multi-line message out of a draft, the cursor
|
||||
// position needs to be pushed to the end of the input manually.
|
||||
quill.once('editor-change', () => {
|
||||
const scroller = scrollerRefInner.current;
|
||||
|
||||
if (scroller != null) {
|
||||
quill.scrollingContainer = scroller;
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
quill.setSelection(quill.getLength(), 0);
|
||||
quill.root.classList.add('ql-editor--loaded');
|
||||
|
@ -831,10 +848,22 @@ export function CompositionInput(props: Props): React.ReactElement {
|
|||
}
|
||||
}
|
||||
);
|
||||
quillRef.current = quill;
|
||||
emojiCompletionRef.current = quill.getModule('emojiCompletion');
|
||||
mentionCompletionRef.current =
|
||||
quill.getModule('mentionCompletion');
|
||||
|
||||
const emojiCompletion = quill.getModule('emojiCompletion');
|
||||
if (!(emojiCompletion instanceof EmojiCompletion)) {
|
||||
throw new Error(
|
||||
'CompositionInput: emojiCompletion module not properly initialized'
|
||||
);
|
||||
}
|
||||
emojiCompletionRef.current = emojiCompletion;
|
||||
|
||||
const mentionCompletion = quill.getModule('mentionCompletion');
|
||||
if (!(mentionCompletion instanceof MentionCompletion)) {
|
||||
throw new Error(
|
||||
'CompositionInput: mentionCompletion module not properly initialized'
|
||||
);
|
||||
}
|
||||
mentionCompletionRef.current = mentionCompletion;
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
@ -918,11 +947,6 @@ export function CompositionInput(props: Props): React.ReactElement {
|
|||
)}
|
||||
{children}
|
||||
<div
|
||||
ref={
|
||||
props.scrollerRef
|
||||
? refMerger(scrollerRefInner, props.scrollerRef)
|
||||
: scrollerRefInner
|
||||
}
|
||||
onClick={focus}
|
||||
onScroll={onScroll}
|
||||
className={classNames(
|
||||
|
|
|
@ -24,7 +24,6 @@ export type CompositionTextAreaProps = {
|
|||
maxLength?: number;
|
||||
placeholder?: string;
|
||||
whenToShowRemainingCount?: number;
|
||||
scrollerRef?: React.RefObject<HTMLDivElement>;
|
||||
onScroll?: (ev: React.UIEvent<HTMLElement, UIEvent>) => void;
|
||||
onPickEmoji: (e: EmojiPickDataType) => void;
|
||||
onChange: (
|
||||
|
@ -71,7 +70,6 @@ export function CompositionTextArea({
|
|||
placeholder,
|
||||
platform,
|
||||
recentEmojis,
|
||||
scrollerRef,
|
||||
skinTone,
|
||||
theme,
|
||||
whenToShowRemainingCount = Infinity,
|
||||
|
@ -153,7 +151,6 @@ export function CompositionTextArea({
|
|||
placeholder={placeholder}
|
||||
platform={platform}
|
||||
quotedMessageId={null}
|
||||
scrollerRef={scrollerRef}
|
||||
sendCounter={0}
|
||||
theme={theme}
|
||||
skinTone={skinTone ?? null}
|
||||
|
|
80
ts/components/SimpleQuillWrapper.tsx
Normal file
80
ts/components/SimpleQuillWrapper.tsx
Normal file
|
@ -0,0 +1,80 @@
|
|||
// Copyright 2025 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import React, { createRef } from 'react';
|
||||
import Quill from '@signalapp/quill-cjs';
|
||||
import type { Delta } from '@signalapp/quill-cjs';
|
||||
|
||||
export type Props = {
|
||||
className: string;
|
||||
defaultValue: Delta | undefined;
|
||||
formats: Array<string>;
|
||||
modules: Record<string, unknown>;
|
||||
onChange?(): void;
|
||||
placeholder: string;
|
||||
readOnly: boolean | undefined;
|
||||
};
|
||||
|
||||
export class SimpleQuillWrapper extends React.Component<Props> {
|
||||
quill: Quill | undefined;
|
||||
quillElement = createRef<HTMLDivElement>();
|
||||
|
||||
override shouldComponentUpdate(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
override componentDidMount(): void {
|
||||
this.createQuill();
|
||||
|
||||
if (!this.quill) {
|
||||
throw new Error(
|
||||
'SimpleQuillWrapper.componentDidMount: this.quill not set!'
|
||||
);
|
||||
}
|
||||
|
||||
this.quill.on('editor-change', this.props.onChange);
|
||||
|
||||
const { defaultValue } = this.props;
|
||||
if (defaultValue) {
|
||||
this.quill.setContents(defaultValue);
|
||||
}
|
||||
}
|
||||
|
||||
override componentWillUnmount(): void {
|
||||
if (!this.quill) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.quill.off('editor-change', this.props.onChange);
|
||||
this.quill = undefined;
|
||||
}
|
||||
|
||||
createQuill(): void {
|
||||
if (this.quill) {
|
||||
throw new Error('createQuill: this.quill already set!');
|
||||
}
|
||||
if (!this.quillElement?.current) {
|
||||
throw new Error('createQuill: this.quillElement is not set!');
|
||||
}
|
||||
|
||||
this.quill = new Quill(this.quillElement.current, {
|
||||
formats: this.props.formats,
|
||||
modules: this.props.modules,
|
||||
placeholder: this.props.placeholder,
|
||||
readOnly: this.props.readOnly,
|
||||
});
|
||||
}
|
||||
|
||||
// eslint-disable-next-line react/no-unused-class-component-methods
|
||||
public getQuill(): Quill | undefined {
|
||||
return this.quill;
|
||||
}
|
||||
|
||||
override render(): JSX.Element {
|
||||
return (
|
||||
<div className={`quill ${this.props.className}`}>
|
||||
<div ref={this.quillElement} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,8 +1,10 @@
|
|||
// Copyright 2020 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type Quill from 'quill';
|
||||
import Delta from 'quill-delta';
|
||||
import type Quill from '@signalapp/quill-cjs';
|
||||
import { Delta } from '@signalapp/quill-cjs';
|
||||
|
||||
import * as log from '../../logging/log';
|
||||
import type { EmojiData } from '../../components/emoji/lib';
|
||||
import {
|
||||
convertShortName,
|
||||
|
@ -77,11 +79,18 @@ export class AutoSubstituteAsciiEmojis {
|
|||
|
||||
const [blot, index] = this.quill.getLeaf(range.index);
|
||||
|
||||
if (blot?.text == null) {
|
||||
const text = blot?.value();
|
||||
if (!text) {
|
||||
return;
|
||||
}
|
||||
if (typeof text !== 'string') {
|
||||
log.error(
|
||||
'AutoSubstituteAsciiEmojis: returned blot value was not a string'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const textBeforeCursor = blot.text.slice(0, index);
|
||||
const textBeforeCursor = text.slice(0, index);
|
||||
const match = textBeforeCursor.match(EMOJI_REGEXP);
|
||||
if (match == null) {
|
||||
return;
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
// Copyright 2020 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import Quill from 'quill';
|
||||
import BlockBlot from '@signalapp/quill-cjs/blots/block';
|
||||
|
||||
const Block = Quill.import('blots/block');
|
||||
export class DirectionalBlot extends BlockBlot {
|
||||
static override tagName = 'div';
|
||||
|
||||
export class DirectionalBlot extends Block {
|
||||
static tagName = 'div';
|
||||
|
||||
static create(value: string): Node {
|
||||
static override create(value: string): HTMLElement {
|
||||
const node = super.create(value);
|
||||
node.setAttribute('dir', 'auto');
|
||||
return node;
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
// Copyright 2020 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type Parchment from 'parchment';
|
||||
import Quill from 'quill';
|
||||
import EmbedBlot from '@signalapp/quill-cjs/blots/embed';
|
||||
|
||||
import { emojiToImage } from '../../components/emoji/lib';
|
||||
|
||||
const Embed: typeof Parchment.Embed = Quill.import('blots/embed');
|
||||
|
||||
// the DOM structure of this EmojiBlot should match the other emoji implementations:
|
||||
// ts/components/conversation/Emojify.tsx
|
||||
// ts/components/emoji/Emoji.tsx
|
||||
|
@ -17,7 +14,7 @@ export type EmojiBlotValue = Readonly<{
|
|||
source?: string;
|
||||
}>;
|
||||
|
||||
export class EmojiBlot extends Embed {
|
||||
export class EmojiBlot extends EmbedBlot {
|
||||
static override blotName = 'emoji';
|
||||
|
||||
static override tagName = 'img';
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright 2020 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import Quill from 'quill';
|
||||
import Delta from 'quill-delta';
|
||||
import type Quill from '@signalapp/quill-cjs';
|
||||
import { Delta } from '@signalapp/quill-cjs';
|
||||
import React from 'react';
|
||||
import _, { isNumber } from 'lodash';
|
||||
|
||||
|
@ -18,8 +18,6 @@ import { getBlotTextPartitions, matchBlotTextPartitions } from '../util';
|
|||
import { handleOutsideClick } from '../../util/handleOutsideClick';
|
||||
import * as log from '../../logging/log';
|
||||
|
||||
const Keyboard = Quill.import('modules/keyboard');
|
||||
|
||||
type EmojiPickerOptions = {
|
||||
onPickEmoji: (emoji: EmojiPickDataType) => void;
|
||||
setEmojiPickerElement: (element: JSX.Element | null) => void;
|
||||
|
@ -72,10 +70,10 @@ export class EmojiCompletion {
|
|||
return true;
|
||||
};
|
||||
|
||||
this.quill.keyboard.addBinding({ key: Keyboard.keys.UP }, changeIndex(-1));
|
||||
this.quill.keyboard.addBinding({ key: Keyboard.keys.RIGHT }, clearResults);
|
||||
this.quill.keyboard.addBinding({ key: Keyboard.keys.DOWN }, changeIndex(1));
|
||||
this.quill.keyboard.addBinding({ key: Keyboard.keys.LEFT }, clearResults);
|
||||
this.quill.keyboard.addBinding({ key: 'ArrowUp' }, changeIndex(-1));
|
||||
this.quill.keyboard.addBinding({ key: 'ArrowRight' }, clearResults);
|
||||
this.quill.keyboard.addBinding({ key: 'ArrowDown' }, changeIndex(1));
|
||||
this.quill.keyboard.addBinding({ key: 'ArrowLeft' }, clearResults);
|
||||
this.quill.keyboard.addBinding(
|
||||
{
|
||||
// 186 + Shift = Colon
|
||||
|
@ -116,8 +114,14 @@ export class EmojiCompletion {
|
|||
getCurrentLeafTextPartitions(): [string, string] {
|
||||
const range = this.quill.getSelection();
|
||||
const [blot, index] = this.quill.getLeaf(range ? range.index : -1);
|
||||
const text = blot?.value();
|
||||
if (text && typeof text !== 'string') {
|
||||
throw new Error(
|
||||
'EmojiCompletion/getCurrentLeafTextPartitions: Blot value was not a string'
|
||||
);
|
||||
}
|
||||
|
||||
return getBlotTextPartitions(blot.text, index);
|
||||
return getBlotTextPartitions(text, index);
|
||||
}
|
||||
|
||||
onSelectionChange(): void {
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
// Copyright 2020 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import Delta from 'quill-delta';
|
||||
import type { Matcher, AttributeMap } from 'quill';
|
||||
import { Delta } from '@signalapp/quill-cjs';
|
||||
import type { AttributeMap } from '@signalapp/quill-cjs';
|
||||
|
||||
import { insertEmojiOps } from '../util';
|
||||
import type { Matcher } from '../util';
|
||||
|
||||
export const matchEmojiImage: Matcher = (
|
||||
node: Element,
|
||||
|
@ -22,9 +23,10 @@ export const matchEmojiImage: Matcher = (
|
|||
};
|
||||
|
||||
export const matchEmojiBlot: Matcher = (
|
||||
node: HTMLElement,
|
||||
delta: Delta,
|
||||
attributes: AttributeMap
|
||||
node,
|
||||
delta,
|
||||
_scroll,
|
||||
attributes
|
||||
): Delta => {
|
||||
if (node.classList.contains('emoji-blot')) {
|
||||
const { emoji: value, source } = node.dataset;
|
||||
|
@ -34,9 +36,10 @@ export const matchEmojiBlot: Matcher = (
|
|||
};
|
||||
|
||||
export const matchEmojiText: Matcher = (
|
||||
node: HTMLElement,
|
||||
_delta: Delta,
|
||||
attributes: AttributeMap
|
||||
node,
|
||||
_delta,
|
||||
_scroll,
|
||||
attributes
|
||||
): Delta => {
|
||||
if (!('data' in node)) {
|
||||
return new Delta();
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import Delta from 'quill-delta';
|
||||
import type { Matcher, AttributeMap } from 'quill';
|
||||
import { Delta } from '@signalapp/quill-cjs';
|
||||
import type { AttributeMap } from '@signalapp/quill-cjs';
|
||||
|
||||
import { QuillFormattingStyle } from './menu';
|
||||
import type { Matcher } from '../util';
|
||||
|
||||
function applyStyleToOps(
|
||||
delta: Delta,
|
||||
|
@ -24,8 +25,9 @@ function applyStyleToOps(
|
|||
}
|
||||
|
||||
export const matchBold: Matcher = (
|
||||
_node: HTMLElement,
|
||||
delta: Delta,
|
||||
_node,
|
||||
delta,
|
||||
_scroll,
|
||||
attributes: AttributeMap
|
||||
): Delta => {
|
||||
if (delta.length() > 0) {
|
||||
|
@ -38,6 +40,7 @@ export const matchBold: Matcher = (
|
|||
export const matchItalic: Matcher = (
|
||||
_node: HTMLElement,
|
||||
delta: Delta,
|
||||
_scroll,
|
||||
attributes: AttributeMap
|
||||
): Delta => {
|
||||
if (delta.length() > 0) {
|
||||
|
@ -48,9 +51,10 @@ export const matchItalic: Matcher = (
|
|||
};
|
||||
|
||||
export const matchStrikethrough: Matcher = (
|
||||
_node: HTMLElement,
|
||||
delta: Delta,
|
||||
attributes: AttributeMap
|
||||
_node,
|
||||
delta,
|
||||
_scroll,
|
||||
attributes
|
||||
): Delta => {
|
||||
if (delta.length() > 0) {
|
||||
return applyStyleToOps(delta, QuillFormattingStyle.strike, attributes);
|
||||
|
@ -60,9 +64,10 @@ export const matchStrikethrough: Matcher = (
|
|||
};
|
||||
|
||||
export const matchMonospace: Matcher = (
|
||||
node: HTMLElement,
|
||||
delta: Delta,
|
||||
attributes: AttributeMap
|
||||
node,
|
||||
delta,
|
||||
_scroll,
|
||||
attributes
|
||||
): Delta => {
|
||||
const classes = [
|
||||
'MessageTextRenderer__formatting--monospace',
|
||||
|
@ -85,9 +90,10 @@ export const matchMonospace: Matcher = (
|
|||
};
|
||||
|
||||
export const matchSpoiler: Matcher = (
|
||||
node: HTMLElement,
|
||||
delta: Delta,
|
||||
attributes: AttributeMap
|
||||
node,
|
||||
delta,
|
||||
_scroll,
|
||||
attributes
|
||||
): Delta => {
|
||||
const classes = [
|
||||
'quill--spoiler',
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
// Copyright 2020 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type Quill from 'quill';
|
||||
import type { KeyboardContext } from 'quill';
|
||||
import type Op from 'quill-delta/dist/Op';
|
||||
import type Quill from '@signalapp/quill-cjs';
|
||||
import type { Op } from '@signalapp/quill-cjs';
|
||||
import type { Context as KeyboardContext } from '@signalapp/quill-cjs/modules/keyboard';
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { Popper } from 'react-popper';
|
||||
|
@ -23,11 +23,11 @@ const MENU_TEXT_BUFFER = 12; // pixels
|
|||
|
||||
// Note: Keyboard shortcuts are defined in the constructor below, and when using
|
||||
// <FormattingButton /> below. They're also referenced in ShortcutGuide.tsx.
|
||||
const BOLD_CHAR = 'B';
|
||||
const ITALIC_CHAR = 'I';
|
||||
const MONOSPACE_CHAR = 'E';
|
||||
const SPOILER_CHAR = 'B';
|
||||
const STRIKETHROUGH_CHAR = 'X';
|
||||
const BOLD_CHAR = 'b';
|
||||
const ITALIC_CHAR = 'i';
|
||||
const MONOSPACE_CHAR = 'e';
|
||||
const SPOILER_CHAR = 'b';
|
||||
const STRIKETHROUGH_CHAR = 'x';
|
||||
|
||||
type FormattingPickerOptions = {
|
||||
i18n: LocalizerType;
|
||||
|
@ -95,42 +95,49 @@ export class FormattingMenu {
|
|||
// above the built-in shortcuts, which don't exactly do what we want.
|
||||
|
||||
const boldCharCode = BOLD_CHAR.charCodeAt(0);
|
||||
this.quill.keyboard.addBinding(
|
||||
{ key: BOLD_CHAR, shortKey: true },
|
||||
(_range, context) =>
|
||||
this.toggleForStyle(QuillFormattingStyle.bold, context)
|
||||
);
|
||||
quill.keyboard.bindings[boldCharCode].unshift(
|
||||
quill.keyboard.bindings[boldCharCode].pop()
|
||||
);
|
||||
// We want to be sure that we're the only handler for this charCode.
|
||||
this.quill.keyboard.bindings[boldCharCode] = [];
|
||||
this.quill.keyboard.addBinding({
|
||||
key: BOLD_CHAR,
|
||||
shortKey: true,
|
||||
handler: (_range, context) =>
|
||||
this.toggleForStyle(QuillFormattingStyle.bold, context),
|
||||
});
|
||||
|
||||
const italicCharCode = ITALIC_CHAR.charCodeAt(0);
|
||||
this.quill.keyboard.addBinding(
|
||||
{ key: ITALIC_CHAR, shortKey: true },
|
||||
(_range, context) =>
|
||||
this.toggleForStyle(QuillFormattingStyle.italic, context)
|
||||
);
|
||||
quill.keyboard.bindings[italicCharCode].unshift(
|
||||
quill.keyboard.bindings[italicCharCode].pop()
|
||||
);
|
||||
// No other handlers for this charCode!
|
||||
this.quill.keyboard.bindings[italicCharCode] = [];
|
||||
this.quill.keyboard.addBinding({
|
||||
key: ITALIC_CHAR,
|
||||
shortKey: true,
|
||||
handler: (_range, context) =>
|
||||
this.toggleForStyle(QuillFormattingStyle.italic, context),
|
||||
});
|
||||
|
||||
// No need for changing priority for these new keybindings
|
||||
// No need for changing priority for these totally new keybindings
|
||||
|
||||
this.quill.keyboard.addBinding(
|
||||
{ key: MONOSPACE_CHAR, shortKey: true },
|
||||
(_range, context) =>
|
||||
this.toggleForStyle(QuillFormattingStyle.monospace, context)
|
||||
);
|
||||
this.quill.keyboard.addBinding(
|
||||
{ key: STRIKETHROUGH_CHAR, shortKey: true, shiftKey: true },
|
||||
(_range, context) =>
|
||||
this.toggleForStyle(QuillFormattingStyle.strike, context)
|
||||
);
|
||||
this.quill.keyboard.addBinding(
|
||||
{ key: SPOILER_CHAR, shortKey: true, shiftKey: true },
|
||||
(_range, context) =>
|
||||
this.toggleForStyle(QuillFormattingStyle.spoiler, context)
|
||||
);
|
||||
this.quill.keyboard.addBinding({
|
||||
key: MONOSPACE_CHAR,
|
||||
shortKey: true,
|
||||
handler: (_range, context) =>
|
||||
this.toggleForStyle(QuillFormattingStyle.monospace, context),
|
||||
});
|
||||
this.quill.keyboard.addBinding({
|
||||
// We need to hook both because of windows/linux and the shift keu
|
||||
key: [STRIKETHROUGH_CHAR, STRIKETHROUGH_CHAR.toUpperCase()],
|
||||
shortKey: true,
|
||||
shiftKey: true,
|
||||
handler: (_range, context) =>
|
||||
this.toggleForStyle(QuillFormattingStyle.strike, context),
|
||||
});
|
||||
this.quill.keyboard.addBinding({
|
||||
// We need to hook both because of windows/linux and the shift keu
|
||||
key: [SPOILER_CHAR, SPOILER_CHAR.toUpperCase()],
|
||||
shortKey: true,
|
||||
shiftKey: true,
|
||||
handler: (_range, context) =>
|
||||
this.toggleForStyle(QuillFormattingStyle.spoiler, context),
|
||||
});
|
||||
}
|
||||
|
||||
destroy(): void {
|
||||
|
@ -261,21 +268,26 @@ export class FormattingMenu {
|
|||
this.render();
|
||||
}
|
||||
|
||||
isStyleEnabledInSelection(style: QuillFormattingStyle): boolean | undefined {
|
||||
const selection = this.quill.getSelection();
|
||||
if (!selection || !selection.length) {
|
||||
return;
|
||||
}
|
||||
const contents = this.quill.getContents(selection.index, selection.length);
|
||||
|
||||
static isStyleEnabledForOps(
|
||||
ops: Array<Op>,
|
||||
style: QuillFormattingStyle
|
||||
): boolean {
|
||||
// Note: we special-case single \n ops because Quill doesn't apply formatting to them
|
||||
if (isAllNewlines(contents.ops)) {
|
||||
if (isAllNewlines(ops)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return contents.ops.every(
|
||||
op => op.attributes?.[style] || isNewlineOnlyOp(op)
|
||||
);
|
||||
return ops.every(op => op.attributes?.[style] || isNewlineOnlyOp(op));
|
||||
}
|
||||
|
||||
isStyleEnabledInSelection(style: QuillFormattingStyle): boolean {
|
||||
const selection = this.quill.getSelection();
|
||||
if (!selection || !selection.length) {
|
||||
return false;
|
||||
}
|
||||
const contents = this.quill.getContents(selection.index, selection.length);
|
||||
|
||||
return FormattingMenu.isStyleEnabledForOps(contents.ops, style);
|
||||
}
|
||||
|
||||
toggleForStyle(style: QuillFormattingStyle, context?: KeyboardContext): void {
|
||||
|
@ -342,7 +354,7 @@ export class FormattingMenu {
|
|||
isActive={isStyleEnabledInSelection(QuillFormattingStyle.bold)}
|
||||
label={i18n('icu:Keyboard--composer--bold')}
|
||||
onLongHover={onLongHover}
|
||||
popupGuideShortcut={`${metaKey} + ${BOLD_CHAR}`}
|
||||
popupGuideShortcut={`${metaKey} + ${BOLD_CHAR.toUpperCase()}`}
|
||||
popupGuideText={i18n('icu:FormatMenu--guide--bold')}
|
||||
style={QuillFormattingStyle.bold}
|
||||
toggleForStyle={toggleForStyle}
|
||||
|
@ -354,7 +366,7 @@ export class FormattingMenu {
|
|||
)}
|
||||
label={i18n('icu:Keyboard--composer--italic')}
|
||||
onLongHover={onLongHover}
|
||||
popupGuideShortcut={`${metaKey} + ${ITALIC_CHAR}`}
|
||||
popupGuideShortcut={`${metaKey} + ${ITALIC_CHAR.toUpperCase()}`}
|
||||
popupGuideText={i18n('icu:FormatMenu--guide--italic')}
|
||||
style={QuillFormattingStyle.italic}
|
||||
toggleForStyle={toggleForStyle}
|
||||
|
@ -366,7 +378,7 @@ export class FormattingMenu {
|
|||
)}
|
||||
label={i18n('icu:Keyboard--composer--strikethrough')}
|
||||
onLongHover={onLongHover}
|
||||
popupGuideShortcut={`${metaKey} + ${shiftKey} + ${STRIKETHROUGH_CHAR}`}
|
||||
popupGuideShortcut={`${metaKey} + ${shiftKey} + ${STRIKETHROUGH_CHAR.toUpperCase()}`}
|
||||
popupGuideText={i18n('icu:FormatMenu--guide--strikethrough')}
|
||||
style={QuillFormattingStyle.strike}
|
||||
toggleForStyle={toggleForStyle}
|
||||
|
@ -378,7 +390,7 @@ export class FormattingMenu {
|
|||
)}
|
||||
label={i18n('icu:Keyboard--composer--monospace')}
|
||||
onLongHover={onLongHover}
|
||||
popupGuideShortcut={`${metaKey} + ${MONOSPACE_CHAR}`}
|
||||
popupGuideShortcut={`${metaKey} + ${MONOSPACE_CHAR.toUpperCase()}`}
|
||||
popupGuideText={i18n('icu:FormatMenu--guide--monospace')}
|
||||
style={QuillFormattingStyle.monospace}
|
||||
toggleForStyle={toggleForStyle}
|
||||
|
@ -389,7 +401,7 @@ export class FormattingMenu {
|
|||
QuillFormattingStyle.spoiler
|
||||
)}
|
||||
onLongHover={onLongHover}
|
||||
popupGuideShortcut={`${metaKey} + ${shiftKey} + ${SPOILER_CHAR}`}
|
||||
popupGuideShortcut={`${metaKey} + ${shiftKey} + ${SPOILER_CHAR.toUpperCase()}`}
|
||||
popupGuideText={i18n('icu:FormatMenu--guide--spoiler')}
|
||||
label={i18n('icu:Keyboard--composer--spoiler')}
|
||||
style={QuillFormattingStyle.spoiler}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
// Copyright 2020 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type Parchment from 'parchment';
|
||||
import Quill from 'quill';
|
||||
|
||||
const Inline: typeof Parchment.Inline = Quill.import('blots/inline');
|
||||
import InlineBlot from '@signalapp/quill-cjs/blots/inline';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
type AnyRecord = Record<string, any>;
|
||||
|
||||
export class MonospaceBlot extends Inline {
|
||||
export class MonospaceBlot extends InlineBlot {
|
||||
static override blotName = 'monospace';
|
||||
static override className = 'quill--monospace';
|
||||
|
||||
static override formats(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
@ -21,10 +21,3 @@ export class MonospaceBlot extends Inline {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
MonospaceBlot.blotName = 'monospace';
|
||||
MonospaceBlot.className = 'quill--monospace';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore See this workaround: https://github.com/quilljs/quill/issues/2312#issuecomment-1097922620
|
||||
Inline.order.splice(Inline.order.indexOf('bold'), 0, MonospaceBlot.blotName);
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
// Copyright 2020 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type Parchment from 'parchment';
|
||||
import Quill from 'quill';
|
||||
|
||||
const Inline: typeof Parchment.Inline = Quill.import('blots/inline');
|
||||
import InlineBlot from '@signalapp/quill-cjs/blots/inline';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
type AnyRecord = Record<string, any>;
|
||||
|
||||
export class SpoilerBlot extends Inline {
|
||||
static override formats(): boolean {
|
||||
return true;
|
||||
export class SpoilerBlot extends InlineBlot {
|
||||
static override blotName = 'spoiler';
|
||||
static override className = 'quill--spoiler';
|
||||
|
||||
static override formats(): AnyRecord {
|
||||
return {
|
||||
spoiler: true,
|
||||
};
|
||||
}
|
||||
|
||||
override optimize(context: AnyRecord): void {
|
||||
|
@ -21,10 +23,3 @@ export class SpoilerBlot extends Inline {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
SpoilerBlot.blotName = 'spoiler';
|
||||
SpoilerBlot.className = 'quill--spoiler';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore See this workaround: https://github.com/quilljs/quill/issues/2312#issuecomment-1097922620
|
||||
Inline.order.splice(Inline.order.indexOf('bold'), 0, SpoilerBlot.blotName);
|
||||
|
|
|
@ -1,23 +1,15 @@
|
|||
// Copyright 2020 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
/* eslint-disable max-classes-per-file */
|
||||
|
||||
import React from 'react';
|
||||
import Parchment from 'parchment';
|
||||
import Quill from 'quill';
|
||||
import EmbedBlot from '@signalapp/quill-cjs/blots/embed';
|
||||
import { render } from 'react-dom';
|
||||
|
||||
import { Emojify } from '../../components/conversation/Emojify';
|
||||
import { normalizeAci } from '../../util/normalizeAci';
|
||||
import type { MentionBlotValue } from '../util';
|
||||
|
||||
declare class QuillEmbed extends Parchment.Embed {
|
||||
contentNode: HTMLElement;
|
||||
}
|
||||
|
||||
const Embed: typeof QuillEmbed = Quill.import('blots/embed');
|
||||
|
||||
export class MentionBlot extends Embed {
|
||||
export class MentionBlot extends EmbedBlot {
|
||||
static override blotName = 'mention';
|
||||
|
||||
static override className = 'mention-blot';
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import _ from 'lodash';
|
||||
import type Quill from 'quill';
|
||||
import Delta from 'quill-delta';
|
||||
import type Quill from '@signalapp/quill-cjs';
|
||||
import { Delta } from '@signalapp/quill-cjs';
|
||||
import type { RefObject } from 'react';
|
||||
import React from 'react';
|
||||
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
// Copyright 2020 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import Delta from 'quill-delta';
|
||||
import { Delta } from '@signalapp/quill-cjs';
|
||||
import type { RefObject } from 'react';
|
||||
import type { Matcher, AttributeMap } from 'quill';
|
||||
|
||||
import { assertDev } from '../../util/assert';
|
||||
import { isAciString } from '../../util/isAciString';
|
||||
import type { MemberRepository } from '../memberRepository';
|
||||
import type { Matcher } from '../util';
|
||||
|
||||
export const matchMention: (
|
||||
memberRepositoryRef: RefObject<MemberRepository>
|
||||
) => Matcher =
|
||||
(memberRepositoryRef: RefObject<MemberRepository>) =>
|
||||
(node: HTMLElement, delta: Delta, attributes: AttributeMap): Delta => {
|
||||
(node, delta, _scroll, attributes): Delta => {
|
||||
const memberRepository = memberRepositoryRef.current;
|
||||
|
||||
if (memberRepository) {
|
||||
|
|
|
@ -1,23 +1,10 @@
|
|||
// Copyright 2020 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type Quill from 'quill';
|
||||
import Delta from 'quill-delta';
|
||||
|
||||
const prepareText = (text: string) => {
|
||||
const entities: Array<[RegExp, string]> = [
|
||||
[/&/g, '&'],
|
||||
[/</g, '<'],
|
||||
[/>/g, '>'],
|
||||
];
|
||||
|
||||
const escapedEntities = entities.reduce(
|
||||
(acc, [re, replaceValue]) => acc.replace(re, replaceValue),
|
||||
text
|
||||
);
|
||||
|
||||
return `<span>${escapedEntities}</span>`;
|
||||
};
|
||||
import type Quill from '@signalapp/quill-cjs';
|
||||
import { Delta } from '@signalapp/quill-cjs';
|
||||
import { FormattingMenu, QuillFormattingStyle } from '../formatting/menu';
|
||||
import { insertEmojiOps } from '../util';
|
||||
|
||||
type ClipboardOptions = Readonly<{
|
||||
isDisabled: boolean;
|
||||
|
@ -50,7 +37,7 @@ export class SignalClipboard {
|
|||
return;
|
||||
}
|
||||
|
||||
const clipboard = this.quill.getModule('clipboard');
|
||||
const { clipboard } = this.quill;
|
||||
const selection = this.quill.getSelection();
|
||||
const text = event.clipboardData.getData('text/plain');
|
||||
const signal = event.clipboardData.getData('text/signal');
|
||||
|
@ -72,11 +59,37 @@ export class SignalClipboard {
|
|||
return;
|
||||
}
|
||||
|
||||
const { ops } = this.quill.getContents(selection.index, selection.length);
|
||||
// Only enable formatting on the pasted text if the entire selection has it enabled!
|
||||
const formats =
|
||||
selection.length === 0
|
||||
? this.quill.getFormat(selection.index)
|
||||
: {
|
||||
[QuillFormattingStyle.bold]: FormattingMenu.isStyleEnabledForOps(
|
||||
ops,
|
||||
QuillFormattingStyle.bold
|
||||
),
|
||||
[QuillFormattingStyle.italic]: FormattingMenu.isStyleEnabledForOps(
|
||||
ops,
|
||||
QuillFormattingStyle.italic
|
||||
),
|
||||
[QuillFormattingStyle.monospace]:
|
||||
FormattingMenu.isStyleEnabledForOps(
|
||||
ops,
|
||||
QuillFormattingStyle.monospace
|
||||
),
|
||||
[QuillFormattingStyle.spoiler]: FormattingMenu.isStyleEnabledForOps(
|
||||
ops,
|
||||
QuillFormattingStyle.spoiler
|
||||
),
|
||||
[QuillFormattingStyle.strike]: FormattingMenu.isStyleEnabledForOps(
|
||||
ops,
|
||||
QuillFormattingStyle.strike
|
||||
),
|
||||
};
|
||||
const clipboardDelta = signal
|
||||
? clipboard.convert(signal)
|
||||
: clipboard.convert(prepareText(text));
|
||||
|
||||
const { scrollTop } = this.quill.scrollingContainer;
|
||||
? clipboard.convert({ html: signal }, formats)
|
||||
: new Delta(insertEmojiOps(clipboard.convert({ text }, formats).ops, {}));
|
||||
|
||||
this.quill.selection.update('silent');
|
||||
|
||||
|
@ -88,7 +101,7 @@ export class SignalClipboard {
|
|||
.concat(clipboardDelta);
|
||||
this.quill.updateContents(delta, 'user');
|
||||
this.quill.setSelection(delta.length() - selection.length, 0, 'silent');
|
||||
this.quill.scrollingContainer.scrollTop = scrollTop;
|
||||
this.quill.scrollSelectionIntoView();
|
||||
|
||||
this.quill.focus();
|
||||
}, 1);
|
||||
|
|
112
ts/quill/types.d.ts
vendored
112
ts/quill/types.d.ts
vendored
|
@ -1,112 +0,0 @@
|
|||
// Copyright 2019 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type UpdatedDelta from 'quill-delta';
|
||||
import type { MentionCompletion } from './mentions/completion';
|
||||
import type { EmojiCompletion } from './emoji/completion';
|
||||
import type { FormattingMenu } from './formatting/menu';
|
||||
import type { SignalClipboard } from './signal-clipboard';
|
||||
|
||||
declare module 'react-quill' {
|
||||
// `react-quill` uses a different but compatible version of Delta
|
||||
// tell it to use the type definition from the `quill-delta` library
|
||||
type DeltaStatic = UpdatedDelta;
|
||||
}
|
||||
|
||||
// We want to extend some existing interfaces.
|
||||
/* eslint-disable no-restricted-syntax */
|
||||
declare module 'quill' {
|
||||
// this type is fixed in @types/quill, but our version of react-quill cannot
|
||||
// use the version of quill that has this fix in its typings
|
||||
// doing this manually allows us to use the correct type
|
||||
// https://github.com/DefinitelyTyped/DefinitelyTyped/commit/6090a81c7dbd02b6b917f903a28c6c010b8432ea#diff-bff5e435d15f8f99f733c837e76945bced86bb85e93a75467015cc9b33b48212
|
||||
interface UpdatedKey {
|
||||
key: string | number;
|
||||
shiftKey?: boolean;
|
||||
shortKey?: boolean;
|
||||
}
|
||||
|
||||
export type AttributeMap = {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
[key: string]: any;
|
||||
};
|
||||
export type Matcher = (
|
||||
node: HTMLElement,
|
||||
delta: UpdatedDelta,
|
||||
attributes: AttributeMap
|
||||
) => UpdatedDelta;
|
||||
|
||||
export type UpdatedTextChangeHandler = (
|
||||
delta: UpdatedDelta,
|
||||
oldContents: UpdatedDelta,
|
||||
source: Sources
|
||||
) => void;
|
||||
|
||||
export type UpdatedEditorChangeHandler = (
|
||||
eventName: 'text-change' | 'selection-change'
|
||||
) => void;
|
||||
|
||||
interface LeafBlot {
|
||||
text?: string;
|
||||
// Quill doesn't make it easy to type this result.
|
||||
// (It's probably doable, but not worth our time.)
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
value(): any;
|
||||
}
|
||||
|
||||
interface HistoryStatic {
|
||||
undo(): void;
|
||||
clear(): void;
|
||||
}
|
||||
|
||||
interface ClipboardStatic {
|
||||
convert(html: string): UpdatedDelta;
|
||||
matchers: Array<unknown>;
|
||||
}
|
||||
|
||||
interface SelectionStatic {
|
||||
update(source: string): void;
|
||||
}
|
||||
|
||||
interface Quill {
|
||||
updateContents(delta: UpdatedDelta, source?: Sources): UpdatedDelta;
|
||||
getContents(index?: number, length?: number): UpdatedDelta;
|
||||
getLeaf(index: number): [LeafBlot, number];
|
||||
// in-code reference missing in @types
|
||||
scrollingContainer: HTMLElement;
|
||||
|
||||
on(
|
||||
eventName: 'text-change',
|
||||
handler: UpdatedTextChangeHandler
|
||||
): EventEmitter;
|
||||
on(
|
||||
eventName: 'editor-change',
|
||||
handler: UpdatedEditorChangeHandler
|
||||
): EventEmitter;
|
||||
|
||||
getModule(module: 'clipboard'): ClipboardStatic;
|
||||
getModule(module: 'emojiCompletion'): EmojiCompletion;
|
||||
getModule(module: 'formattingMenu'): FormattingMenu;
|
||||
getModule(module: 'history'): HistoryStatic;
|
||||
getModule(module: 'mentionCompletion'): MentionCompletion;
|
||||
getModule(module: 'signalClipboard'): SignalClipboard;
|
||||
getModule(module: string): unknown;
|
||||
|
||||
selection: SelectionStatic;
|
||||
options: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export type KeyboardContext = {
|
||||
format: Record<string, unknown>;
|
||||
};
|
||||
|
||||
interface KeyboardStatic {
|
||||
addBinding(
|
||||
key: UpdatedKey,
|
||||
callback: (range: RangeStatic, context: KeyboardContext) => void
|
||||
): void;
|
||||
// in-code reference missing in @types
|
||||
bindings: Record<string | number, Array<unknown>>;
|
||||
}
|
||||
}
|
||||
/* eslint-enable no-restricted-syntax */
|
|
@ -2,9 +2,8 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import emojiRegex from 'emoji-regex';
|
||||
import Delta from 'quill-delta';
|
||||
import type { LeafBlot, DeltaOperation, AttributeMap } from 'quill';
|
||||
import type Op from 'quill-delta/dist/Op';
|
||||
import { Delta } from '@signalapp/quill-cjs';
|
||||
import type { AttributeMap, Op, Parchment } from '@signalapp/quill-cjs';
|
||||
|
||||
import type {
|
||||
DisplayNode,
|
||||
|
@ -19,6 +18,14 @@ import { isNotNil } from '../util/isNotNil';
|
|||
import type { AciString } from '../types/ServiceId';
|
||||
import { emojiToData } from '../components/emoji/lib';
|
||||
|
||||
export type Matcher = (
|
||||
node: HTMLElement,
|
||||
delta: Delta,
|
||||
_scroll: Record<string, unknown>,
|
||||
// Note: this field is added in our fork
|
||||
attributes: AttributeMap
|
||||
) => Delta;
|
||||
|
||||
export type MentionBlotValue = {
|
||||
aci: AciString;
|
||||
title: string;
|
||||
|
@ -28,13 +35,13 @@ export type FormattingBlotValue = {
|
|||
style: BodyRange.Style;
|
||||
};
|
||||
|
||||
export const isEmojiBlot = (blot: LeafBlot): blot is EmojiBlot =>
|
||||
export const isEmojiBlot = (blot: Parchment.LeafBlot): blot is EmojiBlot =>
|
||||
blot.value() && blot.value().emoji;
|
||||
|
||||
export const isMentionBlot = (blot: LeafBlot): blot is MentionBlot =>
|
||||
export const isMentionBlot = (blot: Parchment.LeafBlot): blot is MentionBlot =>
|
||||
blot.value() && blot.value().mention;
|
||||
|
||||
export const isFormatting = (blot: LeafBlot): blot is MentionBlot =>
|
||||
export const isFormatting = (blot: Parchment.LeafBlot): blot is MentionBlot =>
|
||||
blot.value() && blot.value().style;
|
||||
|
||||
export type RetainOp = Op & { retain: number };
|
||||
|
@ -63,7 +70,7 @@ export const isInsertEmojiOp = (op: Op): op is InsertEmojiOp =>
|
|||
export const isInsertMentionOp = (op: Op): op is InsertMentionOp =>
|
||||
isSpecificInsertOp(op, 'mention');
|
||||
|
||||
export const getTextFromOps = (ops: Array<DeltaOperation>): string =>
|
||||
export const getTextFromOps = (ops: Array<Op>): string =>
|
||||
ops
|
||||
.reduce((acc, op) => {
|
||||
if (typeof op.insert === 'string') {
|
||||
|
@ -130,31 +137,31 @@ function extractAllFormats(
|
|||
...params,
|
||||
style: BOLD,
|
||||
previousData: result[BOLD],
|
||||
hasStyle: op?.attributes?.[QuillFormattingStyle.bold],
|
||||
hasStyle: Boolean(op?.attributes?.[QuillFormattingStyle.bold]),
|
||||
});
|
||||
result[ITALIC] = extractFormatRange({
|
||||
...params,
|
||||
style: ITALIC,
|
||||
previousData: result[ITALIC],
|
||||
hasStyle: op?.attributes?.[QuillFormattingStyle.italic],
|
||||
hasStyle: Boolean(op?.attributes?.[QuillFormattingStyle.italic]),
|
||||
});
|
||||
result[MONOSPACE] = extractFormatRange({
|
||||
...params,
|
||||
style: MONOSPACE,
|
||||
previousData: result[MONOSPACE],
|
||||
hasStyle: op?.attributes?.[QuillFormattingStyle.monospace],
|
||||
hasStyle: Boolean(op?.attributes?.[QuillFormattingStyle.monospace]),
|
||||
});
|
||||
result[SPOILER] = extractFormatRange({
|
||||
...params,
|
||||
style: SPOILER,
|
||||
previousData: result[SPOILER],
|
||||
hasStyle: op?.attributes?.[QuillFormattingStyle.spoiler],
|
||||
hasStyle: Boolean(op?.attributes?.[QuillFormattingStyle.spoiler]),
|
||||
});
|
||||
result[STRIKETHROUGH] = extractFormatRange({
|
||||
...params,
|
||||
style: STRIKETHROUGH,
|
||||
previousData: result[STRIKETHROUGH],
|
||||
hasStyle: op?.attributes?.[QuillFormattingStyle.strike],
|
||||
hasStyle: Boolean(op?.attributes?.[QuillFormattingStyle.strike]),
|
||||
});
|
||||
|
||||
return result;
|
||||
|
@ -280,12 +287,18 @@ export const getBlotTextPartitions = (
|
|||
};
|
||||
|
||||
export const matchBlotTextPartitions = (
|
||||
blot: LeafBlot,
|
||||
blot: Parchment.LeafBlot | null,
|
||||
index: number,
|
||||
leftRegExp: RegExp,
|
||||
rightRegExp?: RegExp
|
||||
): Array<RegExpMatchArray | null> => {
|
||||
const [leftText, rightText] = getBlotTextPartitions(blot.text, index);
|
||||
const text = blot?.value();
|
||||
if (text && typeof text !== 'string') {
|
||||
// This can be an EmojiBlot, for example
|
||||
return [];
|
||||
}
|
||||
|
||||
const [leftText, rightText] = getBlotTextPartitions(text, index);
|
||||
|
||||
const leftMatch = leftRegExp.exec(leftText);
|
||||
let rightMatch = null;
|
||||
|
|
|
@ -23,7 +23,6 @@ export type SmartCompositionTextAreaProps = Pick<
|
|||
| 'theme'
|
||||
| 'maxLength'
|
||||
| 'whenToShowRemainingCount'
|
||||
| 'scrollerRef'
|
||||
>;
|
||||
|
||||
export const SmartCompositionTextArea = memo(function SmartCompositionTextArea(
|
||||
|
|
|
@ -46,7 +46,7 @@ describe('emojiCompletion', () => {
|
|||
it('returns left and right text', () => {
|
||||
mockQuill.getSelection.returns({ index: 0, length: 0 });
|
||||
const blot = {
|
||||
text: ':smile:',
|
||||
value: () => ':smile:',
|
||||
};
|
||||
mockQuill.getLeaf.returns([blot, 2]);
|
||||
const [leftLeafText, rightLeafText] =
|
||||
|
@ -79,7 +79,7 @@ describe('emojiCompletion', () => {
|
|||
});
|
||||
|
||||
const blot = {
|
||||
text: 'smi',
|
||||
value: () => 'smi',
|
||||
};
|
||||
mockQuill.getLeaf.returns([blot, 3]);
|
||||
|
||||
|
@ -99,7 +99,7 @@ describe('emojiCompletion', () => {
|
|||
});
|
||||
|
||||
const blot = {
|
||||
text: '10:30',
|
||||
value: () => '10:30',
|
||||
};
|
||||
mockQuill.getLeaf.returns([blot, 5]);
|
||||
|
||||
|
@ -119,7 +119,7 @@ describe('emojiCompletion', () => {
|
|||
});
|
||||
|
||||
const blot = {
|
||||
text: ':s',
|
||||
value: () => ':s',
|
||||
};
|
||||
mockQuill.getLeaf.returns([blot, 2]);
|
||||
|
||||
|
@ -139,7 +139,7 @@ describe('emojiCompletion', () => {
|
|||
});
|
||||
|
||||
const blot = {
|
||||
text: ':smy',
|
||||
value: () => ':smy',
|
||||
};
|
||||
mockQuill.getLeaf.returns([blot, 4]);
|
||||
|
||||
|
@ -159,7 +159,7 @@ describe('emojiCompletion', () => {
|
|||
});
|
||||
|
||||
const blot = {
|
||||
text: ':smi',
|
||||
value: () => ':smi',
|
||||
};
|
||||
mockQuill.getLeaf.returns([blot, 4]);
|
||||
|
||||
|
@ -185,7 +185,7 @@ describe('emojiCompletion', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
const blot = {
|
||||
text,
|
||||
value: () => text,
|
||||
};
|
||||
mockQuill.getLeaf.returns([blot, 7]);
|
||||
|
||||
|
@ -210,7 +210,7 @@ describe('emojiCompletion', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
const blot = {
|
||||
text,
|
||||
value: () => text,
|
||||
};
|
||||
mockQuill.getSelection.returns({
|
||||
index: 13,
|
||||
|
@ -246,7 +246,7 @@ describe('emojiCompletion', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
const blot = {
|
||||
text,
|
||||
value: () => text,
|
||||
};
|
||||
mockQuill.getLeaf.returns([blot, 7]);
|
||||
|
||||
|
@ -274,7 +274,7 @@ describe('emojiCompletion', () => {
|
|||
describe('and given it matches a short name', () => {
|
||||
beforeEach(() => {
|
||||
const blot = {
|
||||
text: validEmoji,
|
||||
value: () => validEmoji,
|
||||
};
|
||||
mockQuill.getLeaf.returns([blot, middleCursorIndex]);
|
||||
|
||||
|
@ -297,7 +297,7 @@ describe('emojiCompletion', () => {
|
|||
describe('and given it does not match a short name', () => {
|
||||
beforeEach(() => {
|
||||
const blot = {
|
||||
text: invalidEmoji,
|
||||
value: () => invalidEmoji,
|
||||
};
|
||||
mockQuill.getLeaf.returns([blot, middleCursorIndex]);
|
||||
|
||||
|
@ -323,7 +323,7 @@ describe('emojiCompletion', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
const blot = {
|
||||
text,
|
||||
value: () => text,
|
||||
};
|
||||
mockQuill.getLeaf.returns([blot, 6]);
|
||||
|
||||
|
@ -365,7 +365,7 @@ describe('emojiCompletion', () => {
|
|||
});
|
||||
|
||||
const blot = {
|
||||
text,
|
||||
value: () => text,
|
||||
};
|
||||
mockQuill.getLeaf.returns([blot, index]);
|
||||
|
||||
|
@ -393,7 +393,7 @@ describe('emojiCompletion', () => {
|
|||
});
|
||||
|
||||
const blot = {
|
||||
text,
|
||||
value: () => text,
|
||||
};
|
||||
mockQuill.getLeaf.returns([blot, index]);
|
||||
|
||||
|
|
|
@ -2,10 +2,11 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { assert } from 'chai';
|
||||
import Delta from 'quill-delta';
|
||||
import { Delta } from '@signalapp/quill-cjs';
|
||||
import type { SinonStub } from 'sinon';
|
||||
import sinon from 'sinon';
|
||||
import type { Quill, KeyboardStatic } from 'quill';
|
||||
import type Quill from '@signalapp/quill-cjs';
|
||||
import type Keyboard from '@signalapp/quill-cjs/modules/keyboard';
|
||||
|
||||
import type { MutableRefObject } from 'react';
|
||||
import type { MentionCompletionOptions } from '../../../quill/mentions/completion';
|
||||
|
@ -17,6 +18,10 @@ import { ThemeType } from '../../../types/Util';
|
|||
import { getDefaultConversationWithServiceId } from '../../../test-both/helpers/getDefaultConversation';
|
||||
import { setupI18n } from '../../../util/setupI18n';
|
||||
|
||||
type MiniLeafBlot = {
|
||||
value: () => string;
|
||||
};
|
||||
|
||||
const me: ConversationType = getDefaultConversationWithServiceId({
|
||||
id: '666777',
|
||||
title: 'Fred Savage',
|
||||
|
@ -70,7 +75,7 @@ describe('MentionCompletion', () => {
|
|||
Partial<{ [K in keyof Quill]: SinonStub }>,
|
||||
'keyboard'
|
||||
> & {
|
||||
keyboard: Partial<{ [K in keyof KeyboardStatic]: SinonStub }>;
|
||||
keyboard: Partial<{ [K in keyof Keyboard]: SinonStub }>;
|
||||
};
|
||||
let mentionCompletion: MentionCompletion;
|
||||
|
||||
|
@ -169,7 +174,10 @@ describe('MentionCompletion', () => {
|
|||
beforeEach(() => {
|
||||
mentionCompletion.results = members;
|
||||
mockQuill.getSelection?.returns({ index: 5 });
|
||||
mockQuill.getLeaf?.returns([{ text: '@shia' }, 5]);
|
||||
const blot: MiniLeafBlot = {
|
||||
value: () => '@shia',
|
||||
};
|
||||
mockQuill.getLeaf?.returns([blot, 5]);
|
||||
|
||||
insertMentionStub = sinon.stub(mentionCompletion, 'insertMention');
|
||||
});
|
||||
|
@ -210,7 +218,10 @@ describe('MentionCompletion', () => {
|
|||
describe('from the middle of a string', () => {
|
||||
beforeEach(() => {
|
||||
mockQuill.getSelection?.returns({ index: 9 });
|
||||
mockQuill.getLeaf?.returns([{ text: 'foo @shia bar' }, 9]);
|
||||
const blot: MiniLeafBlot = {
|
||||
value: () => 'foo @shia bar',
|
||||
};
|
||||
mockQuill.getLeaf?.returns([blot, 9]);
|
||||
});
|
||||
|
||||
it('inserts correctly', () => {
|
||||
|
@ -237,8 +248,8 @@ describe('MentionCompletion', () => {
|
|||
beforeEach(() => {
|
||||
mockQuill.getSelection?.returns({ index });
|
||||
|
||||
const blot = {
|
||||
text,
|
||||
const blot: MiniLeafBlot = {
|
||||
value: () => text,
|
||||
};
|
||||
mockQuill.getLeaf?.returns([blot, index]);
|
||||
|
||||
|
@ -265,8 +276,8 @@ describe('MentionCompletion', () => {
|
|||
const text = '@zoe';
|
||||
const index = text.length;
|
||||
mockQuill.getSelection?.returns({ index });
|
||||
const blot = {
|
||||
text,
|
||||
const blot: MiniLeafBlot = {
|
||||
value: () => text,
|
||||
};
|
||||
mockQuill.getLeaf?.returns([blot, index]);
|
||||
mentionCompletion.completeMention(2);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import { assert } from 'chai';
|
||||
import type { RefObject } from 'react';
|
||||
import Delta from 'quill-delta';
|
||||
import { Delta } from '@signalapp/quill-cjs';
|
||||
|
||||
import type { AciString } from '../../../types/ServiceId';
|
||||
import { generateAci } from '../../../types/ServiceId';
|
||||
|
@ -101,6 +101,7 @@ describe('matchMention', () => {
|
|||
title: memberMahershala.title,
|
||||
}),
|
||||
EMPTY_DELTA,
|
||||
{},
|
||||
existingAttributes
|
||||
);
|
||||
const { ops } = result;
|
||||
|
@ -129,6 +130,7 @@ describe('matchMention', () => {
|
|||
title: memberMahershala.title,
|
||||
}),
|
||||
EMPTY_DELTA,
|
||||
{},
|
||||
{}
|
||||
);
|
||||
const { ops } = result;
|
||||
|
@ -155,6 +157,7 @@ describe('matchMention', () => {
|
|||
title: 'Nonexistent',
|
||||
}),
|
||||
EMPTY_DELTA,
|
||||
{},
|
||||
{}
|
||||
);
|
||||
const { ops } = result;
|
||||
|
@ -178,6 +181,7 @@ describe('matchMention', () => {
|
|||
title: 'Nonexistent',
|
||||
}),
|
||||
EMPTY_DELTA,
|
||||
{},
|
||||
{}
|
||||
);
|
||||
const { ops } = result;
|
||||
|
@ -195,7 +199,12 @@ describe('matchMention', () => {
|
|||
});
|
||||
|
||||
it('passes other clipboard elements through', () => {
|
||||
const result = matcher(createMockElement('ignore', {}), EMPTY_DELTA, {});
|
||||
const result = matcher(
|
||||
createMockElement('ignore', {}),
|
||||
EMPTY_DELTA,
|
||||
{},
|
||||
{}
|
||||
);
|
||||
assert.equal(result, EMPTY_DELTA);
|
||||
});
|
||||
});
|
|
@ -93,6 +93,178 @@
|
|||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:21:51.887Z"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/@signalapp/quill-cjs/core/editor.js",
|
||||
"line": " innerHTML",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2025-01-10T05:52:01.516Z",
|
||||
"reasonDetail": "Reading contents of DOM"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/@signalapp/quill-cjs/core/editor.js",
|
||||
"line": " const [start, end] = outerHTML.split(`>${innerHTML}<`);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2025-01-10T05:52:01.516Z",
|
||||
"reasonDetail": "Reading contents of DOM"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-outerHTML",
|
||||
"path": "node_modules/@signalapp/quill-cjs/core/editor.js",
|
||||
"line": " outerHTML,",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2025-01-10T05:52:01.516Z",
|
||||
"reasonDetail": "Reading contents of DOM"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-outerHTML",
|
||||
"path": "node_modules/@signalapp/quill-cjs/core/editor.js",
|
||||
"line": " const [start, end] = outerHTML.split(`>${innerHTML}<`);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2025-01-10T05:52:01.516Z",
|
||||
"reasonDetail": "Reading contents of DOM"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-outerHTML",
|
||||
"path": "node_modules/@signalapp/quill-cjs/core/editor.js",
|
||||
"line": " return blot.domNode instanceof Element ? blot.domNode.outerHTML : '';",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2025-01-10T05:52:01.516Z",
|
||||
"reasonDetail": "Reading contents of DOM"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/@signalapp/quill-cjs/core/quill.js",
|
||||
"line": " this.container.innerHTML = '';",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/@signalapp/quill-cjs/core/quill.js",
|
||||
"line": " const html = this.container.innerHTML.trim();",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2025-01-10T05:52:01.516Z",
|
||||
"reasonDetail": "Reading contents of DOM"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/@signalapp/quill-cjs/dist/quill.core.js",
|
||||
"reasonCategory": "notExercisedByOurApp",
|
||||
"updated": "2025-01-22T02:55:11.616Z"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-outerHTML",
|
||||
"path": "node_modules/@signalapp/quill-cjs/dist/quill.core.js",
|
||||
"reasonCategory": "notExercisedByOurApp",
|
||||
"updated": "2025-01-22T02:55:11.616Z"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/@signalapp/quill-cjs/dist/quill.js",
|
||||
"reasonCategory": "notExercisedByOurApp",
|
||||
"updated": "2025-01-22T02:55:11.616Z"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-outerHTML",
|
||||
"path": "node_modules/@signalapp/quill-cjs/dist/quill.js",
|
||||
"reasonCategory": "notExercisedByOurApp",
|
||||
"updated": "2025-01-22T02:55:11.616Z"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/@signalapp/quill-cjs/modules/normalizeExternalHTML/normalizers/msWord.js",
|
||||
"line": " li.innerHTML = listItem.element.innerHTML;",
|
||||
"reasonCategory": "notExercisedByOurApp",
|
||||
"updated": "2025-01-10T05:52:01.516Z"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/@signalapp/quill-cjs/modules/normalizeExternalHTML/normalizers/msWord.js",
|
||||
"line": " const html = doc.documentElement.innerHTML;",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2025-01-10T05:52:01.516Z",
|
||||
"reasonDetail": "Reading contents of DOM"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/@signalapp/quill-cjs/modules/syntax.js",
|
||||
"line": " container.innerHTML = highlight(this.options.hljs, language, text);",
|
||||
"reasonCategory": "notExercisedByOurApp",
|
||||
"updated": "2025-01-10T05:52:01.516Z"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/@signalapp/quill-cjs/themes/base.js",
|
||||
"line": " button.innerHTML = icons[name][''] + icons[name].rtl;",
|
||||
"reasonCategory": "notExercisedByOurApp",
|
||||
"updated": "2025-01-10T05:52:01.516Z"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/@signalapp/quill-cjs/themes/base.js",
|
||||
"line": " button.innerHTML = icons[name];",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/@signalapp/quill-cjs/themes/base.js",
|
||||
"line": " button.innerHTML = icons[name][value];",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/@signalapp/quill-cjs/ui/color-picker.js",
|
||||
"line": " this.label.innerHTML = label;",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/@signalapp/quill-cjs/ui/icon-picker.js",
|
||||
"line": " if (this.label.innerHTML === item.innerHTML) return;",
|
||||
"reasonCategory": "notExercisedByOurApp",
|
||||
"updated": "2025-01-10T05:52:01.516Z"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/@signalapp/quill-cjs/ui/icon-picker.js",
|
||||
"line": " item.innerHTML = icons[item.getAttribute('data-value') || ''];",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/@signalapp/quill-cjs/ui/icon-picker.js",
|
||||
"line": " this.label.innerHTML = item.innerHTML;",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/@signalapp/quill-cjs/ui/picker.js",
|
||||
"line": " label.innerHTML = DropdownIcon;",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/@signalapp/quill-cjs/ui/tooltip.js",
|
||||
"line": " this.root.innerHTML = this.constructor.TEMPLATE;",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/@sindresorhus/is/dist/index.js",
|
||||
|
@ -761,6 +933,49 @@
|
|||
"reasonCategory": "testCode",
|
||||
"updated": "2024-06-24T19:19:28.335Z"
|
||||
},
|
||||
{
|
||||
"rule": "thenify-multiArgs",
|
||||
"path": "node_modules/p-event/index.js",
|
||||
"line": "\t\t\tmultiArgs: false,",
|
||||
"reasonCategory": "falseMatch",
|
||||
"updated": "2024-12-20T19:43:51.589Z"
|
||||
},
|
||||
{
|
||||
"rule": "thenify-multiArgs",
|
||||
"path": "node_modules/p-event/index.js",
|
||||
"line": "\t\tmultiArgs: false,",
|
||||
"reasonCategory": "falseMatch",
|
||||
"updated": "2024-12-20T19:43:51.589Z"
|
||||
},
|
||||
{
|
||||
"rule": "thenify-multiArgs",
|
||||
"path": "node_modules/p-event/index.js",
|
||||
"line": "\t\t\tconst value = options.multiArgs ? args : args[0];",
|
||||
"reasonCategory": "falseMatch|testCode|exampleCode|otherUtilityCode|regexMatchedSafeCode|notExercisedByOurApp|ruleNeeded|usageTrusted",
|
||||
"updated": "2024-12-20T19:43:51.589Z",
|
||||
"reasonDetail": "<optional>"
|
||||
},
|
||||
{
|
||||
"rule": "thenify-multiArgs",
|
||||
"path": "node_modules/p-event/index.js",
|
||||
"line": "\t\tconst value = options.multiArgs ? args : args[0];",
|
||||
"reasonCategory": "otherUtilityCode",
|
||||
"updated": "2024-12-20T19:43:51.589Z"
|
||||
},
|
||||
{
|
||||
"rule": "thenify-multiArgs",
|
||||
"path": "node_modules/p-event/index.js",
|
||||
"line": "\t\terror = options.multiArgs ? args : args[0];",
|
||||
"reasonCategory": "otherUtilityCode",
|
||||
"updated": "2024-12-20T19:46:49.191Z"
|
||||
},
|
||||
{
|
||||
"rule": "thenify-multiArgs",
|
||||
"path": "node_modules/p-event/index.js",
|
||||
"line": "\t\tconst value = options.multiArgs ? args : args[0];",
|
||||
"reasonCategory": "otherUtilityCode",
|
||||
"updated": "2024-12-20T19:46:49.191Z"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/parse-entities/decode-entity.browser.js",
|
||||
|
@ -863,295 +1078,6 @@
|
|||
"updated": "2022-01-04T20:32:10.596Z",
|
||||
"reasonDetail": "Sample code never required by us."
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/core/quill.js",
|
||||
"line": " let html = this.container.innerHTML.trim();",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/core/quill.js",
|
||||
"line": " this.container.innerHTML = '';",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/dist/quill.core.js",
|
||||
"line": " this.container.innerHTML = html.replace(/\\>\\r?\\n +\\</g, '><'); // Remove spaces between tags",
|
||||
"reasonCategory": "notExercisedByOurApp",
|
||||
"updated": "2023-05-17T16:29:59.196Z"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/dist/quill.core.js",
|
||||
"line": " this.container.innerHTML = '';",
|
||||
"reasonCategory": "notExercisedByOurApp",
|
||||
"updated": "2023-05-17T16:29:59.196Z"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/dist/quill.core.js",
|
||||
"line": " var html = this.container.innerHTML.trim();",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/dist/quill.core.js",
|
||||
"line": " this.container.innerHTML = '';",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/dist/quill.core.js",
|
||||
"line": " debug.log('convert', this.container.innerHTML, delta);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/dist/quill.core.js",
|
||||
"line": " this.container.innerHTML = '';",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/dist/quill.js",
|
||||
"line": " var html = this.container.innerHTML.trim();",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/dist/quill.js",
|
||||
"line": " label.innerHTML = _dropdown2.default;",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/dist/quill.js",
|
||||
"line": " button.innerHTML = icons[name][''] + icons[name]['rtl'];",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/dist/quill.js",
|
||||
"line": " button.innerHTML = icons[name];",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/dist/quill.js",
|
||||
"line": " button.innerHTML = icons[name][value];",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/dist/quill.js",
|
||||
"line": " this.container.innerHTML = '';",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/dist/quill.js",
|
||||
"line": " debug.log('convert', this.container.innerHTML, delta);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/dist/quill.js",
|
||||
"line": " _this.label.innerHTML = label;",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/dist/quill.js",
|
||||
"line": " item.innerHTML = icons[item.getAttribute('data-value') || ''];",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/dist/quill.js",
|
||||
"line": " this.label.innerHTML = item.innerHTML;",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/dist/quill.js",
|
||||
"line": " this.root.innerHTML = this.constructor.TEMPLATE;",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/dist/quill.js",
|
||||
"line": " this.domNode.innerHTML = _highlight(text);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/dist/quill.js",
|
||||
"line": " // this.container.innerHTML = html.replace(/\\>\\r?\\n +\\</g, '><'); // Remove spaces between tags",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2023-09-28T00:50:24.377Z"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/dist/quill.js",
|
||||
"line": " // this.container.innerHTML = '';",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2023-09-28T00:50:24.377Z"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/dist/quill.js",
|
||||
"line": " // this.container.innerHTML = '';",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2023-09-28T00:50:24.377Z"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/dist/quill.min.js",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/modules/clipboard.js",
|
||||
"line": " this.container.innerHTML = html.replace(/\\>\\r?\\n +\\</g, '><'); // Remove spaces between tags",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/modules/clipboard.js",
|
||||
"line": " this.container.innerHTML = '';",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/modules/clipboard.js",
|
||||
"line": " this.container.innerHTML = '';",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/modules/clipboard.js",
|
||||
"line": " debug.log('convert', this.container.innerHTML, delta);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2021-12-01T01:31:12.757Z"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/modules/syntax.js",
|
||||
"line": " this.domNode.innerHTML = highlight(text);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/themes/base.js",
|
||||
"line": " button.innerHTML = icons[name][''] + icons[name]['rtl'];",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/themes/base.js",
|
||||
"line": " button.innerHTML = icons[name];",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/themes/base.js",
|
||||
"line": " button.innerHTML = icons[name][value];",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/ui/color-picker.js",
|
||||
"line": " this.label.innerHTML = label;",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/ui/icon-picker.js",
|
||||
"line": " item.innerHTML = icons[item.getAttribute('data-value') || ''];",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/ui/icon-picker.js",
|
||||
"line": " this.label.innerHTML = item.innerHTML;",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/ui/picker.js",
|
||||
"line": " label.innerHTML = DropdownIcon;",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/quill/ui/tooltip.js",
|
||||
"line": " this.root.innerHTML = this.constructor.TEMPLATE;",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for quill"
|
||||
},
|
||||
{
|
||||
"rule": "eval",
|
||||
"path": "node_modules/raw-body/node_modules/depd/index.js",
|
||||
|
@ -1201,51 +1127,6 @@
|
|||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-14T18:53:33.345Z"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/react-quill/dist/react-quill.js",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for react-quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/react-quill/dist/react-quill.js",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for react-quill"
|
||||
},
|
||||
{
|
||||
"rule": "React-findDOMNode",
|
||||
"path": "node_modules/react-quill/dist/react-quill.js",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for react-quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/react-quill/lib/index.js",
|
||||
"line": " (_b = (_a = _this).onEditorChangeText) === null || _b === void 0 ? void 0 : _b.call(_a, _this.editor.root.innerHTML, rangeOrDelta, source, _this.unprivilegedEditor);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for react-quill"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/react-quill/lib/index.js",
|
||||
"line": " getHTML: function () { return e.root.innerHTML; },",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for react-quill"
|
||||
},
|
||||
{
|
||||
"rule": "React-findDOMNode",
|
||||
"path": "node_modules/react-quill/lib/index.js",
|
||||
"line": " var element = react_dom_1.default.findDOMNode(this.editingArea);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-10-13T18:36:57.012Z",
|
||||
"reasonDetail": "necessary for react-quill"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.browser.cjs.js",
|
||||
|
@ -2008,13 +1889,6 @@
|
|||
"updated": "2022-06-25T00:06:19.860Z",
|
||||
"reasonDetail": "Not used for DOM manipulation"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "ts/components/CompositionInput.tsx",
|
||||
"line": " const scrollerRefInner = React.useRef<HTMLDivElement>(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2022-10-03T16:06:12.837Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "ts/components/CompositionRecording.tsx",
|
||||
|
@ -2811,48 +2685,5 @@
|
|||
"line": " message.innerHTML = window.i18n('icu:optimizingApplication');",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2021-09-17T21:02:59.414Z"
|
||||
},
|
||||
{
|
||||
"rule": "thenify-multiArgs",
|
||||
"path": "node_modules/p-event/index.js",
|
||||
"line": "\t\t\tmultiArgs: false,",
|
||||
"reasonCategory": "falseMatch",
|
||||
"updated": "2024-12-20T19:43:51.589Z"
|
||||
},
|
||||
{
|
||||
"rule": "thenify-multiArgs",
|
||||
"path": "node_modules/p-event/index.js",
|
||||
"line": "\t\t\tconst value = options.multiArgs ? args : args[0];",
|
||||
"reasonCategory": "falseMatch|testCode|exampleCode|otherUtilityCode|regexMatchedSafeCode|notExercisedByOurApp|ruleNeeded|usageTrusted",
|
||||
"updated": "2024-12-20T19:43:51.589Z",
|
||||
"reasonDetail": "<optional>"
|
||||
},
|
||||
{
|
||||
"rule": "thenify-multiArgs",
|
||||
"path": "node_modules/p-event/index.js",
|
||||
"line": "\t\tmultiArgs: false,",
|
||||
"reasonCategory": "falseMatch",
|
||||
"updated": "2024-12-20T19:43:51.589Z"
|
||||
},
|
||||
{
|
||||
"rule": "thenify-multiArgs",
|
||||
"path": "node_modules/p-event/index.js",
|
||||
"line": "\t\tconst value = options.multiArgs ? args : args[0];",
|
||||
"reasonCategory": "otherUtilityCode",
|
||||
"updated": "2024-12-20T19:43:51.589Z"
|
||||
},
|
||||
{
|
||||
"rule": "thenify-multiArgs",
|
||||
"path": "node_modules/p-event/index.js",
|
||||
"line": "\t\terror = options.multiArgs ? args : args[0];",
|
||||
"reasonCategory": "otherUtilityCode",
|
||||
"updated": "2024-12-20T19:46:49.191Z"
|
||||
},
|
||||
{
|
||||
"rule": "thenify-multiArgs",
|
||||
"path": "node_modules/p-event/index.js",
|
||||
"line": "\t\tconst value = options.multiArgs ? args : args[0];",
|
||||
"reasonCategory": "otherUtilityCode",
|
||||
"updated": "2024-12-20T19:46:49.191Z"
|
||||
}
|
||||
]
|
||||
|
|
Loading…
Add table
Reference in a new issue