Начинать обход дерева `DOM` следует с корневого элемента. В нашем случае рутовым элементов является `body`.
Рекомендация - лучше стараться максимально упрощать требования, чтобы легче получалось обдумывать создаваемый алгоритм.
Начните с простой разметки, а затем добавляйте дополнительные, вложенные элементы.
<span>text1</span><span>text2</span>
Следует сформулировать два вопроса.
1. Как лучше удалять текстовый узел?
2. Как избежать бесконечного вызова рекурсии?
Алгоритм:
1. Вызывая функцию, стартуем обход дерева с элемента `body`. Передаём элемент при первом вызове.
2. Получаем коллекцию дочерних сущностей переданного элемента.
3. Фильтруем сущности с типом `ELEMENT_NODE`, кроме элемента с именем `SCRIPT`.
4. Удаляем сущности с типом `TEXT_NODE` в отдельной итерации или предыдущей итерации. Используем для этого метод `remove` прямо на узле (ответ на первый вопрос).
5. Итерируем только по найденным элементам (ответ на второй вопрос). Вызываем рекурсивно функцию, передавая найденный элемент. Если во вложенном элементе будут найдены только текстовые узлы, повторного вызова функцию не случится для текущей глубины. Но программа возвратится к предыдущей итерации и продолжит рекурсивный вызов со следующими элементами.
UPD. Раз уже есть примеры реализации, добавлю код.
function deleteTextNodesRecursive(element) {
const childNodes = element.childNodes;
var elements = [...childNodes].filter((val) => {
if (val.nodeType === 3) {
val.remove();
}
return val.nodeType === 1 && val.nodeName.toLowerCase() !== 'script';
});
if (elements.length) {
elements.forEach((el) => {
return deleteTextNodesRecursive(el);
});
}
return document.body;
}
console.log(deleteTextNodesRecursive(document.body));