Fix counter rendering in Obsidian
- Remove start-of-line anchor from regex to match anywhere in text - Improve text node processing to handle inline counters - Simplify markdown post processor logic - Remove unused editor-change event handler 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
93
main.ts
93
main.ts
@@ -7,16 +7,6 @@ export default class CounterPlugin extends Plugin {
|
|||||||
this.registerMarkdownPostProcessor((element, context) => {
|
this.registerMarkdownPostProcessor((element, context) => {
|
||||||
this.processCounters(element, context);
|
this.processCounters(element, context);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.registerEvent(
|
|
||||||
this.app.workspace.on('editor-change', () => {
|
|
||||||
const view = this.app.workspace.getActiveViewOfType(MarkdownView);
|
|
||||||
if (view) {
|
|
||||||
// Refresh the preview to update counters
|
|
||||||
view.previewMode.rerender(true);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onunload() {
|
onunload() {
|
||||||
@@ -24,51 +14,69 @@ export default class CounterPlugin extends Plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
processCounters(element: HTMLElement, context: MarkdownPostProcessorContext) {
|
processCounters(element: HTMLElement, context: MarkdownPostProcessorContext) {
|
||||||
const counterRegex = /^~\s*\(\s*(\d*)\s*\)\s*(.*)$/;
|
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 }> = [];
|
const nodesToReplace: Array<{ node: Node; parent: Node; replacements: Array<{type: 'text' | 'counter', content: string, value?: number, label?: string}> }> = [];
|
||||||
|
|
||||||
let node: Node | null;
|
let node: Node | null;
|
||||||
while ((node = walker.nextNode()) !== null) {
|
while ((node = walker.nextNode()) !== null) {
|
||||||
const text = node.textContent || '';
|
const text = node.textContent || '';
|
||||||
const lines = text.split('\n');
|
|
||||||
|
|
||||||
lines.forEach((line, index) => {
|
if (counterRegex.test(text)) {
|
||||||
const match = line.match(counterRegex);
|
counterRegex.lastIndex = 0;
|
||||||
if (match && node) {
|
const replacements: Array<{type: 'text' | 'counter', content: string, value?: number, label?: string}> = [];
|
||||||
nodesToReplace.push({ node, parent: node.parentNode! });
|
let lastIndex = 0;
|
||||||
}
|
let match;
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
nodesToReplace.forEach(({ node, parent }) => {
|
while ((match = counterRegex.exec(text)) !== null) {
|
||||||
const text = node.textContent || '';
|
if (match.index > lastIndex) {
|
||||||
const lines = text.split('\n');
|
replacements.push({
|
||||||
const fragment = document.createDocumentFragment();
|
type: 'text',
|
||||||
|
content: text.substring(lastIndex, match.index)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
lines.forEach((line, index) => {
|
const value = match[1] === '' ? 0 : parseInt(match[1], 10);
|
||||||
const match = line.match(counterRegex);
|
|
||||||
|
|
||||||
if (match) {
|
|
||||||
const currentValue = match[1] === '' ? 0 : parseInt(match[1], 10);
|
|
||||||
const label = match[2].trim();
|
const label = match[2].trim();
|
||||||
|
|
||||||
const counterContainer = this.createCounterElement(
|
replacements.push({
|
||||||
currentValue,
|
type: 'counter',
|
||||||
label,
|
content: match[0],
|
||||||
node,
|
value: value,
|
||||||
context
|
label: label
|
||||||
);
|
});
|
||||||
|
|
||||||
fragment.appendChild(counterContainer);
|
lastIndex = match.index + match[0].length;
|
||||||
} else {
|
|
||||||
if (line) {
|
|
||||||
fragment.appendChild(document.createTextNode(line));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index < lines.length - 1) {
|
if (lastIndex < text.length) {
|
||||||
fragment.appendChild(document.createTextNode('\n'));
|
replacements.push({
|
||||||
|
type: 'text',
|
||||||
|
content: text.substring(lastIndex)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (replacements.length > 0) {
|
||||||
|
nodesToReplace.push({ node, parent: node.parentNode!, replacements });
|
||||||
|
}
|
||||||
|
|
||||||
|
counterRegex.lastIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nodesToReplace.forEach(({ node, parent, replacements }) => {
|
||||||
|
const fragment = document.createDocumentFragment();
|
||||||
|
|
||||||
|
replacements.forEach(replacement => {
|
||||||
|
if (replacement.type === 'counter') {
|
||||||
|
const counterContainer = this.createCounterElement(
|
||||||
|
replacement.value!,
|
||||||
|
replacement.label!,
|
||||||
|
context
|
||||||
|
);
|
||||||
|
fragment.appendChild(counterContainer);
|
||||||
|
} else {
|
||||||
|
fragment.appendChild(document.createTextNode(replacement.content));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -79,7 +87,6 @@ export default class CounterPlugin extends Plugin {
|
|||||||
createCounterElement(
|
createCounterElement(
|
||||||
value: number,
|
value: number,
|
||||||
label: string,
|
label: string,
|
||||||
sourceNode: Node,
|
|
||||||
context: MarkdownPostProcessorContext
|
context: MarkdownPostProcessorContext
|
||||||
): HTMLElement {
|
): HTMLElement {
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
|
|||||||
Reference in New Issue
Block a user