@ckeditor/ckeditor5-minimap
Version:
Content minimap feature for CKEditor 5.
137 lines (129 loc) • 3.71 kB
JavaScript
/**
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
/**
* @module minimap/minimapiframeview
*/
import { IframeView } from 'ckeditor5/src/ui.js';
import { toUnit } from 'ckeditor5/src/utils.js';
const toPx = /* #__PURE__ */ toUnit('px');
/**
* The internal `<iframe>` view that hosts the minimap content.
*
* @internal
*/
export default class MinimapIframeView extends IframeView {
/**
* Cached view constructor options for re-use in other methods.
*/
_options;
/**
* Creates an instance of the internal minimap iframe.
*/
constructor(locale, options) {
super(locale);
const bind = this.bindTemplate;
this.set('top', 0);
this.set('height', 0);
this._options = options;
this.extendTemplate({
attributes: {
tabindex: -1,
'aria-hidden': 'true',
class: [
'ck-minimap__iframe'
],
style: {
top: bind.to('top', top => toPx(top)),
height: bind.to('height', height => toPx(height))
}
}
});
}
/**
* @inheritDoc
*/
render() {
return super.render().then(() => {
this._prepareDocument();
});
}
/**
* Sets the new height of the iframe.
*/
setHeight(newHeight) {
this.height = newHeight;
}
/**
* Sets the top offset of the iframe to move it around vertically.
*/
setTopOffset(newOffset) {
this.top = newOffset;
}
/**
* Sets the internal structure of the `<iframe>` readying it to display the
* minimap element.
*/
_prepareDocument() {
const iframeDocument = this.element.contentWindow.document;
const domRootClone = iframeDocument.adoptNode(this._options.domRootClone);
const boxStyles = this._options.useSimplePreview ? `
.ck.ck-editor__editable_inline img {
filter: contrast( 0 );
}
p, li, a, figcaption, span {
background: hsl(0, 0%, 80%) !important;
color: hsl(0, 0%, 80%) !important;
}
h1, h2, h3, h4 {
background: hsl(0, 0%, 60%) !important;
color: hsl(0, 0%, 60%) !important;
}
` : '';
const pageStyles = this._options.pageStyles.map(definition => {
if (typeof definition === 'string') {
return `<style>${definition}</style>`;
}
else {
return `<link rel="stylesheet" type="text/css" href="${definition.href}">`;
}
}).join('\n');
const html = `<!DOCTYPE html><html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
${pageStyles}
<style>
html, body {
margin: 0 !important;
padding: 0 !important;
}
html {
overflow: hidden;
}
body {
transform: scale( ${this._options.scaleRatio} );
transform-origin: 0 0;
overflow: visible;
}
.ck.ck-editor__editable_inline {
margin: 0 !important;
border-color: transparent !important;
outline-color: transparent !important;
box-shadow: none !important;
}
.ck.ck-content {
background: white;
}
${boxStyles}
</style>
</head>
<body class="${this._options.extraClasses || ''}"></body>
</html>`;
iframeDocument.open();
iframeDocument.write(html);
iframeDocument.close();
iframeDocument.body.appendChild(domRootClone);
}
}