Files
dwroller/scripts/normalize-rules-db.js

84 lines
2.8 KiB
JavaScript

#!/usr/bin/env node
const path = require('path');
const fs = require('fs');
const { db, logToFile } = require('../database/sqlite-db');
function nowTs() { return new Date().toISOString().replace(/[:.]/g,'-'); }
function titleCase(str) {
return str.toLowerCase().split(/\s+/).map(w => {
if (!w) return '';
return w[0].toUpperCase() + w.slice(1);
}).join(' ');
}
function cleanTitle(title) {
if (!title) return title;
const letters = title.replace(/[^A-Za-z]/g,'');
const uppers = (title.match(/[A-Z]/g) || []).length;
// if mostly uppercase, convert to title case
if (letters && (uppers / letters.length) > 0.5) {
return titleCase(title.replace(/\s+/g,' ').trim());
}
// otherwise trim
return title.trim();
}
function cleanContent(text) {
if (!text) return text;
let s = String(text);
s = s.replace(/\r\n/g, '\n');
s = s.replace(/[ \t]+/g, ' ');
// remove hyphenation at line breaks
s = s.replace(/-\n\s*/g, '');
// collapse more than 2 newlines into paragraph breaks
s = s.replace(/\n{3,}/g, '\n\n');
// join lines that look like soft-wrapped lines: a line break between
// a non-punctuation end and a lowercase/digit start
s = s.replace(/([^\.\!\?\:\;\"\'\)\]\}])\n(\s*[a-z0-9])/g, '$1 $2');
// trim spaces at start/end of lines
s = s.split('\n').map(l => l.trim()).join('\n');
// collapse repeated spaces
s = s.replace(/ {2,}/g, ' ');
// trim overall
s = s.trim();
return s;
}
function backupRules(rows) {
const backupDir = path.join(__dirname, '..', 'database', 'backups');
if (!fs.existsSync(backupDir)) fs.mkdirSync(backupDir, { recursive: true });
const file = path.join(backupDir, `rules-backup-${nowTs()}.json`);
fs.writeFileSync(file, JSON.stringify({ backedAt: new Date().toISOString(), count: rows.length, rows }, null, 2), 'utf8');
return file;
}
function main() {
console.log('Backing up rules table and normalizing content...');
const rows = db.prepare('SELECT id, title, content FROM rules').all();
if (!rows || rows.length === 0) {
console.log('No rules found in DB. Exiting.');
return;
}
const backupFile = backupRules(rows);
console.log('Backup written to', backupFile);
const updateStmt = db.prepare('UPDATE rules SET title = ?, content = ? WHERE id = ?');
let changed = 0;
db.transaction(() => {
for (const r of rows) {
const cleanedTitle = cleanTitle(r.title || '');
const cleanedContent = cleanContent(r.content || '');
if ((cleanedTitle !== (r.title||'').trim()) || (cleanedContent !== (r.content||'').trim())) {
updateStmt.run(cleanedTitle, cleanedContent, r.id);
changed++;
}
}
})();
console.log(`Normalization complete. Rows updated: ${changed}`);
logToFile('normalize-rules-db: completed', { updated: changed });
}
main();