editium 1.0.1
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 +21 -0
- package/README.md +424 -0
- package/dist/Editium.d.ts +4 -0
- package/dist/ResizableImage.d.ts +9 -0
- package/dist/TableElement.d.ts +21 -0
- package/dist/Toolbar.d.ts +31 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.esm.js +3128 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +3154 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +99 -0
- package/dist/utils.d.ts +55 -0
- package/package.json +105 -0
- package/vanilla/README.md +409 -0
- package/vanilla/build-bundle.js +41 -0
- package/vanilla/editium.bundle.js +3257 -0
- package/vanilla/editium.css +772 -0
- package/vanilla/editium.js +2453 -0
- package/vanilla/example/README.md +69 -0
- package/vanilla/example/demo.css +351 -0
- package/vanilla/example/demo.js +122 -0
- package/vanilla/example/index.html +202 -0
- package/vanilla/package.json +30 -0
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { BaseElement, BaseText } from 'slate';
|
|
2
|
+
export type FormatType = 'bold' | 'italic' | 'underline' | 'code' | 'strikethrough' | 'superscript' | 'subscript';
|
|
3
|
+
export type AlignmentType = 'left' | 'center' | 'right' | 'justify';
|
|
4
|
+
export type BlockType = 'paragraph' | 'heading-one' | 'heading-two' | 'heading-three' | 'heading-four' | 'heading-five' | 'heading-six' | 'heading-seven' | 'heading-eight' | 'bulleted-list' | 'numbered-list' | 'list-item' | 'blockquote' | 'code-block' | 'horizontal-rule' | 'image' | 'table' | 'table-row' | 'table-cell';
|
|
5
|
+
export type ToolbarItem = FormatType | BlockType | AlignmentType | 'link' | 'indent' | 'outdent' | 'undo' | 'redo' | 'separator' | 'view-output' | 'text-color' | 'bg-color' | 'table' | 'find-replace' | 'fullscreen';
|
|
6
|
+
export declare const ALL_TOOLBAR_ITEMS: ToolbarItem[];
|
|
7
|
+
export interface CustomElement extends BaseElement {
|
|
8
|
+
type: BlockType;
|
|
9
|
+
url?: string;
|
|
10
|
+
align?: AlignmentType;
|
|
11
|
+
children: CustomText[];
|
|
12
|
+
}
|
|
13
|
+
export interface CustomText extends BaseText {
|
|
14
|
+
text: string;
|
|
15
|
+
bold?: boolean;
|
|
16
|
+
italic?: boolean;
|
|
17
|
+
underline?: boolean;
|
|
18
|
+
code?: boolean;
|
|
19
|
+
strikethrough?: boolean;
|
|
20
|
+
superscript?: boolean;
|
|
21
|
+
subscript?: boolean;
|
|
22
|
+
color?: string;
|
|
23
|
+
backgroundColor?: string;
|
|
24
|
+
search?: boolean;
|
|
25
|
+
searchCurrent?: boolean;
|
|
26
|
+
}
|
|
27
|
+
export interface LinkElement extends BaseElement {
|
|
28
|
+
type: 'link';
|
|
29
|
+
url: string;
|
|
30
|
+
title?: string;
|
|
31
|
+
target?: '_blank' | '_self';
|
|
32
|
+
children: CustomText[];
|
|
33
|
+
}
|
|
34
|
+
export interface ImageElement extends BaseElement {
|
|
35
|
+
type: 'image';
|
|
36
|
+
url: string;
|
|
37
|
+
alt?: string;
|
|
38
|
+
width?: number;
|
|
39
|
+
height?: number;
|
|
40
|
+
align?: AlignmentType;
|
|
41
|
+
children: CustomText[];
|
|
42
|
+
}
|
|
43
|
+
export interface TableElement extends BaseElement {
|
|
44
|
+
type: 'table';
|
|
45
|
+
align?: AlignmentType;
|
|
46
|
+
width?: number;
|
|
47
|
+
children: TableRowElement[];
|
|
48
|
+
}
|
|
49
|
+
export interface TableRowElement extends BaseElement {
|
|
50
|
+
type: 'table-row';
|
|
51
|
+
children: TableCellElement[];
|
|
52
|
+
}
|
|
53
|
+
export interface TableCellElement extends BaseElement {
|
|
54
|
+
type: 'table-cell';
|
|
55
|
+
align?: AlignmentType;
|
|
56
|
+
children: (CustomElement | CustomText)[];
|
|
57
|
+
}
|
|
58
|
+
export interface EditiumProps {
|
|
59
|
+
/** Initial editor content. Default: empty paragraph with empty text node */
|
|
60
|
+
initialValue?: string | CustomElement[];
|
|
61
|
+
/** Callback when content changes. Default: undefined (no callback) */
|
|
62
|
+
onChange?: (html: string, json: CustomElement[]) => void;
|
|
63
|
+
/** Toolbar items to display. Default: 'all' */
|
|
64
|
+
toolbar?: ToolbarItem[] | 'all';
|
|
65
|
+
/** Placeholder text when editor is empty. Default: 'Start typing...' */
|
|
66
|
+
placeholder?: string;
|
|
67
|
+
/** CSS class name for the editor container. Default: '' */
|
|
68
|
+
className?: string;
|
|
69
|
+
/** Inline styles for the editor container. Default: {} */
|
|
70
|
+
style?: React.CSSProperties;
|
|
71
|
+
/** Whether the editor is read-only. Default: false */
|
|
72
|
+
readOnly?: boolean;
|
|
73
|
+
/** Custom image upload handler. Default: undefined */
|
|
74
|
+
onImageUpload?: (file: File) => Promise<string>;
|
|
75
|
+
/** Search query string for highlighting. Default: '' */
|
|
76
|
+
searchQuery?: string;
|
|
77
|
+
/** Array of search match locations. Default: [] */
|
|
78
|
+
searchMatches?: Array<{
|
|
79
|
+
path: any;
|
|
80
|
+
offset: number;
|
|
81
|
+
text: string;
|
|
82
|
+
}>;
|
|
83
|
+
/** Index of current search match. Default: 0 */
|
|
84
|
+
currentMatchIndex?: number;
|
|
85
|
+
/** Whether to show word count. Default: true */
|
|
86
|
+
showWordCount?: boolean;
|
|
87
|
+
/** Editor height. Default: '200px' */
|
|
88
|
+
height?: string | number;
|
|
89
|
+
/** Minimum editor height. Default: '150px' */
|
|
90
|
+
minHeight?: string | number;
|
|
91
|
+
/** Maximum editor height. Default: '250px' */
|
|
92
|
+
maxHeight?: string | number;
|
|
93
|
+
}
|
|
94
|
+
declare module 'slate' {
|
|
95
|
+
interface CustomTypes {
|
|
96
|
+
Element: CustomElement | LinkElement | ImageElement | TableElement | TableRowElement | TableCellElement;
|
|
97
|
+
Text: CustomText;
|
|
98
|
+
}
|
|
99
|
+
}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Editor, Path } from 'slate';
|
|
2
|
+
import { CustomElement, FormatType, BlockType, LinkElement, AlignmentType, ImageElement } from './types';
|
|
3
|
+
export declare const isAlignmentActive: (editor: Editor, alignment: AlignmentType) => boolean;
|
|
4
|
+
export declare const toggleAlignment: (editor: Editor, alignment: AlignmentType) => void;
|
|
5
|
+
export declare const indentListItem: (editor: Editor) => void;
|
|
6
|
+
export declare const outdentListItem: (editor: Editor) => void;
|
|
7
|
+
export declare const isMarkActive: (editor: Editor, format: FormatType) => boolean;
|
|
8
|
+
export declare const isBlockActive: (editor: Editor, format: BlockType) => boolean;
|
|
9
|
+
export declare const toggleMark: (editor: Editor, format: FormatType) => void;
|
|
10
|
+
export declare const applyColor: (editor: Editor, color: string | null) => void;
|
|
11
|
+
export declare const applyBackgroundColor: (editor: Editor, color: string | null) => void;
|
|
12
|
+
export declare const getActiveColor: (editor: Editor) => string | null;
|
|
13
|
+
export declare const getActiveBackgroundColor: (editor: Editor) => string | null;
|
|
14
|
+
export declare const toggleBlock: (editor: Editor, format: BlockType) => void;
|
|
15
|
+
export declare const insertHorizontalRule: (editor: Editor) => void;
|
|
16
|
+
export declare const insertImage: (editor: Editor, url: string, alt?: string, width?: number) => void;
|
|
17
|
+
export declare const isValidImageUrl: (url: string) => boolean;
|
|
18
|
+
export declare const insertLink: (editor: Editor, url: string, title?: string, target?: "_blank" | "_self") => void;
|
|
19
|
+
export declare const isLinkActive: (editor: Editor) => boolean;
|
|
20
|
+
export declare const getLinkAtCursor: (editor: Editor) => LinkElement | null;
|
|
21
|
+
export declare const unwrapLink: (editor: Editor) => void;
|
|
22
|
+
export declare const wrapLink: (editor: Editor, url: string, title?: string, target?: "_blank" | "_self") => void;
|
|
23
|
+
export declare const insertTable: (editor: Editor, rows?: number, cols?: number) => void;
|
|
24
|
+
export declare const isInTable: (editor: Editor) => boolean;
|
|
25
|
+
export declare const addTableRow: (editor: Editor) => void;
|
|
26
|
+
export declare const removeTableRow: (editor: Editor) => void;
|
|
27
|
+
export declare const addTableColumn: (editor: Editor) => void;
|
|
28
|
+
export declare const removeTableColumn: (editor: Editor) => void;
|
|
29
|
+
export declare const setTableAlignment: (editor: Editor, alignment: AlignmentType) => void;
|
|
30
|
+
export declare const findAllMatches: (editor: Editor, searchQuery: string) => Array<{
|
|
31
|
+
path: Path;
|
|
32
|
+
offset: number;
|
|
33
|
+
text: string;
|
|
34
|
+
}>;
|
|
35
|
+
export declare const navigateToMatch: (editor: Editor, match: {
|
|
36
|
+
path: Path;
|
|
37
|
+
offset: number;
|
|
38
|
+
text: string;
|
|
39
|
+
}) => void;
|
|
40
|
+
export declare const replaceMatch: (editor: Editor, match: {
|
|
41
|
+
path: Path;
|
|
42
|
+
offset: number;
|
|
43
|
+
text: string;
|
|
44
|
+
}, replaceText: string) => void;
|
|
45
|
+
export declare const replaceAllMatches: (editor: Editor, matches: Array<{
|
|
46
|
+
path: Path;
|
|
47
|
+
offset: number;
|
|
48
|
+
text: string;
|
|
49
|
+
}>, replaceText: string) => void;
|
|
50
|
+
export declare const serializeToHtml: (nodes: (CustomElement | LinkElement | ImageElement)[]) => string;
|
|
51
|
+
export declare const defaultInitialValue: CustomElement[];
|
|
52
|
+
export declare const getTextContent: (nodes: any[]) => string;
|
|
53
|
+
export declare const countWords: (text: string) => number;
|
|
54
|
+
export declare const countCharacters: (text: string) => number;
|
|
55
|
+
export declare const countCharactersNoSpaces: (text: string) => number;
|
package/package.json
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "editium",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "A powerful and feature-rich React rich text editor component built with Slate.js, featuring comprehensive formatting options, tables, images, find & replace, and more",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"module": "dist/index.esm.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"vanilla",
|
|
12
|
+
"README.md",
|
|
13
|
+
"LICENSE"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "rollup -c",
|
|
17
|
+
"build:watch": "rollup -c -w",
|
|
18
|
+
"dev": "npm run build:watch",
|
|
19
|
+
"example": "cd example && npm start",
|
|
20
|
+
"prepublishOnly": "npm run build",
|
|
21
|
+
"test": "vitest run",
|
|
22
|
+
"test:watch": "vitest",
|
|
23
|
+
"test:ui": "vitest --ui",
|
|
24
|
+
"test:coverage": "vitest run --coverage",
|
|
25
|
+
"semantic-release": "semantic-release"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"react",
|
|
29
|
+
"editor",
|
|
30
|
+
"rich-text",
|
|
31
|
+
"slate",
|
|
32
|
+
"wysiwyg",
|
|
33
|
+
"text-editor",
|
|
34
|
+
"contenteditable",
|
|
35
|
+
"markdown",
|
|
36
|
+
"formatting",
|
|
37
|
+
"tables",
|
|
38
|
+
"images",
|
|
39
|
+
"find-replace",
|
|
40
|
+
"fullscreen",
|
|
41
|
+
"word-count",
|
|
42
|
+
"character-count",
|
|
43
|
+
"slate-editor",
|
|
44
|
+
"react-editor",
|
|
45
|
+
"text-formatting",
|
|
46
|
+
"content-editor",
|
|
47
|
+
"document-editor"
|
|
48
|
+
],
|
|
49
|
+
"author": {
|
|
50
|
+
"name": "NabarupDev",
|
|
51
|
+
"url": "https://github.com/NabarupDev"
|
|
52
|
+
},
|
|
53
|
+
"repository": {
|
|
54
|
+
"type": "git",
|
|
55
|
+
"url": "https://github.com/NabarupDev/Editium.git"
|
|
56
|
+
},
|
|
57
|
+
"bugs": {
|
|
58
|
+
"url": "https://github.com/NabarupDev/Editium/issues"
|
|
59
|
+
},
|
|
60
|
+
"homepage": "https://github.com/NabarupDev/Editium#readme",
|
|
61
|
+
"license": "MIT",
|
|
62
|
+
"peerDependencies": {
|
|
63
|
+
"react": ">=16.8.0",
|
|
64
|
+
"react-dom": ">=16.8.0"
|
|
65
|
+
},
|
|
66
|
+
"dependencies": {
|
|
67
|
+
"@heroicons/react": "^2.2.0",
|
|
68
|
+
"slate": "^0.103.0",
|
|
69
|
+
"slate-history": "^0.100.0",
|
|
70
|
+
"slate-react": "^0.108.0"
|
|
71
|
+
},
|
|
72
|
+
"devDependencies": {
|
|
73
|
+
"@rollup/plugin-commonjs": "^25.0.7",
|
|
74
|
+
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
75
|
+
"@rollup/plugin-typescript": "^11.1.5",
|
|
76
|
+
"@semantic-release/changelog": "^6.0.3",
|
|
77
|
+
"@semantic-release/git": "^10.0.1",
|
|
78
|
+
"@semantic-release/github": "^11.0.6",
|
|
79
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
80
|
+
"@testing-library/react": "^16.3.0",
|
|
81
|
+
"@testing-library/user-event": "^14.6.1",
|
|
82
|
+
"@types/react": "^18.2.45",
|
|
83
|
+
"@types/react-dom": "^18.2.18",
|
|
84
|
+
"@vitejs/plugin-react": "^5.0.4",
|
|
85
|
+
"@vitest/ui": "^3.2.4",
|
|
86
|
+
"conventional-changelog-conventionalcommits": "^9.1.0",
|
|
87
|
+
"jsdom": "^27.0.0",
|
|
88
|
+
"react": "^18.2.0",
|
|
89
|
+
"react-dom": "^18.2.0",
|
|
90
|
+
"rollup": "^4.9.1",
|
|
91
|
+
"rollup-plugin-peer-deps-external": "^2.2.4",
|
|
92
|
+
"rollup-plugin-postcss": "^4.0.2",
|
|
93
|
+
"semantic-release": "^24.2.9",
|
|
94
|
+
"tslib": "^2.8.1",
|
|
95
|
+
"typescript": "^5.3.3",
|
|
96
|
+
"vitest": "^3.2.4"
|
|
97
|
+
},
|
|
98
|
+
"engines": {
|
|
99
|
+
"node": ">=14.0.0",
|
|
100
|
+
"npm": ">=6.0.0"
|
|
101
|
+
},
|
|
102
|
+
"publishConfig": {
|
|
103
|
+
"access": "public"
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
# Editium Vanilla JavaScript Editor
|
|
2
|
+
|
|
3
|
+
A lightweight, powerful rich text editor built with pure vanilla JavaScript. Zero dependencies, framework-agnostic, and production-ready.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Zero Dependencies** - Pure vanilla JavaScript, no external frameworks required
|
|
8
|
+
- **Lightweight** - Minimal footprint with maximum functionality
|
|
9
|
+
- **Rich Text Editing** - Comprehensive formatting options (bold, italic, underline, strikethrough, etc.)
|
|
10
|
+
- **Advanced Features** - Tables, images, code blocks, and more
|
|
11
|
+
- **Customizable** - Flexible toolbar and styling options
|
|
12
|
+
- **Production Ready** - Battle-tested and reliable
|
|
13
|
+
- **Multiple Formats** - Export to HTML, plain text, or JSON
|
|
14
|
+
- **Keyboard Shortcuts** - Efficient editing with standard shortcuts
|
|
15
|
+
- **Responsive** - Works seamlessly on all screen sizes
|
|
16
|
+
- **Accessible** - ARIA support and keyboard navigation
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
### CDN (Recommended)
|
|
21
|
+
|
|
22
|
+
**Single Bundle** - All-in-one file including JavaScript, CSS, and icons:
|
|
23
|
+
|
|
24
|
+
```html
|
|
25
|
+
<script src="https://unpkg.com/editium@1.0.0/vanilla/editium.bundle.js"></script>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Alternative CDNs:**
|
|
29
|
+
```html
|
|
30
|
+
<!-- jsDelivr -->
|
|
31
|
+
<script src="https://cdn.jsdelivr.net/npm/editium@1.0.0/vanilla/editium.bundle.js"></script>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Separate Files** - For more control:
|
|
35
|
+
|
|
36
|
+
```html
|
|
37
|
+
<!-- unpkg -->
|
|
38
|
+
<link rel="stylesheet" href="https://unpkg.com/editium@1.0.0/vanilla/editium.css">
|
|
39
|
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css">
|
|
40
|
+
<script src="https://unpkg.com/editium@1.0.0/vanilla/editium.js"></script>
|
|
41
|
+
|
|
42
|
+
<!-- jsDelivr -->
|
|
43
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/editium@1.0.0/vanilla/editium.css">
|
|
44
|
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css">
|
|
45
|
+
<script src="https://cdn.jsdelivr.net/npm/editium@1.0.0/vanilla/editium.js"></script>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### NPM
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
npm install editium
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
```javascript
|
|
55
|
+
import 'editium/vanilla/editium.css';
|
|
56
|
+
import Editium from 'editium/vanilla/editium.js';
|
|
57
|
+
|
|
58
|
+
const editor = new Editium({
|
|
59
|
+
container: document.getElementById('editor'),
|
|
60
|
+
placeholder: 'Start typing...',
|
|
61
|
+
toolbar: 'all'
|
|
62
|
+
});
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Self-Hosted
|
|
66
|
+
|
|
67
|
+
Download the files from the [GitHub repository](https://github.com/NabarupDev/Editium) and include them in your project:
|
|
68
|
+
|
|
69
|
+
```html
|
|
70
|
+
<link rel="stylesheet" href="path/to/editium.css">
|
|
71
|
+
<script src="path/to/editium.js"></script>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Quick Start
|
|
75
|
+
|
|
76
|
+
```html
|
|
77
|
+
<!DOCTYPE html>
|
|
78
|
+
<html lang="en">
|
|
79
|
+
<head>
|
|
80
|
+
<meta charset="UTF-8">
|
|
81
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
82
|
+
<title>Editium Editor</title>
|
|
83
|
+
<script src="https://unpkg.com/editium@1.0.0/vanilla/editium.bundle.js"></script>
|
|
84
|
+
</head>
|
|
85
|
+
<body>
|
|
86
|
+
<div id="editor"></div>
|
|
87
|
+
|
|
88
|
+
<script>
|
|
89
|
+
const editor = new Editium({
|
|
90
|
+
container: document.getElementById('editor'),
|
|
91
|
+
placeholder: 'Start typing...',
|
|
92
|
+
toolbar: 'all',
|
|
93
|
+
showWordCount: true
|
|
94
|
+
});
|
|
95
|
+
</script>
|
|
96
|
+
</body>
|
|
97
|
+
</html>
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Configuration
|
|
101
|
+
|
|
102
|
+
### Options
|
|
103
|
+
|
|
104
|
+
```javascript
|
|
105
|
+
const editor = new Editium({
|
|
106
|
+
container: document.getElementById('editor'),
|
|
107
|
+
placeholder: 'Start typing...',
|
|
108
|
+
toolbar: 'all',
|
|
109
|
+
showWordCount: true,
|
|
110
|
+
readOnly: false,
|
|
111
|
+
className: 'custom-class',
|
|
112
|
+
height: '300px',
|
|
113
|
+
minHeight: '200px',
|
|
114
|
+
maxHeight: '400px',
|
|
115
|
+
onChange: (content) => {
|
|
116
|
+
console.log('Content changed:', content);
|
|
117
|
+
},
|
|
118
|
+
onImageUpload: async (file) => {
|
|
119
|
+
const url = await uploadToServer(file);
|
|
120
|
+
return url;
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Available Options
|
|
126
|
+
|
|
127
|
+
| Option | Type | Default | Description |
|
|
128
|
+
|--------|------|---------|-------------|
|
|
129
|
+
| `container` | HTMLElement | required | DOM element to attach the editor |
|
|
130
|
+
| `placeholder` | string | `''` | Placeholder text when editor is empty |
|
|
131
|
+
| `toolbar` | string \| array | `'all'` | Toolbar configuration ('all' or array of items) |
|
|
132
|
+
| `showWordCount` | boolean | `false` | Display word and character count |
|
|
133
|
+
| `readOnly` | boolean | `false` | Make editor read-only |
|
|
134
|
+
| `className` | string | `''` | Custom CSS class for wrapper |
|
|
135
|
+
| `height` | string \| number | `'200px'` | Default editor height |
|
|
136
|
+
| `minHeight` | string \| number | `'150px'` | Minimum height before content shrinks |
|
|
137
|
+
| `maxHeight` | string \| number | `'250px'` | Maximum height before scrolling |
|
|
138
|
+
| `onChange` | function | `null` | Callback when content changes |
|
|
139
|
+
| `onImageUpload` | function | `null` | Custom image upload handler |
|
|
140
|
+
|
|
141
|
+
### Height Configuration
|
|
142
|
+
|
|
143
|
+
Heights can be specified as strings (`'300px'`, `'20rem'`, `'50vh'`) or numbers (`300` converts to `'300px'`).
|
|
144
|
+
|
|
145
|
+
```javascript
|
|
146
|
+
const editor = new Editium({
|
|
147
|
+
container: document.getElementById('editor'),
|
|
148
|
+
height: 400,
|
|
149
|
+
minHeight: 200,
|
|
150
|
+
maxHeight: 600
|
|
151
|
+
});
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Toolbar
|
|
155
|
+
|
|
156
|
+
### Predefined Toolbar
|
|
157
|
+
|
|
158
|
+
```javascript
|
|
159
|
+
toolbar: 'all'
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Custom Toolbar
|
|
163
|
+
|
|
164
|
+
```javascript
|
|
165
|
+
toolbar: [
|
|
166
|
+
'bold', 'italic', 'underline',
|
|
167
|
+
'separator',
|
|
168
|
+
'heading-one', 'heading-two',
|
|
169
|
+
'separator',
|
|
170
|
+
'bulleted-list', 'numbered-list',
|
|
171
|
+
'separator',
|
|
172
|
+
'link', 'image', 'table',
|
|
173
|
+
'separator',
|
|
174
|
+
'undo', 'redo'
|
|
175
|
+
]
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Available Items
|
|
179
|
+
|
|
180
|
+
#### Text Formatting
|
|
181
|
+
- `bold`, `italic`, `underline`, `strikethrough`
|
|
182
|
+
- `code`, `superscript`, `subscript`
|
|
183
|
+
|
|
184
|
+
#### Block Formats
|
|
185
|
+
- `paragraph`
|
|
186
|
+
- `heading-one`, `heading-two`, `heading-three`, `heading-four`, `heading-five`, `heading-six`
|
|
187
|
+
- `blockquote`, `code-block`
|
|
188
|
+
|
|
189
|
+
#### Alignment
|
|
190
|
+
- `left`, `center`, `right`, `justify`
|
|
191
|
+
|
|
192
|
+
#### Colors
|
|
193
|
+
- `text-color`, `bg-color`
|
|
194
|
+
|
|
195
|
+
#### Lists
|
|
196
|
+
- `bulleted-list`, `numbered-list`
|
|
197
|
+
- `indent`, `outdent`
|
|
198
|
+
|
|
199
|
+
#### Insert
|
|
200
|
+
- `link`, `image`, `table`, `horizontal-rule`
|
|
201
|
+
|
|
202
|
+
#### History
|
|
203
|
+
- `undo`, `redo`
|
|
204
|
+
|
|
205
|
+
#### View
|
|
206
|
+
- `preview`, `view-html`, `view-json`, `find-replace`, `fullscreen`
|
|
207
|
+
|
|
208
|
+
#### Other
|
|
209
|
+
- `separator`
|
|
210
|
+
|
|
211
|
+
## API
|
|
212
|
+
|
|
213
|
+
```javascript
|
|
214
|
+
// Get content
|
|
215
|
+
const html = editor.getHTML();
|
|
216
|
+
const text = editor.getText();
|
|
217
|
+
const json = editor.getJSON();
|
|
218
|
+
|
|
219
|
+
// Set content
|
|
220
|
+
editor.setContent('<p>New content</p>');
|
|
221
|
+
|
|
222
|
+
// Clear and focus
|
|
223
|
+
editor.clear();
|
|
224
|
+
editor.focus();
|
|
225
|
+
|
|
226
|
+
// Cleanup
|
|
227
|
+
editor.destroy();
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## Usage Examples
|
|
231
|
+
|
|
232
|
+
### Basic Editor
|
|
233
|
+
|
|
234
|
+
```html
|
|
235
|
+
<div id="basic-editor"></div>
|
|
236
|
+
|
|
237
|
+
<script>
|
|
238
|
+
const basicEditor = new Editium({
|
|
239
|
+
container: document.getElementById('basic-editor'),
|
|
240
|
+
placeholder: 'Write something...',
|
|
241
|
+
toolbar: ['bold', 'italic', 'underline', 'separator', 'link']
|
|
242
|
+
});
|
|
243
|
+
</script>
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Full-Featured Editor
|
|
247
|
+
|
|
248
|
+
```html
|
|
249
|
+
<div id="full-editor"></div>
|
|
250
|
+
|
|
251
|
+
<script>
|
|
252
|
+
const fullEditor = new Editium({
|
|
253
|
+
container: document.getElementById('full-editor'),
|
|
254
|
+
placeholder: 'Start writing your document...',
|
|
255
|
+
toolbar: 'all',
|
|
256
|
+
showWordCount: true,
|
|
257
|
+
onChange: (content) => {
|
|
258
|
+
console.log('Content updated:', content.html);
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
</script>
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### Read-Only Viewer
|
|
265
|
+
|
|
266
|
+
```html
|
|
267
|
+
<div id="viewer"></div>
|
|
268
|
+
|
|
269
|
+
<script>
|
|
270
|
+
const viewer = new Editium({
|
|
271
|
+
container: document.getElementById('viewer'),
|
|
272
|
+
readOnly: true,
|
|
273
|
+
toolbar: []
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
viewer.setContent('<h1>Document Title</h1><p>Document content...</p>');
|
|
277
|
+
</script>
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
## Advanced Features
|
|
281
|
+
|
|
282
|
+
### Custom Image Upload Handler
|
|
283
|
+
|
|
284
|
+
```html
|
|
285
|
+
<div id="editor-with-upload"></div>
|
|
286
|
+
|
|
287
|
+
<script>
|
|
288
|
+
const editorWithUpload = new Editium({
|
|
289
|
+
container: document.getElementById('editor-with-upload'),
|
|
290
|
+
toolbar: 'all',
|
|
291
|
+
onImageUpload: async (file) => {
|
|
292
|
+
const formData = new FormData();
|
|
293
|
+
formData.append('image', file);
|
|
294
|
+
|
|
295
|
+
const response = await fetch('/api/upload', {
|
|
296
|
+
method: 'POST',
|
|
297
|
+
body: formData
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
const data = await response.json();
|
|
301
|
+
return data.url;
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
</script>
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Saving and Loading Content
|
|
308
|
+
|
|
309
|
+
```html
|
|
310
|
+
<div id="editor"></div>
|
|
311
|
+
<button onclick="saveContent()">Save</button>
|
|
312
|
+
|
|
313
|
+
<script>
|
|
314
|
+
const editor = new Editium({
|
|
315
|
+
container: document.getElementById('editor'),
|
|
316
|
+
toolbar: 'all'
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
function saveContent() {
|
|
320
|
+
const content = {
|
|
321
|
+
html: editor.getHTML(),
|
|
322
|
+
text: editor.getText(),
|
|
323
|
+
json: editor.getJSON()
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
localStorage.setItem('editorContent', JSON.stringify(content));
|
|
327
|
+
|
|
328
|
+
// Or send to server
|
|
329
|
+
fetch('/api/save', {
|
|
330
|
+
method: 'POST',
|
|
331
|
+
headers: { 'Content-Type': 'application/json' },
|
|
332
|
+
body: JSON.stringify(content)
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// Load saved content
|
|
337
|
+
const savedContent = localStorage.getItem('editorContent');
|
|
338
|
+
if (savedContent) {
|
|
339
|
+
const content = JSON.parse(savedContent);
|
|
340
|
+
editor.setContent(content.html);
|
|
341
|
+
}
|
|
342
|
+
</script>
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
## Keyboard Shortcuts
|
|
346
|
+
|
|
347
|
+
- `Ctrl/Cmd + B` - Bold
|
|
348
|
+
- `Ctrl/Cmd + I` - Italic
|
|
349
|
+
- `Ctrl/Cmd + U` - Underline
|
|
350
|
+
- `Ctrl/Cmd + Z` - Undo
|
|
351
|
+
- `Ctrl/Cmd + Y` - Redo
|
|
352
|
+
- `F11` - Toggle fullscreen
|
|
353
|
+
- `Ctrl/Cmd + F` - Find & Replace
|
|
354
|
+
|
|
355
|
+
## Customization
|
|
356
|
+
|
|
357
|
+
Custom styling example:
|
|
358
|
+
|
|
359
|
+
```css
|
|
360
|
+
/* Customize wrapper */
|
|
361
|
+
.editium-wrapper {
|
|
362
|
+
border: 2px solid #007bff;
|
|
363
|
+
border-radius: 8px;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/* Customize toolbar */
|
|
367
|
+
.editium-toolbar {
|
|
368
|
+
background-color: #f0f0f0;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/* Customize editor area */
|
|
372
|
+
.editium-editor {
|
|
373
|
+
min-height: 300px;
|
|
374
|
+
font-size: 16px;
|
|
375
|
+
line-height: 1.8;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/* Custom placeholder color */
|
|
379
|
+
.editium-editor:empty:before {
|
|
380
|
+
color: #999;
|
|
381
|
+
}
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
## Browser Compatibility
|
|
385
|
+
|
|
386
|
+
- Chrome (latest)
|
|
387
|
+
- Firefox (latest)
|
|
388
|
+
- Safari (latest)
|
|
389
|
+
- Edge (latest)
|
|
390
|
+
|
|
391
|
+
## Links
|
|
392
|
+
|
|
393
|
+
- **NPM Package**: https://www.npmjs.com/package/editium
|
|
394
|
+
- **GitHub Repository**: https://github.com/NabarupDev/Editium
|
|
395
|
+
- **Issues**: https://github.com/NabarupDev/Editium/issues
|
|
396
|
+
- **unpkg CDN**: https://unpkg.com/editium@1.0.0/vanilla/
|
|
397
|
+
- **jsDelivr CDN**: https://cdn.jsdelivr.net/npm/editium@1.0.0/vanilla/
|
|
398
|
+
|
|
399
|
+
## License
|
|
400
|
+
|
|
401
|
+
MIT License - See [LICENSE](../LICENSE) file for details.
|
|
402
|
+
|
|
403
|
+
## Contributing
|
|
404
|
+
|
|
405
|
+
Contributions are welcome! Please submit a Pull Request.
|
|
406
|
+
|
|
407
|
+
---
|
|
408
|
+
|
|
409
|
+
Made with ❤️ by [NabarupDev](https://github.com/NabarupDev)
|