Remove blank lines from all Sefaria source texts on Source Sheet, button at top
// ==UserScript==
// @name Sefaria Source Sheet Newline Cleaner
// @namespace http://binjomin.hu/
// @version 0.2
// @license MIT
// @description Remove blank lines from all Sefaria source texts on Source Sheet, button at top
// @author Binjomin Szanto-Varnagy
// @match https://*.sefaria.org/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
function hasBlankLines(text) {
const lines = text.split('\n');
return lines.some(line => line.trim() === '');
}
function sourcesHaveBlankLines() {
const textSpans = document.querySelectorAll('.sourceContentText span[data-slate-string="true"]');
for (const span of textSpans) {
if (hasBlankLines(span.textContent)) {
return true;
}
}
return false;
}
function cleanAllSources() {
const containers = document.querySelectorAll('.sourceContentText');
let cleanedCount = 0;
for (const container of containers) {
const textSpans = container.querySelectorAll('span[data-slate-string="true"]');
for (const span of textSpans) {
let lines = span.textContent.split('\n');
const before = lines.length;
lines = lines.filter(line => line.trim().length > 0);
if (lines.length !== before) {
span.textContent = lines.join('\n');
cleanedCount++;
}
}
}
return cleanedCount;
}
function createButton() {
if (document.getElementById('sefaria-clean-btn')) return;
const btn = document.createElement('button');
btn.id = 'sefaria-clean-btn';
btn.textContent = 'Remove Blank Lines from All Sources';
btn.style.position = 'fixed';
btn.style.top = '10px';
btn.style.left = '10px';
btn.style.zIndex = '9999';
btn.style.padding = '8px 12px';
btn.style.fontSize = '14px';
btn.style.backgroundColor = '#007bff';
btn.style.color = 'white';
btn.style.border = 'none';
btn.style.borderRadius = '4px';
btn.style.cursor = 'pointer';
btn.style.boxShadow = '0 2px 6px rgba(0,0,0,0.2)';
btn.title = 'Click to remove blank lines from all Sefaria sources';
btn.addEventListener('click', () => {
const count = cleanAllSources();
if (count > 0) {
btn.textContent = `Blank Lines Removed (${count} spans)`;
btn.style.backgroundColor = '#28a745';
setTimeout(() => {
btn.textContent = 'Remove Blank Lines from All Sources';
btn.style.backgroundColor = '#007bff';
}, 2000);
} else {
btn.textContent = 'No Blank Lines Found';
btn.style.backgroundColor = '#6c757d';
setTimeout(() => {
btn.textContent = 'Remove Blank Lines from All Sources';
btn.style.backgroundColor = '#007bff';
}, 2000);
}
});
document.body.appendChild(btn);
}
function init() {
if (sourcesHaveBlankLines()) {
createButton();
} else {
// Always show the button so user can retry after reload
createButton();
}
}
setTimeout(init, 1500);
const observer = new MutationObserver(() => {
createButton(); // Ensure button exists even after reloads
});
observer.observe(document.body, { childList: true, subtree: true });
})();