tulih-editor 0.1.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.
Files changed (122) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +331 -0
  3. package/dist/tulih-editor.css +1 -0
  4. package/dist/tulih-editor.es.js +3051 -0
  5. package/dist/tulih-editor.es.js.map +1 -0
  6. package/dist/tulih-editor.umd.js +8 -0
  7. package/dist/tulih-editor.umd.js.map +1 -0
  8. package/dist/types/core/Editor.d.ts +20 -0
  9. package/dist/types/core/PluginManager.d.ts +22 -0
  10. package/dist/types/core/helpers.d.ts +22 -0
  11. package/dist/types/index.d.ts +5 -0
  12. package/dist/types/plugins/align.d.ts +3 -0
  13. package/dist/types/plugins/autoLinkify.d.ts +3 -0
  14. package/dist/types/plugins/autosave.d.ts +3 -0
  15. package/dist/types/plugins/block.d.ts +3 -0
  16. package/dist/types/plugins/caseTransform.d.ts +3 -0
  17. package/dist/types/plugins/codeBlock.d.ts +3 -0
  18. package/dist/types/plugins/colors.d.ts +3 -0
  19. package/dist/types/plugins/darkMode.d.ts +3 -0
  20. package/dist/types/plugins/direction.d.ts +3 -0
  21. package/dist/types/plugins/dragDrop.d.ts +3 -0
  22. package/dist/types/plugins/emoji.d.ts +3 -0
  23. package/dist/types/plugins/emojiAutocomplete.d.ts +3 -0
  24. package/dist/types/plugins/findReplace.d.ts +3 -0
  25. package/dist/types/plugins/floatingToolbar.d.ts +3 -0
  26. package/dist/types/plugins/fontFamily.d.ts +3 -0
  27. package/dist/types/plugins/fontSize.d.ts +3 -0
  28. package/dist/types/plugins/fullscreen.d.ts +3 -0
  29. package/dist/types/plugins/history.d.ts +3 -0
  30. package/dist/types/plugins/hr.d.ts +3 -0
  31. package/dist/types/plugins/iframe.d.ts +3 -0
  32. package/dist/types/plugins/image.d.ts +3 -0
  33. package/dist/types/plugins/imageProps.d.ts +3 -0
  34. package/dist/types/plugins/imageTools.d.ts +3 -0
  35. package/dist/types/plugins/indent.d.ts +3 -0
  36. package/dist/types/plugins/index.d.ts +2 -0
  37. package/dist/types/plugins/inline.d.ts +3 -0
  38. package/dist/types/plugins/inlineCode.d.ts +3 -0
  39. package/dist/types/plugins/keyboardShortcuts.d.ts +3 -0
  40. package/dist/types/plugins/lineHeight.d.ts +3 -0
  41. package/dist/types/plugins/link.d.ts +3 -0
  42. package/dist/types/plugins/linkTooltip.d.ts +3 -0
  43. package/dist/types/plugins/list.d.ts +3 -0
  44. package/dist/types/plugins/markdown.d.ts +3 -0
  45. package/dist/types/plugins/mediaEmbed.d.ts +3 -0
  46. package/dist/types/plugins/pasteImage.d.ts +3 -0
  47. package/dist/types/plugins/pastePlain.d.ts +3 -0
  48. package/dist/types/plugins/pre.d.ts +3 -0
  49. package/dist/types/plugins/readOnly.d.ts +3 -0
  50. package/dist/types/plugins/shortcutCustomizer.d.ts +3 -0
  51. package/dist/types/plugins/shortcutsHelp.d.ts +3 -0
  52. package/dist/types/plugins/source.d.ts +3 -0
  53. package/dist/types/plugins/specialChars.d.ts +3 -0
  54. package/dist/types/plugins/statusBar.d.ts +3 -0
  55. package/dist/types/plugins/subSuper.d.ts +3 -0
  56. package/dist/types/plugins/table.d.ts +3 -0
  57. package/dist/types/plugins/tableBg.d.ts +3 -0
  58. package/dist/types/plugins/tableTools.d.ts +3 -0
  59. package/dist/types/plugins/toolbarCollapse.d.ts +3 -0
  60. package/dist/types/plugins/unlink.d.ts +3 -0
  61. package/dist/types/plugins/wordCount.d.ts +3 -0
  62. package/dist/types/types.d.ts +226 -0
  63. package/package.json +66 -0
  64. package/src/core/Editor.ts +460 -0
  65. package/src/core/PluginManager.ts +140 -0
  66. package/src/core/helpers.ts +209 -0
  67. package/src/css.d.ts +2 -0
  68. package/src/index.ts +87 -0
  69. package/src/plugins/align.ts +72 -0
  70. package/src/plugins/autoLinkify.ts +34 -0
  71. package/src/plugins/autosave.ts +69 -0
  72. package/src/plugins/block.ts +32 -0
  73. package/src/plugins/caseTransform.ts +54 -0
  74. package/src/plugins/codeBlock.ts +93 -0
  75. package/src/plugins/colors.ts +68 -0
  76. package/src/plugins/darkMode.ts +123 -0
  77. package/src/plugins/direction.ts +30 -0
  78. package/src/plugins/dragDrop.ts +68 -0
  79. package/src/plugins/emoji.ts +188 -0
  80. package/src/plugins/emojiAutocomplete.ts +183 -0
  81. package/src/plugins/findReplace.ts +229 -0
  82. package/src/plugins/floatingToolbar.ts +258 -0
  83. package/src/plugins/fontFamily.ts +41 -0
  84. package/src/plugins/fontSize.ts +32 -0
  85. package/src/plugins/fullscreen.ts +36 -0
  86. package/src/plugins/history.ts +14 -0
  87. package/src/plugins/hr.ts +118 -0
  88. package/src/plugins/iframe.ts +88 -0
  89. package/src/plugins/image.ts +107 -0
  90. package/src/plugins/imageProps.ts +119 -0
  91. package/src/plugins/imageTools.ts +344 -0
  92. package/src/plugins/indent.ts +29 -0
  93. package/src/plugins/index.ts +101 -0
  94. package/src/plugins/inline.ts +17 -0
  95. package/src/plugins/inlineCode.ts +21 -0
  96. package/src/plugins/keyboardShortcuts.ts +92 -0
  97. package/src/plugins/lineHeight.ts +40 -0
  98. package/src/plugins/link.ts +344 -0
  99. package/src/plugins/linkTooltip.ts +63 -0
  100. package/src/plugins/list.ts +141 -0
  101. package/src/plugins/markdown.ts +61 -0
  102. package/src/plugins/mediaEmbed.ts +44 -0
  103. package/src/plugins/pasteImage.ts +61 -0
  104. package/src/plugins/pastePlain.ts +43 -0
  105. package/src/plugins/pre.ts +11 -0
  106. package/src/plugins/readOnly.ts +46 -0
  107. package/src/plugins/shortcutCustomizer.ts +125 -0
  108. package/src/plugins/shortcutsHelp.ts +51 -0
  109. package/src/plugins/source.ts +77 -0
  110. package/src/plugins/specialChars.ts +64 -0
  111. package/src/plugins/statusBar.ts +85 -0
  112. package/src/plugins/subSuper.ts +20 -0
  113. package/src/plugins/table.ts +166 -0
  114. package/src/plugins/tableBg.ts +11 -0
  115. package/src/plugins/tableTools.ts +475 -0
  116. package/src/plugins/toolbarCollapse.ts +14 -0
  117. package/src/plugins/unlink.ts +29 -0
  118. package/src/plugins/wordCount.ts +34 -0
  119. package/src/styles/base.css +258 -0
  120. package/src/styles/editor.css +309 -0
  121. package/src/styles/index.css +6 -0
  122. package/src/types.ts +278 -0
@@ -0,0 +1,20 @@
1
+ import type { EditorOptions, ResolvedOptions, Features, EditorUtils, TulihEditorStatic, EditorInstance } from '../types';
2
+ export default class Editor implements EditorInstance {
3
+ features: Features;
4
+ options: ResolvedOptions;
5
+ utils: EditorUtils;
6
+ container: HTMLElement | null;
7
+ editor: HTMLElement | null;
8
+ toolbar: HTMLElement | null;
9
+ textarea: HTMLTextAreaElement;
10
+ private _ctx;
11
+ constructor(target: string | Element, options: EditorOptions | undefined, TulihEditor: TulihEditorStatic);
12
+ getContent(): string;
13
+ setContent(html: string): void;
14
+ getText(): string;
15
+ getWordCount(): number;
16
+ getCharCount(): number;
17
+ setReadOnly(ro: boolean): void;
18
+ isReadOnly(): boolean;
19
+ destroy(): void;
20
+ }
@@ -0,0 +1,22 @@
1
+ import type { Plugin, PluginContext, Features, PluginManagerInstance } from '../types';
2
+ /**
3
+ * Registry and lifecycle manager for plugins. Resolves toolbar order,
4
+ * dependency order, and one-time CSS injection.
5
+ */
6
+ export default class PluginManager implements PluginManagerInstance {
7
+ private _plugins;
8
+ private _map;
9
+ private _injectedCSS;
10
+ private _cssInjected;
11
+ register(name: string, plugin: Plugin): this;
12
+ unregister(name: string): void;
13
+ get(name: string): Plugin | null;
14
+ has(name: string): boolean;
15
+ getNames(): string[];
16
+ private _resolveOrder;
17
+ initAll(ctx: PluginContext): void;
18
+ destroyAll(ctx: PluginContext): void;
19
+ getToolbarHTML(features: Features, toolbar?: string[][]): string;
20
+ getModalHTML(features: Features): string;
21
+ injectAllCSS(): void;
22
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Shared DOM utilities used by the editor core and plugins.
3
+ */
4
+ declare const blockSelector = "p,h1,h2,h3,blockquote,pre,ul,ol,li,table,hr,iframe,.te-embed";
5
+ declare const inlineTags: string[];
6
+ declare function qs(selector: string, root?: Document | Element | null): Element | null;
7
+ declare function qsa(selector: string, root?: Document | Element | null): Element[];
8
+ declare function exec(command: string, value?: string): void;
9
+ declare function getSelectionHtml(): string;
10
+ declare function hasBlockDescendant(el: Element): boolean;
11
+ declare function isInlineElement(el: Node): boolean;
12
+ declare function wrapNodeInP(node: Node): HTMLParagraphElement;
13
+ declare function wrapIframe(node: Element | null): HTMLDivElement | undefined;
14
+ declare function normalizeParagraphs(root: Element | null): void;
15
+ declare function ensureInitialParagraph(root: Element | null): void;
16
+ declare function isInsideEditor(editor: Element, node: Node | null): boolean;
17
+ declare function getBlockElement(editor: Element): Element | null;
18
+ declare function setBtnActive(toolbar: Element | null, selector: string, active: boolean): void;
19
+ declare function updateToolbarState(editor: HTMLElement, blockSelect: HTMLSelectElement | null, alignSelect: HTMLSelectElement | null, toolbar: HTMLElement | null): void;
20
+ declare function escapeHtml(str: string): string;
21
+ declare function removeNode(node: Node | null): void;
22
+ export { qs, qsa, exec, getSelectionHtml, blockSelector, inlineTags, hasBlockDescendant, isInlineElement, wrapNodeInP, wrapIframe, normalizeParagraphs, ensureInitialParagraph, isInsideEditor, getBlockElement, setBtnActive, updateToolbarState, escapeHtml, removeNode, };
@@ -0,0 +1,5 @@
1
+
2
+ import type { TulihEditorStatic } from './types';
3
+ declare const TulihEditor: TulihEditorStatic;
4
+ export default TulihEditor;
5
+ export type { Plugin, PluginContext, EditorOptions, EditorInstance, Features, SanitizeOptions, ResolvedOptions, EditorUtils, UploadImageHandler, BrowseImageHandler, TulihEditorStatic, PluginManagerInstance, HTMLProvider, CSSProvider, TeHistory, TeEditorElement, TeWrapperElement, } from './types';
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const align: Plugin;
3
+ export default align;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const autoLinkify: Plugin;
3
+ export default autoLinkify;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const autosave: Plugin;
3
+ export default autosave;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const block: Plugin;
3
+ export default block;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const caseTransform: Plugin;
3
+ export default caseTransform;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const codeBlock: Plugin;
3
+ export default codeBlock;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const colors: Plugin;
3
+ export default colors;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const darkMode: Plugin;
3
+ export default darkMode;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const direction: Plugin;
3
+ export default direction;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const dragDrop: Plugin;
3
+ export default dragDrop;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const emoji: Plugin;
3
+ export default emoji;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const emojiAutocomplete: Plugin;
3
+ export default emojiAutocomplete;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const findReplace: Plugin;
3
+ export default findReplace;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const floatingToolbar: Plugin;
3
+ export default floatingToolbar;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const fontFamily: Plugin;
3
+ export default fontFamily;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const fontSize: Plugin;
3
+ export default fontSize;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const fullscreen: Plugin;
3
+ export default fullscreen;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const history: Plugin;
3
+ export default history;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const hr: Plugin;
3
+ export default hr;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const iframe: Plugin;
3
+ export default iframe;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const image: Plugin;
3
+ export default image;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const imageProps: Plugin;
3
+ export default imageProps;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const imageTools: Plugin;
3
+ export default imageTools;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const indent: Plugin;
3
+ export default indent;
@@ -0,0 +1,2 @@
1
+ import type { PluginManagerInstance } from '../types';
2
+ export default function registerDefaultPlugins(pm: PluginManagerInstance): void;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const inline: Plugin;
3
+ export default inline;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const inlineCode: Plugin;
3
+ export default inlineCode;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const keyboardShortcuts: Plugin;
3
+ export default keyboardShortcuts;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const lineHeight: Plugin;
3
+ export default lineHeight;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const link: Plugin;
3
+ export default link;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const linkTooltip: Plugin;
3
+ export default linkTooltip;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const list: Plugin;
3
+ export default list;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const markdown: Plugin;
3
+ export default markdown;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const mediaEmbed: Plugin;
3
+ export default mediaEmbed;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const pasteImage: Plugin;
3
+ export default pasteImage;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const pastePlain: Plugin;
3
+ export default pastePlain;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const pre: Plugin;
3
+ export default pre;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const readOnly: Plugin;
3
+ export default readOnly;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const shortcutCustomizer: Plugin;
3
+ export default shortcutCustomizer;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const shortcutsHelp: Plugin;
3
+ export default shortcutsHelp;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const source: Plugin;
3
+ export default source;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const specialChars: Plugin;
3
+ export default specialChars;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const statusBar: Plugin;
3
+ export default statusBar;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const subSuper: Plugin;
3
+ export default subSuper;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const table: Plugin;
3
+ export default table;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const tableBg: Plugin;
3
+ export default tableBg;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const tableTools: Plugin;
3
+ export default tableTools;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const toolbarCollapse: Plugin;
3
+ export default toolbarCollapse;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const unlink: Plugin;
3
+ export default unlink;
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../types';
2
+ declare const wordCount: Plugin;
3
+ export default wordCount;
@@ -0,0 +1,226 @@
1
+ /**
2
+ * Public type definitions for TulihEditor.
3
+ *
4
+ * These types describe the plugin contract, the editor options, and the
5
+ * runtime context (`ctx`) handed to every plugin's `init`/`destroy` hook.
6
+ */
7
+ /**
8
+ * Map of plugin name -> enabled. Every built-in plugin is listed for
9
+ * autocomplete, but any custom plugin name is accepted too.
10
+ */
11
+ export interface Features {
12
+ block?: boolean;
13
+ inline?: boolean;
14
+ pre?: boolean;
15
+ inlineCode?: boolean;
16
+ subSuper?: boolean;
17
+ removeFormat?: boolean;
18
+ keyboardShortcuts?: boolean;
19
+ readOnly?: boolean;
20
+ linkTooltip?: boolean;
21
+ emojiAutocomplete?: boolean;
22
+ statusBar?: boolean;
23
+ codeBlock?: boolean;
24
+ mediaEmbed?: boolean;
25
+ dragDrop?: boolean;
26
+ pastePlain?: boolean;
27
+ findReplace?: boolean;
28
+ indent?: boolean;
29
+ list?: boolean;
30
+ lineHeight?: boolean;
31
+ fontSize?: boolean;
32
+ fontFamily?: boolean;
33
+ specialChars?: boolean;
34
+ colors?: boolean;
35
+ tableBg?: boolean;
36
+ align?: boolean;
37
+ markdown?: boolean;
38
+ link?: boolean;
39
+ image?: boolean;
40
+ imageProps?: boolean;
41
+ imageTools?: boolean;
42
+ iframe?: boolean;
43
+ table?: boolean;
44
+ tableTools?: boolean;
45
+ hr?: boolean;
46
+ unlink?: boolean;
47
+ emoji?: boolean;
48
+ direction?: boolean;
49
+ source?: boolean;
50
+ history?: boolean;
51
+ fullscreen?: boolean;
52
+ toolbarCollapse?: boolean;
53
+ autosave?: boolean;
54
+ autoLinkify?: boolean;
55
+ caseTransform?: boolean;
56
+ shortcutsHelp?: boolean;
57
+ floatingToolbar?: boolean;
58
+ darkMode?: boolean;
59
+ shortcutCustomizer?: boolean;
60
+ minimal?: boolean;
61
+ [name: string]: boolean | undefined;
62
+ }
63
+ export interface SanitizeOptions {
64
+ allowedTags: string[];
65
+ allowedAttributes: string[];
66
+ }
67
+ /** Options accepted by `TulihEditor.attach(target, options)`. */
68
+ export interface EditorOptions {
69
+ /** Enable/disable individual features (plugins). */
70
+ features?: Features;
71
+ /** Hide the classic toolbar; use the floating toolbar only. */
72
+ minimal?: boolean;
73
+ /** Custom toolbar layout. Each inner array is one button group (divider between groups). */
74
+ toolbar?: string[][];
75
+ /** Editor body height. A number is treated as pixels. */
76
+ height?: number | string;
77
+ /** Custom HTML sanitization rules (merged over the defaults). */
78
+ sanitize?: Partial<SanitizeOptions>;
79
+ /** URL schemes permitted for links. Defaults to http, https, mailto, tel. */
80
+ allowedUrlSchemes?: string[];
81
+ /** URL schemes permitted for images. Defaults to http, https, data. */
82
+ allowedImageSchemes?: string[];
83
+ /** Hostnames permitted for iframe embeds. */
84
+ iframeAllowlist?: string[];
85
+ /** `sandbox` attribute applied to embedded iframes. */
86
+ iframeSandbox?: string;
87
+ /** `allow` attribute applied to embedded iframes. */
88
+ iframeAllow?: string;
89
+ /** Start the editor in read-only mode. */
90
+ readOnly?: boolean;
91
+ }
92
+ /** Options after merging with defaults, stored on the editor instance. */
93
+ export interface ResolvedOptions {
94
+ sanitize: SanitizeOptions;
95
+ urlSchemes: string[];
96
+ imageSchemes: string[];
97
+ iframeAllowlist: string[];
98
+ iframeSandbox: string;
99
+ iframeAllow: string;
100
+ readOnly: boolean;
101
+ }
102
+ export interface EditorUtils {
103
+ sanitizeHTML(html: string, sanOpts?: Partial<SanitizeOptions>): string;
104
+ isSafeUrl(url: string, schemes: string[]): boolean;
105
+ isAllowedIframeUrl(url: string): boolean;
106
+ }
107
+ export type UploadImageHandler = (file: File | Blob, callback: (url: string) => void) => void;
108
+ export type BrowseImageHandler = (context: unknown, callback: (url: string) => void) => void;
109
+ /** Either a static HTML string or a builder that receives the active features. */
110
+ export type HTMLProvider = string | ((features: Features) => string);
111
+ export type CSSProvider = string | ((features?: Features) => string);
112
+ /**
113
+ * A TulihEditor plugin. The only required field is `name`; everything else is
114
+ * optional. Plugins contribute toolbar buttons, modals, CSS, and behavior.
115
+ */
116
+ export interface Plugin {
117
+ /** Unique plugin name. Used as the feature flag key. */
118
+ name: string;
119
+ /** Sort order in the toolbar. Plugins are grouped per 10-unit range. */
120
+ order?: number;
121
+ /** Names of plugins that must initialize before this one. */
122
+ deps?: string[];
123
+ /** Toolbar markup injected into the toolbar. */
124
+ toolbarHTML?: HTMLProvider;
125
+ /** Modal markup injected after the editor body. */
126
+ modalHTML?: HTMLProvider;
127
+ /** CSS automatically injected into <head> once, on first load. */
128
+ css?: CSSProvider;
129
+ /** Called once per editor instance after the DOM is built. */
130
+ init?(ctx: PluginContext): void;
131
+ /** Called when an editor instance is destroyed. */
132
+ destroy?(ctx: PluginContext): void;
133
+ }
134
+ export interface PluginContext {
135
+ /** Wrapper element containing toolbar, editor body and modals. */
136
+ wrapper: HTMLElement;
137
+ /** The contenteditable editor body (`.te-editor`). */
138
+ editor: HTMLElement;
139
+ /** The toolbar element (`.te-toolbar`). */
140
+ toolbar: HTMLElement;
141
+ /** The original textarea the editor is attached to. */
142
+ textarea: HTMLTextAreaElement;
143
+ /** Resolved feature flags for this instance. */
144
+ features: Features;
145
+ /** Resolved options for this instance. */
146
+ options: ResolvedOptions;
147
+ /** Sanitization / URL helpers. */
148
+ utils: EditorUtils;
149
+ /** The global TulihEditor object. */
150
+ TulihEditor: TulihEditorStatic;
151
+ /** Save the current selection range onto the wrapper. */
152
+ saveSel(): void;
153
+ /** Restore a previously saved selection range. */
154
+ restoreSel(): void;
155
+ /** Refresh toolbar active states (bold/italic/lists/undo/redo). */
156
+ updateActiveStates(): void;
157
+ /** Set by the pastePlain plugin to toggle plain-text pasting. */
158
+ _pastePlain?: boolean;
159
+ /** Plugins may stash additional state on the context. */
160
+ [key: string]: unknown;
161
+ }
162
+ export interface EditorInstance {
163
+ /** Wrapper element. */
164
+ container: HTMLElement | null;
165
+ /** Contenteditable editor body. */
166
+ editor: HTMLElement | null;
167
+ /** Toolbar element. */
168
+ toolbar: HTMLElement | null;
169
+ /** Original textarea. */
170
+ textarea: HTMLTextAreaElement;
171
+ /** Resolved feature flags. */
172
+ features: Features;
173
+ /** Resolved options. */
174
+ options: ResolvedOptions;
175
+ /** Sanitization / URL helpers. */
176
+ utils: EditorUtils;
177
+ /** Get the editor HTML content. */
178
+ getContent(): string;
179
+ /** Replace the editor content (sanitized). */
180
+ setContent(html: string): void;
181
+ /** Get the plain text content. */
182
+ getText(): string;
183
+ /** Get the current word count. */
184
+ getWordCount(): number;
185
+ /** Get the current character count. */
186
+ getCharCount(): number;
187
+ /** Toggle read-only mode. */
188
+ setReadOnly(readOnly: boolean): void;
189
+ /** Whether the editor is currently read-only. */
190
+ isReadOnly(): boolean;
191
+ /** Tear down the editor and restore the original textarea. */
192
+ destroy(): void;
193
+ }
194
+ export interface PluginManagerInstance {
195
+ register(name: string, plugin: Plugin): this;
196
+ unregister(name: string): void;
197
+ get(name: string): Plugin | null;
198
+ has(name: string): boolean;
199
+ getNames(): string[];
200
+ initAll(ctx: PluginContext): void;
201
+ destroyAll(ctx: PluginContext): void;
202
+ getToolbarHTML(features: Features, toolbar?: string[][]): string;
203
+ getModalHTML(features: Features): string;
204
+ injectAllCSS(): void;
205
+ }
206
+ export interface TulihEditorStatic {
207
+ pluginManager: PluginManagerInstance;
208
+ instances: EditorInstance[];
209
+ onBrowseImage: BrowseImageHandler | null;
210
+ onUploadImage?: UploadImageHandler | null;
211
+ setBrowseImage(handler: BrowseImageHandler): void;
212
+ attach(target: string | Element, options?: EditorOptions): EditorInstance | undefined;
213
+ create(target: string | Element, options?: EditorOptions): EditorInstance | undefined;
214
+ }
215
+ export interface TeHistory {
216
+ undo: string[];
217
+ redo: string[];
218
+ }
219
+ /** Editor body element with the table-history expando used by history/table plugins. */
220
+ export type TeEditorElement = HTMLElement & {
221
+ _tableHist?: TeHistory;
222
+ };
223
+ /** Wrapper element with the saved-selection expando. */
224
+ export type TeWrapperElement = HTMLElement & {
225
+ __savedRange?: Range | null;
226
+ };
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "tulih-editor",
3
+ "version": "0.1.0",
4
+ "description": "A lightweight, zero-dependency WYSIWYG rich text editor for the browser, built on contenteditable with a modular plugin system. ~50 plugins, written in TypeScript.",
5
+ "type": "module",
6
+ "main": "./dist/tulih-editor.umd.js",
7
+ "module": "./dist/tulih-editor.es.js",
8
+ "types": "./dist/types/index.d.ts",
9
+ "unpkg": "./dist/tulih-editor.umd.js",
10
+ "jsdelivr": "./dist/tulih-editor.umd.js",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/types/index.d.ts",
14
+ "import": "./dist/tulih-editor.es.js",
15
+ "require": "./dist/tulih-editor.umd.js"
16
+ },
17
+ "./style.css": "./dist/tulih-editor.css",
18
+ "./dist/*": "./dist/*"
19
+ },
20
+ "sideEffects": [
21
+ "**/*.css",
22
+ "./src/index.ts"
23
+ ],
24
+ "files": [
25
+ "dist",
26
+ "src",
27
+ "README.md",
28
+ "LICENSE"
29
+ ],
30
+ "scripts": {
31
+ "dev": "vite",
32
+ "build": "npm run clean && npm run build:js && npm run build:types",
33
+ "build:js": "vite build",
34
+ "build:types": "tsc -p tsconfig.build.json && node scripts/fix-dts.mjs",
35
+ "clean": "rimraf dist",
36
+ "typecheck": "tsc --noEmit",
37
+ "test": "node --test",
38
+ "prepublishOnly": "npm run build"
39
+ },
40
+ "keywords": [
41
+ "wysiwyg",
42
+ "rich-text-editor",
43
+ "editor",
44
+ "contenteditable",
45
+ "html-editor",
46
+ "text-editor",
47
+ "tulih-editor",
48
+ "typescript"
49
+ ],
50
+ "author": "Hendra Randy Nomura <https://github.com/hr-nomura>",
51
+ "license": "MIT",
52
+ "repository": {
53
+ "type": "git",
54
+ "url": "git+https://github.com/hr-nomura/tulih-editor.git"
55
+ },
56
+ "bugs": {
57
+ "url": "https://github.com/hr-nomura/tulih-editor/issues"
58
+ },
59
+ "homepage": "https://github.com/hr-nomura/tulih-editor#readme",
60
+ "devDependencies": {
61
+ "jsdom": "^25.0.1",
62
+ "rimraf": "^6.0.1",
63
+ "typescript": "^5.6.0",
64
+ "vite": "^6.0.0"
65
+ }
66
+ }