tex-editor 1.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 ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024 Marcello Violini (marcellov7)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,233 @@
1
+ <img src="images/tex_logo.png" width="250" alt="Logo">
2
+
3
+ TEX is a ultra-lightweight and straightforward JavaScript library for creating rich text editors (WYSIWYG) directly in the browser. It is designed to work with both `<textarea>` and `<div>` elements.
4
+
5
+ > Live demo: [https://codepen.io/marcellov7/pen/BabGydp](https://codepen.io/marcellov7/pen/BabGydp)
6
+
7
+ ## Key Features
8
+
9
+ - Pure JavaScript, no dependencies, written in ES6.
10
+ - Simple and intuitive user interface.
11
+ - Wide selection of predefined buttons for text formatting.
12
+ - Support for inserting HTML directly into the editor.
13
+ - Support for plugins.
14
+ - Easily Customizable themes to fit your website design.
15
+ - Ultra lightweight and fast.
16
+ - Light and dark mode.
17
+
18
+ [![Live demo](/images/screenshot.jpg?raw=true "Demo")](/images/screenshot.jpg)
19
+
20
+ ## Comparisons
21
+
22
+ | library | size (min+gzip) | size (min) | jquery | bootstrap | react | link |
23
+ |---------------|-----------------|------------|--------|-----------|-------|------|
24
+ | TEX | 2.3kB | 6.3kB | | | | https://github.com/marcellov7/tex |
25
+ | quill | 43kB | 205kB | | | | https://github.com/quilljs/quill |
26
+ | trix | 47kB | 204kB | | | | https://github.com/basecamp/trix |
27
+ | ckeditor | 163kB | 551kB | | | | https://ckeditor.com |
28
+ | trumbowyg | 8kB | 23kB | x | | | https://github.com/Alex-D/Trumbowyg |
29
+ | summernote | 26kB | 93kB | x | x | | https://github.com/summernote/summernote |
30
+ | froala | 52kB | 186kB | x | | | https://github.com/froala/wysiwyg-editor |
31
+ | tinymce | 157kB | 491kB | x | | | https://github.com/tinymce/tinymce |
32
+
33
+ ## How to Use TEX
34
+
35
+ You can use TEX either via a `<script>` tag (CDN) or by installing it from npm.
36
+
37
+ ### Option 1 — CDN / `<script>` tag
38
+
39
+ 1. Link TEX to your HTML:
40
+ ```html
41
+ <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/marcellov7/tex@main/src/tex.min.css">
42
+ <script src="https://cdn.jsdelivr.net/gh/marcellov7/tex@main/src/tex.min.js"></script>
43
+ ```
44
+ The library is then available as the global `window.tex`.
45
+
46
+ ### Option 2 — npm (bundlers, React, Vue, etc.)
47
+
48
+ ```bash
49
+ npm install tex-editor
50
+ ```
51
+ ```javascript
52
+ import tex from 'tex-editor'
53
+ // don't forget the stylesheet:
54
+ import 'tex-editor/src/tex.css'
55
+ ```
56
+
57
+ Then add HTML elements where you want to display the text editors:
58
+
59
+ ```html
60
+ <div id="editor">Hello</div>
61
+ <!--or-->
62
+ <textarea id="editor">Hello</textarea>
63
+ ```
64
+
65
+ ## Usage
66
+
67
+ ### Initialization
68
+
69
+ To initialize TEX, use the `tex.init()` method, passing in an object with the desired settings. Here's how you can do it:
70
+
71
+ ```javascript
72
+ const tex = window.tex;
73
+
74
+ tex.init({
75
+ element: document.getElementById("editor"),
76
+ buttons: ['bold', 'italic', 'underline', 'textColor', 'heading1', 'heading2', 'paragraph', 'removeFormat', 'olist', 'ulist', 'code', 'line', 'link', 'image', 'html'],
77
+ onChange: (content) => {
78
+ console.log("Editor :", content);
79
+ }
80
+ });
81
+ ```
82
+
83
+ ### API
84
+ ```javascript
85
+ // ES6 (after `npm install tex-editor`)
86
+ import tex from 'tex-editor'
87
+ // or
88
+ import { exec, init, destroy, getContent, setContent } from 'tex-editor'
89
+ ```
90
+
91
+ ### Parameters
92
+
93
+ - `element`: The HTML element (either `<textarea>` or `<div>`) to be converted into a text editor.
94
+ - `buttons`: An array of buttons to be displayed in the editor toolbar.
95
+ - `plugins`: An array of plugins.
96
+ - `paragraphSeparator` : 'p', // optional, default = 'div'
97
+ - `cssStyle`: false | true, // Outputs <span style="font-weight: bold;"></span> instead of <b></b>
98
+ - `theme`: 'dark' | default (light),
99
+ - `onChange`: A callback function to be executed when the content of the editor changes.
100
+
101
+ ### Get Content
102
+ ```javascript
103
+ tex.getContent(document.getElementById("editor"));
104
+ ```
105
+ ### Set Content
106
+ ```javascript
107
+ tex.setContent(document.getElementById("editor"), "<p>Text in <strong>HTML</strong> format</p>")
108
+ ```
109
+ ### Exec
110
+ ```javascript
111
+ // Execute a document command.
112
+ // Reference: https://developer.mozilla.org/en/docs/Web/API/Document/execCommand
113
+ tex.exec(command<string>, value<string>)
114
+ ```
115
+
116
+ ### Destroy
117
+ ```javascript
118
+ tex.destroy(document.getElementById("editor"));
119
+ ```
120
+
121
+ ## Usage in React
122
+
123
+ TEX works on a real DOM node, so in React you initialize it inside `useEffect`
124
+ using a `ref`, and tear it down in the cleanup function.
125
+
126
+ ```jsx
127
+ import { useEffect, useRef } from 'react'
128
+ import tex from 'tex-editor'
129
+ import 'tex-editor/src/tex.css'
130
+
131
+ export default function TexEditor({ value = '', onChange }) {
132
+ const ref = useRef(null)
133
+
134
+ useEffect(() => {
135
+ const element = ref.current
136
+ tex.init({
137
+ element,
138
+ buttons: ['bold', 'italic', 'underline', 'heading1', 'link', 'html'],
139
+ theme: 'light',
140
+ onChange,
141
+ })
142
+ if (value) tex.setContent(element, value)
143
+
144
+ return () => tex.destroy(element)
145
+ }, [])
146
+
147
+ // The element MUST have a unique `id` — TEX uses it internally.
148
+ return <div id="my-tex-editor" ref={ref} />
149
+ }
150
+ ```
151
+
152
+ > Run `tex.init` only once (empty dependency array). Use `tex.setContent` /
153
+ > `tex.getContent` to read or update the content afterwards. The target element
154
+ > must have a unique `id`, since TEX relies on it to manage the editor instance.
155
+
156
+ ### List of predefined buttons
157
+
158
+ - fontSize
159
+ - bold
160
+ - italic
161
+ - underline
162
+ - strikethrough
163
+ - heading1
164
+ - heading2
165
+ - paragraph
166
+ - removeFormat
167
+ - quote
168
+ - olist
169
+ - ulist
170
+ - code
171
+ - line
172
+ - link
173
+ - image
174
+ - html
175
+ - textColor
176
+ - textBackColor
177
+ - indent
178
+ - outdent
179
+ - undo
180
+ - redo
181
+ - justifyCenter
182
+ - justifyFull
183
+ - justifyLeft
184
+ - justifyRight
185
+
186
+ ## Plugins
187
+ > Plugin demo: [https://codepen.io/marcellov7/pen/poYqEMV](https://codepen.io/marcellov7/pen/poYqEMV)
188
+
189
+ ```js
190
+ var pluginImageUpload = {
191
+ name: 'pluginImageUpload',
192
+ icon: '-↑-',
193
+ title: 'Image Upload',
194
+ result: function(res) {
195
+ //Example function to display an input and upload the image.
196
+ }
197
+ };
198
+ ```
199
+
200
+ Initialise the button in the position you want and the plugin, like this:
201
+ ```js
202
+ tex.init({
203
+ element: document.getElementById("editor"),
204
+ buttons: ['pluginImageUpload', 'bold', 'fontSize', 'bold', 'italic'],
205
+ plugins: [pluginImageUpload],
206
+ onChange: () => {
207
+ }
208
+ });
209
+ ```
210
+
211
+ ## Styles
212
+ For example:
213
+ If you want to change the height of the editor after the DOM has been initialized, you can do so by targeting the ".tex-content" class and adjusting the height property in your CSS file.
214
+
215
+ ```css
216
+ .tex-content {
217
+ height: 400px;
218
+ }
219
+ ```
220
+
221
+ ## Contributing
222
+
223
+ If you'd like to contribute to TEX, follow these steps:
224
+
225
+ 1. Fork this repository.
226
+ 2. Create a new branch for your changes: `git checkout -b feature/new-feature`.
227
+ 3. Commit your changes: `git commit -am 'Add new feature'`.
228
+ 4. Push your branch: `git push origin feature/new-feature`.
229
+ 5. Submit a pull request for your changes.
230
+
231
+ ## License
232
+
233
+ TEX is released under the [MIT License](LICENSE).
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "tex-editor",
3
+ "version": "1.0.0",
4
+ "description": "Ultra-lightweight WYSIWYG rich text editor in pure JavaScript, no dependencies. Works with both <textarea> and <div> elements.",
5
+ "main": "src/tex.js",
6
+ "unpkg": "src/tex.js",
7
+ "jsdelivr": "src/tex.js",
8
+ "style": "src/tex.css",
9
+ "files": [
10
+ "src",
11
+ "README.md",
12
+ "LICENSE"
13
+ ],
14
+ "keywords": [
15
+ "wysiwyg",
16
+ "editor",
17
+ "rich-text",
18
+ "rte",
19
+ "contenteditable",
20
+ "textarea",
21
+ "lightweight",
22
+ "no-dependencies"
23
+ ],
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://github.com/marcellov7/tex.git"
27
+ },
28
+ "homepage": "https://github.com/marcellov7/tex#readme",
29
+ "bugs": {
30
+ "url": "https://github.com/marcellov7/tex/issues"
31
+ },
32
+ "author": "Marcello Violini (marcellov7)",
33
+ "license": "MIT"
34
+ }
package/src/tex.css ADDED
@@ -0,0 +1,91 @@
1
+ .tex-container {
2
+ border: 1px solid #efefef;
3
+ box-sizing: border-box;
4
+ border-radius: 4px;
5
+ overflow: hidden;
6
+ }
7
+
8
+ .tex-container.theme-dark {
9
+ border-color: #383838;
10
+ }
11
+
12
+ .tex-content, .htmlContent {
13
+ box-sizing: border-box;
14
+ background-color: #fff;
15
+ height: 300px;
16
+ width: 100%;
17
+ outline: 0;
18
+ overflow-y: auto;
19
+ padding: 10px;
20
+ }
21
+
22
+ .theme-dark .tex-content, .theme-dark .htmlContent {
23
+ background-color: #10131a;
24
+ color: white;
25
+ }
26
+
27
+ .tex-actionbar {
28
+ background-color: #FFF;
29
+ border-bottom: 1px solid #efefef;
30
+ padding:5px;
31
+ }
32
+ .theme-dark .tex-actionbar {
33
+ background-color: #10131a;
34
+ border-color: #383838;
35
+ }
36
+
37
+ .tex-button {
38
+ position: relative;
39
+ background-color: #f7f7f7;
40
+ border: none;
41
+ cursor: pointer;
42
+ height: 30px;
43
+ outline: 0;
44
+ min-width: 30px;
45
+ vertical-align: bottom;
46
+ color: #000;
47
+ margin-right: 3px;
48
+ border-radius: 4px;
49
+ border-bottom: 1px solid lightgray;
50
+ }
51
+
52
+ .theme-dark .tex-button {
53
+ background-color: #181d27;
54
+ color: #ffF;
55
+ border-bottom: 1px solid #383838;
56
+ }
57
+
58
+ .tex-button:hover{
59
+ background-color: #f2f2f2;
60
+ }
61
+
62
+ .theme-dark .tex-button:hover{
63
+ background-color: #353434;
64
+ }
65
+
66
+ .tex-button-selected {
67
+ background-color: #F0F0F0;
68
+ }
69
+
70
+ .tex-modal{
71
+ position: absolute;
72
+ background-color: white;
73
+ border: 1px solid #ccc;
74
+ padding:5px;
75
+ }
76
+
77
+ .tex-button > *:nth-child(2) {
78
+ position: absolute;
79
+ top: 0;
80
+ left: 0;
81
+ opacity: 0;
82
+ height: 30px;
83
+ width: 30px;
84
+ -webkit-appearance: none;
85
+ -moz-appearance: none;
86
+ appearance: none;
87
+ background: transparent;
88
+ cursor: pointer;
89
+ border: 0;
90
+ padding: 0;
91
+ }
package/src/tex.js ADDED
@@ -0,0 +1,406 @@
1
+ (function (global, factory) {
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3
+ typeof define === 'function' && define.amd ? define(['exports'], factory) :
4
+ factory((global.tex = {}));
5
+ }(this, (function (exports) { 'use strict'
6
+
7
+ var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key] } } } return target }
8
+
9
+ var colorPicker = function(button, type) {
10
+ var input = button.querySelector('input[type="color"]')
11
+ input = document.createElement('input')
12
+ input.type = 'color'
13
+ input.style.display = 'block'
14
+ button.appendChild(input)
15
+ input.addEventListener('input', () => {
16
+ exec(type, input.value)
17
+ if (type == "textColor") {
18
+ button.querySelector('span').style.color = input.value
19
+ exec('foreColor', input.value)
20
+ }
21
+ if (type == "textBackColor") {
22
+ button.querySelector('#textBackColor').style.background = input.value
23
+ exec('backColor', input.value)
24
+ }
25
+ })
26
+
27
+ return false
28
+ }
29
+
30
+ var selectOptions = function(button) {
31
+ var input = button.querySelector('select')
32
+ input = document.createElement('select')
33
+ const fontSizes = [3, 4, 5, 6, 7]
34
+ fontSizes.forEach(size => {
35
+ const option = document.createElement('option')
36
+ option.value = size
37
+ option.textContent = size
38
+ input.appendChild(option)
39
+ })
40
+ button.appendChild(input)
41
+ input.addEventListener('change', () => {
42
+ exec('fontSize', input.value)
43
+ })
44
+ return false
45
+ }
46
+
47
+ var paragraphSeparatorString = 'defaultParagraphSeparator'
48
+ var formatBlock = 'formatBlock'
49
+ var addEventListener = function addEventListener(parent, type, listener) {
50
+ return parent.addEventListener(type, listener)
51
+ }
52
+ var appendChild = function appendChild(parent, child) {
53
+ return parent.appendChild(child)
54
+ }
55
+ var createElement = function createElement(tag) {
56
+ return document.createElement(tag)
57
+ }
58
+ var queryCommandState = function queryCommandState(command) {
59
+ return document.queryCommandState(command)
60
+ }
61
+ var queryCommandValue = function queryCommandValue(command) {
62
+ return document.queryCommandValue(command)
63
+ }
64
+
65
+ var exec = function exec(command) {
66
+ var value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null
67
+ return document.execCommand(command, false, value)
68
+ }
69
+
70
+ var defaultActions = {
71
+ fontSize: {
72
+ icon: '🗚',
73
+ title: 'Font Size',
74
+ result: () => {}
75
+ },
76
+ bold: {
77
+ icon: '<b>B</b>',
78
+ title: 'Bold',
79
+ state: () => queryCommandState('bold'),
80
+ result: () => exec('bold')
81
+ },
82
+ italic: {
83
+ icon: '<i>I</i>',
84
+ title: 'Italic',
85
+ state: () => queryCommandState('italic'),
86
+ result: () => exec('italic')
87
+ },
88
+ underline: {
89
+ icon: '<u>U</u>',
90
+ title: 'Underline',
91
+ state: () => queryCommandState('underline'),
92
+ result: () => exec('underline')
93
+ },
94
+ removeFormat: {
95
+ icon: '⌫',
96
+ title: 'Remove Format',
97
+ result: () => exec('removeFormat')
98
+ },
99
+ strikethrough: {
100
+ icon: '<strike>S</strike>',
101
+ title: 'Strike-through',
102
+ state: () => queryCommandState('strikeThrough'),
103
+ result: () => exec('strikeThrough')
104
+ },
105
+ heading1: {
106
+ icon: '<b>H<sub>1</sub></b>',
107
+ title: 'Heading 1',
108
+ result: () => exec(formatBlock, '<h1>')
109
+ },
110
+ heading2: {
111
+ icon: '<b>H<sub>2</sub></b>',
112
+ title: 'Heading 2',
113
+ result: () => exec(formatBlock, '<h2>')
114
+ },
115
+ paragraph: {
116
+ icon: '&#182;',
117
+ title: 'Paragraph',
118
+ result: () => exec(formatBlock, '<p>')
119
+ },
120
+ quote: {
121
+ icon: '&#8220; &#8221;',
122
+ title: 'Quote',
123
+ result: () => exec(formatBlock, '<blockquote>')
124
+ },
125
+ olist: {
126
+ icon: '&#35;',
127
+ title: 'Ordered List',
128
+ result: () => exec('insertOrderedList')
129
+ },
130
+ ulist: {
131
+ icon: '&#8226;',
132
+ title: 'Unordered List',
133
+ result: () => exec('insertUnorderedList')
134
+ },
135
+ code: {
136
+ icon: '&lt;/&gt;',
137
+ title: 'Code',
138
+ result: () => exec(formatBlock, '<pre>')
139
+ },
140
+ line: {
141
+ icon: '&#8213;',
142
+ title: 'Horizontal Line',
143
+ result: () => exec('insertHorizontalRule')
144
+ },
145
+ link: {
146
+ icon: '&#128279;',
147
+ title: 'Link',
148
+ result: () => {
149
+ const url = window.prompt('Enter the link URL')
150
+ if (url) exec('createLink', url)
151
+ }
152
+ },
153
+ image: {
154
+ icon: 'Img',
155
+ title: 'Image',
156
+ result: () => {
157
+ const url = window.prompt('Enter the image URL')
158
+ if (url) exec('insertImage', url)
159
+ }
160
+ },
161
+ html: {
162
+ icon: 'HTML',
163
+ title: 'Html',
164
+ result: ({ content }) => {
165
+ const parentElement = content.parentNode
166
+ const htmlContentElement = parentElement.querySelector('.htmlContent')
167
+ const elementContentElement = parentElement.querySelector('.tex-content')
168
+
169
+ if (htmlContentElement) {
170
+ if (htmlContentElement.style.display === 'none') {
171
+ htmlContentElement.style.display = 'block'
172
+ elementContentElement.style.display = 'none'
173
+ } else {
174
+ htmlContentElement.style.display = 'none'
175
+ elementContentElement.style.display = 'block'
176
+ }
177
+ }
178
+ }
179
+ },
180
+ textColor: {
181
+ icon: 'A',
182
+ title: 'Text Color',
183
+ result: () => {}
184
+ },
185
+ textBackColor: {
186
+ icon: '<span id="textBackColor" style="padding:3px; background:lightgray;">A</span>',
187
+ title: 'Text Color',
188
+ result: () => {}
189
+ },
190
+ indent: {
191
+ icon: '&rsaquo;',
192
+ title: 'Indent',
193
+ result: () => exec('indent')
194
+ },
195
+ outdent: {
196
+ icon: '&lsaquo;',
197
+ title: 'Outdent',
198
+ result: () => exec('outdent')
199
+ },
200
+ undo: {
201
+ icon: '↶',
202
+ title: 'Undo',
203
+ result: () => exec('undo')
204
+ },
205
+ redo: {
206
+ icon: '↷',
207
+ title: 'Redo',
208
+ result: () => exec('redo')
209
+ },
210
+ justifyCenter: {
211
+ icon: '⇥⇤',
212
+ title: 'Justify Center',
213
+ result: () => exec('justifyCenter')
214
+ },
215
+ justifyFull: {
216
+ icon: '⇤⇥',
217
+ title: 'Justify Full',
218
+ result: () => exec('justifyFull')
219
+ },
220
+ justifyLeft: {
221
+ icon: '⇤',
222
+ title: 'Justify Left',
223
+ result: () => exec('justifyLeft')
224
+ },
225
+ justifyRight: {
226
+ icon: '⇥',
227
+ title: 'Justify Right',
228
+ result: () => exec('justifyRight')
229
+ }
230
+ }
231
+
232
+ var destroy = el => {
233
+ var element = document.querySelector(`[tex-id="${el.id}"]`)
234
+ var elementBase = document.getElementById(el.id)
235
+ var content = element.querySelector('.tex-content')
236
+ var actionbar = element.querySelector('.tex-actionbar')
237
+ if (element) {
238
+ var contentClone = content.cloneNode(true)
239
+ content.parentNode.replaceChild(contentClone, content)
240
+
241
+ var actionbarClone = actionbar.cloneNode(true)
242
+ actionbar.parentNode.replaceChild(actionbarClone, actionbar)
243
+
244
+ actionbarClone.remove()
245
+
246
+ if (elementBase.tagName.toLowerCase() === 'textarea') {
247
+ elementBase.style.display = 'block'
248
+ element.remove()
249
+ } else {
250
+ element.innerHTML = contentClone.innerHTML
251
+ element.removeAttribute("tex-id")
252
+ element.classList.remove("theme-light", "theme-dark", "tex-container")
253
+ }
254
+ }
255
+ }
256
+
257
+ var getContent = el => {
258
+ const element = document.querySelector(`[tex-id="${el.id}"]`)
259
+ const content = element.querySelector('.tex-content')
260
+ return content.innerHTML
261
+ }
262
+ var setContent = (el, content) => {
263
+ const element = document.querySelector(`[tex-id="${el.id}"]`)
264
+ const contentElement = element.querySelector('.tex-content')
265
+ contentElement.innerHTML = content
266
+ element.querySelector('.htmlContent').value = content
267
+ el.value = content
268
+ if (element.texOnChange) element.texOnChange(content)
269
+ }
270
+
271
+ var init = settings => {
272
+ var theme = settings.theme || 'light'
273
+ var paragraphSeparator = settings[paragraphSeparatorString] || 'div'
274
+ var editorContainer = createElement('div')
275
+ editorContainer.className = 'tex-container'
276
+ editorContainer.classList.add(`theme-${theme}`)
277
+ editorContainer.setAttribute("tex-id", settings.element.id)
278
+ editorContainer.texOnChange = settings.onChange
279
+ var actionbar = createElement('div')
280
+ actionbar.className = 'tex-actionbar'
281
+ appendChild(editorContainer, actionbar)
282
+
283
+ var content = settings.element.content = createElement('div')
284
+ content.contentEditable = true
285
+ content.className = 'tex-content tex-editor'
286
+
287
+ if (settings.element.tagName.toLowerCase() === 'textarea') {
288
+ content.innerHTML = settings.element.value
289
+ } else {
290
+ content.innerHTML = settings.element.innerHTML
291
+ }
292
+
293
+ content.onkeydown = event => {
294
+ if (event.key === 'Enter' && queryCommandValue(formatBlock) === 'blockquote') {
295
+ setTimeout(() => exec(formatBlock, `<${paragraphSeparator}>`), 0)
296
+ }
297
+ }
298
+ appendChild(editorContainer, content)
299
+ settings.element.parentNode.insertBefore(editorContainer, settings.element.nextSibling);
300
+
301
+ let actions = []
302
+
303
+ if (settings.buttons) {
304
+
305
+ if (settings.plugins) {
306
+ console.log(settings.plugins)
307
+ settings.plugins.forEach(function(plugin) {
308
+ defaultActions[plugin.name] = plugin
309
+ })
310
+ }
311
+
312
+ actions = settings.buttons.map(buttonKey => {
313
+ var defaultAction = defaultActions[buttonKey]
314
+ if (defaultAction) {
315
+ return { icon: defaultAction.icon, title: defaultAction.title, key: buttonKey, result: defaultAction.result }
316
+ }
317
+ }).filter(action => action !== undefined)
318
+ } else if (settings.actions) {
319
+ actions = settings.actions.map(action => {
320
+ if (typeof action === 'string') return defaultActions[action]
321
+ else if (action.name === 'custom') return { icon: action.icon, title: action.title, result: action.result }
322
+ else if (defaultActions[action.name]) return { ...defaultActions[action.name], ...action }
323
+ return action
324
+ })
325
+ }
326
+
327
+ actions.forEach(action => {
328
+ var button = createElement('button')
329
+ button.className = 'tex-button'
330
+ button.innerHTML = "<span>"+action.icon+"</span>"
331
+ button.title = action.title
332
+ button.setAttribute('type', 'button')
333
+ button.onclick = () => action.result({action, content, button}) && content.focus()
334
+
335
+ if (action.state) {
336
+ var handler = () => button.classList[action.state() ? 'add' : 'remove']('tex-button-selected')
337
+ addEventListener(content, 'keyup', handler)
338
+ addEventListener(content, 'mouseup', handler)
339
+ addEventListener(button, 'click', handler)
340
+ }
341
+
342
+ appendChild(actionbar, button)
343
+
344
+ if(action.key == 'fontSize'){
345
+ selectOptions(button)
346
+ }
347
+ if(action.key=='textColor'){
348
+ colorPicker(button, 'textColor')
349
+ }
350
+ if(action.key=='textBackColor'){
351
+ colorPicker(button, 'textBackColor')
352
+ }
353
+
354
+ })
355
+
356
+ if (settings.cssStyle) exec('styleWithCSS')
357
+ exec(paragraphSeparatorString, paragraphSeparator)
358
+
359
+ if (settings.element.tagName.toLowerCase() === 'textarea') {
360
+ settings.element.style.display = 'none'
361
+ } else {
362
+ document.getElementById(settings.element.id).remove()
363
+ editorContainer.id = settings.element.id
364
+ }
365
+
366
+ var htmlContent = createElement('textarea')
367
+ htmlContent.setAttribute('class', 'htmlContent')
368
+ appendChild(editorContainer, htmlContent)
369
+
370
+ htmlContent.value = content.innerHTML
371
+ htmlContent.style.display = 'none'
372
+
373
+ content.oninput = ({ target: { firstChild } }) => {
374
+ if (firstChild && firstChild.nodeType === 3) exec(formatBlock, `<${paragraphSeparator}>`)
375
+ else if (content.innerHTML === '<br>') content.innerHTML = ''
376
+
377
+ settings.onChange(content.innerHTML)
378
+
379
+ if (settings.element.tagName.toLowerCase() === 'textarea') {
380
+ settings.element.value = content.innerHTML
381
+ }
382
+
383
+ htmlContent.value = content.innerHTML
384
+ }
385
+
386
+ htmlContent.oninput = ({ target: { firstChild } }) => {
387
+ content.innerHTML = htmlContent.value
388
+ settings.element.value = content.innerHTML
389
+ settings.onChange(content.innerHTML)
390
+ }
391
+
392
+ return settings.element
393
+ }
394
+
395
+ var tex = { exec: exec, init: init, destroy: destroy, getContent: getContent, setContent: setContent }
396
+
397
+ exports.exec = exec
398
+ exports.init = init
399
+ exports.destroy = destroy
400
+ exports.getContent = getContent
401
+ exports.setContent = setContent
402
+ exports['default'] = tex
403
+
404
+ Object.defineProperty(exports, '__esModule', { value: true })
405
+
406
+ })))