@ckeditor/ckeditor5-minimap 35.4.0 → 36.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 CHANGED
@@ -2,7 +2,7 @@ Software License Agreement
2
2
  ==========================
3
3
 
4
4
  **CKEditor 5 Minimap Feature** – https://github.com/ckeditor/ckeditor5-minimap <br>
5
- Copyright (c) 2003-2022, [CKSource Holding sp. z o.o.](https://cksource.com) All rights reserved.
5
+ Copyright (c) 2003-2023, [CKSource Holding sp. z o.o.](https://cksource.com) 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).
8
8
 
package/build/minimap.js CHANGED
@@ -1,4 +1,4 @@
1
1
  /*!
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md.
4
- */(()=>{var t={544:(t,e,i)=>{"use strict";i.d(e,{Z:()=>r});var n=i(609),o=i.n(n)()((function(t){return t[1]}));o.push([t.id,':root{--ck-color-minimap-tracker-background:208,0%,51%;--ck-color-minimap-iframe-outline:#bfbfbf;--ck-color-minimap-iframe-shadow:rgba(0,0,0,.11);--ck-color-minimap-progress-background:#666}.ck.ck-minimap{background:var(--ck-color-base-background);position:absolute;user-select:none}.ck.ck-minimap,.ck.ck-minimap iframe{height:100%;width:100%}.ck.ck-minimap iframe{border:0;box-shadow:0 2px 5px var(--ck-color-minimap-iframe-shadow);margin:0;outline:1px solid var(--ck-color-minimap-iframe-outline);pointer-events:none;position:relative}.ck.ck-minimap .ck.ck-minimap__position-tracker{background:hsla(var(--ck-color-minimap-tracker-background),.2);position:absolute;top:0;transition:background .1s ease-in-out;width:100%;z-index:1}.ck.ck-minimap .ck.ck-minimap__position-tracker:hover{background:hsla(var(--ck-color-minimap-tracker-background),.3)}.ck.ck-minimap .ck.ck-minimap__position-tracker.ck-minimap__position-tracker_dragging,.ck.ck-minimap .ck.ck-minimap__position-tracker.ck-minimap__position-tracker_dragging:hover{background:hsla(var(--ck-color-minimap-tracker-background),.4)}.ck.ck-minimap .ck.ck-minimap__position-tracker.ck-minimap__position-tracker_dragging:after,.ck.ck-minimap .ck.ck-minimap__position-tracker.ck-minimap__position-tracker_dragging:hover:after{opacity:1}.ck.ck-minimap .ck.ck-minimap__position-tracker:after{background:var(--ck-color-minimap-progress-background);border:1px solid var(--ck-color-base-background);border-radius:3px;color:var(--ck-color-base-background);content:attr(data-progress) "%";font-size:10px;opacity:0;padding:2px 4px;position:absolute;right:5px;top:5px;transition:opacity .1s ease-in-out}',""]);const r=o},609:t=>{"use strict";t.exports=function(t){var e=[];return e.toString=function(){return this.map((function(e){var i=t(e);return e[2]?"@media ".concat(e[2]," {").concat(i,"}"):i})).join("")},e.i=function(t,i,n){"string"==typeof t&&(t=[[null,t,""]]);var o={};if(n)for(var r=0;r<this.length;r++){var s=this[r][0];null!=s&&(o[s]=!0)}for(var a=0;a<t.length;a++){var c=[].concat(t[a]);n&&o[c[0]]||(i&&(c[2]?c[2]="".concat(i," and ").concat(c[2]):c[2]=i),e.push(c))}},e}},62:(t,e,i)=>{"use strict";var n,o=function(){return void 0===n&&(n=Boolean(window&&document&&document.all&&!window.atob)),n},r=function(){var t={};return function(e){if(void 0===t[e]){var i=document.querySelector(e);if(window.HTMLIFrameElement&&i instanceof window.HTMLIFrameElement)try{i=i.contentDocument.head}catch(t){i=null}t[e]=i}return t[e]}}(),s=[];function a(t){for(var e=-1,i=0;i<s.length;i++)if(s[i].identifier===t){e=i;break}return e}function c(t,e){for(var i={},n=[],o=0;o<t.length;o++){var r=t[o],c=e.base?r[0]+e.base:r[0],l=i[c]||0,h="".concat(c," ").concat(l);i[c]=l+1;var m=a(h),d={css:r[1],media:r[2],sourceMap:r[3]};-1!==m?(s[m].references++,s[m].updater(d)):s.push({identifier:h,updater:f(d,e),references:1}),n.push(h)}return n}function l(t){var e=document.createElement("style"),n=t.attributes||{};if(void 0===n.nonce){var o=i.nc;o&&(n.nonce=o)}if(Object.keys(n).forEach((function(t){e.setAttribute(t,n[t])})),"function"==typeof t.insert)t.insert(e);else{var s=r(t.insert||"head");if(!s)throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.");s.appendChild(e)}return e}var h,m=(h=[],function(t,e){return h[t]=e,h.filter(Boolean).join("\n")});function d(t,e,i,n){var o=i?"":n.media?"@media ".concat(n.media," {").concat(n.css,"}"):n.css;if(t.styleSheet)t.styleSheet.cssText=m(e,o);else{var r=document.createTextNode(o),s=t.childNodes;s[e]&&t.removeChild(s[e]),s.length?t.insertBefore(r,s[e]):t.appendChild(r)}}function p(t,e,i){var n=i.css,o=i.media,r=i.sourceMap;if(o?t.setAttribute("media",o):t.removeAttribute("media"),r&&"undefined"!=typeof btoa&&(n+="\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(r))))," */")),t.styleSheet)t.styleSheet.cssText=n;else{for(;t.firstChild;)t.removeChild(t.firstChild);t.appendChild(document.createTextNode(n))}}var u=null,g=0;function f(t,e){var i,n,o;if(e.singleton){var r=g++;i=u||(u=l(e)),n=d.bind(null,i,r,!1),o=d.bind(null,i,r,!0)}else i=l(e),n=p.bind(null,i,e),o=function(){!function(t){if(null===t.parentNode)return!1;t.parentNode.removeChild(t)}(i)};return n(t),function(e){if(e){if(e.css===t.css&&e.media===t.media&&e.sourceMap===t.sourceMap)return;n(t=e)}else o()}}t.exports=function(t,e){(e=e||{}).singleton||"boolean"==typeof e.singleton||(e.singleton=o());var i=c(t=t||[],e);return function(t){if(t=t||[],"[object Array]"===Object.prototype.toString.call(t)){for(var n=0;n<i.length;n++){var o=a(i[n]);s[o].references--}for(var r=c(t,e),l=0;l<i.length;l++){var h=a(i[l]);0===s[h].references&&(s[h].updater(),s.splice(h,1))}i=r}}}},704:(t,e,i)=>{t.exports=i(79)("./src/core.js")},492:(t,e,i)=>{t.exports=i(79)("./src/engine.js")},273:(t,e,i)=>{t.exports=i(79)("./src/ui.js")},209:(t,e,i)=>{t.exports=i(79)("./src/utils.js")},79:t=>{"use strict";t.exports=CKEditor5.dll}},e={};function i(n){var o=e[n];if(void 0!==o)return o.exports;var r=e[n]={id:n,exports:{}};return t[n](r,r.exports,i),r.exports}i.n=t=>{var e=t&&t.__esModule?()=>t.default:()=>t;return i.d(e,{a:e}),e},i.d=(t,e)=>{for(var n in e)i.o(e,n)&&!i.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),i.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},i.nc=void 0;var n={};(()=>{"use strict";i.r(n),i.d(n,{Minimap:()=>b});var t=i(704),e=i(209),o=i(273);const r=(0,e.toUnit)("px");class s extends o.IframeView{constructor(t,e){super(t);const i=this.bindTemplate;this.set("top",0),this.set("height",0),this._options=e,this.extendTemplate({attributes:{class:["ck-minimap__iframe"],style:{top:i.to("top",(t=>r(t))),height:i.to("height",(t=>r(t)))}}})}render(){return super.render().then((()=>{this._prepareDocument()}))}setHeight(t){this.height=t}setTopOffset(t){this.top=t}_prepareDocument(){const t=this.element.contentWindow.document,e=t.adoptNode(this._options.domRootClone),i=this._options.useSimplePreview?"\n\t\t\t.ck.ck-editor__editable_inline img {\n\t\t\t\tfilter: contrast( 0 );\n\t\t\t}\n\n\t\t\tp, li, a, figcaption, span {\n\t\t\t\tbackground: hsl(0, 0%, 80%) !important;\n\t\t\t\tcolor: hsl(0, 0%, 80%) !important;\n\t\t\t}\n\n\t\t\th1, h2, h3, h4 {\n\t\t\t\tbackground: hsl(0, 0%, 60%) !important;\n\t\t\t\tcolor: hsl(0, 0%, 60%) !important;\n\t\t\t}\n\t\t":"",n=`<!DOCTYPE html><html lang="en">\n\t\t\t<head>\n\t\t\t\t<meta charset="utf-8">\n\t\t\t\t<meta name="viewport" content="width=device-width, initial-scale=1">\n\t\t\t\t${this._options.pageStyles.map((t=>"string"==typeof t?`<style>${t}</style>`:`<link rel="stylesheet" type="text/css" href="${t.href}">`)).join("\n")}\n\t\t\t\t<style>\n\t\t\t\t\thtml, body {\n\t\t\t\t\t\tmargin: 0 !important;\n\t\t\t\t\t\tpadding: 0 !important;\n\t\t\t\t\t}\n\n\t\t\t\t\thtml {\n\t\t\t\t\t\toverflow: hidden;\n\t\t\t\t\t}\n\n\t\t\t\t\tbody {\n\t\t\t\t\t\ttransform: scale( ${this._options.scaleRatio} );\n\t\t\t\t\t\ttransform-origin: 0 0;\n\t\t\t\t\t\toverflow: visible;\n\t\t\t\t\t}\n\n\t\t\t\t\t.ck.ck-editor__editable_inline {\n\t\t\t\t\t\tmargin: 0 !important;\n\t\t\t\t\t\tborder-color: transparent !important;\n\t\t\t\t\t\toutline-color: transparent !important;\n\t\t\t\t\t\tbox-shadow: none !important;\n\t\t\t\t\t}\n\n\t\t\t\t\t.ck.ck-content {\n\t\t\t\t\t\tbackground: white;\n\t\t\t\t\t}\n\n\t\t\t\t\t${i}\n\t\t\t\t</style>\n\t\t\t</head>\n\t\t\t<body class="${this._options.extraClasses||""}"></body>\n\t\t</html>`;t.open(),t.write(n),t.close(),t.body.appendChild(e)}}const a=(0,e.toUnit)("px");class c extends o.View{constructor(t){super(t);const e=this.bindTemplate;this.set("height",0),this.set("top",0),this.set("scrollProgress",0),this.set("_isDragging",!1),this.setTemplate({tag:"div",attributes:{class:["ck","ck-minimap__position-tracker",e.if("_isDragging","ck-minimap__position-tracker_dragging")],style:{top:e.to("top",(t=>a(t))),height:e.to("height",(t=>a(t)))},"data-progress":e.to("scrollProgress")},on:{mousedown:e.to((()=>{this._isDragging=!0}))}})}render(){super.render(),this.listenTo(e.global.document,"mousemove",((t,e)=>{this._isDragging&&this.fire("drag",e.movementY)}),{useCapture:!0}),this.listenTo(e.global.document,"mouseup",(()=>{this._isDragging=!1}),{useCapture:!0})}setHeight(t){this.height=t}setTopOffset(t){this.top=t}setScrollProgress(t){this.scrollProgress=t}}class l extends o.View{constructor({locale:t,scaleRatio:e,pageStyles:i,extraClasses:n,useSimplePreview:o,domRootClone:r}){super(t);const a=this.bindTemplate;this._positionTrackerView=new c(t),this._positionTrackerView.delegate("drag").to(this),this._scaleRatio=e,this._minimapIframeView=new s(t,{useSimplePreview:o,pageStyles:i,extraClasses:n,scaleRatio:e,domRootClone:r}),this.setTemplate({tag:"div",attributes:{class:["ck","ck-minimap"]},children:[this._positionTrackerView],on:{click:a.to(this._handleMinimapClick.bind(this)),wheel:a.to(this._handleMinimapMouseWheel.bind(this))}})}destroy(){this._minimapIframeView.destroy(),super.destroy()}get height(){return new e.Rect(this.element).height}get scrollHeight(){return Math.max(0,Math.min(this.height,this._minimapIframeView.height)-this._positionTrackerView.height)}render(){super.render(),this._minimapIframeView.render(),this.element.appendChild(this._minimapIframeView.element)}setContentHeight(t){this._minimapIframeView.setHeight(t*this._scaleRatio)}setScrollProgress(t){const e=this._minimapIframeView,i=this._positionTrackerView;if(e.height<this.height)e.setTopOffset(0),i.setTopOffset((e.height-i.height)*t);else{const n=e.height-this.height;e.setTopOffset(-n*t),i.setTopOffset((this.height-i.height)*t)}i.setScrollProgress(Math.round(100*t))}setPositionTrackerHeight(t){this._positionTrackerView.setHeight(t*this._scaleRatio)}_handleMinimapClick(t){const i=this._positionTrackerView;if(t.target===i.element)return;const n=new e.Rect(i.element),o=(t.clientY-n.top-n.height/2)/this._minimapIframeView.height;this.fire("click",o)}_handleMinimapMouseWheel(t){this.fire("drag",t.deltaY*this._scaleRatio)}}var h=i(492);function m(t,e){const i=t.editing.view.document,n=i.getRoot(e),o=new h.DomConverter(i),r=new h.Renderer(o,i.selection),s=t.editing.view.getDomRoot().cloneNode();return o.bindElements(s,n),r.markToSync("children",n),r.markToSync("attributes",n),n.on("change:children",((t,e)=>r.markToSync("children",e))),n.on("change:attributes",((t,e)=>r.markToSync("attributes",e))),n.on("change:text",((t,e)=>r.markToSync("text",e))),r.render(),t.editing.view.on("render",(()=>r.render())),t.on("destroy",(()=>{o.unbindDomElement(s)})),s}function d(t){return new e.Rect(t===e.global.document.body?e.global.window:t)}function p(t){return t===e.global.document.body?e.global.window:t}var u=i(62),g=i.n(u),f=i(544),k={injectType:"singletonStyleTag",attributes:{"data-cke":!0},insert:"head",singleton:!0};g()(f.Z,k);f.Z.locals;class b extends t.Plugin{static get pluginName(){return"Minimap"}init(){const t=this.editor;this._minimapView=null,this._scrollableRootAncestor=null,this.listenTo(t.ui,"ready",this._onUiReady.bind(this))}destroy(){this._minimapView.destroy(),this._minimapView.element.remove()}_onUiReady(){const t=this.editor,i=this._editingRootElement=t.ui.getEditableElement();this._scrollableRootAncestor=function(t){do{if(!(t=t.parentElement))return null;const i=e.global.window.getComputedStyle(t).overflowY;if("auto"===i||"scroll"===i)break}while("BODY"!=t.tagName);return t}(i),i.ownerDocument.body.contains(i)?(this._initializeMinimapView(),this.listenTo(t.editing.view,"render",(()=>{this._syncMinimapToEditingRootScrollPosition()})),this._syncMinimapToEditingRootScrollPosition()):t.ui.once("update",this._onUiReady.bind(this))}_initializeMinimapView(){const t=this.editor,i=t.locale,n=t.config.get("minimap.useSimplePreview"),o=t.config.get("minimap.container"),r=this._scrollableRootAncestor,s=d(this._editingRootElement).width,a=d(o).width/s,c=this._minimapView=new l({locale:i,scaleRatio:a,pageStyles:Array.from(e.global.document.styleSheets).map((t=>t.href&&!t.href.startsWith(e.global.window.location.origin)?{href:t.href}:Array.from(t.cssRules).filter((t=>!(t instanceof CSSMediaRule))).map((t=>t.cssText)).join(" \n"))),extraClasses:t.config.get("minimap.extraClasses"),useSimplePreview:n,domRootClone:m(t)});c.render(),c.listenTo(e.global.document,"scroll",((t,i)=>{if(r===e.global.document.body){if(i.target!==e.global.document)return}else if(i.target!==r)return;this._syncMinimapToEditingRootScrollPosition()}),{useCapture:!0,usePassive:!0}),c.listenTo(e.global.window,"resize",(()=>{this._syncMinimapToEditingRootScrollPosition()})),c.on("drag",((t,i)=>{let n;n=0===c.scrollHeight?0:i/c.scrollHeight;const o=n*(r.scrollHeight-((s=r)===e.global.document.body?e.global.window.innerHeight:s.clientHeight));var s;p(r).scrollBy(0,Math.round(o))})),c.on("click",((t,e)=>{const i=e*r.scrollHeight;p(r).scrollBy(0,Math.round(i))})),o.appendChild(c.element)}_syncMinimapToEditingRootScrollPosition(){const t=this._editingRootElement,e=this._minimapView;e.setContentHeight(t.offsetHeight);const i=d(t),n=d(this._scrollableRootAncestor);let o;n.contains(i)||i.top>n.top?o=0:(o=(i.top-n.top)/(n.height-i.height),o=Math.max(0,Math.min(o,1))),e.setPositionTrackerHeight(n.getIntersection(i).height),e.setScrollProgress(o)}}})(),(window.CKEditor5=window.CKEditor5||{}).minimap=n})();
4
+ */(()=>{var t={544:(t,e,i)=>{"use strict";i.d(e,{Z:()=>r});var n=i(609),o=i.n(n)()((function(t){return t[1]}));o.push([t.id,':root{--ck-color-minimap-tracker-background:208,0%,51%;--ck-color-minimap-iframe-outline:#bfbfbf;--ck-color-minimap-iframe-shadow:rgba(0,0,0,.11);--ck-color-minimap-progress-background:#666}.ck.ck-minimap{background:var(--ck-color-base-background);position:absolute;user-select:none}.ck.ck-minimap,.ck.ck-minimap iframe{height:100%;width:100%}.ck.ck-minimap iframe{border:0;box-shadow:0 2px 5px var(--ck-color-minimap-iframe-shadow);margin:0;outline:1px solid var(--ck-color-minimap-iframe-outline);pointer-events:none;position:relative}.ck.ck-minimap .ck.ck-minimap__position-tracker{background:hsla(var(--ck-color-minimap-tracker-background),.2);position:absolute;top:0;transition:background .1s ease-in-out;width:100%;z-index:1}.ck.ck-minimap .ck.ck-minimap__position-tracker:hover{background:hsla(var(--ck-color-minimap-tracker-background),.3)}.ck.ck-minimap .ck.ck-minimap__position-tracker.ck-minimap__position-tracker_dragging,.ck.ck-minimap .ck.ck-minimap__position-tracker.ck-minimap__position-tracker_dragging:hover{background:hsla(var(--ck-color-minimap-tracker-background),.4)}.ck.ck-minimap .ck.ck-minimap__position-tracker.ck-minimap__position-tracker_dragging:after,.ck.ck-minimap .ck.ck-minimap__position-tracker.ck-minimap__position-tracker_dragging:hover:after{opacity:1}.ck.ck-minimap .ck.ck-minimap__position-tracker:after{background:var(--ck-color-minimap-progress-background);border:1px solid var(--ck-color-base-background);border-radius:3px;color:var(--ck-color-base-background);content:attr(data-progress) "%";font-size:10px;opacity:0;padding:2px 4px;position:absolute;right:5px;top:5px;transition:opacity .1s ease-in-out}',""]);const r=o},609:t=>{"use strict";t.exports=function(t){var e=[];return e.toString=function(){return this.map((function(e){var i=t(e);return e[2]?"@media ".concat(e[2]," {").concat(i,"}"):i})).join("")},e.i=function(t,i,n){"string"==typeof t&&(t=[[null,t,""]]);var o={};if(n)for(var r=0;r<this.length;r++){var s=this[r][0];null!=s&&(o[s]=!0)}for(var a=0;a<t.length;a++){var c=[].concat(t[a]);n&&o[c[0]]||(i&&(c[2]?c[2]="".concat(i," and ").concat(c[2]):c[2]=i),e.push(c))}},e}},62:(t,e,i)=>{"use strict";var n,o=function(){return void 0===n&&(n=Boolean(window&&document&&document.all&&!window.atob)),n},r=function(){var t={};return function(e){if(void 0===t[e]){var i=document.querySelector(e);if(window.HTMLIFrameElement&&i instanceof window.HTMLIFrameElement)try{i=i.contentDocument.head}catch(t){i=null}t[e]=i}return t[e]}}(),s=[];function a(t){for(var e=-1,i=0;i<s.length;i++)if(s[i].identifier===t){e=i;break}return e}function c(t,e){for(var i={},n=[],o=0;o<t.length;o++){var r=t[o],c=e.base?r[0]+e.base:r[0],l=i[c]||0,h="".concat(c," ").concat(l);i[c]=l+1;var m=a(h),d={css:r[1],media:r[2],sourceMap:r[3]};-1!==m?(s[m].references++,s[m].updater(d)):s.push({identifier:h,updater:f(d,e),references:1}),n.push(h)}return n}function l(t){var e=document.createElement("style"),n=t.attributes||{};if(void 0===n.nonce){var o=i.nc;o&&(n.nonce=o)}if(Object.keys(n).forEach((function(t){e.setAttribute(t,n[t])})),"function"==typeof t.insert)t.insert(e);else{var s=r(t.insert||"head");if(!s)throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.");s.appendChild(e)}return e}var h,m=(h=[],function(t,e){return h[t]=e,h.filter(Boolean).join("\n")});function d(t,e,i,n){var o=i?"":n.media?"@media ".concat(n.media," {").concat(n.css,"}"):n.css;if(t.styleSheet)t.styleSheet.cssText=m(e,o);else{var r=document.createTextNode(o),s=t.childNodes;s[e]&&t.removeChild(s[e]),s.length?t.insertBefore(r,s[e]):t.appendChild(r)}}function p(t,e,i){var n=i.css,o=i.media,r=i.sourceMap;if(o?t.setAttribute("media",o):t.removeAttribute("media"),r&&"undefined"!=typeof btoa&&(n+="\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(r))))," */")),t.styleSheet)t.styleSheet.cssText=n;else{for(;t.firstChild;)t.removeChild(t.firstChild);t.appendChild(document.createTextNode(n))}}var g=null,u=0;function f(t,e){var i,n,o;if(e.singleton){var r=u++;i=g||(g=l(e)),n=d.bind(null,i,r,!1),o=d.bind(null,i,r,!0)}else i=l(e),n=p.bind(null,i,e),o=function(){!function(t){if(null===t.parentNode)return!1;t.parentNode.removeChild(t)}(i)};return n(t),function(e){if(e){if(e.css===t.css&&e.media===t.media&&e.sourceMap===t.sourceMap)return;n(t=e)}else o()}}t.exports=function(t,e){(e=e||{}).singleton||"boolean"==typeof e.singleton||(e.singleton=o());var i=c(t=t||[],e);return function(t){if(t=t||[],"[object Array]"===Object.prototype.toString.call(t)){for(var n=0;n<i.length;n++){var o=a(i[n]);s[o].references--}for(var r=c(t,e),l=0;l<i.length;l++){var h=a(i[l]);0===s[h].references&&(s[h].updater(),s.splice(h,1))}i=r}}}},704:(t,e,i)=>{t.exports=i(79)("./src/core.js")},492:(t,e,i)=>{t.exports=i(79)("./src/engine.js")},273:(t,e,i)=>{t.exports=i(79)("./src/ui.js")},209:(t,e,i)=>{t.exports=i(79)("./src/utils.js")},79:t=>{"use strict";t.exports=CKEditor5.dll}},e={};function i(n){var o=e[n];if(void 0!==o)return o.exports;var r=e[n]={id:n,exports:{}};return t[n](r,r.exports,i),r.exports}i.n=t=>{var e=t&&t.__esModule?()=>t.default:()=>t;return i.d(e,{a:e}),e},i.d=(t,e)=>{for(var n in e)i.o(e,n)&&!i.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),i.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},i.nc=void 0;var n={};(()=>{"use strict";i.r(n),i.d(n,{Minimap:()=>b});var t=i(704),e=i(209),o=i(273);const r=(0,e.toUnit)("px");class s extends o.IframeView{constructor(t,e){super(t);const i=this.bindTemplate;this.set("top",0),this.set("height",0),this._options=e,this.extendTemplate({attributes:{class:["ck-minimap__iframe"],style:{top:i.to("top",(t=>r(t))),height:i.to("height",(t=>r(t)))}}})}render(){return super.render().then((()=>{this._prepareDocument()}))}setHeight(t){this.height=t}setTopOffset(t){this.top=t}_prepareDocument(){const t=this.element.contentWindow.document,e=t.adoptNode(this._options.domRootClone),i=this._options.useSimplePreview?"\n\t\t\t.ck.ck-editor__editable_inline img {\n\t\t\t\tfilter: contrast( 0 );\n\t\t\t}\n\n\t\t\tp, li, a, figcaption, span {\n\t\t\t\tbackground: hsl(0, 0%, 80%) !important;\n\t\t\t\tcolor: hsl(0, 0%, 80%) !important;\n\t\t\t}\n\n\t\t\th1, h2, h3, h4 {\n\t\t\t\tbackground: hsl(0, 0%, 60%) !important;\n\t\t\t\tcolor: hsl(0, 0%, 60%) !important;\n\t\t\t}\n\t\t":"",n=`<!DOCTYPE html><html lang="en">\n\t\t\t<head>\n\t\t\t\t<meta charset="utf-8">\n\t\t\t\t<meta name="viewport" content="width=device-width, initial-scale=1">\n\t\t\t\t${this._options.pageStyles.map((t=>"string"==typeof t?`<style>${t}</style>`:`<link rel="stylesheet" type="text/css" href="${t.href}">`)).join("\n")}\n\t\t\t\t<style>\n\t\t\t\t\thtml, body {\n\t\t\t\t\t\tmargin: 0 !important;\n\t\t\t\t\t\tpadding: 0 !important;\n\t\t\t\t\t}\n\n\t\t\t\t\thtml {\n\t\t\t\t\t\toverflow: hidden;\n\t\t\t\t\t}\n\n\t\t\t\t\tbody {\n\t\t\t\t\t\ttransform: scale( ${this._options.scaleRatio} );\n\t\t\t\t\t\ttransform-origin: 0 0;\n\t\t\t\t\t\toverflow: visible;\n\t\t\t\t\t}\n\n\t\t\t\t\t.ck.ck-editor__editable_inline {\n\t\t\t\t\t\tmargin: 0 !important;\n\t\t\t\t\t\tborder-color: transparent !important;\n\t\t\t\t\t\toutline-color: transparent !important;\n\t\t\t\t\t\tbox-shadow: none !important;\n\t\t\t\t\t}\n\n\t\t\t\t\t.ck.ck-content {\n\t\t\t\t\t\tbackground: white;\n\t\t\t\t\t}\n\n\t\t\t\t\t${i}\n\t\t\t\t</style>\n\t\t\t</head>\n\t\t\t<body class="${this._options.extraClasses||""}"></body>\n\t\t</html>`;t.open(),t.write(n),t.close(),t.body.appendChild(e)}}const a=(0,e.toUnit)("px");class c extends o.View{constructor(t){super(t);const e=this.bindTemplate;this.set("height",0),this.set("top",0),this.set("scrollProgress",0),this.set("_isDragging",!1),this.setTemplate({tag:"div",attributes:{class:["ck","ck-minimap__position-tracker",e.if("_isDragging","ck-minimap__position-tracker_dragging")],style:{top:e.to("top",(t=>a(t))),height:e.to("height",(t=>a(t)))},"data-progress":e.to("scrollProgress")},on:{mousedown:e.to((()=>{this._isDragging=!0}))}})}render(){super.render(),this.listenTo(e.global.document,"mousemove",((t,e)=>{this._isDragging&&this.fire("drag",e.movementY)}),{useCapture:!0}),this.listenTo(e.global.document,"mouseup",(()=>{this._isDragging=!1}),{useCapture:!0})}setHeight(t){this.height=t}setTopOffset(t){this.top=t}setScrollProgress(t){this.scrollProgress=t}}class l extends o.View{constructor({locale:t,scaleRatio:e,pageStyles:i,extraClasses:n,useSimplePreview:o,domRootClone:r}){super(t);const a=this.bindTemplate;this._positionTrackerView=new c(t),this._positionTrackerView.delegate("drag").to(this),this._scaleRatio=e,this._minimapIframeView=new s(t,{useSimplePreview:o,pageStyles:i,extraClasses:n,scaleRatio:e,domRootClone:r}),this.setTemplate({tag:"div",attributes:{class:["ck","ck-minimap"]},children:[this._positionTrackerView],on:{click:a.to(this._handleMinimapClick.bind(this)),wheel:a.to(this._handleMinimapMouseWheel.bind(this))}})}destroy(){this._minimapIframeView.destroy(),super.destroy()}get height(){return new e.Rect(this.element).height}get scrollHeight(){return Math.max(0,Math.min(this.height,this._minimapIframeView.height)-this._positionTrackerView.height)}render(){super.render(),this._minimapIframeView.render(),this.element.appendChild(this._minimapIframeView.element)}setContentHeight(t){this._minimapIframeView.setHeight(t*this._scaleRatio)}setScrollProgress(t){const e=this._minimapIframeView,i=this._positionTrackerView;if(e.height<this.height)e.setTopOffset(0),i.setTopOffset((e.height-i.height)*t);else{const n=e.height-this.height;e.setTopOffset(-n*t),i.setTopOffset((this.height-i.height)*t)}i.setScrollProgress(Math.round(100*t))}setPositionTrackerHeight(t){this._positionTrackerView.setHeight(t*this._scaleRatio)}_handleMinimapClick(t){const i=this._positionTrackerView;if(t.target===i.element)return;const n=new e.Rect(i.element),o=(t.clientY-n.top-n.height/2)/this._minimapIframeView.height;this.fire("click",o)}_handleMinimapMouseWheel(t){this.fire("drag",t.deltaY*this._scaleRatio)}}var h=i(492);function m(t,e){const i=t.editing.view.document,n=i.getRoot(e),o=new h.DomConverter(i),r=new h.Renderer(o,i.selection),s=t.editing.view.getDomRoot().cloneNode();return o.bindElements(s,n),r.markToSync("children",n),r.markToSync("attributes",n),n.on("change:children",((t,e)=>r.markToSync("children",e))),n.on("change:attributes",((t,e)=>r.markToSync("attributes",e))),n.on("change:text",((t,e)=>r.markToSync("text",e))),r.render(),t.editing.view.on("render",(()=>r.render())),t.on("destroy",(()=>{o.unbindDomElement(s)})),s}function d(t){return new e.Rect(t===e.global.document.body?e.global.window:t)}function p(t){return t===e.global.document.body?e.global.window:t}var g=i(62),u=i.n(g),f=i(544),k={injectType:"singletonStyleTag",attributes:{"data-cke":!0},insert:"head",singleton:!0};u()(f.Z,k);f.Z.locals;class b extends t.Plugin{static get pluginName(){return"Minimap"}init(){const t=this.editor;this._minimapView=null,this._scrollableRootAncestor=null,this.listenTo(t.ui,"ready",this._onUiReady.bind(this))}destroy(){this._minimapView.destroy(),this._minimapView.element.remove()}_onUiReady(){const t=this.editor,i=this._editingRootElement=t.ui.getEditableElement();this._scrollableRootAncestor=(0,e.findClosestScrollableAncestor)(i),i.ownerDocument.body.contains(i)?(this._initializeMinimapView(),this.listenTo(t.editing.view,"render",(()=>{this._syncMinimapToEditingRootScrollPosition()})),this._syncMinimapToEditingRootScrollPosition()):t.ui.once("update",this._onUiReady.bind(this))}_initializeMinimapView(){const t=this.editor,i=t.locale,n=t.config.get("minimap.useSimplePreview"),o=t.config.get("minimap.container"),r=this._scrollableRootAncestor,s=d(this._editingRootElement).width,a=d(o).width/s,c=this._minimapView=new l({locale:i,scaleRatio:a,pageStyles:Array.from(e.global.document.styleSheets).map((t=>t.href&&!t.href.startsWith(e.global.window.location.origin)?{href:t.href}:Array.from(t.cssRules).filter((t=>!(t instanceof CSSMediaRule))).map((t=>t.cssText)).join(" \n"))),extraClasses:t.config.get("minimap.extraClasses"),useSimplePreview:n,domRootClone:m(t)});c.render(),c.listenTo(e.global.document,"scroll",((t,i)=>{if(r===e.global.document.body){if(i.target!==e.global.document)return}else if(i.target!==r)return;this._syncMinimapToEditingRootScrollPosition()}),{useCapture:!0,usePassive:!0}),c.listenTo(e.global.window,"resize",(()=>{this._syncMinimapToEditingRootScrollPosition()})),c.on("drag",((t,i)=>{let n;n=0===c.scrollHeight?0:i/c.scrollHeight;const o=n*(r.scrollHeight-((s=r)===e.global.document.body?e.global.window.innerHeight:s.clientHeight));var s;p(r).scrollBy(0,Math.round(o))})),c.on("click",((t,e)=>{const i=e*r.scrollHeight;p(r).scrollBy(0,Math.round(i))})),o.appendChild(c.element)}_syncMinimapToEditingRootScrollPosition(){const t=this._editingRootElement,e=this._minimapView;e.setContentHeight(t.offsetHeight);const i=d(t),n=d(this._scrollableRootAncestor);let o;n.contains(i)||i.top>n.top?o=0:(o=(i.top-n.top)/(n.height-i.height),o=Math.max(0,Math.min(o,1))),e.setPositionTrackerHeight(n.getIntersection(i).height),e.setScrollProgress(o)}}})(),(window.CKEditor5=window.CKEditor5||{}).minimap=n})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ckeditor/ckeditor5-minimap",
3
- "version": "35.4.0",
3
+ "version": "36.0.0",
4
4
  "description": "Content minimap feature for CKEditor 5.",
5
5
  "keywords": [
6
6
  "ckeditor",
@@ -12,23 +12,24 @@
12
12
  ],
13
13
  "main": "src/index.js",
14
14
  "dependencies": {
15
- "ckeditor5": "^35.4.0"
15
+ "ckeditor5": "^36.0.0"
16
16
  },
17
17
  "devDependencies": {
18
- "@ckeditor/ckeditor5-alignment": "^35.4.0",
19
- "@ckeditor/ckeditor5-basic-styles": "^35.4.0",
20
- "@ckeditor/ckeditor5-cloud-services": "^35.4.0",
21
- "@ckeditor/ckeditor5-code-block": "^35.4.0",
22
- "@ckeditor/ckeditor5-core": "^35.4.0",
23
- "@ckeditor/ckeditor5-dev-utils": "^31.0.0",
24
- "@ckeditor/ckeditor5-easy-image": "^35.4.0",
25
- "@ckeditor/ckeditor5-editor-decoupled": "^35.4.0",
26
- "@ckeditor/ckeditor5-font": "^35.4.0",
27
- "@ckeditor/ckeditor5-image": "^35.4.0",
28
- "@ckeditor/ckeditor5-indent": "^35.4.0",
29
- "@ckeditor/ckeditor5-page-break": "^35.4.0",
30
- "@ckeditor/ckeditor5-table": "^35.4.0",
31
- "@ckeditor/ckeditor5-theme-lark": "^35.4.0",
18
+ "@ckeditor/ckeditor5-alignment": "^36.0.0",
19
+ "@ckeditor/ckeditor5-basic-styles": "^36.0.0",
20
+ "@ckeditor/ckeditor5-cloud-services": "^36.0.0",
21
+ "@ckeditor/ckeditor5-code-block": "^36.0.0",
22
+ "@ckeditor/ckeditor5-core": "^36.0.0",
23
+ "@ckeditor/ckeditor5-dev-utils": "^32.0.0",
24
+ "@ckeditor/ckeditor5-easy-image": "^36.0.0",
25
+ "@ckeditor/ckeditor5-editor-decoupled": "^36.0.0",
26
+ "@ckeditor/ckeditor5-font": "^36.0.0",
27
+ "@ckeditor/ckeditor5-image": "^36.0.0",
28
+ "@ckeditor/ckeditor5-indent": "^36.0.0",
29
+ "@ckeditor/ckeditor5-page-break": "^36.0.0",
30
+ "@ckeditor/ckeditor5-table": "^36.0.0",
31
+ "@ckeditor/ckeditor5-theme-lark": "^36.0.0",
32
+ "typescript": "^4.8.4",
32
33
  "webpack": "^5.58.1",
33
34
  "webpack-cli": "^4.9.0"
34
35
  },
@@ -47,13 +48,16 @@
47
48
  },
48
49
  "files": [
49
50
  "lang",
50
- "src",
51
+ "src/**/*.js",
52
+ "src/**/*.d.ts",
51
53
  "theme",
52
54
  "build",
53
55
  "ckeditor5-metadata.json",
54
56
  "CHANGELOG.md"
55
57
  ],
56
58
  "scripts": {
57
- "dll:build": "webpack"
59
+ "dll:build": "webpack",
60
+ "build": "tsc -p ./tsconfig.release.json",
61
+ "postversion": "npm run build"
58
62
  }
59
63
  }
package/src/index.js CHANGED
@@ -1,10 +1,8 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
-
6
5
  /**
7
6
  * @module minimap
8
7
  */
9
-
10
8
  export { default as Minimap } from './minimap';
package/src/minimap.js CHANGED
@@ -1,299 +1,154 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
-
6
5
  /**
7
6
  * @module minimap/minimap
8
7
  */
9
-
10
8
  import { Plugin } from 'ckeditor5/src/core';
11
- import { global } from 'ckeditor5/src/utils';
9
+ import { findClosestScrollableAncestor, global } from 'ckeditor5/src/utils';
12
10
  import MinimapView from './minimapview';
13
- import {
14
- cloneEditingViewDomRoot,
15
- getClientHeight,
16
- getDomElementRect,
17
- getPageStyles,
18
- getScrollable,
19
- findClosestScrollableAncestor
20
- } from './utils';
21
-
11
+ import { cloneEditingViewDomRoot, getClientHeight, getDomElementRect, getPageStyles, getScrollable } from './utils';
22
12
  // @if CK_DEBUG_MINIMAP // const RectDrawer = require( '@ckeditor/ckeditor5-utils/tests/_utils/rectdrawer' ).default;
23
-
24
13
  import '../theme/minimap.css';
25
-
26
14
  /**
27
15
  * The content minimap feature.
28
- *
29
- * @extends module:core/plugin~Plugin
30
16
  */
31
17
  export default class Minimap extends Plugin {
32
- /**
33
- * @inheritDoc
34
- */
35
- static get pluginName() {
36
- return 'Minimap';
37
- }
38
-
39
- /**
40
- * @inheritDoc
41
- */
42
- init() {
43
- const editor = this.editor;
44
-
45
- /**
46
- * The reference to the view of the minimap.
47
- *
48
- * @private
49
- * @member {module:minimap/minimapview~MinimapView}
50
- */
51
- this._minimapView = null;
52
-
53
- /**
54
- * The DOM element closest to the editable element of the editor as returned
55
- * by {@link module:core/editor/editorui~EditorUI#getEditableElement}.
56
- *
57
- * @private
58
- * @member {HTMLElement}
59
- */
60
- this._scrollableRootAncestor = null;
61
-
62
- this.listenTo( editor.ui, 'ready', this._onUiReady.bind( this ) );
63
- }
64
-
65
- /**
66
- * @inheritDoc
67
- */
68
- destroy() {
69
- this._minimapView.destroy();
70
- this._minimapView.element.remove();
71
- }
72
-
73
- /**
74
- * Initializes the minimap view element and starts the layout synchronization
75
- * on the editing view `render` event.
76
- *
77
- * @private
78
- */
79
- _onUiReady() {
80
- const editor = this.editor;
81
-
82
- // TODO: This will not work with the multi-root editor.
83
- const editingRootElement = this._editingRootElement = editor.ui.getEditableElement();
84
-
85
- this._scrollableRootAncestor = findClosestScrollableAncestor( editingRootElement );
86
-
87
- // DOM root element is not yet attached to the document.
88
- if ( !editingRootElement.ownerDocument.body.contains( editingRootElement ) ) {
89
- editor.ui.once( 'update', this._onUiReady.bind( this ) );
90
-
91
- return;
92
- }
93
-
94
- this._initializeMinimapView();
95
-
96
- this.listenTo( editor.editing.view, 'render', () => {
97
- this._syncMinimapToEditingRootScrollPosition();
98
- } );
99
-
100
- this._syncMinimapToEditingRootScrollPosition();
101
- }
102
-
103
- /**
104
- * Initializes the minimap view and attaches listeners that make it responsive to the environment (document)
105
- * but also allow the minimap to control the document (scroll position).
106
- *
107
- * @private
108
- */
109
- _initializeMinimapView() {
110
- const editor = this.editor;
111
- const locale = editor.locale;
112
- const useSimplePreview = editor.config.get( 'minimap.useSimplePreview' );
113
- const minimapContainerElement = editor.config.get( 'minimap.container' );
114
- const scrollableRootAncestor = this._scrollableRootAncestor;
115
-
116
- // TODO: This should be dynamic, the root width could change as the viewport scales if not fixed unit.
117
- const editingRootElementWidth = getDomElementRect( this._editingRootElement ).width;
118
- const minimapContainerWidth = getDomElementRect( minimapContainerElement ).width;
119
- const minimapScaleRatio = minimapContainerWidth / editingRootElementWidth;
120
-
121
- const minimapView = this._minimapView = new MinimapView( {
122
- locale,
123
- scaleRatio: minimapScaleRatio,
124
- pageStyles: getPageStyles(),
125
- extraClasses: editor.config.get( 'minimap.extraClasses' ),
126
- useSimplePreview,
127
- domRootClone: cloneEditingViewDomRoot( editor )
128
- } );
129
-
130
- minimapView.render();
131
-
132
- // Scrollable ancestor scroll -> minimap position update.
133
- minimapView.listenTo( global.document, 'scroll', ( evt, data ) => {
134
- if ( scrollableRootAncestor === global.document.body ) {
135
- if ( data.target !== global.document ) {
136
- return;
137
- }
138
- } else if ( data.target !== scrollableRootAncestor ) {
139
- return;
140
- }
141
-
142
- this._syncMinimapToEditingRootScrollPosition();
143
- }, { useCapture: true, usePassive: true } );
144
-
145
- // Viewport resize -> minimap position update.
146
- minimapView.listenTo( global.window, 'resize', () => {
147
- this._syncMinimapToEditingRootScrollPosition();
148
- } );
149
-
150
- // Dragging the visible content area -> document (scrollable) position update.
151
- minimapView.on( 'drag', ( evt, movementY ) => {
152
- let movementYPercentage;
153
-
154
- if ( minimapView.scrollHeight === 0 ) {
155
- movementYPercentage = 0;
156
- } else {
157
- movementYPercentage = movementY / minimapView.scrollHeight;
158
- }
159
-
160
- const absoluteScrollProgress = movementYPercentage *
161
- ( scrollableRootAncestor.scrollHeight - getClientHeight( scrollableRootAncestor ) );
162
- const scrollable = getScrollable( scrollableRootAncestor );
163
-
164
- scrollable.scrollBy( 0, Math.round( absoluteScrollProgress ) );
165
- } );
166
-
167
- // Clicking the minimap -> center the document (scrollable) to the corresponding position.
168
- minimapView.on( 'click', ( evt, percentage ) => {
169
- const absoluteScrollProgress = percentage * scrollableRootAncestor.scrollHeight;
170
- const scrollable = getScrollable( scrollableRootAncestor );
171
-
172
- scrollable.scrollBy( 0, Math.round( absoluteScrollProgress ) );
173
- } );
174
-
175
- minimapContainerElement.appendChild( minimapView.element );
176
- }
177
-
178
- /**
179
- * @private
180
- */
181
- _syncMinimapToEditingRootScrollPosition() {
182
- const editingRootElement = this._editingRootElement;
183
- const minimapView = this._minimapView;
184
-
185
- minimapView.setContentHeight( editingRootElement.offsetHeight );
186
-
187
- const editingRootRect = getDomElementRect( editingRootElement );
188
- const scrollableRootAncestorRect = getDomElementRect( this._scrollableRootAncestor );
189
- let scrollProgress;
190
-
191
- // @if CK_DEBUG_MINIMAP // RectDrawer.clear();
192
- // @if CK_DEBUG_MINIMAP // RectDrawer.draw( scrollableRootAncestorRect, { outlineColor: 'red' }, 'scrollableRootAncestor' );
193
- // @if CK_DEBUG_MINIMAP // RectDrawer.draw( editingRootRect, { outlineColor: 'green' }, 'editingRoot' );
194
-
195
- // The root is completely visible in the scrollable ancestor.
196
- if ( scrollableRootAncestorRect.contains( editingRootRect ) ) {
197
- scrollProgress = 0;
198
- } else {
199
- if ( editingRootRect.top > scrollableRootAncestorRect.top ) {
200
- scrollProgress = 0;
201
- } else {
202
- scrollProgress = ( editingRootRect.top - scrollableRootAncestorRect.top ) /
203
- ( scrollableRootAncestorRect.height - editingRootRect.height );
204
-
205
- scrollProgress = Math.max( 0, Math.min( scrollProgress, 1 ) );
206
- }
207
- }
208
-
209
- // The intersection helps to change the tracker height when there is a lot of padding around the root.
210
- // Note: It is **essential** that the height is set first because the progress depends on the correct tracker height.
211
- minimapView.setPositionTrackerHeight( scrollableRootAncestorRect.getIntersection( editingRootRect ).height );
212
- minimapView.setScrollProgress( scrollProgress );
213
- }
18
+ /**
19
+ * @inheritDoc
20
+ */
21
+ static get pluginName() {
22
+ return 'Minimap';
23
+ }
24
+ /**
25
+ * @inheritDoc
26
+ */
27
+ init() {
28
+ const editor = this.editor;
29
+ this._minimapView = null;
30
+ this._scrollableRootAncestor = null;
31
+ this.listenTo(editor.ui, 'ready', this._onUiReady.bind(this));
32
+ }
33
+ /**
34
+ * @inheritDoc
35
+ */
36
+ destroy() {
37
+ this._minimapView.destroy();
38
+ this._minimapView.element.remove();
39
+ }
40
+ /**
41
+ * Initializes the minimap view element and starts the layout synchronization
42
+ * on the editing view `render` event.
43
+ */
44
+ _onUiReady() {
45
+ const editor = this.editor;
46
+ // TODO: This will not work with the multi-root editor.
47
+ const editingRootElement = this._editingRootElement = editor.ui.getEditableElement();
48
+ this._scrollableRootAncestor = findClosestScrollableAncestor(editingRootElement);
49
+ // DOM root element is not yet attached to the document.
50
+ if (!editingRootElement.ownerDocument.body.contains(editingRootElement)) {
51
+ editor.ui.once('update', this._onUiReady.bind(this));
52
+ return;
53
+ }
54
+ this._initializeMinimapView();
55
+ this.listenTo(editor.editing.view, 'render', () => {
56
+ this._syncMinimapToEditingRootScrollPosition();
57
+ });
58
+ this._syncMinimapToEditingRootScrollPosition();
59
+ }
60
+ /**
61
+ * Initializes the minimap view and attaches listeners that make it responsive to the environment (document)
62
+ * but also allow the minimap to control the document (scroll position).
63
+ */
64
+ _initializeMinimapView() {
65
+ const editor = this.editor;
66
+ const locale = editor.locale;
67
+ const useSimplePreview = editor.config.get('minimap.useSimplePreview');
68
+ // TODO: Throw an error if there is no `minimap` in config.
69
+ const minimapContainerElement = editor.config.get('minimap.container');
70
+ const scrollableRootAncestor = this._scrollableRootAncestor;
71
+ // TODO: This should be dynamic, the root width could change as the viewport scales if not fixed unit.
72
+ const editingRootElementWidth = getDomElementRect(this._editingRootElement).width;
73
+ const minimapContainerWidth = getDomElementRect(minimapContainerElement).width;
74
+ const minimapScaleRatio = minimapContainerWidth / editingRootElementWidth;
75
+ const minimapView = this._minimapView = new MinimapView({
76
+ locale,
77
+ scaleRatio: minimapScaleRatio,
78
+ pageStyles: getPageStyles(),
79
+ extraClasses: editor.config.get('minimap.extraClasses'),
80
+ useSimplePreview,
81
+ domRootClone: cloneEditingViewDomRoot(editor)
82
+ });
83
+ minimapView.render();
84
+ // Scrollable ancestor scroll -> minimap position update.
85
+ minimapView.listenTo(global.document, 'scroll', (evt, data) => {
86
+ if (scrollableRootAncestor === global.document.body) {
87
+ if (data.target !== global.document) {
88
+ return;
89
+ }
90
+ }
91
+ else if (data.target !== scrollableRootAncestor) {
92
+ return;
93
+ }
94
+ this._syncMinimapToEditingRootScrollPosition();
95
+ }, { useCapture: true, usePassive: true });
96
+ // Viewport resize -> minimap position update.
97
+ minimapView.listenTo(global.window, 'resize', () => {
98
+ this._syncMinimapToEditingRootScrollPosition();
99
+ });
100
+ // Dragging the visible content area -> document (scrollable) position update.
101
+ minimapView.on('drag', (evt, movementY) => {
102
+ let movementYPercentage;
103
+ if (minimapView.scrollHeight === 0) {
104
+ movementYPercentage = 0;
105
+ }
106
+ else {
107
+ movementYPercentage = movementY / minimapView.scrollHeight;
108
+ }
109
+ const absoluteScrollProgress = movementYPercentage *
110
+ (scrollableRootAncestor.scrollHeight - getClientHeight(scrollableRootAncestor));
111
+ const scrollable = getScrollable(scrollableRootAncestor);
112
+ scrollable.scrollBy(0, Math.round(absoluteScrollProgress));
113
+ });
114
+ // Clicking the minimap -> center the document (scrollable) to the corresponding position.
115
+ minimapView.on('click', (evt, percentage) => {
116
+ const absoluteScrollProgress = percentage * scrollableRootAncestor.scrollHeight;
117
+ const scrollable = getScrollable(scrollableRootAncestor);
118
+ scrollable.scrollBy(0, Math.round(absoluteScrollProgress));
119
+ });
120
+ minimapContainerElement.appendChild(minimapView.element);
121
+ }
122
+ /**
123
+ * @private
124
+ */
125
+ _syncMinimapToEditingRootScrollPosition() {
126
+ const editingRootElement = this._editingRootElement;
127
+ const minimapView = this._minimapView;
128
+ minimapView.setContentHeight(editingRootElement.offsetHeight);
129
+ const editingRootRect = getDomElementRect(editingRootElement);
130
+ const scrollableRootAncestorRect = getDomElementRect(this._scrollableRootAncestor);
131
+ let scrollProgress;
132
+ // @if CK_DEBUG_MINIMAP // RectDrawer.clear();
133
+ // @if CK_DEBUG_MINIMAP // RectDrawer.draw( scrollableRootAncestorRect, { outlineColor: 'red' }, 'scrollableRootAncestor' );
134
+ // @if CK_DEBUG_MINIMAP // RectDrawer.draw( editingRootRect, { outlineColor: 'green' }, 'editingRoot' );
135
+ // The root is completely visible in the scrollable ancestor.
136
+ if (scrollableRootAncestorRect.contains(editingRootRect)) {
137
+ scrollProgress = 0;
138
+ }
139
+ else {
140
+ if (editingRootRect.top > scrollableRootAncestorRect.top) {
141
+ scrollProgress = 0;
142
+ }
143
+ else {
144
+ scrollProgress = (editingRootRect.top - scrollableRootAncestorRect.top) /
145
+ (scrollableRootAncestorRect.height - editingRootRect.height);
146
+ scrollProgress = Math.max(0, Math.min(scrollProgress, 1));
147
+ }
148
+ }
149
+ // The intersection helps to change the tracker height when there is a lot of padding around the root.
150
+ // Note: It is **essential** that the height is set first because the progress depends on the correct tracker height.
151
+ minimapView.setPositionTrackerHeight(scrollableRootAncestorRect.getIntersection(editingRootRect).height);
152
+ minimapView.setScrollProgress(scrollProgress);
153
+ }
214
154
  }
215
-
216
- /**
217
- * The configuration of the minimap feature. Introduced by the {@link module:minimap/minimap~Minimap} feature.
218
- *
219
- * Read more in {@link module:minimap/minimap~MinimapConfig}.
220
- *
221
- * @member {module:minimap/minimap~MinimapConfig} module:core/editor/editorconfig~EditorConfig#minimap
222
- */
223
-
224
- /**
225
- * The configuration of the {@link module:minimap/minimap~Minimap} feature.
226
- *
227
- * ClassicEditor
228
- * .create( {
229
- * minimap: ... // Minimap feature config.
230
- * } )
231
- * .then( ... )
232
- * .catch( ... );
233
- *
234
- * See {@link module:core/editor/editorconfig~EditorConfig all editor options}.
235
- *
236
- * @interface MinimapConfig
237
- */
238
-
239
- /**
240
- * The DOM element container for the minimap.
241
- *
242
- * **Note**: The container must have a fixed `width` and `overflow: hidden` for the minimap to work correctly.
243
- *
244
- * @member {HTMLElement} module:minimap/minimap~MinimapConfig#container
245
- */
246
-
247
- /**
248
- * When set to `true`, the minimap will render content as simple boxes instead of replicating the look of the content (default).
249
- *
250
- * @member {Boolean} module:minimap/minimap~MinimapConfig#useSimplePreview
251
- */
252
-
253
- /**
254
- * Extra CSS class (or classes) that will be set internally on the `<body>` element of the `<iframe>` enclosing the minimap.
255
- *
256
- * By default, the minimap feature will attempt to clone all website styles and re-apply them in the `<iframe>` for the best accuracy.
257
- * However, this may not work if the content of your editor inherits the styles from parent containers, resulting in inconsistent
258
- * look and imprecise scrolling of the minimap.
259
- *
260
- * This optional configuration can address these issues by ensuring the same CSS rules apply to the content of the minimap
261
- * and the original content of the editor.
262
- *
263
- * For instance, consider the following DOM structure:
264
- *
265
- * <div class="website">
266
- * <!-- ... -->
267
- * <div class="styled-container">
268
- * <!-- ... -->
269
- * <div id="editor">
270
- * <!-- content of the editor -->
271
- * </div>
272
- * </div>
273
- * <!-- ... -->
274
- * </div>
275
- *
276
- * and the following CSS styles:
277
- *
278
- * .website p {
279
- * font-size: 13px;
280
- * }
281
- *
282
- * .styled-container p {
283
- * color: #ccc;
284
- * }
285
- *
286
- * To maintain the consistency of styling (`font-size` and `color` of paragraphs), you will need to pass the CSS class names
287
- * of these containers:
288
- *
289
- * ClassicEditor
290
- * .create( document.getElementById( 'editor' ), {
291
- * minimap: {
292
- * extraClasses: 'website styled-container'
293
- * }
294
- * } )
295
- * .then( ... )
296
- * .catch( ... );
297
- *
298
- * @member {String} module:minimap/minimap~MinimapConfig#extraClasses
299
- */