2025-09-13 12:20:50 -04:00
|
|
|
#!/usr/bin/env node
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Updates attachment links in markdown files after files are moved to Organized folder
|
|
|
|
|
* Usage: node .scripts/update-attachment-links.js [specific-file.ext]
|
2025-09-15 08:49:07 -04:00
|
|
|
*
|
2025-09-13 12:20:50 -04:00
|
|
|
* If no argument provided, updates all files in Organized folder
|
|
|
|
|
* If specific filename provided, only updates references to that file
|
|
|
|
|
*/
|
|
|
|
|
|
2025-09-15 08:49:07 -04:00
|
|
|
import fs from 'node:fs'
|
|
|
|
|
import path from 'node:path'
|
2025-09-13 12:20:50 -04:00
|
|
|
|
2025-10-12 21:04:59 -04:00
|
|
|
const organizedDir = '05_Attachments/Organized'
|
2025-09-15 08:49:07 -04:00
|
|
|
const args = process.argv.slice(2)
|
|
|
|
|
const specificFile = args[0]
|
2025-09-13 12:20:50 -04:00
|
|
|
|
|
|
|
|
// Get list of files to update references for
|
2025-09-15 08:49:07 -04:00
|
|
|
let filesToUpdate = []
|
2025-09-13 12:20:50 -04:00
|
|
|
|
|
|
|
|
if (specificFile) {
|
2025-09-15 08:49:07 -04:00
|
|
|
// Update references for a specific file
|
|
|
|
|
filesToUpdate = [specificFile]
|
|
|
|
|
console.log(`Updating references for: ${specificFile}`)
|
|
|
|
|
} else if (fs.existsSync(organizedDir)) {
|
|
|
|
|
// Update references for all files in Organized folder
|
|
|
|
|
filesToUpdate = fs.readdirSync(organizedDir)
|
|
|
|
|
console.log(`Found ${filesToUpdate.length} files in Organized folder`)
|
2025-09-13 12:20:50 -04:00
|
|
|
} else {
|
2025-09-15 08:49:07 -04:00
|
|
|
console.log('Organized folder does not exist yet')
|
|
|
|
|
process.exit(0)
|
2025-09-13 12:20:50 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Function to walk directory
|
|
|
|
|
function walkDir(dir, callback) {
|
2025-09-15 08:49:07 -04:00
|
|
|
fs.readdirSync(dir).forEach((f) => {
|
|
|
|
|
const dirPath = path.join(dir, f)
|
|
|
|
|
const isDirectory = fs.statSync(dirPath).isDirectory()
|
|
|
|
|
if (isDirectory) {
|
|
|
|
|
// Skip node_modules, .git, and the Organized folder itself
|
|
|
|
|
if (
|
|
|
|
|
!f.includes('node_modules') &&
|
|
|
|
|
!f.includes('.git') &&
|
|
|
|
|
dirPath !== organizedDir
|
|
|
|
|
) {
|
|
|
|
|
walkDir(dirPath, callback)
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
callback(path.join(dir, f))
|
|
|
|
|
}
|
|
|
|
|
})
|
2025-09-13 12:20:50 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Process all markdown files
|
2025-09-15 08:49:07 -04:00
|
|
|
let updatedCount = 0
|
|
|
|
|
const updatedFiles = []
|
2025-09-13 12:20:50 -04:00
|
|
|
|
|
|
|
|
walkDir('.', (filepath) => {
|
2025-09-15 08:49:07 -04:00
|
|
|
if (filepath.endsWith('.md')) {
|
|
|
|
|
let content = fs.readFileSync(filepath, 'utf8')
|
|
|
|
|
const originalContent = content
|
|
|
|
|
|
|
|
|
|
// For each file to update, fix references
|
|
|
|
|
filesToUpdate.forEach((filename) => {
|
|
|
|
|
// Escape special regex characters in filename
|
|
|
|
|
const escapedFile = filename.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
|
|
|
|
|
|
|
|
// Pattern 1: ![[filename]] without path
|
|
|
|
|
const pattern1 = new RegExp(`!\\[\\[${escapedFile}\\]\\]`, 'g')
|
|
|
|
|
content = content.replace(
|
|
|
|
|
pattern1,
|
2025-10-12 21:04:59 -04:00
|
|
|
`![[05_Attachments/Organized/${filename}]]`,
|
2025-09-15 08:49:07 -04:00
|
|
|
)
|
|
|
|
|
|
2025-10-12 21:04:59 -04:00
|
|
|
// Pattern 2: ![[05_Attachments/filename]] (file in root being moved)
|
2025-09-15 08:49:07 -04:00
|
|
|
const pattern2 = new RegExp(
|
2025-10-12 21:04:59 -04:00
|
|
|
`!\\[\\[05_Attachments/${escapedFile}\\]\\]`,
|
2025-09-15 08:49:07 -04:00
|
|
|
'g',
|
|
|
|
|
)
|
|
|
|
|
content = content.replace(
|
|
|
|
|
pattern2,
|
2025-10-12 21:04:59 -04:00
|
|
|
`![[05_Attachments/Organized/${filename}]]`,
|
2025-09-15 08:49:07 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Pattern 3: [[filename]] without ! (for PDFs and other non-embedded links)
|
|
|
|
|
// Only if not already pointing to Organized
|
|
|
|
|
const pattern3 = new RegExp(`\\[\\[${escapedFile}\\]\\]`, 'g')
|
|
|
|
|
const pattern3Organized = new RegExp(
|
2025-10-12 21:04:59 -04:00
|
|
|
`\\[\\[05_Attachments/Organized/${escapedFile}\\]\\]`,
|
2025-09-15 08:49:07 -04:00
|
|
|
'g',
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Only replace if not already pointing to Organized and not preceded by !
|
|
|
|
|
if (!pattern3Organized.test(content)) {
|
|
|
|
|
content = content.replace(
|
|
|
|
|
pattern3,
|
2025-10-12 21:04:59 -04:00
|
|
|
`[[05_Attachments/Organized/${filename}]]`,
|
2025-09-15 08:49:07 -04:00
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-12 21:04:59 -04:00
|
|
|
// Pattern 4: [[05_Attachments/filename]] without !
|
2025-09-15 08:49:07 -04:00
|
|
|
const pattern4 = new RegExp(
|
2025-10-12 21:04:59 -04:00
|
|
|
`\\[\\[05_Attachments/${escapedFile}\\]\\]`,
|
2025-09-15 08:49:07 -04:00
|
|
|
'g',
|
|
|
|
|
)
|
|
|
|
|
content = content.replace(
|
|
|
|
|
pattern4,
|
2025-10-12 21:04:59 -04:00
|
|
|
`[[05_Attachments/Organized/${filename}]]`,
|
2025-09-15 08:49:07 -04:00
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Write back if changed
|
|
|
|
|
if (content !== originalContent) {
|
|
|
|
|
fs.writeFileSync(filepath, content, 'utf8')
|
|
|
|
|
updatedFiles.push(filepath)
|
|
|
|
|
updatedCount++
|
2025-09-13 12:20:50 -04:00
|
|
|
}
|
2025-09-15 08:49:07 -04:00
|
|
|
}
|
|
|
|
|
})
|
2025-09-13 12:20:50 -04:00
|
|
|
|
|
|
|
|
// Report results
|
|
|
|
|
if (updatedCount > 0) {
|
2025-09-15 08:49:07 -04:00
|
|
|
console.log(`\nUpdated ${updatedCount} files:`)
|
|
|
|
|
updatedFiles.forEach((file) => console.log(` - ${file}`))
|
2025-09-13 12:20:50 -04:00
|
|
|
} else {
|
2025-09-15 08:49:07 -04:00
|
|
|
console.log('\nNo files needed updating')
|
2025-09-13 12:20:50 -04:00
|
|
|
}
|
|
|
|
|
|
2025-09-15 08:49:07 -04:00
|
|
|
console.log('\nDone!')
|