markdown-actions 1.0.8 → 1.0.9

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/src/index.js CHANGED
@@ -156,83 +156,122 @@ export function insertHeader(textarea, level = 1, toggle = false) {
156
156
  if (!textarea || textarea.disabled || textarea.readOnly) return
157
157
  if (level < 1 || level > 6) level = 1
158
158
 
159
+ debugLog('insertHeader', `============ START ============`);
159
160
  debugLog('insertHeader', `Level: ${level}, Toggle: ${toggle}`);
161
+ debugLog('insertHeader', `Initial cursor: ${textarea.selectionStart}-${textarea.selectionEnd}`);
160
162
 
161
163
  const headerKey = `header${level === 1 ? '1' : level}`
162
164
  const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1)
165
+ debugLog('insertHeader', `Style prefix: "${style.prefix}"`);
163
166
 
164
- // Save original cursor position
167
+ // Save original positions and get line info BEFORE applyLineOperation
168
+ const value = textarea.value
165
169
  const originalStart = textarea.selectionStart
166
170
  const originalEnd = textarea.selectionEnd
167
- const value = textarea.value
168
171
 
169
- // Find line boundaries
172
+ // Find the current line boundaries to check existing header
170
173
  let lineStart = originalStart
171
174
  while (lineStart > 0 && value[lineStart - 1] !== '\n') {
172
175
  lineStart--
173
176
  }
174
-
175
177
  let lineEnd = originalEnd
176
178
  while (lineEnd < value.length && value[lineEnd] !== '\n') {
177
179
  lineEnd++
178
180
  }
179
181
 
180
- // Get the current line
181
- const currentLine = value.slice(lineStart, lineEnd)
182
- debugLog('insertHeader', `Current line: "${currentLine}"`);
182
+ // Get current line and check for existing header
183
+ const currentLineContent = value.slice(lineStart, lineEnd)
184
+ debugLog('insertHeader', `Current line (before): "${currentLineContent}"`);
183
185
 
184
- // Check for existing header
185
- const existingHeaderMatch = currentLine.match(/^(#{1,6})\s*/)
186
+ const existingHeaderMatch = currentLineContent.match(/^(#{1,6})\s*/)
186
187
  const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0
187
188
  const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0
188
189
 
189
- debugLog('insertHeader', `Existing level: ${existingLevel}, Target level: ${level}`);
190
-
191
- // Determine the new line content
192
- let newLine
193
- let prefixChange = 0
194
-
195
- if (toggle && existingLevel === level) {
196
- // Toggle off - remove the header
197
- debugLog('insertHeader', 'Toggling OFF header');
198
- newLine = currentLine.replace(/^#{1,6}\s*/, '')
199
- prefixChange = -existingPrefixLength
200
- } else if (existingLevel > 0) {
201
- // Replace existing header with new one
202
- debugLog('insertHeader', 'Replacing header');
203
- const cleanedLine = currentLine.replace(/^#{1,6}\s*/, '')
204
- newLine = style.prefix + cleanedLine
205
- prefixChange = style.prefix.length - existingPrefixLength
206
- } else {
207
- // Add new header
208
- debugLog('insertHeader', 'Adding new header');
209
- newLine = style.prefix + currentLine
210
- prefixChange = style.prefix.length
211
- }
190
+ debugLog('insertHeader', `Existing header check:`);
191
+ debugLog('insertHeader', ` - Match: ${existingHeaderMatch ? `"${existingHeaderMatch[0]}"` : 'none'}`);
192
+ debugLog('insertHeader', ` - Existing level: ${existingLevel}`);
193
+ debugLog('insertHeader', ` - Existing prefix length: ${existingPrefixLength}`);
194
+ debugLog('insertHeader', ` - Target level: ${level}`);
212
195
 
213
- // Build the result
214
- const result = {
215
- text: newLine,
216
- selectionStart: lineStart,
217
- selectionEnd: lineEnd
218
- }
196
+ // Determine if we're toggling off
197
+ const shouldToggleOff = toggle && existingLevel === level
198
+ debugLog('insertHeader', `Should toggle OFF: ${shouldToggleOff} (toggle=${toggle}, existingLevel=${existingLevel}, level=${level})`);
219
199
 
220
- // Adjust cursor position based on prefix change
221
- if (originalStart === originalEnd) {
222
- // No selection - adjust cursor position
223
- result.selectionStart = Math.max(originalStart + prefixChange, lineStart)
224
- result.selectionEnd = result.selectionStart
225
- } else {
226
- // Has selection - preserve it with adjustment
227
- result.selectionStart = Math.max(originalStart + prefixChange, lineStart)
228
- result.selectionEnd = Math.max(originalEnd + prefixChange, lineStart)
229
- }
230
-
231
- debugLog('insertHeader', `Result: "${result.text}" (${result.selectionStart}, ${result.selectionEnd})`);
200
+ // Use applyLineOperation for consistent behavior
201
+ const result = applyLineOperation(
202
+ textarea,
203
+ (ta) => {
204
+ const currentLine = ta.value.slice(ta.selectionStart, ta.selectionEnd)
205
+ debugLog('insertHeader', `Line in operation: "${currentLine}"`);
206
+
207
+ // Remove any existing header formatting
208
+ const cleanedLine = currentLine.replace(/^#{1,6}\s*/, '')
209
+ debugLog('insertHeader', `Cleaned line: "${cleanedLine}"`);
210
+
211
+ let newLine
212
+
213
+ if (shouldToggleOff) {
214
+ // Toggle off - just use the cleaned line
215
+ debugLog('insertHeader', 'ACTION: Toggling OFF - removing header');
216
+ newLine = cleanedLine
217
+ } else if (existingLevel > 0) {
218
+ // Replace existing header with new one
219
+ debugLog('insertHeader', `ACTION: Replacing H${existingLevel} with H${level}`);
220
+ newLine = style.prefix + cleanedLine
221
+ } else {
222
+ // Add new header
223
+ debugLog('insertHeader', 'ACTION: Adding new header');
224
+ newLine = style.prefix + cleanedLine
225
+ }
226
+
227
+ debugLog('insertHeader', `New line: "${newLine}"`);
228
+
229
+ return {
230
+ text: newLine,
231
+ selectionStart: ta.selectionStart,
232
+ selectionEnd: ta.selectionEnd
233
+ }
234
+ },
235
+ {
236
+ prefix: style.prefix,
237
+ // Custom selection adjustment for headers
238
+ adjustSelection: (isRemoving, selStart, selEnd, lineStartPos) => {
239
+ debugLog('insertHeader', `Adjusting selection:`);
240
+ debugLog('insertHeader', ` - isRemoving param: ${isRemoving}`);
241
+ debugLog('insertHeader', ` - shouldToggleOff: ${shouldToggleOff}`);
242
+ debugLog('insertHeader', ` - selStart: ${selStart}, selEnd: ${selEnd}`);
243
+ debugLog('insertHeader', ` - lineStartPos: ${lineStartPos}`);
244
+
245
+ if (shouldToggleOff) {
246
+ // Removing the header entirely
247
+ const adjustment = Math.max(selStart - existingPrefixLength, lineStartPos)
248
+ debugLog('insertHeader', ` - Removing header, adjusting by -${existingPrefixLength}`);
249
+ return {
250
+ start: adjustment,
251
+ end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)
252
+ }
253
+ } else if (existingPrefixLength > 0) {
254
+ // Replacing existing header with new one
255
+ const prefixDiff = style.prefix.length - existingPrefixLength
256
+ debugLog('insertHeader', ` - Replacing header, adjusting by ${prefixDiff}`);
257
+ return {
258
+ start: selStart + prefixDiff,
259
+ end: selEnd + prefixDiff
260
+ }
261
+ } else {
262
+ // Adding new header
263
+ debugLog('insertHeader', ` - Adding header, adjusting by +${style.prefix.length}`);
264
+ return {
265
+ start: selStart + style.prefix.length,
266
+ end: selEnd + style.prefix.length
267
+ }
268
+ }
269
+ }
270
+ }
271
+ )
232
272
 
233
- // Expand selection to full line for replacement
234
- textarea.selectionStart = lineStart
235
- textarea.selectionEnd = lineEnd
273
+ debugLog('insertHeader', `Final result: text="${result.text}", cursor=${result.selectionStart}-${result.selectionEnd}`);
274
+ debugLog('insertHeader', `============ END ============`);
236
275
 
237
276
  insertText(textarea, result)
238
277
  }