@kalebu2468/editor-lessons
Version:
Lesson Tool for Editor.js
292 lines (291 loc) • 12 kB
JavaScript
(function(){"use strict";try{if(typeof document<"u"){var e=document.createElement("style");e.appendChild(document.createTextNode(".ce-lesson{padding:.6em 0 3px;margin:0;line-height:1.25em;outline:none}.ce-lesson p,.ce-lesson div{padding:0!important;margin:0!important}.ce-lesson[contentEditable=true][data-placeholder]:before{position:absolute;content:attr(data-placeholder);color:#707684;font-weight:400;display:none;cursor:text}.ce-lesson[contentEditable=true][data-placeholder]:empty:before{display:block}.ce-lesson[contentEditable=true][data-placeholder]:empty:focus:before{display:none}.ce-example--popup{height:100vh;display:flex;flex-direction:column}.ce-example--popup .ce-example__content{flex-grow:2}.ce-example-popup__overlay{position:fixed;top:0;bottom:0;left:0;right:0;background:#00000085}.ce-example-popup__popup{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:400px;max-width:100%;max-height:90vh;background:white;padding:20px;border-radius:8px;overflow:auto;box-sizing:border-box;display:flex;flex-direction:column;row-gap:16px;height:200px;justify-content:center}.ce-example--popup__input{padding:12px;font-size:15px;color:#757575;width:100%;height:45px;background-color:#f5f5f5;border:none;border-radius:10px}.ce-example--popup__input:focus{border-color:#007bff;outline:none}.ce-example--action__container{display:flex;justify-content:flex-end;column-gap:8px}.ce-example-popup__title{font-size:32px;font-weight:600;color:#333}.ce-example--action__delete{display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;justify-content:center;position:relative;box-sizing:border-box;-webkit-tap-highlight-color:transparent;background-color:transparent;outline:0;margin:0;cursor:pointer;-ms-user-select:none;-webkit-user-select:none;user-select:none;vertical-align:middle;-moz-appearance:none;-webkit-appearance:none;-webkit-text-decoration:none;text-decoration:none;font-family:Roboto,Helvetica,Arial,sans-serif;font-weight:500;font-size:.8125rem;line-height:1.75;letter-spacing:.02857em;text-transform:uppercase;min-width:64px;padding:3px 9px;border-radius:4px;transition:background-color .25s cubic-bezier(.4,0,.2,1) 0ms,box-shadow .25s cubic-bezier(.4,0,.2,1) 0ms,border-color .25s cubic-bezier(.4,0,.2,1) 0ms,color .25s cubic-bezier(.4,0,.2,1) 0ms;border:1px solid rgba(211,47,47,.5);color:#d32f2f}.ce-example--action__ok{display:inline-flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;justify-content:center;position:relative;box-sizing:border-box;-webkit-tap-highlight-color:transparent;background-color:transparent;outline:0;margin:0;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;vertical-align:middle;-moz-appearance:none;-webkit-appearance:none;-webkit-text-decoration:none;text-decoration:none;color:inherit;font-family:Roboto,Helvetica,Arial,sans-serif;font-weight:500;font-size:.8125rem;line-height:1.75;letter-spacing:.02857em;text-transform:uppercase;min-width:64px;border:0px;padding:4px 5px;border-radius:4px;transition:background-color .25s cubic-bezier(.4,0,.2,1) 0ms,box-shadow .25s cubic-bezier(.4,0,.2,1) 0ms,border-color .25s cubic-bezier(.4,0,.2,1) 0ms,color .25s cubic-bezier(.4,0,.2,1) 0ms;color:#1d275a}@media all and (max-width: 730px){.ce-example-popup__popup{top:10px;left:10px;width:calc(100% - 20px);height:calc(100% - 20px);transform:none;max-height:none}}")),document.head.appendChild(e)}}catch(o){console.error("vite-plugin-css-injected-by-js",o)}})();
/**
* Lesson block for the Editor.js.
*
* @author CodeX (team@ifmo.su)
* @copyright CodeX 2018
* @license MIT
* @version 2.0.0
*/
class p {
/**
* Render plugin`s main Element and fill it with saved data
*
* @param {{data: LessonData, config: LessonConfig, api: object}}
* data — previously saved data
* config - user config for Tool
* api - Editor.js API
*/
constructor({ data: e, config: t, api: n, readOnly: s }) {
this.api = n, this.readOnly = s, this._CSS = {
block: this.api.styles.block,
wrapper: "ce-lesson"
}, this._settings = t, this._data = this.normalizeData(e), this._element = null;
}
/**
* Normalize input data
*
* @param {LessonData} data - saved data to process
*
* @returns {LessonData}
* @private
*/
normalizeData(e) {
const t = {};
return typeof e != "object" && (e = {}), t.text = e.text || "", t.level = parseInt(e.level) || this.defaultLevel.number, t;
}
/**
* Return Tool's view
*
* @returns {HTMLLessonElement}
* @public
*/
render() {
return this._element = this.getTag(), this._element;
}
/**
* Method that specified how to merge two Text blocks.
* Called by Editor.js by backspace at the beginning of the Block
*
* @param {LessonData} data - saved data to merger with current block
* @public
*/
merge(e) {
const t = {
text: this.data.text + e.text,
level: this.data.level
};
this.data = t;
}
/**
* Validate Text block data:
* - check for emptiness
*
* @param {LessonData} blockData — data received after saving
* @returns {boolean} false if saved data is not correct, otherwise true
* @public
*/
validate(e) {
return e.text.trim() !== "";
}
/**
* Extract Tool's data from the view
*
* @param {HTMLLessonElement} toolsContent - Text tools rendered view
* @returns {LessonData} - saved data
* @public
*/
save(e) {
return {
text: e.innerHTML || " ",
level: this.currentLevel.number
};
}
/**
* Allow Lesson to be converted to/from other blocks
*/
static get conversionConfig() {
return {
export: "text",
// use 'text' property for other blocks
import: "text"
// fill 'text' property from other block's export string
};
}
/**
* Sanitizer Rules
*/
static get sanitize() {
return {
level: !1,
text: {}
};
}
/**
* Returns true to notify core that read-only is supported
*
* @returns {boolean}
*/
static get isReadOnlySupported() {
return !0;
}
/**
* Get current Tools`s data
*
* @returns {LessonData} Current data
* @private
*/
get data() {
return this._data.text = this._element.innerHTML, this._data.level = this.currentLevel.number, this._data;
}
/**
* Store data in plugin:
* - at the this._data property
* - at the HTML
*
* @param {LessonData} data — data to set
* @private
*/
set data(e) {
if (this._data = this.normalizeData(e), e.level !== void 0 && this._element.parentNode) {
const t = this.getTag();
t.innerHTML = this._element.innerHTML, this._element.parentNode.replaceChild(t, this._element), this._element = t;
}
e.text !== void 0 && (this._element.innerHTML = this._data.text || "");
}
createPopUp() {
const e = document.createElement("div");
e.classList.add(
"ce-example__content",
"ce-example__content--with-bg",
"_ce-example__content--small"
);
const t = document.createElement("div");
t.classList.add("ce-example-popup");
const n = document.createElement("div");
n.classList.add("ce-example-popup__overlay"), t.appendChild(n);
const s = document.createElement("div");
s.classList.add("ce-example-popup__popup");
const i = document.createElement("div");
i.classList.add("ce-example-popup__title"), i.textContent = "Create a Lesson", s.appendChild(i);
const l = document.createElement("input");
l.classList.add("ce-example--popup__input"), s.appendChild(l), l.placeholder = "Lesson Title";
const a = document.createElement("div");
a.classList.add("ce-example--action__container");
const o = document.createElement("button");
o.classList.add("ce-example--action__ok"), o.textContent = "OK", a.appendChild(o), o.addEventListener("click", () => {
const c = l.value;
c ? this.data = { text: c, level: this.currentLevel } : this.api.blocks.delete(this.api.blocks.getCurrentBlockIndex()), e.remove();
});
const r = document.createElement("button");
r.classList.add("ce-example--action__delete"), r.textContent = "Cancel", a.appendChild(r), r.addEventListener("click", function() {
e.remove();
}), s.appendChild(a), t.appendChild(s), e.appendChild(t), document.body.appendChild(e);
}
/**
* Get tag for target level
* By default returns second-leveled Lesson
*
* @returns {HTMLElement}
*/
getTag() {
if (this._data.text) {
const e = document.createElement(this.currentLevel.tag);
return e.innerHTML = this._data.text || "", e.classList.add(this._CSS.wrapper), e.dataset.placeholder = this.api.i18n.t(
this._settings.placeholder || ""
), e.contentEditable = this.readOnly ? "false" : "true", e;
} else {
this.createPopUp();
const e = document.createElement("DIV");
return e.innerHTML = "", e;
}
}
/**
* Get current level
*
* @returns {level}
*/
get currentLevel() {
let e = this.levels.find(
(t) => t.number === this._data.level
);
return e || (e = this.defaultLevel), e;
}
/**
* Return default level
*
* @returns {level}
*/
get defaultLevel() {
if (this._settings.defaultLevel) {
const e = this.levels.find((t) => t.number === this._settings.defaultLevel);
if (e)
return e;
console.warn(
"(ง'̀-'́)ง Lesson Tool: the default level specified was not found in available levels"
);
}
return this.levels[0];
}
/**
* @typedef {object} level
* @property {number} number - level number
* @property {string} tag - tag corresponds with level number
* @property {string} svg - icon
*/
/**
* Available lesson levels
*
* @returns {level[]}
*/
get levels() {
const e = [
{
number: 2,
tag: "H2",
svg: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 7 4 4 20 4 20 7"></polyline><line x1="9" y1="20" x2="15" y2="20"></line><line x1="12" y1="4" x2="12" y2="20"></line></svg>'
}
];
return this._settings.levels ? e.filter((t) => this._settings.levels.includes(t.number)) : e;
}
/**
* Handle H1-H6 tags on paste to substitute it with lesson Tool
*
* @param {PasteEvent} event - event with pasted content
*/
onPaste(e) {
const t = e.detail.data;
let n = this.defaultLevel.number;
switch (t.tagName) {
case "H1":
n = 1;
break;
case "H2":
n = 2;
break;
case "H3":
n = 3;
break;
case "H4":
n = 4;
break;
case "H5":
n = 5;
break;
case "H6":
n = 6;
break;
}
this._settings.levels && (n = this._settings.levels.reduce((s, i) => Math.abs(i - n) < Math.abs(s - n) ? i : s)), this.data = {
level: n,
text: t.innerHTML
};
}
/**
* Used by Editor.js paste handling API.
* Provides configuration to handle H1-H6 tags.
*
* @returns {{handler: (function(HTMLElement): {text: string}), tags: string[]}}
*/
static get pasteConfig() {
return {
tags: ["H2"]
};
}
/**
* Get Tool toolbox settings
* icon - Tool icon's SVG
* title - title to show in toolbox
*
* @returns {{icon: string, title: string}}
*/
static get toolbox() {
return {
icon: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 7 4 4 20 4 20 7"></polyline><line x1="9" y1="20" x2="15" y2="20"></line><line x1="12" y1="4" x2="12" y2="20"></line></svg>',
title: "Lessons"
};
}
}
export {
p as default
};