@ckeditor/ckeditor5-paste-from-office 28.0.0 → 30.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +1 -1
- package/README.md +7 -3
- package/build/paste-from-office.js +1 -1
- package/ckeditor5-metadata.json +11 -0
- package/package.json +25 -23
- package/src/filters/image.js +5 -1
- package/src/filters/list.js +16 -6
- package/src/filters/parse.js +2 -2
- package/src/normalizers/googledocsnormalizer.js +5 -2
- package/src/normalizers/mswordnormalizer.js +4 -5
- package/src/pastefromoffice.js +6 -2
- package/CHANGELOG.md +0 -94
- package/build/paste-from-office.js.map +0 -1
package/LICENSE.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Software License Agreement
|
|
2
2
|
==========================
|
|
3
3
|
|
|
4
|
-
**CKEditor 5
|
|
4
|
+
**CKEditor 5 paste from Office feature** – https://github.com/ckeditor/ckeditor5-paste-from-office <br>
|
|
5
5
|
Copyright (c) 2003-2021, [CKSource](http://cksource.com) Frederico Knabben. All rights reserved.
|
|
6
6
|
|
|
7
7
|
Licensed under the terms of [GNU General Public License Version 2 or later](http://www.gnu.org/licenses/gpl.html).
|
package/README.md
CHANGED
|
@@ -2,13 +2,17 @@ CKEditor 5 paste from Office feature
|
|
|
2
2
|
==================================
|
|
3
3
|
|
|
4
4
|
[](https://www.npmjs.com/package/@ckeditor/ckeditor5-paste-from-office)
|
|
5
|
-
[](https://coveralls.io/github/ckeditor/ckeditor5?branch=master)
|
|
6
|
+
[](https://travis-ci.com/ckeditor/ckeditor5)
|
|
7
7
|
|
|
8
|
-
This package implements the [
|
|
8
|
+
This package implements the [paste from Office](https://docs.ckeditor.com/ckeditor5/latest/features/paste-from-office.html) feature for CKEditor 5.
|
|
9
9
|
|
|
10
10
|
Paste from Office allows copying content from Microsoft Word without loosing any formatting.
|
|
11
11
|
|
|
12
|
+
## Demo
|
|
13
|
+
|
|
14
|
+
Check out the demos for the [paste from office](https://ckeditor.com/docs/ckeditor5/latest/features/pasting/paste-from-word.html#demo) and [paste from Google Docs](https://ckeditor.com/docs/ckeditor5/latest/features/pasting/paste-from-google-docs.html#demo) features.
|
|
15
|
+
|
|
12
16
|
## Documentation
|
|
13
17
|
|
|
14
18
|
See the [`@ckeditor/ckeditor5-paste-from-office` package](https://docs.ckeditor.com/ckeditor5/latest/api/paste-from-office.html) page in [CKEditor 5 documentation](https://docs.ckeditor.com/ckeditor5/latest/).
|
|
@@ -2,4 +2,4 @@
|
|
|
2
2
|
* @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
|
|
3
3
|
* For licensing, see LICENSE.md.
|
|
4
4
|
*/
|
|
5
|
-
window.CKEditor5=window.CKEditor5||{},window.CKEditor5.pasteFromOffice=function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)n.d(r,i,function(t){return e[t]}.bind(null,i));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=4)}([function(e,t,n){e.exports=n(1)("./src/engine.js")},function(e,t){e.exports=CKEditor5.dll},function(e,t,n){e.exports=n(1)("./src/core.js")},function(e,t,n){e.exports=n(1)("./src/clipboard.js")},function(e,t,n){"use strict";n.r(t),n.d(t,"PasteFromOffice",(function(){return b}));var r=n(2),i=n(3),o=n(0);function s(e,t){if(!e.childCount)return;const n=new o.UpcastWriter(e.document),r=function(e,t){const n=t.createRangeIn(e),r=new o.Matcher({name:/^p|h\d+$/,styles:{"mso-list":/.*/}}),i=[];for(const e of n)if("elementStart"===e.type&&r.match(e.item)){const t=a(e.item);i.push({element:e.item,id:t.id,order:t.order,indent:t.indent})}return i}(e,n);if(!r.length)return;let i=null,s=1;r.forEach((e,a)=>{const u=function(e,t){if(!e)return!0;if(e.id!==t.id)return t.indent-e.indent!=1;const n=t.element.previousSibling;if(!n)return!0;return r=n,!(r.is("element","ol")||r.is("element","ul"));var r}(r[a-1],e),f=u?null:r[a-1],
|
|
5
|
+
window.CKEditor5=window.CKEditor5||{},window.CKEditor5.pasteFromOffice=function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)n.d(r,i,function(t){return e[t]}.bind(null,i));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=4)}([function(e,t,n){e.exports=n(1)("./src/engine.js")},function(e,t){e.exports=CKEditor5.dll},function(e,t,n){e.exports=n(1)("./src/core.js")},function(e,t,n){e.exports=n(1)("./src/clipboard.js")},function(e,t,n){"use strict";n.r(t),n.d(t,"PasteFromOffice",(function(){return b}));var r=n(2),i=n(3),o=n(0);function s(e,t){if(!e.childCount)return;const n=new o.UpcastWriter(e.document),r=function(e,t){const n=t.createRangeIn(e),r=new o.Matcher({name:/^p|h\d+$/,styles:{"mso-list":/.*/}}),i=[];for(const e of n)if("elementStart"===e.type&&r.match(e.item)){const t=a(e.item);i.push({element:e.item,id:t.id,order:t.order,indent:t.indent})}return i}(e,n);if(!r.length)return;let i=null,s=1;r.forEach((e,a)=>{const u=function(e,t){if(!e)return!0;if(e.id!==t.id)return t.indent-e.indent!=1;const n=t.element.previousSibling;if(!n)return!0;return r=n,!(r.is("element","ol")||r.is("element","ul"));var r}(r[a-1],e),f=u?null:r[a-1],p=(m=e,(d=f)?m.indent-d.indent:m.indent-1);var d,m;if(u&&(i=null,s=1),!i||0!==p){const r=function(e,t){const n=new RegExp(`@list l${e.id}:level${e.indent}\\s*({[^}]*)`,"gi"),r=/mso-level-number-format:([^;]{0,100});/gi,i=n.exec(t);let o="decimal",s="ol";if(i&&i[1]){const t=r.exec(i[1]);if(t&&t[1]&&(o=t[1].trim(),s="bullet"!==o&&"image"!==o?"ol":"ul"),"bullet"===o){const t=function(e){const t=function(e){if(e.getChild(0).is("$text"))return null;for(const t of e.getChildren()){if(!t.is("element","span"))continue;const e=t.getChild(0);return e.is("$text")?e:e.getChild(0)}}(e);if(!t)return null;const n=t._data;if("o"===n)return"circle";if("·"===n)return"disc";if("§"===n)return"square";return null}(e.element);t&&(o=t)}}return{type:s,style:c(o)}}(e,t);if(i){if(e.indent>s){const e=i.getChild(i.childCount-1),t=e.getChild(e.childCount-1);i=l(r,t,n),s+=1}else if(e.indent<s){const t=s-e.indent;i=function(e,t){const n=e.getAncestors({parentFirst:!0});let r=null,i=0;for(const e of n)if("ul"!==e.name&&"ol"!==e.name||i++,i===t){r=e;break}return r}(i,t),s=parseInt(e.indent)}}else i=l(r,e.element,n);e.indent<=s&&(i.is("element",r.type)||(i=n.rename(r.type,i)))}const g=function(e,t){return function(e,t){const n=new o.Matcher({name:"span",styles:{"mso-list":"Ignore"}}),r=t.createRangeIn(e);for(const e of r)"elementStart"===e.type&&n.match(e.item)&&t.remove(e.item)}(e,t),t.rename("li",e)}(e.element,n);n.appendChild(g,i)})}function c(e){switch(e){case"arabic-leading-zero":return"decimal-leading-zero";case"alpha-upper":return"upper-alpha";case"alpha-lower":return"lower-alpha";case"roman-upper":return"upper-roman";case"roman-lower":return"lower-roman";case"circle":case"disc":case"square":return e;default:return null}}function l(e,t,n){const r=t.parent,i=n.createElement(e.type),o=r.getChildIndex(t)+1;return n.insertChild(o,i,r),e.style&&n.setStyle("list-style-type",e.style,i),i}function a(e){const t={},n=e.getStyle("mso-list");if(n){const e=n.match(/(^|\s{1,100})l(\d+)/i),r=n.match(/\s{0,100}lfo(\d+)/i),i=n.match(/\s{0,100}level(\d+)/i);e&&r&&i&&(t.id=e[2],t.order=r[1],t.indent=i[1])}return t}const u=/id=("|')docs-internal-guid-[-0-9a-f]+("|')/i;class f{constructor(e){this.document=e}isActive(e){return u.test(e)}execute(e){const t=new o.UpcastWriter(this.document),{body:n}=e._parsedData;!function(e,t){for(const n of e.getChildren())if(n.is("element","b")&&"normal"===n.getStyle("font-weight")){const r=e.getChildIndex(n);t.remove(n),t.insertChild(r,n.getChildren(),e)}}(n,t),function(e,t){for(const n of t.createRangeIn(e)){const e=n.item;if(e.is("element","li")){const n=e.getChild(0);n&&n.is("element","p")&&t.unwrapElement(n)}}}(n,t),e.content=n}}function p(e,t){if(!e.childCount)return;const n=new o.UpcastWriter;!function(e,t,n){const r=n.createRangeIn(t),i=new o.Matcher({name:"img"}),s=[];for(const t of r)if(i.match(t.item)){const n=t.item,r=n.getAttribute("v:shapes")?n.getAttribute("v:shapes").split(" "):[];r.length&&r.every(t=>e.indexOf(t)>-1)?s.push(n):n.getAttribute("src")||s.push(n)}for(const e of s)n.remove(e)}(function(e,t){const n=t.createRangeIn(e),r=new o.Matcher({name:/v:(.+)/}),i=[];for(const e of n){if("elementStart"!=e.type)continue;const t=e.item,n=t.previousSibling&&t.previousSibling.name||null;r.match(t)&&t.getAttribute("o:gfxdata")&&"v:shapetype"!==n&&i.push(e.item.getAttribute("id"))}return i}(e,n),e,n),function(e,t){const n=t.createRangeIn(e),r=new o.Matcher({name:/v:(.+)/}),i=[];for(const e of n)"elementStart"==e.type&&r.match(e.item)&&i.push(e.item);for(const e of i)t.remove(e)}(e,n);const r=function(e,t){const n=t.createRangeIn(e),r=new o.Matcher({name:"img"}),i=[];for(const e of n)r.match(e.item)&&e.item.getAttribute("src").startsWith("file://")&&i.push(e.item);return i}(e,n);r.length&&function(e,t,n){if(e.length===t.length)for(let i=0;i<e.length;i++){const o=`data:${t[i].type};base64,${r=t[i].hex,btoa(r.match(/\w{2}/g).map(e=>String.fromCharCode(parseInt(e,16))).join(""))}`;n.setAttribute("src",o,e[i])}var r}(r,function(e){if(!e)return[];const t=/{\\pict[\s\S]+?\\bliptag-?\d+(\\blipupi-?\d+)?({\\\*\\blipuid\s?[\da-fA-F]+)?[\s}]*?/,n=new RegExp("(?:("+t.source+"))([\\da-fA-F\\s]+)\\}","g"),r=e.match(n),i=[];if(r)for(const e of r){let n=!1;e.includes("\\pngblip")?n="image/png":e.includes("\\jpegblip")&&(n="image/jpeg"),n&&i.push({hex:e.replace(t,"").replace(/[^\da-fA-F]/g,""),type:n})}return i}(t),n)}const d=/<meta\s*name="?generator"?\s*content="?microsoft\s*word\s*\d+"?\/?>/i,m=/xmlns:o="urn:schemas-microsoft-com/i;class g{constructor(e){this.document=e}isActive(e){return d.test(e)||m.test(e)}execute(e){const{body:t,stylesString:n}=e._parsedData;s(t,n),p(t,e.dataTransfer.getData("text/rtf")),e.content=t}}function h(e){return e.replace(/<span(?: class="Apple-converted-space"|)>(\s+)<\/span>/g,(e,t)=>1===t.length?" ":Array(t.length+1).join(" ").substr(0,t.length))}function y(e,t){const n=new DOMParser,r=function(e){return h(h(e)).replace(/(<span\s+style=['"]mso-spacerun:yes['"]>[^\S\r\n]*?)[\r\n]+([^\S\r\n]*<\/span>)/g,"$1$2").replace(/<span\s+style=['"]mso-spacerun:yes['"]><\/span>/g,"").replace(/ <\//g," </").replace(/ <o:p><\/o:p>/g," <o:p></o:p>").replace(/<o:p>( |\u00A0)<\/o:p>/g,"").replace(/>([^\S\r\n]*[\r\n]\s*)</g,"><")}(function(e){const t=e.indexOf("</body>");if(t<0)return e;const n=e.indexOf("</html>",t+"</body>".length);return e.substring(0,t+"</body>".length)+(n>=0?e.substring(n):"")}(e=e.replace(/<!--\[if gte vml 1]>/g,""))),i=n.parseFromString(r,"text/html");!function(e){e.querySelectorAll("span[style*=spacerun]").forEach(e=>{const t=e.innerText.length||0;e.innerHTML=Array(t+1).join(" ").substr(0,t)})}(i);const s=i.body.innerHTML,c=function(e,t){const n=new o.ViewDocument(t),r=new o.DomConverter(n,{blockFillerMode:"nbsp"}),i=e.createDocumentFragment(),s=e.body.childNodes;for(;s.length>0;)i.appendChild(s[0]);return r.domToView(i,{skipComments:!0})}(i,t),l=function(e){const t=[],n=[],r=Array.from(e.getElementsByTagName("style"));for(const e of r)e.sheet&&e.sheet.cssRules&&e.sheet.cssRules.length&&(t.push(e.sheet),n.push(e.innerHTML));return{styles:t,stylesString:n.join(" ")}}(i);return{body:c,bodyString:s,styles:l.styles,stylesString:l.stylesString}}class b extends r.Plugin{static get pluginName(){return"PasteFromOffice"}static get requires(){return[i.ClipboardPipeline]}init(){const e=this.editor,t=e.editing.view.document,n=[];n.push(new g(t)),n.push(new f(t)),e.plugins.get("ClipboardPipeline").on("inputTransformation",(e,r)=>{if(r._isTransformedWithPasteFromOffice)return;const i=r.dataTransfer.getData("text/html"),o=n.find(e=>e.isActive(i));o&&(r._parsedData=y(i,t.stylesProcessor),o.execute(r),r._isTransformedWithPasteFromOffice=!0)},{priority:"high"})}}}]);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"plugins": [
|
|
3
|
+
{
|
|
4
|
+
"name": "Paste from Office",
|
|
5
|
+
"className": "PasteFromOffice",
|
|
6
|
+
"description": "Handles the content pasted from Microsoft Office or Google Docs and transforms it (if necessary) to a valid structure which can then be understood by the editor features.",
|
|
7
|
+
"docs": "features/pasting/paste-from-word.html",
|
|
8
|
+
"path": "src/pastefromoffice.js"
|
|
9
|
+
}
|
|
10
|
+
]
|
|
11
|
+
}
|
package/package.json
CHANGED
|
@@ -1,38 +1,39 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ckeditor/ckeditor5-paste-from-office",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "30.0.0",
|
|
4
4
|
"description": "Paste from Office feature for CKEditor 5.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ckeditor",
|
|
7
7
|
"ckeditor5",
|
|
8
8
|
"ckeditor 5",
|
|
9
9
|
"ckeditor5-feature",
|
|
10
|
-
"ckeditor5-plugin"
|
|
10
|
+
"ckeditor5-plugin",
|
|
11
|
+
"ckeditor5-dll"
|
|
11
12
|
],
|
|
12
13
|
"main": "src/index.js",
|
|
13
14
|
"dependencies": {
|
|
14
|
-
"ckeditor5": "^
|
|
15
|
+
"ckeditor5": "^30.0.0"
|
|
15
16
|
},
|
|
16
17
|
"devDependencies": {
|
|
17
|
-
"@ckeditor/ckeditor5-basic-styles": "^
|
|
18
|
-
"@ckeditor/ckeditor5-clipboard": "^
|
|
19
|
-
"@ckeditor/ckeditor5-cloud-services": "^
|
|
20
|
-
"@ckeditor/ckeditor5-core": "^
|
|
21
|
-
"@ckeditor/ckeditor5-dev-utils": "^25.
|
|
22
|
-
"@ckeditor/ckeditor5-easy-image": "^
|
|
23
|
-
"@ckeditor/ckeditor5-engine": "^
|
|
24
|
-
"@ckeditor/ckeditor5-editor-classic": "^
|
|
25
|
-
"@ckeditor/ckeditor5-enter": "^
|
|
26
|
-
"@ckeditor/ckeditor5-font": "^
|
|
27
|
-
"@ckeditor/ckeditor5-heading": "^
|
|
28
|
-
"@ckeditor/ckeditor5-image": "^
|
|
29
|
-
"@ckeditor/ckeditor5-link": "^
|
|
30
|
-
"@ckeditor/ckeditor5-list": "^
|
|
31
|
-
"@ckeditor/ckeditor5-page-break": "^
|
|
32
|
-
"@ckeditor/ckeditor5-paragraph": "^
|
|
33
|
-
"@ckeditor/ckeditor5-table": "^
|
|
34
|
-
"@ckeditor/ckeditor5-theme-lark": "^
|
|
35
|
-
"@ckeditor/ckeditor5-utils": "^
|
|
18
|
+
"@ckeditor/ckeditor5-basic-styles": "^30.0.0",
|
|
19
|
+
"@ckeditor/ckeditor5-clipboard": "^30.0.0",
|
|
20
|
+
"@ckeditor/ckeditor5-cloud-services": "^30.0.0",
|
|
21
|
+
"@ckeditor/ckeditor5-core": "^30.0.0",
|
|
22
|
+
"@ckeditor/ckeditor5-dev-utils": "^25.4.0",
|
|
23
|
+
"@ckeditor/ckeditor5-easy-image": "^30.0.0",
|
|
24
|
+
"@ckeditor/ckeditor5-engine": "^30.0.0",
|
|
25
|
+
"@ckeditor/ckeditor5-editor-classic": "^30.0.0",
|
|
26
|
+
"@ckeditor/ckeditor5-enter": "^30.0.0",
|
|
27
|
+
"@ckeditor/ckeditor5-font": "^30.0.0",
|
|
28
|
+
"@ckeditor/ckeditor5-heading": "^30.0.0",
|
|
29
|
+
"@ckeditor/ckeditor5-image": "^30.0.0",
|
|
30
|
+
"@ckeditor/ckeditor5-link": "^30.0.0",
|
|
31
|
+
"@ckeditor/ckeditor5-list": "^30.0.0",
|
|
32
|
+
"@ckeditor/ckeditor5-page-break": "^30.0.0",
|
|
33
|
+
"@ckeditor/ckeditor5-paragraph": "^30.0.0",
|
|
34
|
+
"@ckeditor/ckeditor5-table": "^30.0.0",
|
|
35
|
+
"@ckeditor/ckeditor5-theme-lark": "^30.0.0",
|
|
36
|
+
"@ckeditor/ckeditor5-utils": "^30.0.0",
|
|
36
37
|
"webpack": "^4.43.0",
|
|
37
38
|
"webpack-cli": "^3.3.11"
|
|
38
39
|
},
|
|
@@ -53,7 +54,8 @@
|
|
|
53
54
|
"lang",
|
|
54
55
|
"src",
|
|
55
56
|
"theme",
|
|
56
|
-
"build"
|
|
57
|
+
"build",
|
|
58
|
+
"ckeditor5-metadata.json"
|
|
57
59
|
],
|
|
58
60
|
"scripts": {
|
|
59
61
|
"dll:build": "webpack"
|
package/src/filters/image.js
CHANGED
|
@@ -66,6 +66,10 @@ function findAllShapesIds( documentFragment, writer ) {
|
|
|
66
66
|
const shapesIds = [];
|
|
67
67
|
|
|
68
68
|
for ( const value of range ) {
|
|
69
|
+
if ( value.type != 'elementStart' ) {
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
|
|
69
73
|
const el = value.item;
|
|
70
74
|
const prevSiblingName = el.previousSibling && el.previousSibling.name || null;
|
|
71
75
|
|
|
@@ -125,7 +129,7 @@ function removeAllShapeElements( documentFragment, writer ) {
|
|
|
125
129
|
const shapes = [];
|
|
126
130
|
|
|
127
131
|
for ( const value of range ) {
|
|
128
|
-
if ( shapeElementsMatcher.match( value.item ) ) {
|
|
132
|
+
if ( value.type == 'elementStart' && shapeElementsMatcher.match( value.item ) ) {
|
|
129
133
|
shapes.push( value.item );
|
|
130
134
|
}
|
|
131
135
|
}
|
package/src/filters/list.js
CHANGED
|
@@ -225,18 +225,28 @@ function findBulletedListStyle( element ) {
|
|
|
225
225
|
// @param {module:engine/view/element~Element} element
|
|
226
226
|
// @returns {module:engine/view/text~Text|null}
|
|
227
227
|
function findListMarkerNode( element ) {
|
|
228
|
-
// If the first child is a text node, it is
|
|
228
|
+
// If the first child is a text node, it is the data for the element.
|
|
229
|
+
// The list-style marker is not present here.
|
|
229
230
|
if ( element.getChild( 0 ).is( '$text' ) ) {
|
|
230
231
|
return null;
|
|
231
232
|
}
|
|
232
233
|
|
|
233
|
-
const
|
|
234
|
+
for ( const childNode of element.getChildren() ) {
|
|
235
|
+
// The list-style marker will be inside the `<span>` element. Let's ignore all non-span elements.
|
|
236
|
+
// It may happen that the `<a>` element is added as the first child. Most probably, it's an anchor element.
|
|
237
|
+
if ( !childNode.is( 'element', 'span' ) ) {
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
234
240
|
|
|
235
|
-
|
|
236
|
-
return textNodeOrElement;
|
|
237
|
-
}
|
|
241
|
+
const textNodeOrElement = childNode.getChild( 0 );
|
|
238
242
|
|
|
239
|
-
|
|
243
|
+
// If already found the marker element, use it.
|
|
244
|
+
if ( textNodeOrElement.is( '$text' ) ) {
|
|
245
|
+
return textNodeOrElement;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return textNodeOrElement.getChild( 0 );
|
|
249
|
+
}
|
|
240
250
|
}
|
|
241
251
|
|
|
242
252
|
// Parses the `list-style-type` value extracted directly from the Word CSS stylesheet and returns proper CSS definition.
|
package/src/filters/parse.js
CHANGED
|
@@ -56,7 +56,7 @@ export function parseHtml( htmlString, stylesProcessor ) {
|
|
|
56
56
|
};
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
// Transforms native `Document` object into {@link module:engine/view/documentfragment~DocumentFragment}.
|
|
59
|
+
// Transforms native `Document` object into {@link module:engine/view/documentfragment~DocumentFragment}. Comments are skipped.
|
|
60
60
|
//
|
|
61
61
|
// @param {Document} htmlDocument Native `Document` object to be transformed.
|
|
62
62
|
// @param {module:engine/view/stylesmap~StylesProcessor} stylesProcessor
|
|
@@ -71,7 +71,7 @@ function documentToView( htmlDocument, stylesProcessor ) {
|
|
|
71
71
|
fragment.appendChild( nodes[ 0 ] );
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
return domConverter.domToView( fragment );
|
|
74
|
+
return domConverter.domToView( fragment, { skipComments: true } );
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
// Extracts both `CSSStyleSheet` and string representation from all `style` elements available in a provided `htmlDocument`.
|
|
@@ -45,8 +45,11 @@ export default class GoogleDocsNormalizer {
|
|
|
45
45
|
*/
|
|
46
46
|
execute( data ) {
|
|
47
47
|
const writer = new UpcastWriter( this.document );
|
|
48
|
+
const { body: documentFragment } = data._parsedData;
|
|
48
49
|
|
|
49
|
-
removeBoldWrapper(
|
|
50
|
-
unwrapParagraphInListItem(
|
|
50
|
+
removeBoldWrapper( documentFragment, writer );
|
|
51
|
+
unwrapParagraphInListItem( documentFragment, writer );
|
|
52
|
+
|
|
53
|
+
data.content = documentFragment;
|
|
51
54
|
}
|
|
52
55
|
}
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
* @module paste-from-office/normalizers/mswordnormalizer
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { parseHtml } from '../filters/parse';
|
|
11
10
|
import { transformListItemLikeElementsIntoLists } from '../filters/list';
|
|
12
11
|
import { replaceImagesSourceWithBase64 } from '../filters/image';
|
|
13
12
|
|
|
@@ -44,11 +43,11 @@ export default class MSWordNormalizer {
|
|
|
44
43
|
* @inheritDoc
|
|
45
44
|
*/
|
|
46
45
|
execute( data ) {
|
|
47
|
-
const { body, stylesString } =
|
|
46
|
+
const { body: documentFragment, stylesString } = data._parsedData;
|
|
48
47
|
|
|
49
|
-
transformListItemLikeElementsIntoLists(
|
|
50
|
-
replaceImagesSourceWithBase64(
|
|
48
|
+
transformListItemLikeElementsIntoLists( documentFragment, stylesString );
|
|
49
|
+
replaceImagesSourceWithBase64( documentFragment, data.dataTransfer.getData( 'text/rtf' ) );
|
|
51
50
|
|
|
52
|
-
data.content =
|
|
51
|
+
data.content = documentFragment;
|
|
53
52
|
}
|
|
54
53
|
}
|
package/src/pastefromoffice.js
CHANGED
|
@@ -13,6 +13,8 @@ import { ClipboardPipeline } from 'ckeditor5/src/clipboard';
|
|
|
13
13
|
import GoogleDocsNormalizer from './normalizers/googledocsnormalizer';
|
|
14
14
|
import MSWordNormalizer from './normalizers/mswordnormalizer';
|
|
15
15
|
|
|
16
|
+
import { parseHtml } from './filters/parse';
|
|
17
|
+
|
|
16
18
|
/**
|
|
17
19
|
* The Paste from Office plugin.
|
|
18
20
|
*
|
|
@@ -57,7 +59,7 @@ export default class PasteFromOffice extends Plugin {
|
|
|
57
59
|
editor.plugins.get( 'ClipboardPipeline' ).on(
|
|
58
60
|
'inputTransformation',
|
|
59
61
|
( evt, data ) => {
|
|
60
|
-
if ( data.
|
|
62
|
+
if ( data._isTransformedWithPasteFromOffice ) {
|
|
61
63
|
return;
|
|
62
64
|
}
|
|
63
65
|
|
|
@@ -65,9 +67,11 @@ export default class PasteFromOffice extends Plugin {
|
|
|
65
67
|
const activeNormalizer = normalizers.find( normalizer => normalizer.isActive( htmlString ) );
|
|
66
68
|
|
|
67
69
|
if ( activeNormalizer ) {
|
|
70
|
+
data._parsedData = parseHtml( htmlString, viewDocument.stylesProcessor );
|
|
71
|
+
|
|
68
72
|
activeNormalizer.execute( data );
|
|
69
73
|
|
|
70
|
-
data.
|
|
74
|
+
data._isTransformedWithPasteFromOffice = true;
|
|
71
75
|
}
|
|
72
76
|
},
|
|
73
77
|
{ priority: 'high' }
|
package/CHANGELOG.md
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
Changelog
|
|
2
|
-
=========
|
|
3
|
-
|
|
4
|
-
All changes in the package are documented in the main repository. See: https://github.com/ckeditor/ckeditor5/blob/master/CHANGELOG.md.
|
|
5
|
-
|
|
6
|
-
Changes for the past releases are available below.
|
|
7
|
-
|
|
8
|
-
## [19.0.0](https://github.com/ckeditor/ckeditor5-paste-from-office/compare/v18.0.0...v19.0.0) (2020-04-29)
|
|
9
|
-
|
|
10
|
-
Internal changes only (updated dependencies, documentation, etc.).
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
## [18.0.0](https://github.com/ckeditor/ckeditor5-paste-from-office/compare/v17.0.0...v18.0.0) (2020-03-19)
|
|
14
|
-
|
|
15
|
-
### Features
|
|
16
|
-
|
|
17
|
-
* Added support for basic list indentation when pasting from Microsoft Word. Closes [ckeditor/ckeditor5#2518](https://github.com/ckeditor/ckeditor5/issues/2518). ([58ae829](https://github.com/ckeditor/ckeditor5-paste-from-office/commit/58ae829))
|
|
18
|
-
|
|
19
|
-
Thanks to [gjhenrique](https://github.com/gjhenrique) for the contribution!
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
## [17.0.0](https://github.com/ckeditor/ckeditor5-paste-from-office/compare/v16.0.0...v17.0.0) (2020-02-19)
|
|
23
|
-
|
|
24
|
-
Internal changes only (updated dependencies, documentation, etc.).
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
## [16.0.0](https://github.com/ckeditor/ckeditor5-paste-from-office/compare/v15.0.0...v16.0.0) (2019-12-04)
|
|
28
|
-
|
|
29
|
-
### Bug fixes
|
|
30
|
-
|
|
31
|
-
* Fixed handling `mso-list:normal`. Closes [ckeditor/ckeditor5#5712](https://github.com/ckeditor/ckeditor5/issues/5712). ([2054e69](https://github.com/ckeditor/ckeditor5-paste-from-office/commit/2054e69))
|
|
32
|
-
|
|
33
|
-
Thanks [@bendemboski](https://github.com/bendemboski)!
|
|
34
|
-
* Fixed various issues with oddly formatted space run spans. ([2cd7b0f](https://github.com/ckeditor/ckeditor5-paste-from-office/commit/2cd7b0f))
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
## [15.0.0](https://github.com/ckeditor/ckeditor5-paste-from-office/compare/v11.1.0...v15.0.0) (2019-10-23)
|
|
38
|
-
|
|
39
|
-
### Other changes
|
|
40
|
-
|
|
41
|
-
* Remove the `fixListIndentation()` filter in favor of improved list converters fix. See [ckeditor/ckeditor5-list#115](https://github.com/ckeditor/ckeditor5-list/issues/115). ([d594038](https://github.com/ckeditor/ckeditor5-paste-from-office/commit/d594038))
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
## [11.1.0](https://github.com/ckeditor/ckeditor5-paste-from-office/compare/v11.0.4...v11.1.0) (2019-08-26)
|
|
45
|
-
|
|
46
|
-
### Features
|
|
47
|
-
|
|
48
|
-
* Prevent of bolding entire content pasted from Google Docs. Closes [#61](https://github.com/ckeditor/ckeditor5-paste-from-office/issues/61). ([8102de3](https://github.com/ckeditor/ckeditor5-paste-from-office/commit/8102de3))
|
|
49
|
-
* Provide support for pasting lists from Google Docs. Closes [#69](https://github.com/ckeditor/ckeditor5-paste-from-office/issues/69). ([6ad2a62](https://github.com/ckeditor/ckeditor5-paste-from-office/commit/6ad2a62))
|
|
50
|
-
|
|
51
|
-
### Other changes
|
|
52
|
-
|
|
53
|
-
* The issue tracker for this package was moved to https://github.com/ckeditor/ckeditor5/issues. See [ckeditor/ckeditor5#1988](https://github.com/ckeditor/ckeditor5/issues/1988). ([22edb90](https://github.com/ckeditor/ckeditor5-paste-from-office/commit/22edb90))
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
## [11.0.4](https://github.com/ckeditor/ckeditor5-paste-from-office/compare/v11.0.3...v11.0.4) (2019-07-10)
|
|
57
|
-
|
|
58
|
-
Internal changes only (updated dependencies, documentation, etc.).
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
## [11.0.3](https://github.com/ckeditor/ckeditor5-paste-from-office/compare/v11.0.2...v11.0.3) (2019-07-04)
|
|
62
|
-
|
|
63
|
-
Internal changes only (updated dependencies, documentation, etc.).
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
## [11.0.2](https://github.com/ckeditor/ckeditor5-paste-from-office/compare/v11.0.1...v11.0.2) (2019-06-05)
|
|
67
|
-
|
|
68
|
-
### Other changes
|
|
69
|
-
|
|
70
|
-
* Loosen a dependency of a clipboard plugin in the paste from Office plugin so that it can be overridden. Closes [#56](https://github.com/ckeditor/ckeditor5-paste-from-office/issues/56). ([561f22b](https://github.com/ckeditor/ckeditor5-paste-from-office/commit/561f22b))
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
## [11.0.1](https://github.com/ckeditor/ckeditor5-paste-from-office/compare/v11.0.0...v11.0.1) (2019-04-10)
|
|
74
|
-
|
|
75
|
-
Internal changes only (updated dependencies, documentation, etc.).
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
## [11.0.0](https://github.com/ckeditor/ckeditor5-paste-from-office/compare/v10.0.0...v11.0.0) (2019-02-28)
|
|
79
|
-
|
|
80
|
-
### Bug fixes
|
|
81
|
-
|
|
82
|
-
* Ensured correct lists ordering for separate list items with the same `mso-list` id. Closes [#43](https://github.com/ckeditor/ckeditor5-paste-from-office/issues/43). ([4ebc363](https://github.com/ckeditor/ckeditor5-paste-from-office/commit/4ebc363))
|
|
83
|
-
* Handle "spacerun spans" with mixed whitespaces. Closes [#49](https://github.com/ckeditor/ckeditor5-paste-from-office/issues/49). Closes [#50](https://github.com/ckeditor/ckeditor5-paste-from-office/issues/50). ([7fb132f](https://github.com/ckeditor/ckeditor5-paste-from-office/commit/7fb132f))
|
|
84
|
-
|
|
85
|
-
Huge thanks to [Matt Kobs](https://github.com/kobsy) for this contribution!
|
|
86
|
-
|
|
87
|
-
### BREAKING CHANGES
|
|
88
|
-
|
|
89
|
-
* Upgraded minimal versions of Node to `8.0.0` and npm to `5.7.1`. See: [ckeditor/ckeditor5#1507](https://github.com/ckeditor/ckeditor5/issues/1507). ([612ea3c](https://github.com/ckeditor/ckeditor5-cloud-services/commit/612ea3c))
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
## [10.0.0](https://github.com/ckeditor/ckeditor5-paste-from-office/tree/v10.0.0) (2018-12-05)
|
|
93
|
-
|
|
94
|
-
Initial implementation of the Paste from Office feature.
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["webpack://CKEditor5.pasteFromOffice/webpack/bootstrap","webpack://CKEditor5.pasteFromOffice/./src/filters/image.js","webpack://CKEditor5.pasteFromOffice/./src/filters/list.js","webpack://CKEditor5.pasteFromOffice/./src/filters/parse.js","webpack://CKEditor5.pasteFromOffice/./src/filters/removeboldwrapper.js","webpack://CKEditor5.pasteFromOffice/./src/filters/space.js","webpack://CKEditor5.pasteFromOffice/./src/index.js","webpack://CKEditor5.pasteFromOffice/./src/normalizers/googledocsnormalizer.js","webpack://CKEditor5.pasteFromOffice/./src/normalizers/mswordnormalizer.js","webpack://CKEditor5.pasteFromOffice/./src/pastefromoffice.js","webpack://CKEditor5.pasteFromOffice/delegated ./clipboard.js from dll-reference CKEditor5.dll","webpack://CKEditor5.pasteFromOffice/delegated ./core.js from dll-reference CKEditor5.dll","webpack://CKEditor5.pasteFromOffice/delegated ./engine.js from dll-reference CKEditor5.dll","webpack://CKEditor5.pasteFromOffice/external \"CKEditor5.dll\""],"names":[],"mappings":";;;;;;QAAA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;;QAEA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;;;QAGA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA,0CAA0C,gCAAgC;QAC1E;QACA;;QAEA;QACA;QACA;QACA,wDAAwD,kBAAkB;QAC1E;QACA,iDAAiD,cAAc;QAC/D;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA,yCAAyC,iCAAiC;QAC1E,gHAAgH,mBAAmB,EAAE;QACrI;QACA;;QAEA;QACA;QACA;QACA,2BAA2B,0BAA0B,EAAE;QACvD,iCAAiC,eAAe;QAChD;QACA;QACA;;QAEA;QACA,sDAAsD,+DAA+D;;QAErH;QACA;;;QAGA;QACA;;;;;;;;;;;;;AClFA;AAAA;AAAA;AAAA;AAAA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAE6D;;AAE7D;AACA;AACA;AACA;AACA,WAAW,qDAAqD;AAChE,WAAW,OAAO;AAClB;AACO;AACP;AACA;AACA;;AAEA,0BAA0B,iEAAY;AACtC;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,WAAW,OAAO;AAClB,aAAa,OAAO;AACpB;AACO;AACP,mCAAmC,EAAE;AACrC;AACA,EAAE;AACF;;AAEA;AACA;AACA;AACA,WAAW,qDAAqD;AAChE;AACA,WAAW,6CAA6C;AACxD,aAAa,eAAe;AAC5B;AACA;;AAEA,kCAAkC,4DAAO;AACzC;AACA,EAAE;;AAEF;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,WAAW,eAAe;AAC1B,WAAW,qDAAqD;AAChE,WAAW,6CAA6C;AACxD;AACA;;AAEA,kCAAkC,4DAAO;AACzC;AACA,EAAE;;AAEF;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,IAAI;AACJ;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,WAAW,qDAAqD;AAChE,WAAW,6CAA6C;AACxD;AACA;;AAEA,kCAAkC,4DAAO;AACzC;AACA,EAAE;;AAEF;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,WAAW,qDAAqD;AAChE,WAAW,6CAA6C;AACxD,aAAa,OAAO;AACpB,aAAa,2CAA2C;AACxD,aAAa,2CAA2C;AACxD;AACA;;AAEA,kCAAkC,4DAAO;AACzC;AACA,EAAE;;AAEF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,WAAW,OAAO;AAClB,aAAa,eAAe;AAC5B;AACA,QAAQ,OAAO;AACf,QAAQ,OAAO;AACf;AACA;AACA;AACA;;AAEA,8BAA8B,+CAA+C,iCAAiC;AAC9G,8FAA8F;AAC9F;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,IAAI;AACJ;AACA;;AAEA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,WAAW,2CAA2C;AACtD,WAAW,eAAe;AAC1B;AACA,WAAW,6CAA6C;AACxD;AACA;AACA;AACA,kBAAkB,0BAA0B;AAC5C,0BAA0B,8BAA8B,SAAS,mDAAmD;AACpH;AACA;AACA;AACA;;;;;;;;;;;;;ACzNA;AAAA;AAAA;AAAA;AAAA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAE6D;;AAE7D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW,qDAAqD;AAChE,WAAW,OAAO;AAClB;AACO;AACP;AACA;AACA;;AAEA,oBAAoB,iEAAY;AAChC;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,IAAI;AACJ;AACA;;AAEA;AACA;AACA,IAAI;AACJ;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA,EAAE;AACF;;AAEA;AACA;AACA;AACA,WAAW,qDAAqD;AAChE,WAAW,6CAA6C;AACxD;AACO;AACP;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,WAAW,qDAAqD;AAChE;AACA,WAAW,6CAA6C;AACxD,aAAa,eAAe;AAC5B;AACA,OAAO,uCAAuC;AAC9C,OAAO,OAAO;AACd,OAAO,OAAO;AACd,OAAO,OAAO;AACd;AACA;;AAEA;AACA,qCAAqC,4DAAO;AAC5C;AACA;AACA;AACA;AACA,EAAE;;AAEF;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,IAAI;AACJ;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,sBAAsB;AACtB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW,OAAO;AAClB;AACA,WAAW,OAAO;AAClB,aAAa,OAAO;AACpB,aAAa,OAAO;AACpB,aAAa,YAAY;AACzB;AACA;AACA;AACA,+CAA+C,kBAAkB,QAAQ,sBAAsB,MAAM,GAAG;AACxG,yDAAyD,IAAI;;AAE7D;;AAEA,+BAA+B;AAC/B,iBAAiB;;AAEjB;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,WAAW,mCAAmC;AAC9C,aAAa;AACb;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA,EAAE;AACF;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,WAAW,mCAAmC;AAC9C,aAAa;AACb;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,WAAW,YAAY;AACvB,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,WAAW,OAAO;AAClB;AACA,WAAW,mCAAmC;AAC9C,WAAW,6CAA6C;AACxD,aAAa,mCAAmC;;AAEhD;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA,IAAI,+CAA+C;AACnD;AACA,WAAW,mCAAmC;AAC9C,WAAW,6CAA6C;AACxD,aAAa,mCAAmC;AAChD;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW,mCAAmC;AAC9C,aAAa,OAAO;AACpB,aAAa,OAAO;AACpB,aAAa,OAAO;AACpB,aAAa,OAAO;AACpB;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,WAAW,mCAAmC;AAC9C,WAAW,6CAA6C;AACxD;AACA;AACA,2BAA2B,4DAAO;AAClC;AACA;AACA;AACA;AACA,EAAE;;AAEF;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW,OAAO;AAClB,WAAW,OAAO;AAClB,aAAa;AACb;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,WAAW,OAAO;AAClB,WAAW,OAAO;AAClB,aAAa;AACb;AACA;AACA;;AAEA;AACA;AACA,WAAW,mCAAmC;AAC9C,WAAW,OAAO;AAClB,aAAa,mCAAmC;AAChD;AACA,8CAA8C,oBAAoB;;AAElE;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;;;;;;;;;;;;AClbA;AAAA;AAAA;AAAA;AAAA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEkE;;AAEC;;AAEnE;AACA;AACA;AACA,WAAW,OAAO;AAClB,WAAW,6CAA6C;AACxD,aAAa,OAAO;AACpB,aAAa,qDAAqD;AAClE;AACA,aAAa,OAAO;AACpB,aAAa,sBAAsB;AACnC;AACA,aAAa,OAAO;AACpB;AACO;AACP;;AAEA;AACA;;AAEA,wBAAwB,+DAAgB;;AAExC;AACA;;AAEA,CAAC,qEAAsB;;AAEvB;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,6CAA6C,2DAA2D;AACxG;AACA,WAAW,SAAS;AACpB,WAAW,6CAA6C;AACxD,aAAa;AACb;AACA,0BAA0B,iEAAY;AACtC,0BAA0B,iEAAY,iBAAiB,0BAA0B;AACjF;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,WAAW,SAAS;AACpB,aAAa,OAAO;AACpB,aAAa,sBAAsB;AACnC;AACA,aAAa,OAAO;AACpB;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,WAAW,OAAO;AAClB,aAAa,OAAO;AACpB;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;;;;;;;;;;;;ACrHA;AAAA;AAAA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,WAAW,qDAAqD;AAChE,WAAW,6CAA6C;AACxD;AACe;AACf;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;ACxBA;AAAA;AAAA;AAAA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA,kEAAkE;AAClE,uDAAuD,2EAA2E;AAClI;AACA;AACA;AACA,WAAW,OAAO;AAClB,aAAa,OAAO;AACpB;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA,yFAAyF;AACzF,yBAAyB;AACzB;AACA;AACA;;AAEA;AACA;AACA,0BAA0B;AAC1B,oBAAoB,2EAA2E;AAC/F;AACA,WAAW,SAAS;AACpB;AACO;AACP;AACA;;AAEA;AACA,EAAE;AACF;;AAEA;AACA,qEAAqE;AACrE,gDAAgD,2EAA2E;AAC3H;AACA,gCAAgC,gFAAgF;AAChH,0BAA0B;AAC1B;AACA,WAAW,OAAO;AAClB,aAAa,OAAO;AACpB;AACA;AACA;AACA,EAAE;AACF;;;;;;;;;;;;;AC5DA;AAAA;AAAA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEgD;;AAEjC;AACf,CAAC,yEAAe;AAChB,CAAC,EAAC;;;;;;;;;;;;;ACbF;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEoD;;AAES;AACD;;AAE5D;;AAEA;AACA;AACA;AACA;AACA;AACe;AACf;AACA;AACA;AACA,YAAY,qCAAqC;AACjD;AACA;AACA;AACA;AACA,YAAY;AACZ;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,qBAAqB,iEAAY;;AAEjC,EAAE,0EAAiB;AACnB,EAAE,+EAAyB;AAC3B;AACA;;;;;;;;;;;;;ACnDA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAE6C;AAC4B;AACR;;AAEjE;AACA;;AAEA;AACA;AACA;AACA;AACA;AACe;AACf;AACA;AACA;AACA,YAAY,qCAAqC;AACjD;AACA;AACA;AACA;AACA,YAAY;AACZ;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,SAAS,qBAAqB,GAAG,gEAAS;;AAE1C,EAAE,4FAAsC;AACxC,EAAE,oFAA6B;;AAE/B;AACA;AACA;;;;;;;;;;;;;ACrDA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAE4C;AACQ;;AAEkB;AACR;;AAE9D;AACA;AACA;AACA;AACA;AACA;AACA,kDAAkD,iEAAiE;AACnH;AACA,QAAQ;AACR,QAAQ;AACR;AACA,sDAAsD,0CAA0C;AAChG;AACA;AACA;AACe,8BAA8B,yDAAM;AACnD;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,WAAW,iEAAS;AACpB;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,wBAAwB,qEAAgB;AACxC,wBAAwB,yEAAoB;;AAE5C;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,IAAI;AACJ,IAAI;AACJ;AACA;AACA;;;;;;;;;;;;AC3EA,+H;;;;;;;;;;;ACAA,0H;;;;;;;;;;;ACAA,4H;;;;;;;;;;;ACAA,+B","file":"paste-from-office.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/index.js\");\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module paste-from-office/filters/image\n */\n\n/* globals btoa */\n\nimport { Matcher, UpcastWriter } from 'ckeditor5/src/engine';\n\n/**\n * Replaces source attribute of all `<img>` elements representing regular\n * images (not the Word shapes) with inlined base64 image representation extracted from RTF or Blob data.\n *\n * @param {module:engine/view/documentfragment~DocumentFragment} documentFragment Document fragment on which transform images.\n * @param {String} rtfData The RTF data from which images representation will be used.\n */\nexport function replaceImagesSourceWithBase64( documentFragment, rtfData ) {\n\tif ( !documentFragment.childCount ) {\n\t\treturn;\n\t}\n\n\tconst upcastWriter = new UpcastWriter();\n\tconst shapesIds = findAllShapesIds( documentFragment, upcastWriter );\n\n\tremoveAllImgElementsRepresentingShapes( shapesIds, documentFragment, upcastWriter );\n\tremoveAllShapeElements( documentFragment, upcastWriter );\n\n\tconst images = findAllImageElementsWithLocalSource( documentFragment, upcastWriter );\n\n\tif ( images.length ) {\n\t\treplaceImagesFileSourceWithInlineRepresentation( images, extractImageDataFromRtf( rtfData ), upcastWriter );\n\t}\n}\n\n/**\n * Converts given HEX string to base64 representation.\n *\n * @protected\n * @param {String} hexString The HEX string to be converted.\n * @returns {String} Base64 representation of a given HEX string.\n */\nexport function _convertHexToBase64( hexString ) {\n\treturn btoa( hexString.match( /\\w{2}/g ).map( char => {\n\t\treturn String.fromCharCode( parseInt( char, 16 ) );\n\t} ).join( '' ) );\n}\n\n// Finds all shapes (`<v:*>...</v:*>`) ids. Shapes can represent images (canvas)\n// or Word shapes (which does not have RTF or Blob representation).\n//\n// @param {module:engine/view/documentfragment~DocumentFragment} documentFragment Document fragment\n// from which to extract shape ids.\n// @param {module:engine/view/upcastwriter~UpcastWriter} writer\n// @returns {Array.<String>} Array of shape ids.\nfunction findAllShapesIds( documentFragment, writer ) {\n\tconst range = writer.createRangeIn( documentFragment );\n\n\tconst shapeElementsMatcher = new Matcher( {\n\t\tname: /v:(.+)/\n\t} );\n\n\tconst shapesIds = [];\n\n\tfor ( const value of range ) {\n\t\tconst el = value.item;\n\t\tconst prevSiblingName = el.previousSibling && el.previousSibling.name || null;\n\n\t\t// If shape element have 'o:gfxdata' attribute and is not directly before `<v:shapetype>` element it means it represent Word shape.\n\t\tif ( shapeElementsMatcher.match( el ) && el.getAttribute( 'o:gfxdata' ) && prevSiblingName !== 'v:shapetype' ) {\n\t\t\tshapesIds.push( value.item.getAttribute( 'id' ) );\n\t\t}\n\t}\n\n\treturn shapesIds;\n}\n\n// Removes all `<img>` elements which represents Word shapes and not regular images.\n//\n// @param {Array.<String>} shapesIds Shape ids which will be checked against `<img>` elements.\n// @param {module:engine/view/documentfragment~DocumentFragment} documentFragment Document fragment from which to remove `<img>` elements.\n// @param {module:engine/view/upcastwriter~UpcastWriter} writer\nfunction removeAllImgElementsRepresentingShapes( shapesIds, documentFragment, writer ) {\n\tconst range = writer.createRangeIn( documentFragment );\n\n\tconst imageElementsMatcher = new Matcher( {\n\t\tname: 'img'\n\t} );\n\n\tconst imgs = [];\n\n\tfor ( const value of range ) {\n\t\tif ( imageElementsMatcher.match( value.item ) ) {\n\t\t\tconst el = value.item;\n\t\t\tconst shapes = el.getAttribute( 'v:shapes' ) ? el.getAttribute( 'v:shapes' ).split( ' ' ) : [];\n\n\t\t\tif ( shapes.length && shapes.every( shape => shapesIds.indexOf( shape ) > -1 ) ) {\n\t\t\t\timgs.push( el );\n\t\t\t// Shapes may also have empty source while content is paste in some browsers (Safari).\n\t\t\t} else if ( !el.getAttribute( 'src' ) ) {\n\t\t\t\timgs.push( el );\n\t\t\t}\n\t\t}\n\t}\n\n\tfor ( const img of imgs ) {\n\t\twriter.remove( img );\n\t}\n}\n\n// Removes all shape elements (`<v:*>...</v:*>`) so they do not pollute the output structure.\n//\n// @param {module:engine/view/documentfragment~DocumentFragment} documentFragment Document fragment from which to remove shape elements.\n// @param {module:engine/view/upcastwriter~UpcastWriter} writer\nfunction removeAllShapeElements( documentFragment, writer ) {\n\tconst range = writer.createRangeIn( documentFragment );\n\n\tconst shapeElementsMatcher = new Matcher( {\n\t\tname: /v:(.+)/\n\t} );\n\n\tconst shapes = [];\n\n\tfor ( const value of range ) {\n\t\tif ( shapeElementsMatcher.match( value.item ) ) {\n\t\t\tshapes.push( value.item );\n\t\t}\n\t}\n\n\tfor ( const shape of shapes ) {\n\t\twriter.remove( shape );\n\t}\n}\n\n// Finds all `<img>` elements in a given document fragment which have source pointing to local `file://` resource.\n//\n// @param {module:engine/view/documentfragment~DocumentFragment} documentFragment Document fragment in which to look for `<img>` elements.\n// @param {module:engine/view/upcastwriter~UpcastWriter} writer\n// @returns {Object} result All found images grouped by source type.\n// @returns {Array.<module:engine/view/element~Element>} result.file Array of found `<img>` elements with `file://` source.\n// @returns {Array.<module:engine/view/element~Element>} result.blob Array of found `<img>` elements with `blob:` source.\nfunction findAllImageElementsWithLocalSource( documentFragment, writer ) {\n\tconst range = writer.createRangeIn( documentFragment );\n\n\tconst imageElementsMatcher = new Matcher( {\n\t\tname: 'img'\n\t} );\n\n\tconst imgs = [];\n\n\tfor ( const value of range ) {\n\t\tif ( imageElementsMatcher.match( value.item ) ) {\n\t\t\tif ( value.item.getAttribute( 'src' ).startsWith( 'file://' ) ) {\n\t\t\t\timgs.push( value.item );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn imgs;\n}\n\n// Extracts all images HEX representations from a given RTF data.\n//\n// @param {String} rtfData The RTF data from which to extract images HEX representation.\n// @returns {Array.<Object>} Array of found HEX representations. Each array item is an object containing:\n//\n// \t\t* {String} hex Image representation in HEX format.\n// \t\t* {string} type Type of image, `image/png` or `image/jpeg`.\nfunction extractImageDataFromRtf( rtfData ) {\n\tif ( !rtfData ) {\n\t\treturn [];\n\t}\n\n\tconst regexPictureHeader = /{\\\\pict[\\s\\S]+?\\\\bliptag-?\\d+(\\\\blipupi-?\\d+)?({\\\\\\*\\\\blipuid\\s?[\\da-fA-F]+)?[\\s}]*?/;\n\tconst regexPicture = new RegExp( '(?:(' + regexPictureHeader.source + '))([\\\\da-fA-F\\\\s]+)\\\\}', 'g' );\n\tconst images = rtfData.match( regexPicture );\n\tconst result = [];\n\n\tif ( images ) {\n\t\tfor ( const image of images ) {\n\t\t\tlet imageType = false;\n\n\t\t\tif ( image.includes( '\\\\pngblip' ) ) {\n\t\t\t\timageType = 'image/png';\n\t\t\t} else if ( image.includes( '\\\\jpegblip' ) ) {\n\t\t\t\timageType = 'image/jpeg';\n\t\t\t}\n\n\t\t\tif ( imageType ) {\n\t\t\t\tresult.push( {\n\t\t\t\t\thex: image.replace( regexPictureHeader, '' ).replace( /[^\\da-fA-F]/g, '' ),\n\t\t\t\t\ttype: imageType\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result;\n}\n\n// Replaces `src` attribute value of all given images with the corresponding base64 image representation.\n//\n// @param {Array.<module:engine/view/element~Element>} imageElements Array of image elements which will have its source replaced.\n// @param {Array.<Object>} imagesHexSources Array of images hex sources (usually the result of `extractImageDataFromRtf()` function).\n// The array should be the same length as `imageElements` parameter.\n// @param {module:engine/view/upcastwriter~UpcastWriter} writer\nfunction replaceImagesFileSourceWithInlineRepresentation( imageElements, imagesHexSources, writer ) {\n\t// Assume there is an equal amount of image elements and images HEX sources so they can be matched accordingly based on existing order.\n\tif ( imageElements.length === imagesHexSources.length ) {\n\t\tfor ( let i = 0; i < imageElements.length; i++ ) {\n\t\t\tconst newSrc = `data:${ imagesHexSources[ i ].type };base64,${ _convertHexToBase64( imagesHexSources[ i ].hex ) }`;\n\t\t\twriter.setAttribute( 'src', newSrc, imageElements[ i ] );\n\t\t}\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module paste-from-office/filters/list\n */\n\nimport { Matcher, UpcastWriter } from 'ckeditor5/src/engine';\n\n/**\n * Transforms Word specific list-like elements to the semantic HTML lists.\n *\n * Lists in Word are represented by block elements with special attributes like:\n *\n *\t\t<p class=MsoListParagraphCxSpFirst style='mso-list:l1 level1 lfo1'>...</p> // Paragraph based list.\n *\t\t<h1 style='mso-list:l0 level1 lfo1'>...</h1> // Heading 1 based list.\n *\n * @param {module:engine/view/documentfragment~DocumentFragment} documentFragment The view structure to be transformed.\n * @param {String} stylesString Styles from which list-like elements styling will be extracted.\n */\nexport function transformListItemLikeElementsIntoLists( documentFragment, stylesString ) {\n\tif ( !documentFragment.childCount ) {\n\t\treturn;\n\t}\n\n\tconst writer = new UpcastWriter( documentFragment.document );\n\tconst itemLikeElements = findAllItemLikeElements( documentFragment, writer );\n\n\tif ( !itemLikeElements.length ) {\n\t\treturn;\n\t}\n\n\tlet currentList = null;\n\tlet currentIndentation = 1;\n\n\titemLikeElements.forEach( ( itemLikeElement, i ) => {\n\t\tconst isDifferentList = isNewListNeeded( itemLikeElements[ i - 1 ], itemLikeElement );\n\t\tconst previousItemLikeElement = isDifferentList ? null : itemLikeElements[ i - 1 ];\n\t\tconst indentationDifference = getIndentationDifference( previousItemLikeElement, itemLikeElement );\n\n\t\tif ( isDifferentList ) {\n\t\t\tcurrentList = null;\n\t\t\tcurrentIndentation = 1;\n\t\t}\n\n\t\tif ( !currentList || indentationDifference !== 0 ) {\n\t\t\tconst listStyle = detectListStyle( itemLikeElement, stylesString );\n\n\t\t\tif ( !currentList ) {\n\t\t\t\tcurrentList = insertNewEmptyList( listStyle, itemLikeElement.element, writer );\n\t\t\t} else if ( itemLikeElement.indent > currentIndentation ) {\n\t\t\t\tconst lastListItem = currentList.getChild( currentList.childCount - 1 );\n\t\t\t\tconst lastListItemChild = lastListItem.getChild( lastListItem.childCount - 1 );\n\n\t\t\t\tcurrentList = insertNewEmptyList( listStyle, lastListItemChild, writer );\n\t\t\t\tcurrentIndentation += 1;\n\t\t\t} else if ( itemLikeElement.indent < currentIndentation ) {\n\t\t\t\tconst differentIndentation = currentIndentation - itemLikeElement.indent;\n\n\t\t\t\tcurrentList = findParentListAtLevel( currentList, differentIndentation );\n\t\t\t\tcurrentIndentation = parseInt( itemLikeElement.indent );\n\t\t\t}\n\n\t\t\tif ( itemLikeElement.indent <= currentIndentation ) {\n\t\t\t\tif ( !currentList.is( 'element', listStyle.type ) ) {\n\t\t\t\t\tcurrentList = writer.rename( listStyle.type, currentList );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst listItem = transformElementIntoListItem( itemLikeElement.element, writer );\n\n\t\twriter.appendChild( listItem, currentList );\n\t} );\n}\n\n/**\n * Removes paragraph wrapping content inside a list item.\n *\n * @param {module:engine/view/documentfragment~DocumentFragment} documentFragment\n * @param {module:engine/view/upcastwriter~UpcastWriter} writer\n */\nexport function unwrapParagraphInListItem( documentFragment, writer ) {\n\tfor ( const value of writer.createRangeIn( documentFragment ) ) {\n\t\tconst element = value.item;\n\n\t\tif ( element.is( 'element', 'li' ) ) {\n\t\t\t// Google Docs allows on single paragraph inside LI.\n\t\t\tconst firstChild = element.getChild( 0 );\n\n\t\t\tif ( firstChild && firstChild.is( 'element', 'p' ) ) {\n\t\t\t\twriter.unwrapElement( firstChild );\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Finds all list-like elements in a given document fragment.\n//\n// @param {module:engine/view/documentfragment~DocumentFragment} documentFragment Document fragment\n// in which to look for list-like nodes.\n// @param {module:engine/view/upcastwriter~UpcastWriter} writer\n// @returns {Array.<Object>} Array of found list-like items. Each item is an object containing:\n//\n//\t\t* {module:engine/src/view/element~Element} element List-like element.\n//\t\t* {Number} id List item id parsed from `mso-list` style (see `getListItemData()` function).\n//\t\t* {Number} order List item creation order parsed from `mso-list` style (see `getListItemData()` function).\n//\t\t* {Number} indent List item indentation level parsed from `mso-list` style (see `getListItemData()` function).\nfunction findAllItemLikeElements( documentFragment, writer ) {\n\tconst range = writer.createRangeIn( documentFragment );\n\n\t// Matcher for finding list-like elements.\n\tconst itemLikeElementsMatcher = new Matcher( {\n\t\tname: /^p|h\\d+$/,\n\t\tstyles: {\n\t\t\t'mso-list': /.*/\n\t\t}\n\t} );\n\n\tconst itemLikeElements = [];\n\n\tfor ( const value of range ) {\n\t\tif ( value.type === 'elementStart' && itemLikeElementsMatcher.match( value.item ) ) {\n\t\t\tconst itemData = getListItemData( value.item );\n\n\t\t\titemLikeElements.push( {\n\t\t\t\telement: value.item,\n\t\t\t\tid: itemData.id,\n\t\t\t\torder: itemData.order,\n\t\t\t\tindent: itemData.indent\n\t\t\t} );\n\t\t}\n\t}\n\n\treturn itemLikeElements;\n}\n\n// Extracts list item style from the provided CSS.\n//\n// List item style is extracted from the CSS stylesheet. Each list with its specific style attribute\n// value (`mso-list:l1 level1 lfo1`) has its dedicated properties in a CSS stylesheet defined with a selector like:\n//\n// \t\t@list l1:level1 { ... }\n//\n// It contains `mso-level-number-format` property which defines list numbering/bullet style. If this property\n// is not defined it means default `decimal` numbering.\n//\n// Here CSS string representation is used as `mso-level-number-format` property is an invalid CSS property\n// and will be removed during CSS parsing.\n//\n// @param {Object} listLikeItem List-like item for which list style will be searched for. Usually\n// a result of `findAllItemLikeElements()` function.\n// @param {String} stylesString CSS stylesheet.\n// @returns {Object} result\n// @returns {String} result.type List type, could be `ul` or `ol`.\n// @returns {String|null} result.style List style, for example: `decimal`, `lower-roman`, etc. It is extracted\n// directly from Word stylesheet and adjusted to represent proper values for the CSS `list-style-type` property.\n// If it cannot be adjusted, the `null` value is returned.\nfunction detectListStyle( listLikeItem, stylesString ) {\n\tconst listStyleRegexp = new RegExp( `@list l${ listLikeItem.id }:level${ listLikeItem.indent }\\\\s*({[^}]*)`, 'gi' );\n\tconst listStyleTypeRegex = /mso-level-number-format:([^;]*);/gi;\n\n\tconst listStyleMatch = listStyleRegexp.exec( stylesString );\n\n\tlet listStyleType = 'decimal'; // Decimal is default one.\n\tlet type = 'ol'; // <ol> is default list.\n\n\tif ( listStyleMatch && listStyleMatch[ 1 ] ) {\n\t\tconst listStyleTypeMatch = listStyleTypeRegex.exec( listStyleMatch[ 1 ] );\n\n\t\tif ( listStyleTypeMatch && listStyleTypeMatch[ 1 ] ) {\n\t\t\tlistStyleType = listStyleTypeMatch[ 1 ].trim();\n\t\t\ttype = listStyleType !== 'bullet' && listStyleType !== 'image' ? 'ol' : 'ul';\n\t\t}\n\n\t\t// Styles for the numbered lists are always defined in the Word CSS stylesheet.\n\t\t// Unordered lists MAY contain a value for the Word CSS definition `mso-level-text` but sometimes\n\t\t// this tag is missing. And because of that, we cannot depend on that. We need to predict the list style value\n\t\t// based on the list style marker element.\n\t\tif ( listStyleType === 'bullet' ) {\n\t\t\tconst bulletedStyle = findBulletedListStyle( listLikeItem.element );\n\n\t\t\tif ( bulletedStyle ) {\n\t\t\t\tlistStyleType = bulletedStyle;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\ttype,\n\t\tstyle: mapListStyleDefinition( listStyleType )\n\t};\n}\n\n// Tries to extract the `list-style-type` value based on the marker element for bulleted list.\n//\n// @param {module:engine/view/element~Element} element\n// @returns {module:engine/view/element~Element|null}\nfunction findBulletedListStyle( element ) {\n\tconst listMarkerElement = findListMarkerNode( element );\n\n\tif ( !listMarkerElement ) {\n\t\treturn null;\n\t}\n\n\tconst listMarker = listMarkerElement._data;\n\n\tif ( listMarker === 'o' ) {\n\t\treturn 'circle';\n\t} else if ( listMarker === '·' ) {\n\t\treturn 'disc';\n\t}\n\t// Word returns '§' instead of '■' for the square list style.\n\telse if ( listMarker === '§' ) {\n\t\treturn 'square';\n\t}\n\n\treturn null;\n}\n\n// Tries to find a text node that represents the marker element (list-style-type).\n//\n// @param {module:engine/view/element~Element} element\n// @returns {module:engine/view/text~Text|null}\nfunction findListMarkerNode( element ) {\n\t// If the first child is a text node, it is a value for the element.\n\tif ( element.getChild( 0 ).is( '$text' ) ) {\n\t\treturn null;\n\t}\n\n\tconst textNodeOrElement = element.getChild( 0 ).getChild( 0 );\n\n\tif ( textNodeOrElement.is( '$text' ) ) {\n\t\treturn textNodeOrElement;\n\t}\n\n\treturn textNodeOrElement.getChild( 0 );\n}\n\n// Parses the `list-style-type` value extracted directly from the Word CSS stylesheet and returns proper CSS definition.\n//\n// @param {String|null} value\n// @returns {String|null}\nfunction mapListStyleDefinition( value ) {\n\tswitch ( value ) {\n\t\tcase 'arabic-leading-zero':\n\t\t\treturn 'decimal-leading-zero';\n\t\tcase 'alpha-upper':\n\t\t\treturn 'upper-alpha';\n\t\tcase 'alpha-lower':\n\t\t\treturn 'lower-alpha';\n\t\tcase 'roman-upper':\n\t\t\treturn 'upper-roman';\n\t\tcase 'roman-lower':\n\t\t\treturn 'lower-roman';\n\t\tcase 'circle':\n\t\tcase 'disc':\n\t\tcase 'square':\n\t\t\treturn value;\n\t\tdefault:\n\t\t\treturn null;\n\t}\n}\n\n// Creates empty list of a given type and inserts it after a specified element.\n//\n// @param {Object} listStyle List style object which determines the type of newly created list.\n// Usually a result of `detectListStyle()` function.\n// @param {module:engine/view/element~Element} element Element after which list is inserted.\n// @param {module:engine/view/upcastwriter~UpcastWriter} writer\n// @returns {module:engine/view/element~Element} Newly created list element.\n\nfunction insertNewEmptyList( listStyle, element, writer ) {\n\tconst parent = element.parent;\n\tconst list = writer.createElement( listStyle.type );\n\tconst position = parent.getChildIndex( element ) + 1;\n\n\twriter.insertChild( position, list, parent );\n\n\t// We do not support modifying the marker for a particular list item.\n\t// Set the value for the `list-style-type` property directly to the list container.\n\tif ( listStyle.style ) {\n\t\twriter.setStyle( 'list-style-type', listStyle.style, list );\n\t}\n\n\treturn list;\n}\n\n// Transforms a given element into a semantic list item. As the function operates on a provided\n// {module:engine/src/view/element~Element element} it will modify the view structure to which this element belongs.\n//\n// @param {module:engine/view/element~Element} element Element which will be transformed into a list item.\n// @param {module:engine/view/upcastwriter~UpcastWriter} writer\n// @returns {module:engine/view/element~Element} New element to which the given one was transformed. It is\n// inserted in place of the old element (the reference to the old element is lost due to renaming).\nfunction transformElementIntoListItem( element, writer ) {\n\tremoveBulletElement( element, writer );\n\n\treturn writer.rename( 'li', element );\n}\n\n// Extracts list item information from Word specific list-like element style:\n//\n//\t\t`style=\"mso-list:l1 level1 lfo1\"`\n//\n// where:\n//\n//\t\t* `l1` is a list id (however it does not mean this is a continuous list - see #43),\n//\t\t* `level1` is a list item indentation level,\n//\t\t* `lfo1` is a list insertion order in a document.\n//\n// @param {module:engine/view/element~Element} element Element from which style data is extracted.\n// @returns {Object} result\n// @returns {Number} result.id Parent list id.\n// @returns {Number} result.order List item creation order.\n// @returns {Number} result.indent List item indentation level.\nfunction getListItemData( element ) {\n\tconst data = {};\n\tconst listStyle = element.getStyle( 'mso-list' );\n\n\tif ( listStyle ) {\n\t\tconst idMatch = listStyle.match( /(^|\\s+)l(\\d+)/i );\n\t\tconst orderMatch = listStyle.match( /\\s*lfo(\\d+)/i );\n\t\tconst indentMatch = listStyle.match( /\\s*level(\\d+)/i );\n\n\t\tif ( idMatch && orderMatch && indentMatch ) {\n\t\t\tdata.id = idMatch[ 2 ];\n\t\t\tdata.order = orderMatch[ 1 ];\n\t\t\tdata.indent = indentMatch[ 1 ];\n\t\t}\n\t}\n\n\treturn data;\n}\n\n// Removes span with a numbering/bullet from a given element.\n//\n// @param {module:engine/view/element~Element} element\n// @param {module:engine/view/upcastwriter~UpcastWriter} writer\nfunction removeBulletElement( element, writer ) {\n\t// Matcher for finding `span` elements holding lists numbering/bullets.\n\tconst bulletMatcher = new Matcher( {\n\t\tname: 'span',\n\t\tstyles: {\n\t\t\t'mso-list': 'Ignore'\n\t\t}\n\t} );\n\n\tconst range = writer.createRangeIn( element );\n\n\tfor ( const value of range ) {\n\t\tif ( value.type === 'elementStart' && bulletMatcher.match( value.item ) ) {\n\t\t\twriter.remove( value.item );\n\t\t}\n\t}\n}\n\n// Whether the previous and current items belong to the same list. It is determined based on `item.id`\n// (extracted from `mso-list` style, see #getListItemData) and a previous sibling of the current item.\n//\n// However, it's quite easy to change the `id` attribute for nested lists in Word. It will break the list feature while pasting.\n// Let's check also the `indent` attribute. If the difference between those two elements is equal to 1, we can assume that\n// the `currentItem` is a beginning of the nested list because lists in CKEditor 5 always start with the `indent=0` attribute.\n// See: https://github.com/ckeditor/ckeditor5/issues/7805.\n//\n// @param {Object} previousItem\n// @param {Object} currentItem\n// @returns {Boolean}\nfunction isNewListNeeded( previousItem, currentItem ) {\n\tif ( !previousItem ) {\n\t\treturn true;\n\t}\n\n\tif ( previousItem.id !== currentItem.id ) {\n\t\t// See: https://github.com/ckeditor/ckeditor5/issues/7805.\n\t\t//\n\t\t// * List item 1.\n\t\t// - Nested list item 1.\n\t\tif ( currentItem.indent - previousItem.indent === 1 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tconst previousSibling = currentItem.element.previousSibling;\n\n\tif ( !previousSibling ) {\n\t\treturn true;\n\t}\n\n\t// Even with the same id the list does not have to be continuous (#43).\n\treturn !isList( previousSibling );\n}\n\nfunction isList( element ) {\n\treturn element.is( 'element', 'ol' ) || element.is( 'element', 'ul' );\n}\n\n// Calculates the indentation difference between two given list items (based on the indent attribute\n// extracted from the `mso-list` style, see #getListItemData).\n//\n// @param {Object} previousItem\n// @param {Object} currentItem\n// @returns {Number}\nfunction getIndentationDifference( previousItem, currentItem ) {\n\treturn previousItem ? currentItem.indent - previousItem.indent : currentItem.indent - 1;\n}\n\n// Finds the parent list element (ul/ol) of a given list element with indentation level lower by a given value.\n//\n// @param {module:engine/view/element~Element} listElement List element from which to start looking for a parent list.\n// @param {Number} indentationDifference Indentation difference between lists.\n// @returns {module:engine/view/element~Element} Found list element with indentation level lower by a given value.\nfunction findParentListAtLevel( listElement, indentationDifference ) {\n\tconst ancestors = listElement.getAncestors( { parentFirst: true } );\n\n\tlet parentList = null;\n\tlet levelChange = 0;\n\n\tfor ( const ancestor of ancestors ) {\n\t\tif ( ancestor.name === 'ul' || ancestor.name === 'ol' ) {\n\t\t\tlevelChange++;\n\t\t}\n\n\t\tif ( levelChange === indentationDifference ) {\n\t\t\tparentList = ancestor;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn parentList;\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module paste-from-office/filters/parse\n */\n\n/* globals DOMParser */\n\nimport { DomConverter, ViewDocument } from 'ckeditor5/src/engine';\n\nimport { normalizeSpacing, normalizeSpacerunSpans } from './space';\n\n/**\n * Parses provided HTML extracting contents of `<body>` and `<style>` tags.\n *\n * @param {String} htmlString HTML string to be parsed.\n * @param {module:engine/view/stylesmap~StylesProcessor} stylesProcessor\n * @returns {Object} result\n * @returns {module:engine/view/documentfragment~DocumentFragment} result.body Parsed body\n * content as a traversable structure.\n * @returns {String} result.bodyString Entire body content as a string.\n * @returns {Array.<CSSStyleSheet>} result.styles Array of native `CSSStyleSheet` objects, each representing\n * separate `style` tag from the source HTML.\n * @returns {String} result.stylesString All `style` tags contents combined in the order of occurrence into one string.\n */\nexport function parseHtml( htmlString, stylesProcessor ) {\n\tconst domParser = new DOMParser();\n\n\t// Remove Word specific \"if comments\" so content inside is not omitted by the parser.\n\thtmlString = htmlString.replace( /<!--\\[if gte vml 1]>/g, '' );\n\n\tconst normalizedHtml = normalizeSpacing( cleanContentAfterBody( htmlString ) );\n\n\t// Parse htmlString as native Document object.\n\tconst htmlDocument = domParser.parseFromString( normalizedHtml, 'text/html' );\n\n\tnormalizeSpacerunSpans( htmlDocument );\n\n\t// Get `innerHTML` first as transforming to View modifies the source document.\n\tconst bodyString = htmlDocument.body.innerHTML;\n\n\t// Transform document.body to View.\n\tconst bodyView = documentToView( htmlDocument, stylesProcessor );\n\n\t// Extract stylesheets.\n\tconst stylesObject = extractStyles( htmlDocument );\n\n\treturn {\n\t\tbody: bodyView,\n\t\tbodyString,\n\t\tstyles: stylesObject.styles,\n\t\tstylesString: stylesObject.stylesString\n\t};\n}\n\n// Transforms native `Document` object into {@link module:engine/view/documentfragment~DocumentFragment}.\n//\n// @param {Document} htmlDocument Native `Document` object to be transformed.\n// @param {module:engine/view/stylesmap~StylesProcessor} stylesProcessor\n// @returns {module:engine/view/documentfragment~DocumentFragment}\nfunction documentToView( htmlDocument, stylesProcessor ) {\n\tconst viewDocument = new ViewDocument( stylesProcessor );\n\tconst domConverter = new DomConverter( viewDocument, { blockFillerMode: 'nbsp' } );\n\tconst fragment = htmlDocument.createDocumentFragment();\n\tconst nodes = htmlDocument.body.childNodes;\n\n\twhile ( nodes.length > 0 ) {\n\t\tfragment.appendChild( nodes[ 0 ] );\n\t}\n\n\treturn domConverter.domToView( fragment );\n}\n\n// Extracts both `CSSStyleSheet` and string representation from all `style` elements available in a provided `htmlDocument`.\n//\n// @param {Document} htmlDocument Native `Document` object from which styles will be extracted.\n// @returns {Object} result\n// @returns {Array.<CSSStyleSheet>} result.styles Array of native `CSSStyleSheet` object, each representing\n// separate `style` tag from the source object.\n// @returns {String} result.stylesString All `style` tags contents combined in the order of occurrence as one string.\nfunction extractStyles( htmlDocument ) {\n\tconst styles = [];\n\tconst stylesString = [];\n\tconst styleTags = Array.from( htmlDocument.getElementsByTagName( 'style' ) );\n\n\tfor ( const style of styleTags ) {\n\t\tif ( style.sheet && style.sheet.cssRules && style.sheet.cssRules.length ) {\n\t\t\tstyles.push( style.sheet );\n\t\t\tstylesString.push( style.innerHTML );\n\t\t}\n\t}\n\n\treturn {\n\t\tstyles,\n\t\tstylesString: stylesString.join( ' ' )\n\t};\n}\n\n// Removes leftover content from between closing </body> and closing </html> tag:\n//\n// \t\t<html><body><p>Foo Bar</p></body><span>Fo</span></html> -> <html><body><p>Foo Bar</p></body></html>\n//\n// This function is used as specific browsers (Edge) add some random content after `body` tag when pasting from Word.\n// @param {String} htmlString The HTML string to be cleaned.\n// @returns {String} The HTML string with leftover content removed.\nfunction cleanContentAfterBody( htmlString ) {\n\tconst regexp = /<\\/body>(.*?)(<\\/html>|$)/;\n\tconst match = htmlString.match( regexp );\n\n\tif ( match && match[ 1 ] ) {\n\t\thtmlString = htmlString.slice( 0, match.index ) + htmlString.slice( match.index ).replace( match[ 1 ], '' );\n\t}\n\n\treturn htmlString;\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module paste-from-office/filters/removeboldwrapper\n */\n\n/**\n * Removes `<b>` tag wrapper added by Google Docs to a copied content.\n *\n * @param {module:engine/view/documentfragment~DocumentFragment} documentFragment element `data.content` obtained from clipboard\n * @param {module:engine/view/upcastwriter~UpcastWriter} writer\n */\nexport default function removeBoldWrapper( documentFragment, writer ) {\n\tfor ( const child of documentFragment.getChildren() ) {\n\t\tif ( child.is( 'element', 'b' ) && child.getStyle( 'font-weight' ) === 'normal' ) {\n\t\t\tconst childIndex = documentFragment.getChildIndex( child );\n\n\t\t\twriter.remove( child );\n\t\t\twriter.insertChild( childIndex, child.getChildren(), documentFragment );\n\t\t}\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module paste-from-office/filters/space\n */\n\n/**\n * Replaces last space preceding elements closing tag with ` `. Such operation prevents spaces from being removed\n * during further DOM/View processing (see especially {@link module:engine/view/domconverter~DomConverter#_processDataFromDomText}).\n * This method also takes into account Word specific `<o:p></o:p>` empty tags.\n * Additionally multiline sequences of spaces and new lines between tags are removed (see #39 and #40).\n *\n * @param {String} htmlString HTML string in which spacing should be normalized.\n * @returns {String} Input HTML with spaces normalized.\n */\nexport function normalizeSpacing( htmlString ) {\n\t// Run normalizeSafariSpaceSpans() two times to cover nested spans.\n\treturn normalizeSafariSpaceSpans( normalizeSafariSpaceSpans( htmlString ) )\n\t\t// Remove all \\r\\n from \"spacerun spans\" so the last replace line doesn't strip all whitespaces.\n\t\t.replace( /(<span\\s+style=['\"]mso-spacerun:yes['\"]>[\\s]*?)[\\r\\n]+(\\s*<\\/span>)/g, '$1$2' )\n\t\t.replace( /<span\\s+style=['\"]mso-spacerun:yes['\"]><\\/span>/g, '' )\n\t\t.replace( / <\\//g, '\\u00A0</' )\n\t\t.replace( / <o:p><\\/o:p>/g, '\\u00A0<o:p></o:p>' )\n\t\t// Remove <o:p> block filler from empty paragraph. Safari uses \\u00A0 instead of .\n\t\t.replace( /<o:p>( |\\u00A0)<\\/o:p>/g, '' )\n\t\t// Remove all whitespaces when they contain any \\r or \\n.\n\t\t.replace( />(\\s*[\\r\\n]\\s*)</g, '><' );\n}\n\n/**\n * Normalizes spacing in special Word `spacerun spans` (`<span style='mso-spacerun:yes'>\\s+</span>`) by replacing\n * all spaces with ` ` pairs. This prevents spaces from being removed during further DOM/View processing\n * (see especially {@link module:engine/view/domconverter~DomConverter#_processDataFromDomText}).\n *\n * @param {Document} htmlDocument Native `Document` object in which spacing should be normalized.\n */\nexport function normalizeSpacerunSpans( htmlDocument ) {\n\thtmlDocument.querySelectorAll( 'span[style*=spacerun]' ).forEach( el => {\n\t\tconst innerTextLength = el.innerText.length || 0;\n\n\t\tel.innerHTML = Array( innerTextLength + 1 ).join( '\\u00A0 ' ).substr( 0, innerTextLength );\n\t} );\n}\n\n// Normalizes specific spacing generated by Safari when content pasted from Word (`<span class=\"Apple-converted-space\"> </span>`)\n// by replacing all spaces sequences longer than 1 space with ` ` pairs. This prevents spaces from being removed during\n// further DOM/View processing (see especially {@link module:engine/view/domconverter~DomConverter#_processDataFromDomText}).\n//\n// This function is similar to {@link module:clipboard/utils/normalizeclipboarddata normalizeClipboardData util} but uses\n// regular spaces / sequence for replacement.\n//\n// @param {String} htmlString HTML string in which spacing should be normalized\n// @returns {String} Input HTML with spaces normalized.\nfunction normalizeSafariSpaceSpans( htmlString ) {\n\treturn htmlString.replace( /<span(?: class=\"Apple-converted-space\"|)>(\\s+)<\\/span>/g, ( fullMatch, spaces ) => {\n\t\treturn spaces.length === 1 ? ' ' : Array( spaces.length + 1 ).join( '\\u00A0 ' ).substr( 0, spaces.length );\n\t} );\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module paste-from-office\n */\n\nimport PasteFromOffice from './pastefromoffice';\n\nexport default {\n\tPasteFromOffice\n};\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module paste-from-office/normalizers/googledocsnormalizer\n */\n\nimport { UpcastWriter } from 'ckeditor5/src/engine';\n\nimport removeBoldWrapper from '../filters/removeboldwrapper';\nimport { unwrapParagraphInListItem } from '../filters/list';\n\nconst googleDocsMatch = /id=(\"|')docs-internal-guid-[-0-9a-f]+(\"|')/i;\n\n/**\n * Normalizer for the content pasted from Google Docs.\n *\n * @implements module:paste-from-office/normalizer~Normalizer\n */\nexport default class GoogleDocsNormalizer {\n\t/**\n\t * Creates a new `GoogleDocsNormalizer` instance.\n\t *\n\t * @param {module:engine/view/document~Document} document View document.\n\t */\n\tconstructor( document ) {\n\t\t/**\n\t\t * @readonly\n\t\t * @type {module:engine/view/document~Document}\n\t\t */\n\t\tthis.document = document;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tisActive( htmlString ) {\n\t\treturn googleDocsMatch.test( htmlString );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\texecute( data ) {\n\t\tconst writer = new UpcastWriter( this.document );\n\n\t\tremoveBoldWrapper( data.content, writer );\n\t\tunwrapParagraphInListItem( data.content, writer );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module paste-from-office/normalizers/mswordnormalizer\n */\n\nimport { parseHtml } from '../filters/parse';\nimport { transformListItemLikeElementsIntoLists } from '../filters/list';\nimport { replaceImagesSourceWithBase64 } from '../filters/image';\n\nconst msWordMatch1 = /<meta\\s*name=\"?generator\"?\\s*content=\"?microsoft\\s*word\\s*\\d+\"?\\/?>/i;\nconst msWordMatch2 = /xmlns:o=\"urn:schemas-microsoft-com/i;\n\n/**\n * Normalizer for the content pasted from Microsoft Word.\n *\n * @implements module:paste-from-office/normalizer~Normalizer\n */\nexport default class MSWordNormalizer {\n\t/**\n\t * Creates a new `MSWordNormalizer` instance.\n\t *\n\t * @param {module:engine/view/document~Document} document View document.\n\t */\n\tconstructor( document ) {\n\t\t/**\n\t\t * @readonly\n\t\t * @type {module:engine/view/document~Document}\n\t\t */\n\t\tthis.document = document;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tisActive( htmlString ) {\n\t\treturn msWordMatch1.test( htmlString ) || msWordMatch2.test( htmlString );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\texecute( data ) {\n\t\tconst { body, stylesString } = parseHtml( data.dataTransfer.getData( 'text/html' ), this.document.stylesProcessor );\n\n\t\ttransformListItemLikeElementsIntoLists( body, stylesString );\n\t\treplaceImagesSourceWithBase64( body, data.dataTransfer.getData( 'text/rtf' ) );\n\n\t\tdata.content = body;\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module paste-from-office/pastefromoffice\n */\n\nimport { Plugin } from 'ckeditor5/src/core';\nimport { Clipboard } from 'ckeditor5/src/clipboard';\n\nimport GoogleDocsNormalizer from './normalizers/googledocsnormalizer';\nimport MSWordNormalizer from './normalizers/mswordnormalizer';\n\n/**\n * The Paste from Office plugin.\n *\n * This plugin handles content pasted from Office apps and transforms it (if necessary)\n * to a valid structure which can then be understood by the editor features.\n *\n * Transformation is made by a set of predefined {@link module:paste-from-office/normalizer~Normalizer normalizers}.\n * This plugin includes following normalizers:\n * * {@link module:paste-from-office/normalizers/mswordnormalizer~MSWordNormalizer Microsoft Word normalizer}\n * * {@link module:paste-from-office/normalizers/googledocsnormalizer~GoogleDocsNormalizer Google Docs normalizer}\n *\n * For more information about this feature check the {@glink api/paste-from-office package page}.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class PasteFromOffice extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'PasteFromOffice';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ Clipboard ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst viewDocument = editor.editing.view.document;\n\t\tconst normalizers = [];\n\n\t\tnormalizers.push( new MSWordNormalizer( viewDocument ) );\n\t\tnormalizers.push( new GoogleDocsNormalizer( viewDocument ) );\n\n\t\teditor.plugins.get( 'Clipboard' ).on(\n\t\t\t'inputTransformation',\n\t\t\t( evt, data ) => {\n\t\t\t\tif ( data.isTransformedWithPasteFromOffice ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst htmlString = data.dataTransfer.getData( 'text/html' );\n\t\t\t\tconst activeNormalizer = normalizers.find( normalizer => normalizer.isActive( htmlString ) );\n\n\t\t\t\tif ( activeNormalizer ) {\n\t\t\t\t\tactiveNormalizer.execute( data );\n\n\t\t\t\t\tdata.isTransformedWithPasteFromOffice = true;\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ priority: 'high' }\n\t\t);\n\t}\n}\n","module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ \"dll-reference CKEditor5.dll\"))(\"./src/clipboard.js\");","module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ \"dll-reference CKEditor5.dll\"))(\"./src/core.js\");","module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ \"dll-reference CKEditor5.dll\"))(\"./src/engine.js\");","module.exports = CKEditor5.dll;"],"sourceRoot":""}
|