lightview 1.7.3-b → 1.8.1-b
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/README.md +1 -1
- package/components/chart/chart.html +6 -4
- package/components/chart/example.html +1 -1
- package/components/chart.html +67 -65
- package/components/components.js +10 -2
- package/components/gantt/gantt.html +31 -29
- package/components/gauge/gauge.html +20 -0
- package/components/gauge.html +47 -44
- package/components/orgchart/example.html +1 -1
- package/components/orgchart/orgchart.html +30 -25
- package/components/repl/code-editor.html +64 -0
- package/components/repl/editor.html +37 -0
- package/components/repl/editorjs-inline-tool/index.js +3 -0
- package/components/repl/editorjs-inline-tool/inline-tools.js +28 -0
- package/components/repl/editorjs-inline-tool/tool.js +175 -0
- package/components/repl/repl-with-wysiwyg.html +355 -0
- package/components/repl/repl.html +345 -0
- package/components/repl/sup.js +44 -0
- package/components/repl/wysiwyg-repl.html +258 -0
- package/components/timeline/timeline.html +33 -31
- package/examples/anchor.html +11 -0
- package/examples/chart.html +22 -54
- package/examples/counter.html +5 -3
- package/examples/counter2.html +26 -0
- package/examples/directives.html +19 -17
- package/examples/forgeinform.html +45 -43
- package/examples/form.html +22 -20
- package/examples/gauge.html +2 -0
- package/examples/invalid-template-literals.html +5 -3
- package/examples/message.html +10 -4
- package/examples/nested.html +1 -1
- package/examples/object-bound-form.html +12 -10
- package/examples/remote.html +17 -15
- package/examples/shared.html +41 -0
- package/examples/xor.html +21 -20
- package/lightview.js +107 -72
- package/package.json +7 -2
- package/sites/client.html +48 -0
- package/sites/index.html +247 -0
- package/test/basic.html +15 -13
- package/test/basic.test.mjs +0 -10
- package/test/extended.html +17 -20
- package/types.js +10 -1
- package/unsplash.key +1 -0
- package/components/gauge/guage.html +0 -19
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GenericInlineTool returns an EditorJS.InlineTool capable of wrapping a
|
|
3
|
+
* selected text with any given `tagName`.
|
|
4
|
+
*
|
|
5
|
+
* inspired by
|
|
6
|
+
* @see https://github.com/editor-js/marker/blob/c306bcb33c88eaa3c172eaf387fbcd06ae6b297f/src/index.js
|
|
7
|
+
*/
|
|
8
|
+
var createGenericInlineTool = function (_a) {
|
|
9
|
+
var _b;
|
|
10
|
+
var sanitize = _a.sanitize, shortcut = _a.shortcut, tagName = _a.tagName, toolboxIcon = _a.toolboxIcon;
|
|
11
|
+
return _b = /** @class */ (function () {
|
|
12
|
+
/**
|
|
13
|
+
* @param {{api: object}} - Editor.js API
|
|
14
|
+
*/
|
|
15
|
+
function GenericInlineTool(_a) {
|
|
16
|
+
var api = _a.api;
|
|
17
|
+
this.api = null;
|
|
18
|
+
this.button = null;
|
|
19
|
+
this.tag = null;
|
|
20
|
+
this.iconClasses = null;
|
|
21
|
+
this.api = api;
|
|
22
|
+
/**
|
|
23
|
+
* Toolbar Button
|
|
24
|
+
*
|
|
25
|
+
* @type {HTMLElement|null}
|
|
26
|
+
*/
|
|
27
|
+
this.button = null;
|
|
28
|
+
/**
|
|
29
|
+
* Tag that should is rendered in the editor
|
|
30
|
+
*
|
|
31
|
+
* @type {string}
|
|
32
|
+
*/
|
|
33
|
+
this.tag = tagName;
|
|
34
|
+
/**
|
|
35
|
+
* CSS classes
|
|
36
|
+
*/
|
|
37
|
+
this.iconClasses = {
|
|
38
|
+
base: this.api.styles.inlineToolButton,
|
|
39
|
+
active: this.api.styles.inlineToolButtonActive,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Create button element for Toolbar
|
|
44
|
+
*
|
|
45
|
+
* @return {HTMLButtonElement}
|
|
46
|
+
*/
|
|
47
|
+
GenericInlineTool.prototype.render = function () {
|
|
48
|
+
this.button = document.createElement('button');
|
|
49
|
+
this.button.type = 'button';
|
|
50
|
+
this.button.classList.add(this.iconClasses.base);
|
|
51
|
+
this.button.innerHTML = this.toolboxIcon;
|
|
52
|
+
return this.button;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Wrap/Unwrap selected fragment
|
|
56
|
+
*
|
|
57
|
+
* @param {Range} range - selected fragment
|
|
58
|
+
*/
|
|
59
|
+
GenericInlineTool.prototype.surround = function (range) {
|
|
60
|
+
if (!range) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
var termWrapper = this.api.selection.findParentTag(this.tag);
|
|
64
|
+
/**
|
|
65
|
+
* If start or end of selection is in the highlighted block
|
|
66
|
+
*/
|
|
67
|
+
if (termWrapper) {
|
|
68
|
+
this.unwrap(termWrapper);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
this.wrap(range);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Wrap selection with term-tag
|
|
76
|
+
*
|
|
77
|
+
* @param {Range} range - selected fragment
|
|
78
|
+
*/
|
|
79
|
+
GenericInlineTool.prototype.wrap = function (range) {
|
|
80
|
+
/**
|
|
81
|
+
* Create a wrapper for given tagName
|
|
82
|
+
*/
|
|
83
|
+
var strongElement = document.createElement(this.tag);
|
|
84
|
+
/**
|
|
85
|
+
* SurroundContent throws an error if the Range splits a non-Text node with only one of its boundary points
|
|
86
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Range/surroundContents}
|
|
87
|
+
*
|
|
88
|
+
* // range.surroundContents(span);
|
|
89
|
+
*/
|
|
90
|
+
strongElement.appendChild(range.extractContents());
|
|
91
|
+
range.insertNode(strongElement);
|
|
92
|
+
/**
|
|
93
|
+
* Expand (add) selection to highlighted block
|
|
94
|
+
*/
|
|
95
|
+
this.api.selection.expandToTag(strongElement);
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Unwrap term-tag
|
|
99
|
+
*
|
|
100
|
+
* @param {HTMLElement} termWrapper - term wrapper tag
|
|
101
|
+
*/
|
|
102
|
+
GenericInlineTool.prototype.unwrap = function (termWrapper) {
|
|
103
|
+
/**
|
|
104
|
+
* Expand selection to all term-tag
|
|
105
|
+
*/
|
|
106
|
+
this.api.selection.expandToTag(termWrapper);
|
|
107
|
+
var sel = window.getSelection();
|
|
108
|
+
var range = sel.getRangeAt(0);
|
|
109
|
+
var unwrappedContent = range.extractContents();
|
|
110
|
+
/**
|
|
111
|
+
* Remove empty term-tag
|
|
112
|
+
*/
|
|
113
|
+
termWrapper.parentNode.removeChild(termWrapper);
|
|
114
|
+
/**
|
|
115
|
+
* Insert extracted content
|
|
116
|
+
*/
|
|
117
|
+
range.insertNode(unwrappedContent);
|
|
118
|
+
/**
|
|
119
|
+
* Restore selection
|
|
120
|
+
*/
|
|
121
|
+
sel.removeAllRanges();
|
|
122
|
+
sel.addRange(range);
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* Check and change Term's state for current selection
|
|
126
|
+
*/
|
|
127
|
+
GenericInlineTool.prototype.checkState = function () {
|
|
128
|
+
var termTag = this.api.selection.findParentTag(this.tag);
|
|
129
|
+
this.button.classList.toggle(this.iconClasses.active, !!termTag);
|
|
130
|
+
return !!termTag;
|
|
131
|
+
};
|
|
132
|
+
Object.defineProperty(GenericInlineTool.prototype, "toolboxIcon", {
|
|
133
|
+
/**
|
|
134
|
+
* Get Tool icon's SVG
|
|
135
|
+
* @return {string}
|
|
136
|
+
*/
|
|
137
|
+
get: function () {
|
|
138
|
+
return toolboxIcon;
|
|
139
|
+
},
|
|
140
|
+
enumerable: false,
|
|
141
|
+
configurable: true
|
|
142
|
+
});
|
|
143
|
+
Object.defineProperty(GenericInlineTool, "sanitize", {
|
|
144
|
+
/**
|
|
145
|
+
* Sanitizer rule
|
|
146
|
+
* @return {Object.<string>} {Object.<string>}
|
|
147
|
+
*/
|
|
148
|
+
get: function () {
|
|
149
|
+
return sanitize;
|
|
150
|
+
},
|
|
151
|
+
enumerable: false,
|
|
152
|
+
configurable: true
|
|
153
|
+
});
|
|
154
|
+
Object.defineProperty(GenericInlineTool.prototype, "shortcut", {
|
|
155
|
+
/**
|
|
156
|
+
* Set a shortcut
|
|
157
|
+
*/
|
|
158
|
+
get: function () {
|
|
159
|
+
return shortcut;
|
|
160
|
+
},
|
|
161
|
+
enumerable: false,
|
|
162
|
+
configurable: true
|
|
163
|
+
});
|
|
164
|
+
return GenericInlineTool;
|
|
165
|
+
}()),
|
|
166
|
+
/**
|
|
167
|
+
* Specifies Tool as Inline Toolbar Tool
|
|
168
|
+
*
|
|
169
|
+
* @return {boolean}
|
|
170
|
+
*/
|
|
171
|
+
_b.isInline = true,
|
|
172
|
+
_b;
|
|
173
|
+
};
|
|
174
|
+
export default createGenericInlineTool;
|
|
175
|
+
//# sourceMappingURL=tool.js.map
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>Lightview:Sites</title>
|
|
6
|
+
<script src="https://unpkg.com/@isomorphic-git/lightning-fs"></script>
|
|
7
|
+
<script src="https://unpkg.com/isomorphic-git"></script>
|
|
8
|
+
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
|
9
|
+
<script src="https://unpkg.com/turndown/dist/turndown.js"></script>
|
|
10
|
+
<script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest"></script>
|
|
11
|
+
<script src="https://cdn.jsdelivr.net/npm/@editorjs/header@latest"></script>
|
|
12
|
+
<script src="https://cdn.jsdelivr.net/npm/@editorjs/list@latest"></script>
|
|
13
|
+
<script src="https://cdn.jsdelivr.net/npm/@editorjs/table@latest"></script>
|
|
14
|
+
<script src="https://cdn.jsdelivr.net/npm/@editorjs/embed@latest"></script>
|
|
15
|
+
<script src="https://cdn.jsdelivr.net/npm/editorjs-tooltip@1.1.3/dist/bundle.min.js"></script>
|
|
16
|
+
<script src="https://cdn.jsdelivr.net/npm/editorjs-inline-image@1.1.0/dist/bundle.min.js"></script>
|
|
17
|
+
<script src="https://cdn.jsdelivr.net/npm/@rodrigoodhin/editorjs-image-gallery@0.1.0/dist/bundle.min.js"></script>
|
|
18
|
+
<script src="https://cdn.jsdelivr.net/npm/editorjs-header-with-anchor@2.6.0/dist/bundle.min.js"></script>
|
|
19
|
+
<script src="https://cdn.jsdelivr.net/npm/@editorjs/link@latest"></script>
|
|
20
|
+
<script src="https://cdn.jsdelivr.net/npm/@calumk/editorjs-codeflask@1.0.9/dist/editorjs-codeflask.bundle.min.js"></script>
|
|
21
|
+
<script src="https://cdn.jsdelivr.net/npm/editorjs-github-gist-plugin@1.1.0/dist/main.min.js"></script>
|
|
22
|
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
|
|
23
|
+
<template id="repl">
|
|
24
|
+
|
|
25
|
+
<div id="content" style="flex:auto;min-height:100%;width:750px;max-width:750px;height:100%;border:1px solid;padding:10px;margin:0 auto">
|
|
26
|
+
<div style="display:flex;flex-direction:column;">
|
|
27
|
+
<div id="tabs" style="flex-grow:0;width:100%;border:1px;padding-bottom:5px;text-align:center">
|
|
28
|
+
<span style="padding-right:10px"><label for="headhtml" l-on:click="${onTabClick}">HTML Head</label><input for="headhtml" value="${headhtmlPinned}" type="checkbox" l-on:click="${onPinClick}"></span>
|
|
29
|
+
<span style="padding-right:10px"><label for="wysiwyg" l-on:click="${onTabClick}">WYSIWYG</label><input for="wysiwyg" value="${wysiwygPinned}" type="checkbox" checked l-on:click="${onPinClick}"></span>
|
|
30
|
+
<span style="padding-right:10px"><label for="bodyhtml" l-on:click="${onTabClick}">HTML Body</label><input for="bodyhtml" value="${bodyhtmlPinned}" type="checkbox" l-on:click="${onPinClick}"></span>
|
|
31
|
+
<span style="padding-right:10px"><label for="markdown" l-on:click="${onTabClick}">Markdown (Body)</label><input for="markdown" value="${markdownPinned}" type="checkbox" l-on:click="${onPinClick}"></span>
|
|
32
|
+
<span style="padding-right:10px"><label for="css" l-on:click="${onTabClick}">Style</label><input for="css" value="${cssPinned}" type="checkbox" l-on:click="${onPinClick}"></span>
|
|
33
|
+
<span style="padding-right:10px"><label for="script" l-on:click="${onTabClick}">Script</label><input for="script" value="${scriptPinned}" type="checkbox" l-on:click="${onPinClick}"></span>
|
|
34
|
+
<span style="padding-right:10px"><label for="preview" l-on:click="${onTabClick}">Preview</label><input for="preview" value="${previewPinned}" type="checkbox" l-on:click="${onPinClick}"></span>
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
<div id="wysiwyg" style="max-width:100%;"><slot name="editor"></slot></div>
|
|
38
|
+
<textarea id="headhtml" style="height:200px;max-width:99%;width:99%;margin-right:2px;display:none">${headhtml}</textarea>
|
|
39
|
+
<textarea id="bodyhtml" style="height:200px;max-width:99%;width:99%;margin-right:2px;display:none">${bodyhtml}</textarea>
|
|
40
|
+
<textarea id="markdown" style="height:200px;max-width:99%;width:99%;margin-right:2px;display:none">${markdown}</textarea>
|
|
41
|
+
<textarea id="css" style="height:200px;max-width:99%;width:99%;margin-right:2px;display:none">${cssText}</textarea>
|
|
42
|
+
<textarea id="script" style="height:200px;max-width:99%;width:99%;margin-right:2px;display:none">${scriptText}</textarea>
|
|
43
|
+
<div id="preview" style="max-width:99%;width:99%;margin-right:2px;display:none"></div>
|
|
44
|
+
</div>
|
|
45
|
+
<div style="width:100%;text-align:center">
|
|
46
|
+
<div style="padding:5px">${source}</div>
|
|
47
|
+
<button l-on:click="${doSave}">Save</button>
|
|
48
|
+
<button l-if="${!source.trim().startsWith('http')}" l-on:click="${doReset}">Reset</button>
|
|
49
|
+
</div>
|
|
50
|
+
<style id="style">
|
|
51
|
+
label:hover {
|
|
52
|
+
text-decoration: underline
|
|
53
|
+
}
|
|
54
|
+
</style>
|
|
55
|
+
<script type="lightview/module">
|
|
56
|
+
const turndownService = new TurndownService({headingStyle:"atx",codeBlockStyle:"fenced",emDelimiter:"*"});
|
|
57
|
+
turndownService.keep(() => true);
|
|
58
|
+
|
|
59
|
+
const {html,css,script} = await import("../../types.js");
|
|
60
|
+
self.variables({
|
|
61
|
+
onTabClick:"function",
|
|
62
|
+
onPinClick:"function",
|
|
63
|
+
doSave: "function",
|
|
64
|
+
doReset:"function"
|
|
65
|
+
});
|
|
66
|
+
self.variables({
|
|
67
|
+
wysiwygPinned:"boolean",
|
|
68
|
+
bodyhtmlPinned:"boolean",
|
|
69
|
+
bodyhtml:html,
|
|
70
|
+
markdownPinned:"boolean",
|
|
71
|
+
markdown:html,
|
|
72
|
+
cssPinned:"boolean",
|
|
73
|
+
cssText:css,
|
|
74
|
+
scriptPinned:"boolean",
|
|
75
|
+
scriptText:script,
|
|
76
|
+
headhtmlPinned:"boolean",
|
|
77
|
+
headhtml:html,
|
|
78
|
+
previewPinned:"boolean",
|
|
79
|
+
source:"string",
|
|
80
|
+
},{reactive});
|
|
81
|
+
self.variables({
|
|
82
|
+
src:"string",
|
|
83
|
+
},{imported});
|
|
84
|
+
|
|
85
|
+
bodyhtmlPinned = true;
|
|
86
|
+
|
|
87
|
+
const loadFromFile = async () => {
|
|
88
|
+
const html = await fs.readFile(url.pathname,{encoding:"utf8"});
|
|
89
|
+
source = `IndexedDB://${url.hostname+"_repl"}${url.pathname}`;
|
|
90
|
+
return html;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const loadFromServer = async () => {
|
|
94
|
+
const response = await fetch(url.href);
|
|
95
|
+
const html = await response.text();
|
|
96
|
+
source = url.href;
|
|
97
|
+
return html;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const parseFullHTML = (fullHTML) => {
|
|
101
|
+
const parser = new DOMParser(),
|
|
102
|
+
fragment = parser.parseFromString(fullHTML,"text/html"),
|
|
103
|
+
body_el = fragment?.querySelector("body"),
|
|
104
|
+
style_el = fragment?.querySelector("style"),
|
|
105
|
+
script_el = body_el?.querySelector("script");
|
|
106
|
+
if(style_el) {
|
|
107
|
+
cssText = style_el?.innerHTML;
|
|
108
|
+
style_el.remove();
|
|
109
|
+
} else {
|
|
110
|
+
cssText = "";
|
|
111
|
+
}
|
|
112
|
+
if(script_el) {
|
|
113
|
+
scriptText = script_el?.innerHTML,
|
|
114
|
+
script_el.remove();
|
|
115
|
+
} else {
|
|
116
|
+
scriptText = "";
|
|
117
|
+
}
|
|
118
|
+
headhtml = fragment?.head.innerHTML || "";
|
|
119
|
+
bodyhtml = body_el?.innerHTML;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
let fs,
|
|
123
|
+
url;
|
|
124
|
+
if(src) {
|
|
125
|
+
url = new URL(src,window.location.href);
|
|
126
|
+
fs = new LightningFS(url.hostname+"_repl").promises;
|
|
127
|
+
try {
|
|
128
|
+
parseFullHTML(await loadFromFile());
|
|
129
|
+
} catch(e) {
|
|
130
|
+
try {
|
|
131
|
+
parseFullHTML(await loadFromServer());
|
|
132
|
+
} catch(e) {
|
|
133
|
+
fullHTML = e.message;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
} else {
|
|
137
|
+
url = new URL(window.location.href);
|
|
138
|
+
fs = new LightningFS(url.hostname+"_repl").promises;
|
|
139
|
+
bodyhtml = "";
|
|
140
|
+
headhtml = "";
|
|
141
|
+
scriptText = "";
|
|
142
|
+
cssText = "";
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
// initialize variables
|
|
146
|
+
markdown = "";
|
|
147
|
+
|
|
148
|
+
const tabs = [...self.querySelectorAll("label[for]")]
|
|
149
|
+
.map((label) => {
|
|
150
|
+
const id = label.getAttribute("for");
|
|
151
|
+
return [id,self.getElementById(id),label];
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
const showTab = (targetid) => {
|
|
155
|
+
tabs.forEach(([id,el,label]) => {
|
|
156
|
+
if(id===targetid || self.varsProxy[`${id}Pinned`]) {
|
|
157
|
+
el.style.display = "unset";
|
|
158
|
+
} else if(!self.varsProxy[`${id}Pinned`]) {
|
|
159
|
+
el.style.display = "none";
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
const hideTab = (targetid) => {
|
|
165
|
+
tabs.forEach(([id,el,label]) => {
|
|
166
|
+
if(id===targetid) el.style.display = "none";
|
|
167
|
+
});
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
onTabClick = (event) => {
|
|
171
|
+
showTab(event.target.getAttribute("for"));
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
onPinClick = (event) => {
|
|
175
|
+
const id = event.target.getAttribute("for"),
|
|
176
|
+
checked = self.varsProxy[`${id}Pinned`] = event.target.checked;
|
|
177
|
+
if(checked) onTabClick(event);
|
|
178
|
+
else hideTab(id);
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
doSave = async () => {
|
|
182
|
+
const parts = url.pathname.split("/");
|
|
183
|
+
let dir = "";
|
|
184
|
+
parts.shift();parts.pop();
|
|
185
|
+
for(const part of parts) {
|
|
186
|
+
dir = dir + "/" + part;
|
|
187
|
+
try {
|
|
188
|
+
await fs.mkdir(dir);
|
|
189
|
+
} catch(e) {
|
|
190
|
+
if(e.message==="EEXIST") break;
|
|
191
|
+
throw e;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
fs.writeFile(url.pathname,doPreview(),{encoding:"utf8"},()=>{});
|
|
195
|
+
source = `IndexedDB://${url.hostname+"_repl"}${url.pathname}`;
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
doReset = async () => {
|
|
199
|
+
try {
|
|
200
|
+
await fs.unlink(url.pathname);
|
|
201
|
+
} catch(e) {
|
|
202
|
+
|
|
203
|
+
}
|
|
204
|
+
if(src) {
|
|
205
|
+
try {
|
|
206
|
+
parseFullHTML(await loadFromServer());
|
|
207
|
+
doPreview();
|
|
208
|
+
} catch(e) {
|
|
209
|
+
previewEl.innerHTML = fullHTML = e.message;
|
|
210
|
+
}
|
|
211
|
+
} else {
|
|
212
|
+
bodyhtml = "";
|
|
213
|
+
headhtml = "";
|
|
214
|
+
scriptText = "";
|
|
215
|
+
cssText = "";
|
|
216
|
+
previewEl.innerHTML = "";
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
const doPreview = () => {
|
|
221
|
+
// not quite write, createComponent needs to be reworked to handle a head and import its links
|
|
222
|
+
const template = document.createElement("template");
|
|
223
|
+
template.innerHTML = bodyhtmlEl.value + "<style>" + cssText + "</style>" + '<script type="lightview/module">' + scriptText + "<" + "/script>";
|
|
224
|
+
const component = window.customElements.get("x-preview");
|
|
225
|
+
if(component) { component.setTemplateNode(template); }
|
|
226
|
+
else { Lightview.createComponent("x-preview",template); }
|
|
227
|
+
previewEl.innerHTML = "<x-preview></x-preview>";
|
|
228
|
+
return "<html><head>"+headhtml+"</head><body>"+template.innerHTML+"<body></html>"
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
const wysywigEl = self.getElementById("wysiwyg"),
|
|
232
|
+
markdownEl = self.getElementById("markdown"),
|
|
233
|
+
bodyhtmlEl = self.getElementById("bodyhtml"),
|
|
234
|
+
headhtmlEl = self.getElementById("headhtml"),
|
|
235
|
+
tabsEl = self.getElementById("tabs"),
|
|
236
|
+
styleEl = self.getElementById("style"),
|
|
237
|
+
previewEl = self.getElementById("preview");
|
|
238
|
+
|
|
239
|
+
let prevmarkdown; // prevents indirect recursion
|
|
240
|
+
observe(() => {
|
|
241
|
+
const text = turndownService.turndown(bodyhtml).trim();
|
|
242
|
+
if(text && text!==prevtext) {
|
|
243
|
+
markdown = markdownEl.innerHTML = prevmarkdown = text;
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
let prevbodyhtml; // prevents indirect recursion
|
|
248
|
+
observe(() => {
|
|
249
|
+
const html = marked.parse(markdown).trim();
|
|
250
|
+
if(html && html!==prevbodyhtml) {
|
|
251
|
+
bodyhtml = bodyhtmlEl.innerText = prevbodyhtml = html;
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
const initEditor = () => {
|
|
256
|
+
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
self.addEventListener("connected",() => {
|
|
260
|
+
initEditor();
|
|
261
|
+
doPreview();
|
|
262
|
+
});
|
|
263
|
+
</script>
|
|
264
|
+
</template>
|
|
265
|
+
<script src="../../lightview.js"></script>
|
|
266
|
+
</head>
|
|
267
|
+
<body style="min-height:95vh;">
|
|
268
|
+
<script>Lightview.createComponent("l-repl", document.getElementById("repl"));</script>
|
|
269
|
+
<l-repl style="min-height:95vh" src="../../examples/counter.html"><div id="editor" slot="editor" style="border:solid 1px;max-height:85vh;max-width:740px;overflow:auto;margin-bottom:5px;padding-left:10px;resize:both"></div></l-repl>
|
|
270
|
+
<script type="module">
|
|
271
|
+
//import {Sup} from "./sup.js";
|
|
272
|
+
import createGenericInlineTool,{ItalicInlineTool, UnderlineInlineTool, StrongInlineTool} from "./editorjs-inline-tool/index.js";
|
|
273
|
+
|
|
274
|
+
const LinkToolToolbox = LinkTool.toolbox;
|
|
275
|
+
Object.defineProperty(LinkTool,"toolbox",{get() { return {...LinkToolToolbox,title:"Link With Preview"}}});
|
|
276
|
+
const InlineImageToolbox = InlineImage.toolbox;
|
|
277
|
+
Object.defineProperty(InlineImage,"toolbox",{get() { return {...InlineImageToolbox,title:"Inline Image"}}});
|
|
278
|
+
const editorjsCodeflaskToolbox = editorjsCodeflask.toolbox;
|
|
279
|
+
Object.defineProperty(editorjsCodeflask,"toolbox",{get() { return {...editorjsCodeflaskToolbox,title:"Code"}}});
|
|
280
|
+
|
|
281
|
+
const editor = new EditorJS({
|
|
282
|
+
/**
|
|
283
|
+
* Id of Element that should contain the Editor
|
|
284
|
+
*/
|
|
285
|
+
holder: "editor",
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Available Tools list.
|
|
289
|
+
* Pass Tool's class or Settings object for each Tool you want to use
|
|
290
|
+
*/
|
|
291
|
+
tools: {
|
|
292
|
+
header: Header,
|
|
293
|
+
list: List,
|
|
294
|
+
table: Table,
|
|
295
|
+
embed: Embed,
|
|
296
|
+
linkWithPreview: LinkTool,
|
|
297
|
+
image: {
|
|
298
|
+
class: InlineImage,
|
|
299
|
+
inlineToolbar: true,
|
|
300
|
+
config: {
|
|
301
|
+
embed: {
|
|
302
|
+
display: true,
|
|
303
|
+
},
|
|
304
|
+
unsplash: {
|
|
305
|
+
appName: 'Lightview',
|
|
306
|
+
clientId: 'nRe-dHABvjv2shxyvDFQd3Y9MPni77qBG9ImAVH0wig'
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
},
|
|
310
|
+
imageGallery: ImageGallery,
|
|
311
|
+
sup: {
|
|
312
|
+
class: createGenericInlineTool({
|
|
313
|
+
sanitize: { sup: {} },
|
|
314
|
+
shortcut: "CMD+^",
|
|
315
|
+
tagName:"SUP",
|
|
316
|
+
toolboxIcon: '<i class="fa fa-superscript"></i>'
|
|
317
|
+
})
|
|
318
|
+
},
|
|
319
|
+
sub: {
|
|
320
|
+
class: createGenericInlineTool({
|
|
321
|
+
sanitize: { sub: {} },
|
|
322
|
+
shortcut: "CMD+SHIFT+^",
|
|
323
|
+
tagName:"SUB",
|
|
324
|
+
toolboxIcon: '<i class="fa fa-subscript"></i>'
|
|
325
|
+
})
|
|
326
|
+
},
|
|
327
|
+
code: {
|
|
328
|
+
class: createGenericInlineTool({
|
|
329
|
+
sanitize: { code: {} },
|
|
330
|
+
tagName:"CODE",
|
|
331
|
+
toolboxIcon: '<i class="fa fa-code"></i>'
|
|
332
|
+
})
|
|
333
|
+
},
|
|
334
|
+
gist: Gist,
|
|
335
|
+
precode: editorjsCodeflask,
|
|
336
|
+
i: ItalicInlineTool,
|
|
337
|
+
u: UnderlineInlineTool,
|
|
338
|
+
tooltip: {
|
|
339
|
+
class: Tooltip,
|
|
340
|
+
config: {
|
|
341
|
+
location: 'left',
|
|
342
|
+
highlightColor: '#FFEFD5',
|
|
343
|
+
underline: true,
|
|
344
|
+
backgroundColor: '#154360',
|
|
345
|
+
textColor: '#FDFEFE',
|
|
346
|
+
holder: 'editor',
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
//strong: StrongInlineTool, redundant with bold, which really needs to be replaced
|
|
350
|
+
// https://github.com/hata6502/editorjs-style use as a base for input fields editor
|
|
351
|
+
},
|
|
352
|
+
})
|
|
353
|
+
</script>
|
|
354
|
+
</body>
|
|
355
|
+
</html>
|