@nks-hub/texy-editor 0.1.1 → 0.1.2

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.
@@ -0,0 +1,22 @@
1
+ import type { TexyEditorStrings } from '../types';
2
+ export interface DialogConfig {
3
+ title: string;
4
+ width?: number;
5
+ content: HTMLElement;
6
+ onSubmit: () => void;
7
+ onCancel?: () => void;
8
+ }
9
+ /**
10
+ * Native <dialog> based modal window manager.
11
+ * Replaces jQuery UI Dialog with zero dependencies.
12
+ */
13
+ export declare class DialogManager {
14
+ private container;
15
+ private strings;
16
+ private openDialogs;
17
+ constructor(container: HTMLElement, strings: TexyEditorStrings);
18
+ open(name: string, config: DialogConfig): HTMLDialogElement;
19
+ close(name: string): void;
20
+ closeAll(): void;
21
+ isOpen(name: string): boolean;
22
+ }
@@ -0,0 +1,10 @@
1
+ import type { TexyEditorEvents, TexyEventHandler } from '../types';
2
+ type EventMap = TexyEditorEvents;
3
+ export declare class EventBus {
4
+ private listeners;
5
+ on<K extends keyof EventMap>(event: K, handler: TexyEventHandler<EventMap[K]>): void;
6
+ off<K extends keyof EventMap>(event: K, handler: TexyEventHandler<EventMap[K]>): void;
7
+ emit<K extends keyof EventMap>(event: K, data: EventMap[K]): void;
8
+ removeAll(): void;
9
+ }
10
+ export {};
@@ -0,0 +1,13 @@
1
+ export type ShortcutHandler = () => void;
2
+ export declare class KeyboardManager {
3
+ private textarea;
4
+ private customShortcuts?;
5
+ private bindings;
6
+ private boundHandler;
7
+ constructor(textarea: HTMLTextAreaElement, customShortcuts?: Record<string, string> | undefined);
8
+ register(actionName: string, handler: ShortcutHandler): void;
9
+ attach(): void;
10
+ detach(): void;
11
+ private handleKeydown;
12
+ private parseShortcut;
13
+ }
@@ -0,0 +1,59 @@
1
+ import type { SelectionState } from '../types';
2
+ /**
3
+ * Textarea selection manager.
4
+ * Provides methods to read, manipulate, and replace selected text
5
+ * in a standard HTMLTextAreaElement without any external dependencies.
6
+ */
7
+ export declare class Selection {
8
+ private textarea;
9
+ constructor(textarea: HTMLTextAreaElement);
10
+ /** Detect the line-feed character used in the textarea value */
11
+ get lf(): string;
12
+ /** Get current selection state snapshot */
13
+ getState(): SelectionState;
14
+ /** Get selected text */
15
+ text(): string;
16
+ /** Length of current selection */
17
+ length(): number;
18
+ /** Whether selection is collapsed (cursor without selection) */
19
+ isCursor(): boolean;
20
+ /** Set selection range programmatically */
21
+ select(start: number, length: number): void;
22
+ /** Place cursor at a specific position */
23
+ setCursor(position: number): void;
24
+ /**
25
+ * Replace currently selected text with new content.
26
+ * After replacement, the new text is selected.
27
+ */
28
+ replace(replacement: string): void;
29
+ /**
30
+ * Wrap selection with prefix and suffix.
31
+ * If nothing is selected (cursor), places cursor between prefix and suffix.
32
+ */
33
+ tag(prefix: string, suffix: string): void;
34
+ /**
35
+ * Wrap selection as an inline phrase.
36
+ * Trims trailing whitespace from selection before wrapping.
37
+ */
38
+ phrase(prefix: string, suffix?: string): void;
39
+ /**
40
+ * Remove trailing whitespace from the selection boundary.
41
+ * Useful when double-clicking selects a trailing space.
42
+ */
43
+ trimSelect(): void;
44
+ /**
45
+ * Expand selection to cover complete lines.
46
+ * Useful for block-level operations (lists, headings).
47
+ */
48
+ selectBlock(): void;
49
+ /** Get the full value of the textarea */
50
+ getValue(): string;
51
+ /** Set the full value of the textarea */
52
+ setValue(value: string): void;
53
+ /** Focus the textarea */
54
+ focus(): void;
55
+ /** Get the underlying textarea element */
56
+ getElement(): HTMLTextAreaElement;
57
+ private isCursorAt;
58
+ private dispatchInput;
59
+ }
@@ -0,0 +1,71 @@
1
+ import type { TexyEditorOptions, TexyEditorAPI, TexyEditorEvents, TexyEditorStrings, TexyEventHandler, ViewMode } from '../types';
2
+ import { Selection } from './Selection';
3
+ import { TexyFormatter } from './TexyFormatter';
4
+ import { DialogManager } from './DialogManager';
5
+ export declare class TexyEditor implements TexyEditorAPI {
6
+ private container;
7
+ private textarea;
8
+ private editDiv;
9
+ private previewDiv;
10
+ private previewContent;
11
+ private selection;
12
+ private formatter;
13
+ private events;
14
+ private undoManager;
15
+ private keyboard;
16
+ private toolbarBuilder;
17
+ private dialogManager;
18
+ private strings;
19
+ private options;
20
+ private currentView;
21
+ private isFullscreen;
22
+ private parser;
23
+ private plugins;
24
+ private previewDebounceTimer;
25
+ private lastPreviewedValue;
26
+ private destroyed;
27
+ private actions;
28
+ constructor(textareaOrSelector: HTMLTextAreaElement | string, options?: TexyEditorOptions);
29
+ getValue(): string;
30
+ setValue(value: string): void;
31
+ getSelection(): string;
32
+ replaceSelection(text: string): void;
33
+ wrapSelection(prefix: string, suffix: string): void;
34
+ insertAtCursor(text: string): void;
35
+ focus(): void;
36
+ setView(mode: ViewMode): void;
37
+ getView(): ViewMode;
38
+ execAction(name: string): void;
39
+ on<K extends keyof TexyEditorEvents>(event: K, handler: TexyEventHandler<TexyEditorEvents[K]>): void;
40
+ off<K extends keyof TexyEditorEvents>(event: K, handler: TexyEventHandler<TexyEditorEvents[K]>): void;
41
+ undo(): void;
42
+ redo(): void;
43
+ openWindow(_name: string): void;
44
+ closeWindow(name: string): void;
45
+ toggleFullscreen(): void;
46
+ getTextarea(): HTMLTextAreaElement;
47
+ getContainer(): HTMLElement;
48
+ getStrings(): TexyEditorStrings;
49
+ getDialogManager(): DialogManager;
50
+ getFormatter(): TexyFormatter;
51
+ getSelectionManager(): Selection;
52
+ destroy(): void;
53
+ private buildDOM;
54
+ private applyTheme;
55
+ private updateView;
56
+ private renderPreview;
57
+ private fetchServerPreview;
58
+ private registerActions;
59
+ private handleHeading;
60
+ private handleLink;
61
+ private handleImage;
62
+ private handleTable;
63
+ private handleColor;
64
+ private handleSymbol;
65
+ private handleAcronym;
66
+ private setupKeyboard;
67
+ private setupUndoTracking;
68
+ private setupAutoResize;
69
+ private loadPlugin;
70
+ private createFormField;
71
+ }
@@ -0,0 +1,53 @@
1
+ import { Selection } from './Selection';
2
+ /**
3
+ * Texy markup insertion and toggle operations.
4
+ * Each method manipulates the textarea selection to insert or toggle
5
+ * Texy-formatted markup.
6
+ */
7
+ export declare class TexyFormatter {
8
+ private selection;
9
+ constructor(selection: Selection);
10
+ bold(): void;
11
+ italic(): void;
12
+ deleted(): void;
13
+ inserted(): void;
14
+ superscript(): void;
15
+ subscript(): void;
16
+ inlineCode(): void;
17
+ noTexy(): void;
18
+ quoted(): void;
19
+ link(url: string, text?: string): void;
20
+ acronym(title: string): void;
21
+ image(src: string, alt?: string, align?: '<' | '>' | '<>' | '*', caption?: string): void;
22
+ heading(level: 1 | 2 | 3 | 4): void;
23
+ headingWithPrompt(level: 1 | 2 | 3 | 4, text: string): void;
24
+ unorderedList(): void;
25
+ orderedList(): void;
26
+ orderedListRoman(): void;
27
+ orderedListRomanSmall(): void;
28
+ orderedListAlpha(): void;
29
+ orderedListAlphaSmall(): void;
30
+ blockquote(): void;
31
+ indent(): void;
32
+ unindent(): void;
33
+ alignLeft(): void;
34
+ alignRight(): void;
35
+ alignCenter(): void;
36
+ alignJustify(): void;
37
+ codeBlock(language?: string): void;
38
+ htmlBlock(): void;
39
+ divBlock(modifier?: string): void;
40
+ textBlock(): void;
41
+ commentBlock(): void;
42
+ horizontalRule(): void;
43
+ table(cols: number, rows: number, header?: 'none' | 'top' | 'left'): void;
44
+ colorModifier(color: string): void;
45
+ classModifier(className: string): void;
46
+ insertSymbol(symbol: string): void;
47
+ private toggleInline;
48
+ private applyList;
49
+ private getBullet;
50
+ private toRoman;
51
+ private toLetter;
52
+ private insertAlignment;
53
+ }
@@ -0,0 +1,17 @@
1
+ import type { ToolbarConfig, TexyEditorStrings } from '../types';
2
+ export declare class ToolbarBuilder {
3
+ private strings;
4
+ private actionHandler;
5
+ private toolbar;
6
+ private bottomBar;
7
+ constructor(strings: TexyEditorStrings, actionHandler: (name: string) => void);
8
+ build(config: ToolbarConfig): HTMLElement;
9
+ buildBottomBar(left: string[], rightEdit: string[], rightPreview: string[]): HTMLElement;
10
+ private renderItem;
11
+ private createButton;
12
+ private createCustomButton;
13
+ private createSeparator;
14
+ private createDropdown;
15
+ private isGroup;
16
+ private isCustomButton;
17
+ }
@@ -0,0 +1,17 @@
1
+ export interface UndoState {
2
+ value: string;
3
+ cursorStart: number;
4
+ cursorEnd: number;
5
+ }
6
+ export declare class UndoManager {
7
+ private stack;
8
+ private pointer;
9
+ private maxSteps;
10
+ constructor(maxSteps?: number);
11
+ push(state: UndoState): void;
12
+ undo(): UndoState | null;
13
+ redo(): UndoState | null;
14
+ canUndo(): boolean;
15
+ canRedo(): boolean;
16
+ clear(): void;
17
+ }
@@ -0,0 +1,2 @@
1
+ import type { TexyEditorStrings } from '../types';
2
+ export declare const cs: TexyEditorStrings;
@@ -0,0 +1,2 @@
1
+ import type { TexyEditorStrings } from '../types';
2
+ export declare const en: TexyEditorStrings;
@@ -0,0 +1,6 @@
1
+ import type { TexyEditorStrings } from '../types';
2
+ import { cs } from './cs';
3
+ import { en } from './en';
4
+ export declare function getStrings(lang: string): TexyEditorStrings;
5
+ export declare function registerLanguage(lang: string, strings: TexyEditorStrings): void;
6
+ export { cs, en };
@@ -0,0 +1,13 @@
1
+ export { TexyEditor } from './core/TexyEditor';
2
+ export { Selection } from './core/Selection';
3
+ export { TexyFormatter } from './core/TexyFormatter';
4
+ export { EventBus } from './core/EventBus';
5
+ export { UndoManager } from './core/UndoManager';
6
+ export { KeyboardManager } from './core/KeyboardManager';
7
+ export { ToolbarBuilder } from './core/ToolbarBuilder';
8
+ export { DialogManager } from './core/DialogManager';
9
+ export { TexyParser } from './parser';
10
+ export { youtubePlugin, smileyPlugin, linkRedirectPlugin, bbcodePlugin, imageEmbedPlugin, } from './parser';
11
+ export { getStrings, registerLanguage, cs, en } from './i18n';
12
+ export type { TexyEditorOptions, TexyEditorAPI, TexyEditorEvents, TexyEditorStrings, TexyEventHandler, TexyPlugin, TexyPluginWindowConfig, ToolbarConfig, ToolbarItem, ToolbarGroup, ToolbarCustomButton, ViewMode, SelectionState, UploadHandler, UploadResult, MentionSource, MentionItem, TexyParseRule, TexyParserOptions, TexyParserPlugin, } from './types';
13
+ import './themes/base.css';
@@ -0,0 +1,44 @@
1
+ import type { TexyParserOptions, TexyParserPlugin } from '../types';
2
+ /**
3
+ * Client-side Texy markup parser.
4
+ * Converts Texy source text to HTML for live preview.
5
+ * Supports plugin system for custom syntax extensions.
6
+ */
7
+ export declare class TexyParser {
8
+ private options;
9
+ private plugins;
10
+ constructor(options?: TexyParserOptions);
11
+ /** Add a plugin at runtime */
12
+ addPlugin(plugin: TexyParserPlugin): void;
13
+ /** Remove a plugin by name */
14
+ removePlugin(name: string): void;
15
+ /** Get registered plugins */
16
+ getPlugins(): readonly TexyParserPlugin[];
17
+ parse(input: string): string;
18
+ private parseBlocks;
19
+ /**
20
+ * Split text into block segments.
21
+ * Respects /--...\-- block boundaries.
22
+ */
23
+ private splitBlockSegments;
24
+ private splitParagraphs;
25
+ private tryCommentBlock;
26
+ private tryCodeBlock;
27
+ private tryHtmlBlock;
28
+ private tryDivBlock;
29
+ private tryTextBlock;
30
+ private tryTable;
31
+ private parseTableRow;
32
+ private tryHeading;
33
+ private tryHorizontalRule;
34
+ private tryBlockquote;
35
+ private tryList;
36
+ private parseListItems;
37
+ private tryParagraph;
38
+ private parseAlignModifier;
39
+ parseInline(text: string): string;
40
+ private escapeHtmlPreservingPlaceholders;
41
+ private applyTypography;
42
+ private parseModifierAttrs;
43
+ private escapeHtml;
44
+ }
@@ -0,0 +1,2 @@
1
+ export { TexyParser } from './TexyParser';
2
+ export { youtubePlugin, smileyPlugin, linkRedirectPlugin, bbcodePlugin, imageEmbedPlugin, } from './plugins';
@@ -0,0 +1,15 @@
1
+ import type { TexyParserPlugin } from '../../types';
2
+ /**
3
+ * BBCode plugin for TexyParser.
4
+ *
5
+ * Converts common BBCode tags to HTML:
6
+ * [b]text[/b] → <strong>text</strong>
7
+ * [i]text[/i] → <em>text</em>
8
+ * [u]text[/u] → <u>text</u>
9
+ * [s]text[/s] → <del>text</del>
10
+ * [url=...]text[/url] → <a href="...">text</a>
11
+ * [color=...]text[/color] → <span style="color:...">text</span>
12
+ *
13
+ * Useful for forums and chat applications that support BBCode alongside Texy.
14
+ */
15
+ export declare function bbcodePlugin(): TexyParserPlugin;
@@ -0,0 +1,20 @@
1
+ import type { TexyParserPlugin } from '../../types';
2
+ export interface ImageEmbedPluginOptions {
3
+ /** Max width for embedded images (default: '300px') */
4
+ maxWidth?: string;
5
+ /** CSS class for embedded images */
6
+ className?: string;
7
+ /** Enable linked images: "[* img *]":URL syntax (default: true) */
8
+ enableLinkedImages?: boolean;
9
+ }
10
+ /**
11
+ * Enhanced image embed plugin for TexyParser.
12
+ *
13
+ * Handles external image URLs in Texy image syntax:
14
+ * [* https://example.com/photo.jpg *]
15
+ * [* https://example.com/photo.jpg .(alt text) *]
16
+ *
17
+ * Also supports linked images:
18
+ * "[* https://example.com/photo.jpg *]":https://example.com
19
+ */
20
+ export declare function imageEmbedPlugin(options?: ImageEmbedPluginOptions): TexyParserPlugin;
@@ -0,0 +1,9 @@
1
+ export { youtubePlugin } from './youtube';
2
+ export type { YouTubePluginOptions } from './youtube';
3
+ export { smileyPlugin } from './smiley';
4
+ export type { SmileyPluginOptions } from './smiley';
5
+ export { linkRedirectPlugin } from './link-redirect';
6
+ export type { LinkRedirectPluginOptions } from './link-redirect';
7
+ export { bbcodePlugin } from './bbcode';
8
+ export { imageEmbedPlugin } from './image-embed';
9
+ export type { ImageEmbedPluginOptions } from './image-embed';
@@ -0,0 +1,18 @@
1
+ import type { TexyParserPlugin } from '../../types';
2
+ export interface LinkRedirectPluginOptions {
3
+ /** Redirect service base URL (required) */
4
+ redirectUrl: string;
5
+ /** Domains to exclude from redirect (e.g., own domain) */
6
+ excludeDomains?: string[];
7
+ /** Add target="_blank" to external links (default: true) */
8
+ targetBlank?: boolean;
9
+ /** Add rel="noopener noreferrer" (default: true) */
10
+ noopener?: boolean;
11
+ }
12
+ /**
13
+ * Link redirect plugin for TexyParser.
14
+ *
15
+ * Rewrites external links to go through a redirect service,
16
+ * useful for tracking and safety. Adds target="_blank" to external links.
17
+ */
18
+ export declare function linkRedirectPlugin(options: LinkRedirectPluginOptions): TexyParserPlugin;
@@ -0,0 +1,18 @@
1
+ import type { TexyParserPlugin } from '../../types';
2
+ export interface SmileyPluginOptions {
3
+ /** Base URL for smiley images (required) */
4
+ baseUrl: string;
5
+ /** Image format extension (default: 'gif') */
6
+ format?: string;
7
+ /** Optional ARIA labels map: smiley ID → label text */
8
+ ariaLabels?: Record<string, string>;
9
+ /** CSS class for smiley images */
10
+ className?: string;
11
+ }
12
+ /**
13
+ * Smiley/emoticon plugin for TexyParser.
14
+ *
15
+ * Converts *ID* syntax to smiley images:
16
+ * *123* → <img src="baseUrl/123.gif" alt="smiley" class="smiley">
17
+ */
18
+ export declare function smileyPlugin(options: SmileyPluginOptions): TexyParserPlugin;
@@ -0,0 +1,23 @@
1
+ import type { TexyParserPlugin } from '../../types';
2
+ export interface YouTubePluginOptions {
3
+ /** Iframe width (default: 560) */
4
+ width?: number;
5
+ /** Iframe height (default: 315) */
6
+ height?: number;
7
+ /** Allow fullscreen (default: true) */
8
+ allowFullscreen?: boolean;
9
+ /** Responsive wrapper CSS class */
10
+ wrapperClass?: string;
11
+ }
12
+ /**
13
+ * YouTube embed plugin for TexyParser.
14
+ *
15
+ * Supports Texy image syntax with youtube: prefix:
16
+ * [* youtube:VIDEO_ID *]
17
+ *
18
+ * Also converts YouTube URLs in image syntax:
19
+ * [* https://www.youtube.com/watch?v=ID *]
20
+ * [* https://youtu.be/ID *]
21
+ * [* https://www.youtube.com/shorts/ID *]
22
+ */
23
+ export declare function youtubePlugin(options?: YouTubePluginOptions): TexyParserPlugin;
@@ -0,0 +1,279 @@
1
+ /**
2
+ * Public API type definitions for @nks-hub/texy-editor
3
+ */
4
+ export interface TexyEditorOptions {
5
+ /** Language code for i18n strings */
6
+ language?: string;
7
+ /** Toolbar button configuration */
8
+ toolbar?: ToolbarConfig;
9
+ /** Bottom-left toolbar buttons */
10
+ bottomLeftToolbar?: string[];
11
+ /** Bottom-right toolbar buttons (edit mode) */
12
+ bottomRightEditToolbar?: string[];
13
+ /** Bottom-right toolbar buttons (preview mode) */
14
+ bottomRightPreviewToolbar?: string[];
15
+ /** Editor width (CSS value) */
16
+ width?: string;
17
+ /** Initial view mode */
18
+ defaultView?: ViewMode;
19
+ /** Server-side preview endpoint URL */
20
+ previewPath?: string | null;
21
+ /** Texy config string sent with preview AJAX */
22
+ texyCfg?: string;
23
+ /** Enable client-side live preview */
24
+ livePreview?: boolean;
25
+ /** Live preview debounce delay in ms */
26
+ livePreviewDelay?: number;
27
+ /** Theme preset name or custom CSS class */
28
+ theme?: 'light' | 'dark' | string;
29
+ /** Enable split view (editor + preview side by side) */
30
+ splitView?: boolean;
31
+ /** Enable fullscreen toggle */
32
+ fullscreen?: boolean;
33
+ /** Enable auto-resize textarea */
34
+ autoResize?: boolean;
35
+ /** Max undo history steps */
36
+ maxUndoSteps?: number;
37
+ /** Keyboard shortcuts map override */
38
+ shortcuts?: Record<string, string>;
39
+ /** File upload handler */
40
+ uploadHandler?: UploadHandler | null;
41
+ /** Mention autocomplete data source */
42
+ mentionSource?: MentionSource | null;
43
+ /** Custom CSS variables override */
44
+ cssVars?: Record<string, string>;
45
+ /** Plugins to load */
46
+ plugins?: TexyPlugin[];
47
+ /** ARIA label for the editor */
48
+ ariaLabel?: string;
49
+ }
50
+ export type ToolbarItem = string | null | ToolbarGroup | ToolbarCustomButton;
51
+ export type ToolbarConfig = ToolbarItem[];
52
+ export interface ToolbarGroup {
53
+ type: 'group';
54
+ label?: string;
55
+ items: string[];
56
+ }
57
+ export interface ToolbarCustomButton {
58
+ type: 'button';
59
+ name: string;
60
+ icon?: string;
61
+ label: string;
62
+ action: (editor: TexyEditorAPI) => void;
63
+ }
64
+ export type ViewMode = 'edit' | 'preview' | 'split';
65
+ export interface TexyEditorEvents {
66
+ 'change': {
67
+ value: string;
68
+ };
69
+ 'view:change': {
70
+ mode: ViewMode;
71
+ };
72
+ 'toolbar:action': {
73
+ button: string;
74
+ };
75
+ 'preview:render': {
76
+ html: string;
77
+ };
78
+ 'upload:start': {
79
+ file: File;
80
+ };
81
+ 'upload:complete': {
82
+ url: string;
83
+ file: File;
84
+ };
85
+ 'upload:error': {
86
+ error: Error;
87
+ file: File;
88
+ };
89
+ 'fullscreen:toggle': {
90
+ active: boolean;
91
+ };
92
+ 'undo': void;
93
+ 'redo': void;
94
+ 'focus': void;
95
+ 'blur': void;
96
+ 'mention:query': {
97
+ query: string;
98
+ };
99
+ 'plugin:init': {
100
+ name: string;
101
+ };
102
+ 'destroy': void;
103
+ }
104
+ export type TexyEventHandler<T> = (data: T) => void;
105
+ export interface TexyPlugin {
106
+ name: string;
107
+ init(editor: TexyEditorAPI): void;
108
+ destroy?(): void;
109
+ }
110
+ export interface TexyPluginWindowConfig {
111
+ name: string;
112
+ title: string;
113
+ width?: number;
114
+ height?: number;
115
+ createContent(editor: TexyEditorAPI): HTMLElement;
116
+ onSubmit(editor: TexyEditorAPI, content: HTMLElement): void;
117
+ }
118
+ export interface UploadHandler {
119
+ upload(file: File): Promise<UploadResult>;
120
+ accept?: string;
121
+ maxSize?: number;
122
+ }
123
+ export interface UploadResult {
124
+ url: string;
125
+ alt?: string;
126
+ width?: number;
127
+ height?: number;
128
+ }
129
+ export interface MentionSource {
130
+ search(query: string): Promise<MentionItem[]>;
131
+ template?: (item: MentionItem) => string;
132
+ }
133
+ export interface MentionItem {
134
+ id: string;
135
+ label: string;
136
+ avatar?: string;
137
+ description?: string;
138
+ }
139
+ export interface TexyEditorStrings {
140
+ bold: string;
141
+ italic: string;
142
+ deleted: string;
143
+ inserted: string;
144
+ superscript: string;
145
+ subscript: string;
146
+ code: string;
147
+ codeBlock: string;
148
+ heading1: string;
149
+ heading2: string;
150
+ heading3: string;
151
+ heading4: string;
152
+ link: string;
153
+ linkUrl: string;
154
+ linkText: string;
155
+ image: string;
156
+ imageUrl: string;
157
+ imageAlt: string;
158
+ imageAlign: string;
159
+ unorderedList: string;
160
+ orderedList: string;
161
+ blockquote: string;
162
+ horizontalRule: string;
163
+ table: string;
164
+ tableRows: string;
165
+ tableCols: string;
166
+ color: string;
167
+ symbol: string;
168
+ acronym: string;
169
+ acronymTitle: string;
170
+ alignLeft: string;
171
+ alignRight: string;
172
+ alignCenter: string;
173
+ alignJustify: string;
174
+ indent: string;
175
+ unindent: string;
176
+ fullscreen: string;
177
+ preview: string;
178
+ edit: string;
179
+ splitView: string;
180
+ undo: string;
181
+ redo: string;
182
+ upload: string;
183
+ uploadDragDrop: string;
184
+ previewEmpty: string;
185
+ previewLoading: string;
186
+ headingPrompt: string;
187
+ ok: string;
188
+ cancel: string;
189
+ close: string;
190
+ }
191
+ export interface TexyEditorAPI {
192
+ /** Get current textarea value */
193
+ getValue(): string;
194
+ /** Set textarea value */
195
+ setValue(value: string): void;
196
+ /** Get selected text */
197
+ getSelection(): string;
198
+ /** Replace selection with text */
199
+ replaceSelection(text: string): void;
200
+ /** Wrap selection with prefix/suffix */
201
+ wrapSelection(prefix: string, suffix: string): void;
202
+ /** Insert text at cursor */
203
+ insertAtCursor(text: string): void;
204
+ /** Focus the textarea */
205
+ focus(): void;
206
+ /** Switch view mode */
207
+ setView(mode: ViewMode): void;
208
+ /** Get current view mode */
209
+ getView(): ViewMode;
210
+ /** Execute a toolbar button action by name */
211
+ execAction(name: string): void;
212
+ /** Subscribe to editor event */
213
+ on<K extends keyof TexyEditorEvents>(event: K, handler: TexyEventHandler<TexyEditorEvents[K]>): void;
214
+ /** Unsubscribe from editor event */
215
+ off<K extends keyof TexyEditorEvents>(event: K, handler: TexyEventHandler<TexyEditorEvents[K]>): void;
216
+ /** Undo last change */
217
+ undo(): void;
218
+ /** Redo last undone change */
219
+ redo(): void;
220
+ /** Open a plugin dialog window */
221
+ openWindow(name: string): void;
222
+ /** Close a plugin dialog window */
223
+ closeWindow(name: string): void;
224
+ /** Toggle fullscreen */
225
+ toggleFullscreen(): void;
226
+ /** Get the underlying textarea element */
227
+ getTextarea(): HTMLTextAreaElement;
228
+ /** Get the editor container element */
229
+ getContainer(): HTMLElement;
230
+ /** Get the i18n strings */
231
+ getStrings(): TexyEditorStrings;
232
+ /** Destroy the editor and restore original textarea */
233
+ destroy(): void;
234
+ }
235
+ export interface SelectionState {
236
+ start: number;
237
+ end: number;
238
+ text: string;
239
+ before: string;
240
+ after: string;
241
+ }
242
+ export interface TexyParseRule {
243
+ name: string;
244
+ /** Priority (lower = runs first) */
245
+ priority: number;
246
+ /** Process block-level content */
247
+ block?: (text: string) => string;
248
+ /** Process inline content */
249
+ inline?: (text: string) => string;
250
+ }
251
+ export interface TexyParserOptions {
252
+ rules?: TexyParseRule[];
253
+ plugins?: TexyParserPlugin[];
254
+ enableTypography?: boolean;
255
+ enableAutolinks?: boolean;
256
+ }
257
+ /**
258
+ * Parser plugin interface for extending Texy syntax.
259
+ * Plugins can hook into multiple stages of the parsing pipeline.
260
+ */
261
+ export interface TexyParserPlugin {
262
+ name: string;
263
+ /**
264
+ * Preprocess source text before any parsing (raw Texy input).
265
+ * Useful for converting custom syntax to standard Texy or placeholders.
266
+ */
267
+ preprocess?: (text: string) => string;
268
+ /**
269
+ * Process inline content during inline parsing phase.
270
+ * Receives text with placeholders already extracted (noTexy, code, images, links).
271
+ * Use the provided placeholder function to protect generated HTML.
272
+ */
273
+ processInline?: (text: string, placeholder: (html: string) => string) => string;
274
+ /**
275
+ * Postprocess final HTML output.
276
+ * Useful for expanding placeholders, adding wrappers, or final transformations.
277
+ */
278
+ postprocess?: (html: string) => string;
279
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nks-hub/texy-editor",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Modern TypeScript Texy markup editor with configurable toolbar, live preview, theming, and plugin system",
5
5
  "type": "module",
6
6
  "main": "./dist/texy-editor.cjs",