From 3d0eb2ac060f0476555dc3b6e0aaa87ae96f479f Mon Sep 17 00:00:00 2001 From: mpstaton Date: Tue, 8 Jul 2025 19:24:11 +0300 Subject: [PATCH] feat(clean-references): add reference cleanup service with colon formatting - Implement cleanReferencesSectionService with addColonSyntaxWhereNone function - Add command to format footnote references with consistent colon syntax - Fix regex to handle various footnote reference formats - Preserve leading whitespace and ensure single space after colon - Add TypeScript type safety with proper null checks - Integrate with main plugin command registry The new command formats footnote references from: [^hexId] Text... to: [^hexId]: Text... This improves consistency in citation formatting throughout documents. On branch development Changes to be committed: modified: main.ts new file: src/services/cleanReferencesSectionService.ts --- main.ts | 21 ++++++ src/services/cleanReferencesSectionService.ts | 65 +++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 src/services/cleanReferencesSectionService.ts diff --git a/main.ts b/main.ts index b88929c..6a7c395 100644 --- a/main.ts +++ b/main.ts @@ -1,6 +1,7 @@ import { Notice, Plugin, Editor } from 'obsidian'; import { citationService } from './src/services/citationService'; import { CitationModal } from './src/modals/CitationModal'; +import { cleanReferencesSectionService } from './src/services/cleanReferencesSectionService'; export default class CiteWidePlugin extends Plugin { async onload(): Promise { @@ -9,6 +10,7 @@ export default class CiteWidePlugin extends Plugin { // Register commands this.registerCitationCommands(); + this.registerReferenceCleanupCommands(); } private async loadStyles() { @@ -106,4 +108,23 @@ export default class CiteWidePlugin extends Plugin { } }); } + + private registerReferenceCleanupCommands(): void { + // Command to clean up references section + this.addCommand({ + id: 'clean-references-section', + name: 'Add Colon to Footnote References in Selection', + editorCallback: (editor: Editor) => { + const selection = editor.getSelection(); + if (!selection) { + new Notice('Please select some text first'); + return; + } + + const processed = cleanReferencesSectionService.addColonSyntaxWhereNone(selection); + editor.replaceSelection(processed); + new Notice('References cleaned up successfully'); + } + }); + } } \ No newline at end of file diff --git a/src/services/cleanReferencesSectionService.ts b/src/services/cleanReferencesSectionService.ts new file mode 100644 index 0000000..bc5fc66 --- /dev/null +++ b/src/services/cleanReferencesSectionService.ts @@ -0,0 +1,65 @@ +/** + * Service for cleaning up and normalizing references sections in markdown content + */ + +/** + * Adds colon syntax to footnote references that are missing it + * @param text The text to process + * @returns The processed text with colons added to footnote references + */ +export function addColonSyntaxWhereNone(text: string): string { + if (!text) return text; + + // Split the text into lines and process each line + return text.split('\n').map(line => { + // Match footnote references that don't have a colon after the ID + // Format: [^hexId] Text... + const footnoteRegex = /^(\s*\[\^([a-z0-9]+)\])(?::?\s*)(.*)$/i; + const match = line.match(footnoteRegex); + + if (match && match[1] && match[2] && match[3] !== undefined) { + const leadingSpaceMatch = match[1].match(/^\s*/); + const leadingSpace = leadingSpaceMatch ? leadingSpaceMatch[0] : ''; + const id = match[2]; + const content = match[3].trimStart(); + // Preserve leading space and ensure exactly one space after the colon + return `${leadingSpace}[^${id}]: ${content}`; + } + + return line; + }).join('\n'); +} + +/** + * Processes the current selection in the active editor to add colon syntax to footnotes + * @returns A promise that resolves when the operation is complete + */ +export async function processSelection(): Promise { + // This function would be called from a command or UI component + // that has access to the Obsidian editor instance + const editor = (window as any).activeEditor?.editor; + + if (!editor) { + console.warn('No active editor found'); + return; + } + + const selection = editor.getSelection(); + if (!selection) { + console.warn('No text selected'); + return; + } + + // Process the selected text + const processedText = addColonSyntaxWhereNone(selection); + + // Replace the selection with the processed text + editor.replaceSelection(processedText); +} + +export const cleanReferencesSectionService = { + addColonSyntaxWhereNone, + processSelection +}; + +export default cleanReferencesSectionService;