Fix counter to update only clicked instance
- Track each counter by its original text instead of label - Use indexOf to find and replace specific counter occurrence - Pass originalText to createCounterElement method - Update both MarkdownPostProcessor and Live Preview widget - Prevents all counters with same label from updating together 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
33
main.ts
33
main.ts
@@ -3,12 +3,12 @@ import { Decoration, DecorationSet, EditorView, WidgetType, ViewPlugin, ViewUpda
|
|||||||
import { RangeSetBuilder } from '@codemirror/state';
|
import { RangeSetBuilder } from '@codemirror/state';
|
||||||
|
|
||||||
class CounterWidget extends WidgetType {
|
class CounterWidget extends WidgetType {
|
||||||
constructor(private value: number, private label: string, private plugin: CounterPlugin) {
|
constructor(private value: number, private label: string, private originalText: string, private plugin: CounterPlugin) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
toDOM(view: EditorView): HTMLElement {
|
toDOM(view: EditorView): HTMLElement {
|
||||||
return this.plugin.createCounterElement(this.value, this.label, {} as MarkdownPostProcessorContext);
|
return this.plugin.createCounterElement(this.value, this.label, this.originalText, {} as MarkdownPostProcessorContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,9 +26,10 @@ function buildCounterDecorations(view: EditorView, plugin: CounterPlugin): Decor
|
|||||||
const endPos = startPos + match[0].length;
|
const endPos = startPos + match[0].length;
|
||||||
const value = match[1] === '' ? 0 : parseInt(match[1], 10);
|
const value = match[1] === '' ? 0 : parseInt(match[1], 10);
|
||||||
const label = match[2].trim();
|
const label = match[2].trim();
|
||||||
|
const originalText = match[0];
|
||||||
|
|
||||||
const widget = Decoration.replace({
|
const widget = Decoration.replace({
|
||||||
widget: new CounterWidget(value, label, plugin),
|
widget: new CounterWidget(value, label, originalText, plugin),
|
||||||
});
|
});
|
||||||
|
|
||||||
builder.add(startPos, endPos, widget);
|
builder.add(startPos, endPos, widget);
|
||||||
@@ -76,7 +77,7 @@ export default class CounterPlugin extends Plugin {
|
|||||||
processCounters(element: HTMLElement, context: MarkdownPostProcessorContext) {
|
processCounters(element: HTMLElement, context: MarkdownPostProcessorContext) {
|
||||||
const counterRegex = /~\s*\(\s*(\d*)\s*\)\s*(.+)/g;
|
const counterRegex = /~\s*\(\s*(\d*)\s*\)\s*(.+)/g;
|
||||||
const walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT);
|
const walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT);
|
||||||
const nodesToReplace: Array<{ node: Node; parent: Node; replacements: Array<{type: 'text' | 'counter', content: string, value?: number, label?: string}> }> = [];
|
const nodesToReplace: Array<{ node: Node; parent: Node; replacements: Array<{type: 'text' | 'counter', content: string, value?: number, label?: string, originalText?: string}> }> = [];
|
||||||
|
|
||||||
let node: Node | null;
|
let node: Node | null;
|
||||||
while ((node = walker.nextNode()) !== null) {
|
while ((node = walker.nextNode()) !== null) {
|
||||||
@@ -84,7 +85,7 @@ export default class CounterPlugin extends Plugin {
|
|||||||
|
|
||||||
if (counterRegex.test(text)) {
|
if (counterRegex.test(text)) {
|
||||||
counterRegex.lastIndex = 0;
|
counterRegex.lastIndex = 0;
|
||||||
const replacements: Array<{type: 'text' | 'counter', content: string, value?: number, label?: string}> = [];
|
const replacements: Array<{type: 'text' | 'counter', content: string, value?: number, label?: string, originalText?: string}> = [];
|
||||||
let lastIndex = 0;
|
let lastIndex = 0;
|
||||||
let match;
|
let match;
|
||||||
|
|
||||||
@@ -103,7 +104,8 @@ export default class CounterPlugin extends Plugin {
|
|||||||
type: 'counter',
|
type: 'counter',
|
||||||
content: match[0],
|
content: match[0],
|
||||||
value: value,
|
value: value,
|
||||||
label: label
|
label: label,
|
||||||
|
originalText: match[0]
|
||||||
});
|
});
|
||||||
|
|
||||||
lastIndex = match.index + match[0].length;
|
lastIndex = match.index + match[0].length;
|
||||||
@@ -132,6 +134,7 @@ export default class CounterPlugin extends Plugin {
|
|||||||
const counterContainer = this.createCounterElement(
|
const counterContainer = this.createCounterElement(
|
||||||
replacement.value!,
|
replacement.value!,
|
||||||
replacement.label!,
|
replacement.label!,
|
||||||
|
replacement.originalText!,
|
||||||
context
|
context
|
||||||
);
|
);
|
||||||
fragment.appendChild(counterContainer);
|
fragment.appendChild(counterContainer);
|
||||||
@@ -147,6 +150,7 @@ export default class CounterPlugin extends Plugin {
|
|||||||
createCounterElement(
|
createCounterElement(
|
||||||
initialValue: number,
|
initialValue: number,
|
||||||
label: string,
|
label: string,
|
||||||
|
originalText: string,
|
||||||
context: MarkdownPostProcessorContext
|
context: MarkdownPostProcessorContext
|
||||||
): HTMLElement {
|
): HTMLElement {
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
@@ -178,19 +182,12 @@ export default class CounterPlugin extends Plugin {
|
|||||||
|
|
||||||
const editor = view.editor;
|
const editor = view.editor;
|
||||||
const content = editor.getValue();
|
const content = editor.getValue();
|
||||||
const counterRegex = /~\s*\(\s*\d*\s*\)\s*(.+)/gm;
|
|
||||||
|
|
||||||
let matchIndex = 0;
|
// Find and replace only the first occurrence of this exact counter text
|
||||||
const newContent = content.replace(counterRegex, (match, capturedLabel) => {
|
const index = content.indexOf(originalText);
|
||||||
const currentLabel = capturedLabel.trim();
|
if (index !== -1) {
|
||||||
if (currentLabel === label) {
|
const newText = `~ (${newValue}) ${label}`;
|
||||||
matchIndex++;
|
const newContent = content.substring(0, index) + newText + content.substring(index + originalText.length);
|
||||||
return `~ (${newValue}) ${label}`;
|
|
||||||
}
|
|
||||||
return match;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (content !== newContent) {
|
|
||||||
editor.setValue(newContent);
|
editor.setValue(newContent);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user