diff --git a/src/modals/CitationModal.ts b/src/modals/CitationModal.ts index 6c559f8..2838f6c 100644 --- a/src/modals/CitationModal.ts +++ b/src/modals/CitationModal.ts @@ -65,20 +65,40 @@ export class CitationModal extends Modal { const [type, number] = key.split(':'); const groupEl = container.createDiv({ cls: 'citation-group' }); - // Create header with toggle functionality + // Create header with toggle functionality and actions const header = groupEl.createDiv({ cls: 'citation-group-header' }); - header.createEl('h3', { - text: `${type === 'footnote' ? 'Footnote' : 'Citation'} [${number}] (${group.matches.length} occurrences)` + + // Header content with integrated To Hex button + const headerContent = header.createDiv({ cls: 'citation-group-header-content' }); + const headerTitle = headerContent.createEl('h3'); + + // Add the title text + headerTitle.createSpan({ + text: `${type === 'footnote' ? 'Footnote' : 'Citation'} [${number}] (${group.matches.length} occurrences)` }); - + + // Add Convert to Hex button next to the title + const convertButton = headerTitle.createEl('button', { + text: 'To Hex', + cls: 'mod-cta', + attr: { 'data-action': 'convert-all-group' } + }); + convertButton.addEventListener('click', (e) => { + e.stopPropagation(); + const firstMatch = group.matches[0]; + if (firstMatch) { + this.convertCitationToHex(firstMatch); + } + }); + // Create content container (initially hidden) const content = groupEl.createDiv({ cls: 'citation-group-content' }); - - // Add toggle functionality + + // Add toggle functionality to header header.onclick = () => { content.style.display = content.style.display === 'none' ? 'block' : 'none'; }; - + // Add each citation context group.matches.forEach((match: CitationMatch) => { const contextEl = content.createDiv({ cls: 'citation-context' }); @@ -89,20 +109,13 @@ export class CitationModal extends Modal { // Add action buttons const actions = contextEl.createDiv({ cls: 'citation-actions' }); - + // View button actions.createEl('button', { text: 'View', cls: 'mod-cta', attr: { 'data-action': 'view' } }).addEventListener('click', () => this.scrollToCitation(match)); - - // Convert to Hex button - actions.createEl('button', { - text: 'To Hex', - cls: 'mod-cta', - attr: { 'data-action': 'convert' } - }).addEventListener('click', () => this.convertCitationToHex(match)); }); }); diff --git a/src/services/citationService.ts b/src/services/citationService.ts index 0550406..69dd705 100644 --- a/src/services/citationService.ts +++ b/src/services/citationService.ts @@ -133,12 +133,49 @@ export class CitationService { return updatedContent; } else { - // For standard footnotes and references - const pattern = matchType === 'footnote' - ? `\\[\\^${targetNumber}\\]` - : `\\[${targetNumber}\\]`; - const regex = new RegExp(pattern, 'g'); - return content.replace(regex, `[^${hexId}]`); + // For standard footnotes and references, replace only the specific instance + const matches = this.basicCitationMatch(content); + const targetMatch = matches.find(m => + m.type === matchType && + m.number === targetNumber && + (matchType === 'perplexity' ? m.lineContent === lineContent : true) + ); + + if (!targetMatch) { + return content; + } + + // For reference type with URL, convert to footnote format and add URL to footnotes + const citationWithUrlPattern = new RegExp(`\\[${targetNumber}\\]\\(([^)]+)\\)`); + if (matchType === 'reference' && citationWithUrlPattern.test(targetMatch.original)) { + // Extract the URL from the original citation + const urlMatch = targetMatch.original.match(citationWithUrlPattern); + const url = urlMatch ? urlMatch[1] : ''; + + // Replace the entire [number](url) with [^hex] + const before = content.substring(0, targetMatch.index); + const after = content.substring(targetMatch.index + targetMatch.original.length); + + // Add the URL to the footnotes section if it doesn't exist + let updatedContent = `${before}[^${hexId}]${after}`; + + // Ensure footnotes section exists + if (!updatedContent.includes('# Footnotes')) { + updatedContent += '\n\n# Footnotes\n'; + } + + // Add the footnote definition if it doesn't exist + if (!updatedContent.includes(`[^${hexId}]:`)) { + updatedContent += `\n[^${hexId}]: ${url}`; + } + + return updatedContent; + } else { + // For other types, just replace the number inside the brackets + const before = content.substring(0, targetMatch.index + (matchType === 'footnote' ? 2 : 1)); + const after = content.substring(targetMatch.index + targetMatch.original.length - 1); + return `${before}${hexId}${after}`; + } } }