Elementor-Ausgabe, Referenzartikel, Redaktionsplan
This commit is contained in:
@@ -68,6 +68,8 @@ KONF = node("Konfiguration", "n8n-nodes-base.set", 3.4, [-240, 190], {
|
||||
{"id": nid(), "name": "wp_base", "value": "https://skrift.de", "type": "string"},
|
||||
{"id": nid(), "name": "score_ziel", "value": "={{ $json.body && $json.body.score_ziel ? Number($json.body.score_ziel) : 72 }}", "type": "number"},
|
||||
{"id": nid(), "name": "pause_zwischen_artikeln", "value": 5, "type": "number"},
|
||||
{"id": nid(), "name": "elementor_ausgabe", "value": True, "type": "boolean"},
|
||||
{"id": nid(), "name": "faq_ueberschrift", "value": "Häufige Fragen", "type": "string"},
|
||||
{"id": nid(), "name": "benachrichtigung_an", "value": "privat@lucas-orth.de", "type": "string"},
|
||||
]}, "options": {}})
|
||||
for t in ["Manuell starten", "Webhook Start"]: link(t, KONF)
|
||||
@@ -170,7 +172,19 @@ while ((m = re.exec(String(artikel.content_html || ''))) !== null) {
|
||||
}
|
||||
const shortcodes = (String(artikel.content_html || '').match(/\[skrift_preis[^\]]*\]/g) || []);
|
||||
|
||||
// NeuronWriter bewertet nur den uebergebenen Text. Kurzantwort und FAQ stehen
|
||||
// aber auf der fertigen Seite, also gehoeren sie in die Bewertung. Der gespeicherte
|
||||
// Artikel bleibt unveraendert, das hier ist nur der Pruefkoerper.
|
||||
const faqText = (Array.isArray(artikel.faq) ? artikel.faq : [])
|
||||
.map(f => `<h3>${f.frage || ''}</h3><p>${f.antwort || ''}</p>`).join('\n');
|
||||
const bewertungs_html = [
|
||||
artikel.kurzantwort ? `<p>${artikel.kurzantwort}</p>` : '',
|
||||
artikel.content_html || '',
|
||||
faqText ? `<h2>Häufige Fragen</h2>\n${faqText}` : '',
|
||||
].filter(Boolean).join('\n');
|
||||
|
||||
return [{ json: { slug: meta.slug, artikel, brief, brief_vorhanden: !!brief,
|
||||
bewertungs_html,
|
||||
preis_warnung: preisTreffer.length
|
||||
? `${preisTreffer.length} ausgeschriebene(r) Preis(e) im Text: ${[...new Set(preisTreffer)].slice(0,5).join(', ')}. `
|
||||
+ 'Bitte durch [skrift_preis key="..."] ersetzen.'
|
||||
@@ -182,7 +196,7 @@ link(BRIEF, PRUEFEN)
|
||||
# ---------------------------------------------------------------- Score
|
||||
EVAL = http("Score ermitteln", [1560, 420], "POST",
|
||||
"={{ $('Konfiguration').first().json.nw_base }}/evaluate-content", CRED_NW,
|
||||
body="={{ JSON.stringify({ query: $json.artikel.query_id, html: $json.artikel.content_html, title: $json.artikel.seo_titel || $json.artikel.titel, description: $json.artikel.seo_beschreibung || '' }) }}")
|
||||
body="={{ JSON.stringify({ query: $json.artikel.query_id, html: $json.bewertungs_html || $json.artikel.content_html, title: $json.artikel.seo_titel || $json.artikel.titel, description: $json.artikel.seo_beschreibung || '' }) }}")
|
||||
link(PRUEFEN, EVAL)
|
||||
|
||||
FEHLER_EVAL = code("Fehler Score", [1560, 640], """
|
||||
@@ -220,7 +234,7 @@ NACH = code("Fehlende Begriffe ermitteln", [2220, 640], r"""
|
||||
const s = $input.first().json;
|
||||
const brief = s.brief;
|
||||
|
||||
const text = String(s.artikel.content_html || '')
|
||||
const text = String(s.bewertungs_html || s.artikel.content_html || '')
|
||||
.replace(/<script[\s\S]*?<\/script>/gi, ' ')
|
||||
.replace(/<style[\s\S]*?<\/style>/gi, ' ')
|
||||
.replace(/<[^>]+>/g, ' ')
|
||||
@@ -333,7 +347,7 @@ link(NACH_COMMIT, NACH_OK, out=0)
|
||||
# ================================================================ ERFOLGS-PFAD
|
||||
IMPORT = http("Revision zu NeuronWriter", [2220, 240], "POST",
|
||||
"={{ $('Konfiguration').first().json.nw_base }}/import-content", CRED_NW,
|
||||
body="={{ JSON.stringify({ query: $json.artikel.query_id, html: $json.artikel.content_html, title: $json.artikel.seo_titel || $json.artikel.titel, description: $json.artikel.seo_beschreibung || '' }) }}")
|
||||
body="={{ JSON.stringify({ query: $json.artikel.query_id, html: $json.bewertungs_html || $json.artikel.content_html, title: $json.artikel.seo_titel || $json.artikel.titel, description: $json.artikel.seo_beschreibung || '' }) }}")
|
||||
link(GATE, IMPORT, out=0)
|
||||
|
||||
IMPORT_FEHLER = code("Fehler Revision", [2220, 60], """
|
||||
@@ -422,6 +436,71 @@ const meta = {
|
||||
_seopress_analysis_target_kw: a.keyword || '',
|
||||
};
|
||||
|
||||
// --- Elementor-Struktur aus Artikel und FAQ ---
|
||||
// Zerlegt den Text an den H2-Grenzen in Text-Editor-Widgets und haengt das FAQ
|
||||
// als nested-accordion an, dasselbe Widget wie auf den Leistungsseiten.
|
||||
const konf = $('Konfiguration').first().json;
|
||||
const eid = () => Math.random().toString(16).slice(2, 9);
|
||||
const textWidget = (h) => ({ id: eid(), elType: 'widget', settings: { editor: h },
|
||||
elements: [], widgetType: 'text-editor' });
|
||||
const behaelter = (kinder, innen) => {
|
||||
const s = { content_width: 'full' };
|
||||
if (innen) Object.assign(s, {
|
||||
_title: 'Element',
|
||||
padding: { unit: 'px', top: '8', right: '8', bottom: '8', left: '8', isLinked: true },
|
||||
flex_gap: { column: '20', row: '20', isLinked: true, unit: 'px', size: 20 },
|
||||
});
|
||||
const c = { id: eid(), elType: 'container', settings: s, elements: kinder };
|
||||
if (innen) { c.isInner = true; c.isLocked = true; }
|
||||
return c;
|
||||
};
|
||||
|
||||
function elementorBauen() {
|
||||
const wurzel = [];
|
||||
if (a.kurzantwort) {
|
||||
wurzel.push(behaelter([textWidget(
|
||||
`<div class="skrift-kurzantwort"><p>${a.kurzantwort}</p></div>`)]));
|
||||
}
|
||||
const html = String(a.content_html || '');
|
||||
const stellen = [];
|
||||
const re2 = /<h2[ >]/g;
|
||||
let mm;
|
||||
while ((mm = re2.exec(html)) !== null) stellen.push(mm.index);
|
||||
const bloecke = [];
|
||||
if (!stellen.length) {
|
||||
if (html.trim()) bloecke.push(html.trim());
|
||||
} else {
|
||||
if (stellen[0] > 0 && html.slice(0, stellen[0]).trim()) bloecke.push(html.slice(0, stellen[0]).trim());
|
||||
stellen.forEach((s, i) => {
|
||||
const ende = i + 1 < stellen.length ? stellen[i + 1] : html.length;
|
||||
const b = html.slice(s, ende).trim();
|
||||
if (b) bloecke.push(b);
|
||||
});
|
||||
}
|
||||
bloecke.forEach(b => wurzel.push(behaelter([textWidget(b)])));
|
||||
|
||||
if (meta.faq.length) {
|
||||
const items = [], kinder = [];
|
||||
meta.faq.forEach(f => {
|
||||
items.push({ item_title: f.frage, _id: eid() });
|
||||
kinder.push(behaelter([textWidget(`<p>${f.antwort || ''}</p>`)], true));
|
||||
});
|
||||
wurzel.push(behaelter([
|
||||
textWidget(`<h2>${konf.faq_ueberschrift || 'Häufige Fragen'}</h2>`),
|
||||
{ id: eid(), elType: 'widget', widgetType: 'nested-accordion',
|
||||
settings: { items, faq_schema: 'yes', default_state: 'all_collapsed' },
|
||||
elements: kinder },
|
||||
]));
|
||||
}
|
||||
return wurzel;
|
||||
}
|
||||
|
||||
if (konf.elementor_ausgabe) {
|
||||
meta._elementor_data = JSON.stringify(elementorBauen());
|
||||
meta._elementor_edit_mode = 'builder';
|
||||
meta._elementor_template_type = 'wp-post';
|
||||
}
|
||||
|
||||
const body = {
|
||||
title: a.titel,
|
||||
slug: s.slug,
|
||||
@@ -483,6 +562,10 @@ return [{ json: {
|
||||
+ '. Mu-Plugin skrift-ratgeber-felder.php installiert?'
|
||||
: null,
|
||||
faq_eintraege: faq_ok,
|
||||
elementor: (p.meta || {})._elementor_edit_mode === 'builder'
|
||||
? (() => { try { return JSON.parse((p.meta || {})._elementor_data || '[]').length + ' Container'; }
|
||||
catch (e) { return 'ungueltig'; } })()
|
||||
: 'klassischer Inhalt',
|
||||
seo_titel: (p.meta || {})._seopress_titles_title || null,
|
||||
preis_warnung: v.preis_warnung || null,
|
||||
preis_shortcodes: v.preis_shortcodes || 0,
|
||||
@@ -600,6 +683,7 @@ if (s.importiert.length) {
|
||||
z.push(` ${r.slug} (Score ${r.score}, ${r.aktion})`);
|
||||
z.push(` Vorschau: ${r.vorschau_url}`);
|
||||
z.push(` Bearbeiten: ${r.bearbeiten_url}`);
|
||||
if (r.elementor) z.push(` Layout: ${r.elementor}`);
|
||||
if (r.meta_warnung) z.push(` ACHTUNG: ${r.meta_warnung}`);
|
||||
if (r.preis_warnung) z.push(` PREISE: ${r.preis_warnung}`);
|
||||
if (r.cache_hinweis) z.push(` Hinweis: ${r.cache_hinweis}`);
|
||||
|
||||
Reference in New Issue
Block a user