overtype 1.2.2 → 1.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -15
- package/dist/overtype.cjs +393 -40
- package/dist/overtype.cjs.map +2 -2
- package/dist/overtype.d.ts +169 -0
- package/dist/overtype.esm.js +393 -40
- package/dist/overtype.esm.js.map +2 -2
- package/dist/overtype.js +398 -40
- package/dist/overtype.js.map +2 -2
- package/dist/overtype.min.js +97 -74
- package/package.json +4 -2
- package/src/link-tooltip.js +16 -16
- package/src/overtype.d.ts +23 -1
- package/src/overtype.js +167 -13
- package/src/parser.js +276 -55
- package/src/styles.js +16 -8
- package/src/toolbar.js +63 -2
package/src/toolbar.js
CHANGED
|
@@ -7,10 +7,67 @@ import * as icons from './icons.js';
|
|
|
7
7
|
import * as markdownActions from 'markdown-actions';
|
|
8
8
|
|
|
9
9
|
export class Toolbar {
|
|
10
|
-
constructor(editor) {
|
|
10
|
+
constructor(editor, buttonConfig = null) {
|
|
11
11
|
this.editor = editor;
|
|
12
12
|
this.container = null;
|
|
13
13
|
this.buttons = {};
|
|
14
|
+
this.buttonConfig = buttonConfig;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Check if cursor/selection is inside a markdown link
|
|
19
|
+
* @param {HTMLTextAreaElement} textarea - The textarea element
|
|
20
|
+
* @returns {boolean} True if inside a link
|
|
21
|
+
*/
|
|
22
|
+
isInsideLink(textarea) {
|
|
23
|
+
const value = textarea.value;
|
|
24
|
+
const start = textarea.selectionStart;
|
|
25
|
+
const end = textarea.selectionEnd;
|
|
26
|
+
|
|
27
|
+
// Look backwards for [ and forwards for ](
|
|
28
|
+
let insideLink = false;
|
|
29
|
+
let openBracket = -1;
|
|
30
|
+
let closeBracket = -1;
|
|
31
|
+
|
|
32
|
+
// Find the nearest [ before cursor
|
|
33
|
+
for (let i = start - 1; i >= 0; i--) {
|
|
34
|
+
if (value[i] === '[') {
|
|
35
|
+
openBracket = i;
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
if (value[i] === '\n') {
|
|
39
|
+
break; // Links don't span lines
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Find the nearest ]( after cursor
|
|
44
|
+
if (openBracket >= 0) {
|
|
45
|
+
for (let i = end; i < value.length - 1; i++) {
|
|
46
|
+
if (value[i] === ']' && value[i + 1] === '(') {
|
|
47
|
+
closeBracket = i;
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
if (value[i] === '\n') {
|
|
51
|
+
break; // Links don't span lines
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Check if we're inside [...](...)
|
|
57
|
+
if (openBracket >= 0 && closeBracket >= 0) {
|
|
58
|
+
// Also need to verify the ) exists after ](
|
|
59
|
+
for (let i = closeBracket + 2; i < value.length; i++) {
|
|
60
|
+
if (value[i] === ')') {
|
|
61
|
+
insideLink = true;
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
if (value[i] === '\n' || value[i] === ' ') {
|
|
65
|
+
break; // URLs typically don't have spaces or newlines
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return insideLink;
|
|
14
71
|
}
|
|
15
72
|
|
|
16
73
|
/**
|
|
@@ -24,7 +81,7 @@ export class Toolbar {
|
|
|
24
81
|
this.container.setAttribute('aria-label', 'Text formatting');
|
|
25
82
|
|
|
26
83
|
// Define toolbar buttons
|
|
27
|
-
const buttonConfig = [
|
|
84
|
+
const buttonConfig = this.buttonConfig ?? [
|
|
28
85
|
{ name: 'bold', icon: icons.boldIcon, title: 'Bold (Ctrl+B)', action: 'toggleBold' },
|
|
29
86
|
{ name: 'italic', icon: icons.italicIcon, title: 'Italic (Ctrl+I)', action: 'toggleItalic' },
|
|
30
87
|
{ separator: true },
|
|
@@ -136,6 +193,10 @@ export class Toolbar {
|
|
|
136
193
|
markdownActions.insertLink(textarea);
|
|
137
194
|
break;
|
|
138
195
|
case 'toggleCode':
|
|
196
|
+
// Don't allow code formatting inside links
|
|
197
|
+
if (this.isInsideLink(textarea)) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
139
200
|
markdownActions.toggleCode(textarea);
|
|
140
201
|
break;
|
|
141
202
|
case 'toggleBulletList':
|