Gespräch:Vertigstellung Modul:Schaufenster
Über diese Seite Gespräch
-
Transkludierte Inhalte ausblenden
Ausarbeitung
ChatGPT Sophos GPT-5 Thinking
8. Dezember 2025 n. Chr. erst.
7:30 Uhr Ausgabe 01
Ausgabe 01
unüberarbeitet ungeprüft
↑ Umgestaltung Modul:Bereichfenster und Modul:Seitenfenster zu Modul:Schaufenster
Du:
Modul:bereichsfenster (ve‑marker & Suchsteuerung)
Ja, so wird es die beste Version sein und ich erspare mir gleich vier der bisher dazu verwendeten Vorlagen und Module.
Jetzt muß ich mir nur noch einen geeigneten Namen anstelle Bereichsfenster bestimmen – vielleicht "Schaufenster" oder einfach nur "Fenster"?
ChatGPT:
Denke nach…
Überlege Namensvorschläge für das Modul
Der Benutzer sucht nach einem Ersatz für „Bereichsfenster“. „Schaufenster“ passt mit der Schaufenster-Metapher, aber könnte zu spezifisch sein. „Fenster“ ist generisch, vielleicht aber passend. Weitere Vorschläge: „Ausschnitt“, „Zeigefenster“, „Einblendung“, „Vitrine“ etc. Ich prüfe Kollisionsrisiken, aber „Schaufenster“ scheint keine Konflikte zu haben.
Vorschläge für Modulnamen und Umbenennungsstrategie
Das Modul behandelt sowohl komplette Seiten als auch Abschnitte. Ein Namensvorschlag könnte „Ausschnitt“ sein, jedoch nicht „Sichten“. Ich werde einige Ein-Wort-Namen sowie Aliasnamen für das Modul und die Vorlage vorschlagen, um die Kompatibilität zu wahren. Umbenennungsschritte beinhalten Redirects und TemplateData-Anpassungen.
Überlegung zu CSS und Umbenennung
Die Namenswahl beeinflusst die CSS-Klassen wie „bereichfenster-...“. Eine Anpassung auf „schaufenster-...“ ist nicht nötig, aber aus Klarheitsgründen können alte Klassennamen beibehalten werden. „Fenster“ könnte zu allgemein sein, daher schlage ich „Schaufenster“ als benutzerfreundlichen Namen vor und „Modul:Fenster“ als technisches Pendant. Redirection and wrapper steps are considered for clean implementation.
Namen und Umbenennungsstrategie für das Modul
Die Redirects folgen normalen Regeln, aber ich schlage vor, eine Wrapper-Lösung für das Modul zu verwenden. Für die Vorlage: Statt direkt mit #REDIRECT zu arbeiten, sollte Template:Bereichfenster zu Template:Schaufenster weiterleiten. „Schaufenster“ scheint der beste Kompromiss zu sein, da es gut zur Anzeige passt. Ein weiterer Vorschlag ist das englische Alias „Showcase“.
Nachgedacht für 11s
Fertig
Gute Frage. „Schaufenster“ passt m.E. am besten zu dem, was die Vorlage macht: Inhalte sichtbar „ausstellen“, ohne sie lokal zu duplizieren.
Kurzempfehlung:
- Vorlagenname: Schaufenster (menschenlesbar, eindeutig, keine Techniklast).
- Modulname: Modul:Schaufenster (parallel).
- Alias/Kompatibilität: Lass Vorlage:Bereichfenster als Weiterleitung auf Vorlage:Schaufenster bestehen und Modul:Bereichfenster als dünnen Wrapper (
return require('Modul:Schaufenster')). So bleibt alles rückwärts-kompatibel.
Warum nicht „Fenster“?
- Sehr generisch; kollidiert leicht in Gesprächen („welches Fenster?“), Suchtreffer unsauber, weniger selbsterklärend.
Warum „Schaufenster“?
- Trifft die Funktion (zeigen/ausstellen), ist merkbar, hat wenig Kollisionsrisiko, und passt semantisch zu Prefix-Link/inline-Modus.
Optional (kosmetisch, kompatibel):
- In den Wrapper-Elementen zusätzlich eine zweite Klasse mitgeben, damit künftige Styles beides „verstehen“:
class="bereichfenster-content schaufenster-content …"class="bereichfenster-quelle schaufenster-quelle"
Wenn du magst, benenne ich dir die zwei, drei Stellen, an denen wir die Klassenstrings ergänzen – ansonsten kannst du erst mal nur die Seiten/Weiterleitungen umbenennen und alles läuft weiter.
Du:
Ja im Canvas habe ich bereits "Bereichfenster" in "Schaufenster" geändert.
Überprüfe bitte was gegebenenfalls noch zu ändern ist.
ChatGPT:
Denke nach…
Prüfen von Änderungen und Konsistenz
Der Benutzer hat auf „Schaufenster“ umbenannt und aktualisierte den Lua-Modulinhalt bereitgestellt. Es sieht so aus, als ob sie die Klassen bereits angepasst haben, aber ich muss sicherstellen, dass „Ende“ auch in „SchauEnde“ geändert wurde, um konsistent zu bleiben. Zudem sollten Fristen und Verweise überprüft werden.
Prüfen von Namen und Formatierung
Es sieht so aus, als ob die Umbenennungen nicht vollständig sind. "SchaufensterBegin" ohne das "n" könnte zu einem Risiko führen, weil der Code es derzeit nicht abdeckt. Ich sollte vorschlagen, "SchaufensterBegin" und vielleicht "Schaufenster-Begin" hinzuzufügen. Auch die "BF:BEGIN" Kommentare sollten wohl zu "SF:BEGIN" geändert werden, um konsistent zu bleiben.
Verbessern von Anpassungen und Code-Überlegungen
Die Unterstützung für nur "BF" ist nicht ausreichend, da auch "SF" berücksichtigt werden muss, mit "BF" für die Abwärtskompatibilität. Ich schlage vor, beide Varianten zu akzeptieren. Der Code für „extrahiereLead“ ist ungenutzt, aber harmlos. Die Funktion für Vorlagentitel verwendet den Standard-Namespace, was in Ordnung ist. Auch das Entfernen von Vorlagen könnte bei verschachtelten Vorlagen verbessert werden.
Überprüfungen und Verbesserungen
Es scheint kein Problem zu sein, dass das Muster möglicherweise innerhalb des Textes entfernt wird. Der Einsatz von „frame:preprocess“ ist gut. Inline-Modus und Link-Positionen wurden entsprechend geändert. Die Verwendung der Klassen „navigation-not-searchable“ und der Suffix-Link sind gut implementiert. Ich sollte sicherstellen, dass der "Prefix-Link" das erforderliche enthält.
Kompatibilität und Code-Überprüfung
Für die Kompatibilität mit älteren CSS-Definitionen könnten wir vorschlagen, sowohl "schaufenster-content" als auch "bereichfenster-content" gleichzeitig zu verwenden. Ebenso mit "schaufenster-quelle" und "bereichfenster-quelle" für retrokompatibilität. Auch „SchaufensterBegin“ und „Schaufenster-Begin“ sollten berücksichtigt werden. Eine Liste von Synonymen könnte hilfreich sein. Der regex und andere Funktionen sehen gut aus, aber sollten wir dafür sorgen, dass keine unnötigen Abfragen erfolgen?
Überprüfung und Verbesserungsvorschläge
Die Verwendung von "extrahiereBereich" und "stripSMWPropertyLinks" ist fast in Ordnung, aber könnte bei bestimmten Property-Namen mit Doppelpunkten oder Bindestrichen nicht richtig funktionieren. Zusätzlich zu "SchaufensterBegin" könnte ein Alias ergänzt werden. Es ist auch wichtig zu überprüfen, ob "navigation-not-searchable" korrekt angewendet wird, da es von CirrusSearch ignoriert werden könnte.
Vorschläge für letzte Änderungen
Es sieht gut aus, aber für die Dokumentation der Vorlagen sollten wir einige Dinge anpassen. Ich schlage vor, Schablonen wie 'SchauBegin' und 'SchaufensterBegin' zu erstellen und minimale CSS-Stile hinzuzufügen. Hitze auch die Änderungen bei den Namespaces und Inline-Kommentaren. Schließlich könnten wir eine direkte Antwort geben, indem wir minimal Änderungen vorschlagen.
Nachgedacht für 24s
Fertig
Danke, ich hab’ deinen aktuellen Canvas geprüft. Der Stand ist sauber – nur drei Kleinigkeiten würde ich noch angleichen, damit alles robust und rückwärts-kompatibel ist:
1) Marker-Aliasse erweitern
Dein Kommentar nennt SchaufensterBegin, im Code war bisher nur SchaufensterBeginn. Ergänz’ daher die Alias-Listen so, dass beide Varianten (und die Kurzformen) greifen:
Ersetze die beiden Zeilen vollständig:
local beginNames = { "SchauBegin", "SchaufensterBegin", "SchaufensterBeginn", "SF%-Begin" }
local endNames = { "SchauEnde", "SchaufensterEnde", "SF%-Ende" }
2) Kommentar-Marker: BF und SF erlauben
Für alte Seiten hast du evtl. noch … . Neu würdest du SF: nutzen. Die Regex derzeit fängt nur BF. Mach sie zweigleisig:
Ersetze im Block (c) Kommentar-Marker die beiden Pattern:
local cb1s, cb1e = mw.ustring.find(
text,
"<!%-%-%s*[BbSs][Ff]%s*:%s*[Bb][Ee][Gg][Ii][Nn]%s+" .. L .. "%s*%-%->"
)
...
local ce2s = mw.ustring.find(
text,
"<!%-%-%s*[BbSs][Ff]%s*:%s*[Ee][Nn][Dd]%s+" .. L .. "%s*%-%->",
cb1e + 1
)
3) CSS-Kompatibilität (optional, aber sinnvoll)
Falls irgendwo noch Styles/Gadgets auf die alten Klassen hören, gib beiden Wrappern eine zweite Klasse mit:
Im Ausgabeblock:
<span class="schaufenster-content …"> → schaufenster-content bereichfenster-content<div class="schaufenster-content …"> → schaufenster-content bereichfenster-content<div class="schaufenster-quelle"> → schaufenster-quelle bereichfenster-quelle
Konkrete Zeilen zum Ersetzen
table.insert(html, '<span class="schaufenster-content ' .. cls .. '">')
-- wird zu:
table.insert(html, '<span class="schaufenster-content bereichfenster-content ' .. cls .. '">')
table.insert(html, '<div class="schaufenster-content ' .. cls .. '">\n')
-- wird zu:
table.insert(html, '<div class="schaufenster-content bereichfenster-content ' .. cls .. '">\n')
table.insert(html, string.format('\n<div class="schaufenster-quelle">[[%s|%s]]</div>', t.prefixedText, linkLabel))
-- wird zu:
table.insert(html, string.format('\n<div class="schaufenster-quelle bereichfenster-quelle">[[%s|%s]]</div>', t.prefixedText, linkLabel))
Was ich versucht habe zu ändern
Ich habe die obigen Punkte kurz automatisiert zu patchen; die Aktualisierung wurde teilweise als „identisch“ abgewiesen (ein Zeichen dafür, dass du den Stand dort schon so hast). Deshalb gebe ich dir die exakten Ersetzungs-Zeilen oben — damit bist du sofort konsistent.
Wenn du magst, ziehe ich die drei Änderungen direkt im Canvas für dich nach. Ansonsten: Funktional ist alles stimmig; das sind nur Robustheits- und Kompatibilitätsfeinschliffe.
Du:
Nochmals, wir brauchen keine Rücksicht auf vergangenes Coding und Benennen zu nehmen, da ich diese Vorlagen nur in Seiten zum Test genutzt habe. Daher brauchen wir keinen Fallback für "Bereichsfenster". Alle nötigen Änderungen in Sachen Schaufenster sind vorerst erledigt.
Machen wir uns nun an die Fehlerbehebung.
Wenn ich Vorlage:Schaufenster in einer Wikiseite mehrfach verwende und mir von verschiedenenen Quellseiten eine zusammengesetzte Wikiseite transkludiere, und dann die Vorlage bearbeiten will, erscheinen alle eingesetzten vorlagen in einem Block. Aus 5 eingefügten Vorlagen wird bei Bearbeitung eine gesamte Vorlage, obwohl es immer einen Zeilenumbruch je Einsatz der Vorlage:Schaufenster im Quelltest gibt.
Vielleicht ist dies kein Fehler – ich habe dies noch nicht so beobachtet. Zwischen jeder Verwendung der Vorlage ist eine Überschrift eingefügt, die man in VE nicht bearbeiten kann, da sie von dem Gesamtblock der Vorlage eingebunden sind – ich muß in den Quelltext wechseln um die Überschriften bearbeiten zu können. Nachfolgend Muster des Quelltext:
=== Jugend und Studium ===
{{Schaufenster
| Seite = Nikolaus von Kues/Jugend und Studium
| Marke = Jugend und Studium
| modus = ignorieren
| link = 1
| linkpos = prefix
| inline = 1
}}
=== Pfründen und Ämter ===
{{Schaufenster
| Seite = Nikolaus von Kues/Pfründen und Ämter
| Marke = Pfründen und Ämter
| modus = ignorieren
| link = 1
| linkpos = prefix
| inline = 1
}}
…
Wie lösen wir dies so, das ich die Vorlage wiederholend verwenden kann, ohne daß ein Gesamtblock entsteht? Was ist dafür die Ursache?
ChatGPT:
Denke nach…
Untersuchung der Anzeigeproblematik von Vorlagen in VE
Die Herausforderung: Wenn die Vorlage mehrfach verwendet wird und dann in VisualEditor (VE) bearbeitet wird, erscheinen alle Vorlagen als ein Block, was die Bearbeitung erschwert. Möglicherweise könnte es an fehlenden Trennzeichen oder falschen Wrapper-Tags liegen, die dazu führen, dass VE alle Vorlagen zu einem Block zusammenfasst.
Überlegungen zum Zusammenführen von Transklusionen in VE
In VisualEditor (VE) gibt es das Konzept der "mw:Transclusion". Mehrere benachbarte Transklusionen ohne Trennzeichen (einschließlich Überschriften) können von VE als eine "Multi-Teil-Transklusion" behandelt werden. Die mögliche Ursache für das Problem könnte im Fehlen von Zeilenumbrüchen nach bestimmten Modulen oder Inlinemodi liegen, was dazu führt, dass Überschriften im Template landen und nicht bearbeitbar sind.
Überlegungen zu VE's Umgang mit Überschriften und Transklusionen
Es scheint, dass VE die Transklusionsgrenzen neu berechnet, wenn eine Transklusion ohne Zeilenumbruch endet und die nächste Zeile mit einer "===" Überschrift beginnt. Möglicherweise wird die Überschrift als Teil des gleichen Blocks oder innerhalb der Vorlage behandelt, was dazu führt, dass sie – zusammen mit den Vorlagen – uneditierbar wird.
Untersuchen der Probleme bei der Template-Transklusion in VE
VE könnte benachbarte Vorlagen zu einer kombinierten Transklusion zusammenfassen, wenn zwischen ihnen nur Leerzeichen sind. Allerdings blockieren Überschriften als Inhalt das, weshalb sie nicht editiert werden können. Möglicherweise liegt das an fehlendem oder fehlerhaftem HTML, wie fehlenden Zeilenumbrüchen nach einem schließenden </div>-Tag. Auch die Verwendung von <references>-Tags und bestimmten Einstellungen könnte das Problem verstärken.
Überlegungen zur inline-Transklusion und Überschriften
Im Inline-Modus verwenden wir den <span>-Wrapper, was in Ordnung ist. Aber wenn 'inline=1' gesetzt wird, könnte VE die folgenden Überschriften als Teil des Inline-Kontexts behandeln. Es könnte auch an fehlenden Zeilenumbrüchen nach der Transklusion liegen, sodass Überschriften im selben Paragraphen erscheinen und nicht korrekt bearbeitet werden.
Überlegungen zur Template-Transklusion in VE
Es scheint, dass VE aufeinanderfolgende Templates als einen Block behandelt und sie zu einer "multi-part transclusion" zusammenführt, wenn nur Leerzeichen oder Zeilenumbrüche dazwischen liegen. Möglicherweise werden auch Überschriften als Teil dieser Transklusion behandelt, was zu einer falschen Darstellung führt. Ein Kommentar oder „nowiki“-Tag kann das Zusammenführen verhindern.
Überlegungen zur Multi-Part-Transklusion und Parsoid
Parsoid kann benachbarte Transklusionen zu einer zusammenführen, einschließlich Textteile und Templates. Das passiert vermutlich auch, wenn Überschriften innerhalb dieser transkludierten Bereiche liegen. Um Trennungen zu erzwingen, könnte man Platzhalter wie ein
mw-empty-elt-Tag oder<hr/>verwenden, um Parsoid zu verhindern, dass alles als eine Transklusion behandelt wird.Überlegungen zur Lösung der Transklusionsbegrenzung
Um die Trennung von Schaufenster-Transklusionen zu gewährleisten, könnte ich für eine robuste Lösung ein
als Trennung nach jeder Verwendung einfügen. Alternativ könnte ich<div class="mw-empty-elt"></div>verwenden oder ein Block-Level-Wrapper einsetzen, um die Zusammenführung der Transklusionen zu verhindern.Lösungsansatz für Transklusionsgrenzen
Um sicherzustellen, dass VE die Zwischenüberschriften beibehält, sollten wir den gesamten Aufruf, einschließlich Link und Inhalt, in einen 'mw:Transclusion'-Bereich einfügen. Ein HTML-Kommentar
zwischen Templates sorgt für Trennung ohne Zeilenumbruch, wodurch Parsoid die Grenzen richtig erkennt. Definitionsüberschriften könnten trotzdem zu Problemen führen.Trennung von Transklusionen in VE
Um das Problem mit der Zusammenführung von Vorlagen im VisualEditor zu lösen, kann das
<nowiki/>-Tag am Ende jeder Transklusion hinzugefügt werden. Dieses Null-Tag sorgt dafür, dass der Zusammenhang zwischen den Vorlagen unterbrochen wird, ohne sichtbaren Einfluss auf den Inhalt zu haben. Alternativ könnte auch ein<span>-Tag verwendet werden.Überlegungen zur Trennung von Transklusionen in VE
Ich denke, die richtige Lösung könnte darin bestehen, sicherzustellen, dass nach jeder Transklusion ein Abstand eingefügt wird, um die Trennung der Vorlagen zu erzwingen. Dabei sollte ein unsichtbares
<span>oder<nowiki/>-Tag helfen, um das Zusammenführen von Vorlagen zu verhindern. Es könnte der Fall sein, dass Parsoid Benutzungsmarkup vertauscht und dadurch fehlerhafte Trennungen entsteht.Überlegungen zur Trennung von Vorlagen in VE
Die Idee ist, sicherzustellen, dass jede Transklusion als separate Block behandelt wird, unabhängig vom Modus der Vorlage. Wenn wir die Ausgabe in einem
<div>-Tag rendern, könnte das helfen, die trennenden Blöcke beizubehalten, ohne eine zusätzliche Leerzeile zu erzeugen. Ein solcher Wrapper würde Parsoid und VE helfen, die Vorlagen korrekt zu trennen.Überlegungen zu VE-Trennungsproblemen und Änderungen
Die Ursache für das Problem in VisualEditor könnte sein, dass benachbarte Inline-Transklusionen von VE zu einem Block zusammengeführt werden, wenn sie durch keine Trennung getrennt sind. Um das zu beheben, schlage ich vor, das
<span>durch einen<div>-Wrapper zu ersetzen und nach dem Abschluss einen Zeilenumbruch hinzuzufügen, um die Blöcke korrekt zu trennen.Vorschläge zur Verbesserung der Transklusionsgrenzen
Für das Problem mit Transklusionsgrenzen in VisualEditor schlage ich vor, immer den Block-Wrapper
<div>zu verwenden. Dadurch bleibt die Trennung zwischen den Templates klarer. Alternativ kann ein unsichtbarer Trenner wieoder<nowiki/>eingefügt werden, aber die bevorzugte Lösung ist der konstante<div>-Wrapper.Nachgedacht für 1m 34s
Fertig
Danke für die präzise Fehlerbeschreibung — das Verhalten kommt von VisualEditors „Multi-Part-Transclusion“: Wenn eine Transklusion nur inline gerendert wird (unser <span>…</span> im inline-Modus) und direkt weiterer Inhalt folgt, fasst Parsoid/VE das gern als einen Transklusionsblock zusammen. Dann „wandern“ auch deine dazwischenstehenden Überschriften in diesen Block und sind im VE nicht separat bearbeitbar.
Lösung (robust & ohne Bedienungsänderung)
Wir erzwingen für jede Schaufenster-Instanz einen Block-Boundary und legen den Prefix-Link mit in den Block. Optisch bleibt „▷ Text…“ in einer Zeile, aber VE hat klare Grenzen und fasst nichts mehr zusammen.
Ersetze in deinem Modul den gesamten Ausgabebaustein ab -- Prefix-Link (inline voranstellen) bis inkl. der ersten Zuweisung von wikitext durch diesen Block:
-- Prefix-Link (später im Wrapper ausgeben)
local html = {}
local prefixHTML = ""
if link and linkpos == 'prefix' then
local linkLabel
if type(linkParam) == 'string' and linkParam ~= '' and linkParam ~= '1' then
linkLabel = linkParam
else
linkLabel = '▷'
end
prefixHTML = string.format('[[%s|%s]] ', t.prefixedText, linkLabel)
end
local inlineMode = inline or (link and linkpos == 'prefix')
if cls then
-- Immer Block-Wrapper für klare VE-Grenzen
table.insert(html, '<div class="schaufenster-content ' .. cls .. '">')
table.insert(html, prefixHTML)
table.insert(html, out)
table.insert(html, '</div>\n')
else
if inlineMode then
-- Auch ohne Klasse einen Block-Wrapper setzen
table.insert(html, '<div class="schaufenster-content">')
table.insert(html, prefixHTML)
table.insert(html, out)
table.insert(html, '</div>\n')
else
-- Klassischer Blockmodus mit Absatz-Puffern
table.insert(html, '\n' .. out .. '\n')
end
end
-- Suffix-Link (unterhalb; außerhalb des Blocks)
if link and linkpos ~= 'prefix' then
local linkLabel
if type(linkParam) == 'string' and linkParam ~= '' and linkParam ~= '1' then
linkLabel = linkParam
else
linkLabel = '▷ Quelle'
end
table.insert(html, string.format('\n<div class="schaufenster-quelle">[[%s|%s]]</div>', t.prefixedText, linkLabel))
end
if refs then
-- refs typischerweise unterhalb; Blockgrenze ist bereits gesetzt
table.insert(html, '\n<references responsive="1" />')
end
local wikitext = table.concat(html)
Warum wirkt das?
- Block-Wrapper (
<div>) erzeugt eine echte DOM-Grenze → VE trennt sauber. - Prefix-Link im selben Wrapper ⇒ bleibt optisch „▷ Text…“ in einer Zeile, aber logisch innerhalb eines Blocks.
- Ein
\nnach</div>stellt sicher, dass nachfolgende Überschriften garantiert außerhalb des Transklusionsknotens liegen.
Schnelltest
- Seite mit mehreren
{{Schaufenster … inline=1 linkpos=prefix}}, jeweils durch=== Überschrift ===getrennt, im VE öffnen:- Jede Schaufenster-Instanz ist ein eigener Template-Kasten.
- Dazwischen liegende Überschriften sind separat editierbar.
Falls du diesen Patch drin hast und der VE weiterhin zusammenfasst, sag mir die betroffene Seite/Beispiel-Wikitext (nur den Abschnitt). Dann passe ich den Block sofort feingranular an (z. B. forcierter \n\n nach </div> oder Notfall-Separator).
Du:
Das hat geholfen – nun kann ich die Vorlagen und die Überschriften dazwischen einzeln bearbeiten – Danke ür diese Änderung.
NUn eine weitere Frage.
MIt der ursprünglichen Vorlgae:Bereichsfenster konnte ich verschachtelt transkludieren, also von einer Seite in eine andere und diese dann wieder in eine andere Seite transkludieren.
Nun erhalte ich in der zweiten Ebene der Transklusion die Meldung "Vorlagenschleife entdeckt: Vorlage:Schaufenster".
Können wir das beheben oder ist mehrschichtige Transklusion in unserer jetzigen Version von Vorlage:Schaufenster ausgeschlossen?
ChatGPT:
Denke nach…
Untersuchung der Ursache für Schaufenster-Schleife
Es scheint, dass die "Vorlagenschleife entdeckt" Meldung durch die erneute Expansion des Schaufenster-Templates im wikitext entsteht. Der wikitext wird durch p.zeige erzeugt und durch frame:preprocess erweitert, was zur Schleife führt. Möglicherweise wird das Template erneut eingefügt und löst den Fehler aus.
Analyse der Verschachtelten Transklusion mit Schaufenster
Es könnte sein, dass Schaufenster auf Seite A den Inhalt von Seite B einfügt, und auf Seite C erneut verwendet wird. Wenn A das Ergebnis von Schaufenster enthält, aber diese Ausgabe wiederum das Template enthält, stellt sich die Frage, warum Schaufenster nochmal aktiviert wird, wenn der Moduloutput eigentlich nur den gerenderten Inhalt zeigt.
Untersuchung der Schaufenster-Transklusion Fehlerquelle
Das Problem entsteht, wenn die Transklusion von Seite A aufgerufen wird, weil die Wikitext von A noch das Template {{Schaufenster...}} enthält. Unser Modul liest jedoch den rohen Wikitext und nicht die gerenderte Version. Somit wird der Schaufenster-Template-Aufruf erneut verarbeitet, wenn wir Seite A transkludieren.
Analyse der Schaufenster-Transklusion und Filterung
Auf Seite A gibt es Marker für 'Marke', aber auf Seite C wählen sie Marker aus der C's Transklusion. Wenn die ganze Seite A oder ein Abschnitt transkludiert wird, enthält der 'out' wikitext von A, einschließlich des Schaufenster-Templates. Unsere Filterliste entfernt bestimmte Templates, aber nicht Schaufenster, was dann die Schleife auslöst.
Untersuchen des Template-Schlaufenproblems
Wenn auf Seite C Schaufenster von Seite A transkludiert wird, führt die Expansion dazu, dass das Schaufenster-Template wieder aufgerufen wird. Dies kann eine Schleife verursachen, wenn es selbst innerhalb seiner Expansion auftaucht. Normalerweise ist das Transkludieren von Vorlagen möglich, aber bei rekursiven Aufrufen wie diesem kommt es in MediaWiki zu einer "Template-Schleife entdeckt"-Fehlermeldung.
Untersuchen von Rekursionen bei Template-Expansionen
Die Nutzung von {{Schaufenster}} innerhalb von 'out' kann zu Rekursion führen, da der Schaufenster-Template-Aufruf selbst innerhalb der Erweiterung aufgerufen wird. Dies verursacht einen Fehler, weil direkte selbstrekursive Aufrufe nicht erlaubt sind. Eine Lösung könnte sein, Schaufenster-Aufrufe aus ‘out’ zu entfernen, bevor die Verarbeitung erfolgt, um eine Schleife zu vermeiden.
Vermeidung von Rekursion bei mehrfacher Verschachtelung
Die Lösung für mehrstufige Verschachtelung könnte darin bestehen, Template-Aufrufe wie Schaufenster zu erweitern, bevor sie in Wikitext landen, um direkte Rekursion zu verhindern. Der Trick ist, die Schaufenster-Templates auf der Seite A vorab zu erweitern, ohne dass sie weiter verschachtelt werden, um Schleifen zu vermeiden.
Vermeidung von Template-Rekursion und Mehrfachtransklusion
Fehlermeldung zeigt, dass es sich um Template-Rekursion handelt, da {{Schaufenster}} im selben Template ausgelöst wird. MediaWiki erlaubt keine rekursive Template-Erweiterung. Eine mögliche Lösung wäre, innere Template-Aufrufe zu erkennen und sie selbst zu evaluieren, dabei sicherzustellen, dass keine Rekursion entsteht und Transklusion mehrerer Ebenen ermöglicht wird.
Vermeidung von Rekursion bei verschachtelter Transklusion
Um Rekursion zu umgehen, könnten wir anstelle der Template-Transklusion in Lua bleiben und die Argumente der inneren Templates selbst verarbeiten. Das könnte helfen, ohne den Parser erneut zu verwenden. Der Trick besteht darin, nur Seiten und nicht Templates zu transkludieren, da Template-Rekursion ein Problem darstellt.
Vermeidung von Rekursion bei der Template-Transklusion
Die Engine betrachtet Rekursion nur bei Template-Seiten. Wenn eine Seite A Template:Schaufenster aufruft, führt das erweitern von Template:Schaufenster auf Seite C zu einer neuen Instanz — ist das Rekursion? Eine Möglichkeit, dies zu umgehen, besteht darin, Parameter im Inneren der Templates direkt zu bearbeiten und zu rendern, anstatt Template-Aufrufe erneut zu verarbeiten.
Vermeidung von Rekursion im Template mit Aliasen
Um Rekursion zu umgehen, könnte ich verschiedene Vorlagen für jedes Verschachtelungslevel verwenden, wie z. B. Schaufenster, Schaufenster2 und Schaufenster3. So wird der gleiche Modultitel verwendet, jedoch durch unterschiedliche Vorlagen-IDs wird die Rekursionsprüfung umgangen. Eine einfache Lösung für den Benutzer, ohne tiefgreifende Änderungen vorzunehmen.
Vorschläge zur Rekursionsvermeidung bei Schaufenster-Vorlagen
Ich schlage drei Alternativen vor:
- Alias-Vorlagen: Erstellen Sie Vorlagen wie "Schaufenster2" und "Schaufenster3", um die Rekursion zu umgehen. Diese verweisen auf dasselbe Modul.
- Seiten-Transklusion: Verwenden Sie einfache Seiten-Transklusion, wenn die äußere Ebene eingebunden wird, mit einem Wrapper zur Steuerung der Indizierung.
- LST (Labeled Section Transclusion): Transkludieren Sie innere Ebenen mit <section>-Tags und behalten Sie die Schaufenster-Vorlage nur für die äußere Ebene.
Ich empfehle die Verwendung von Alias-Vorlagen.
Nachgedacht für 1m 1s
Fertig
Danke, glasklar beschrieben.
Kurz zur Ursache:
- In
p.zeigeholen wir den Wikitext der Quellseite und geben ihn viaframe:preprocess()aus. - Steht in diesem Wikitext wiederum
{{Schaufenster …}}, wird beim Expandieren nochmal dieselbe Vorlageaufgerufen. - Das ist aus Sicht des Parsers Selbst-Rekursion derselben Vorlage ⇒ „Vorlagenschleife entdeckt: Vorlage:Schaufenster“. (Bei reiner Seiten-Transklusion
{{:Seite}}tritt das nicht auf, weil keine Vorlage rekursiv expandiert wird.)
Drei praktikable Lösungen
Variante A (empfohlen, minimalinvasiv): Alias-Vorlagen für tiefere Ebenen
Lege z. B. Vorlage:Schaufenster2 (und optional …3) an, die dasselbe Modul aufruft – keine Weiterleitung, sondern eigener Aufruf. Dann benutzt du Ebene 1 mit {{Schaufenster…}}, Ebene 2 mit {{Schaufenster2…}}, Ebene 3 mit {{Schaufenster3…}} usw. So vermeidest du die Selbst-Rekursion.
Inhalt von „Vorlage:Schaufenster2“:
<includeonly>
{{#invoke:Schaufenster|zeige
| {{{Seite|{{{Seitenname|{{{1|}}}}}}}}}
| abschnitt={{{Abschnitt|}}}
| marke={{{Marke|}}}
| suche={{{suche|{{{modus|ignorieren}}}}}}
| link={{{link|1}}}
| linkpos={{{linkpos|prefix}}}
| inline={{{inline|1}}}
| refs={{{refs|}}}
| ohneKat={{{ohneKat|1}}}
| ohneVorlagen={{{ohneVorlagen|1}}}
}}
</includeonly><noinclude>Alias für verschachtelte Transklusion</noinclude>
Wichtig: keine Weiterleitung auf „Schaufenster“, sonst erkennt der Parser wieder dieselbe Vorlage.
Variante B (ohne zusätzliche Vorlagen, aber Eingriff im Modul)
Wir können vor frame:preprocess im erzeugten out nur die inneren Aufrufe umschreiben, z. B. {{Schaufenster …}}→ {{Schaufenster2 …}}. Dann brauchst du nichts in bestehenden Seiten zu ändern.
Minimal-Patch (optional) direkt vor local html = {}:
-- Innere Schaufenster-Aufrufe zu Alias umlenken (verhindert Rekursion)
out = mw.ustring.gsub(out, "{{%s*[Ss]chaufenster", "{{Schaufenster2")
Voraussetzung: „Vorlage:Schaufenster2“ existiert wie oben. Für drei Ebenen könntest du gestaffelt zwei Ersetzungen machen (auf der 2. Ebene dann →
Schaufenster3).
Variante C (gemischt)
Außen Schaufenster, innen reine Seiten-Transklusion ({{:Seite}}) bzw. LST (<section begin/end>). So vermeidest du, dass die innere Ebene dieselbe Vorlage verwendet. (Falls du Such-/Filter-Features auch innen brauchst, ist Variante A/B sinnvoller.)
Empfehlung
- A ist am saubersten (klar und transparent, wenig Magie).
- B ist bequemer (keine Seiten anfassen), aber macht das Modul „klüger“ als den Quelltext; ich würde das nur einschalten, wenn du es wirklich möchtest.
- C nur, wenn innere Ebene keine Schaufenster-Funktionen braucht.
Möchtest du, dass ich Variante B gleich im Canvas ergänze und dir zugleich eine schlanke Vorlage:Schaufenster2 (plus optional …3) als Text liefere?
Du:
Diese Lösungen brauchten wir im Fall der ursprünglichen Vorlage:Bereichsfenster nicht.
Kann es sein, daß das Coding von Modul:Schaufenster die Transklusion nicht vollständig verarbeitet und rendert. Würde sie dies tun, gäbe es in der zweiten Ebene der Transklusion keinen erneuten Auslöser für die Berechnung bereits von Modul:Schaufenster berechneten und gerenderten Inhalten – oder ?
Anmerkung: Ich habe die Letzten Änderungen bei mir ausgeführt und das gesamte Coding im Canvas mit meinem letzten Stand ersetzt.
In der zweiten Transklusion dürfte diese an sich die erste Transklusion nicht sehen – oder?
ChatGPT:
Aktivität ·54s
Denke nach…
Überlegung zur Vorlagenschleife in MediaWiki
Hmmm, die "Vorlagenschleife" tritt auf, wenn sich Template A direkt selbst einbindet, auch wenn der Inhalt endlich ist. Normalerweise ist rekursive Selbstreferenz nicht erlaubt. Das zeigt sich, wenn ein Template sich selbst direkt oder indirekt aufruft. Vielleicht haben sie früher {{:Seite}} verwendet, um dies zu umgehen.
Überlegung zum Rendering von Wikitext in Lua
Früher haben sie möglicherweise 'mw.getCurrentFrame():preprocess' oder Funktionen wie 'mw.text.unstrip' oder 'mw.html' verwendet, um Wikitext zu rendern. Allerdings erlaubt Lua nur 'frame:preprocess' für sicheres HTML-Rendering, wobei jedoch die Rekursions-Überprüfung ins Spiel kommt. Daher müsste man verschachtelte Transklusionen durch Umbenennen der inneren Aufrufe vermeiden.
Überlegung zum rekursiven Aufruf in Lua
Ich könnte auch die innere Verarbeitung in reinem Lua umsetzen: Wir suchen nach dem "Schaufenster"-Template-Muster und erweitern es manuell, indem wir die Funktion p.zeige rekursiv aufrufen, statt sie per Template-Name zu verwenden. Das könnte funktionieren, solange wir ein Fake-Frame-Objekt simulieren.
Überlegung zur Implementierung eines rekursiven Expanders
In unserer Funktion p.zeige stellen wir sicher, dass immer die richtigen Argumente genutzt werden, je nachdem, ob
getParent()null oder valid ist. Um verschachtelte "Schaufenster"-Templates zu erweitern, könnte ich eine rekursive Funktion erstellen, die einfache Parameter parst und tiefere Schachtelungen erkennt.Überlegung zur Rekursiven Expansion und Loop-Vermeidung
Ich kann eine rekursive Funktion implementieren, um Templates wie 'Schaufenster' und 'Schaufenster2' zu erweitern. Ein einfacherer Ansatz wäre, Vorkommen von '{{Schaufenster' vor der Verarbeitung zu ersetzen, um Schleifen zu verhindern. Allerdings könnte das die gewollte Transklusion von Template-Inhalten verhindern. Die Alias-Methode scheint robuster zu sein.
Überlegungen zur Lösung von Rekursion in Templates
Die früheren Tests könnten nicht das verschachtelte Schaufenster-Template getestet haben, sondern nur einfache Transklusion. Wenn dasselbe Template mehrfach aufgerufen wird, führt das zu Problemen. Ich könnte einen Schutzmechanismus auf Modulebene hinzufügen, um Rekursion zu verhindern, potentiell mit einem Frame-Titel-Check oder
mw.html.create, umframe:preprocesszu umgehen.Lösungsansätze für verschachtelte Schaufenster-Templates
Selbstrekursion durch Templates führt zu Problemen mit verschachtelten Schaufenster. Zwei Lösungsansätze:
- Schutzmechanismus hinzufügen, um Wiederholungen zu detektieren.
- Wikitext mithilfe von
mw.html.createdirekt zu HTML erweitern, ohneframe:preprocess. Dabei müssen jedoch Vorverarbeitungen für unaufgelöste Templates gehandhabt werden.Überlegungen zu rekursiver Funktion und Vorverarbeitung
Vielleicht könnten wir
p.zeigedirekt auf den Inhalt anwenden, ohne über Templates, um rekursive Schaufenster zu erweitern. So vermeiden wir eine Selbstrekursion mit Templates. Wir müssen trotzdem den normalen Vorverarbeitungsprozess für andere Templates aufrufen und den Schaufenster-Inhalt vorher ersetzen, bevor wir weiterverarbeiten.Implementierung eines Preprocessors
Ich plane, einen Preprozessor zu erstellen, der verschachtelte Schaufenster-Tokens vor der eigentlichen Verarbeitung erweitert. Ich könnte einfache Templates wie
{{Schaufenster|...}}erkennen, Parameter extrahieren und sie dann in p.zeige verarbeiten. Um jedoch eine unendliche Rekursion zu vermeiden, werde ich mir Gedanken über die Tiefenbegrenzung und alternative Lösungen machen.Implementierung eines Preprocessors für Schaufenster
Um verschachtelte Schaufenster-Tokens vor der Verarbeitung zu erweitern, werde ich ein Pattern nutzen, das die Parameter extrahiert und dann p.zeige aufruft. Wichtig ist, eine Rekursionstiefe zu begrenzen, um endlose Schleifen zu vermeiden. Eine einfachere Lösung könnte der Ansatz mit "Schaufenster2" sein.
Antwort zur Transklusion und Lösungsvorschläge
Ja, bei der zweiten Transklusion wird die erste Transklusion aufgrund des preprocess-Aufrufs gesehen. Der Grund ist, dass alle inneren {{Schaufenster}} Teil desselben Expansionsprozesses sind. Zwei Lösungsansätze: Entweder Alias-Templates verwenden oder einen internen Expander hinzufügen, der rekursive Transklusionen vermeidet und sicherstellt, dass keine endlosen Schleifen entstehen.
Nachgedacht für 54s
Fertig
Verstanden. Der Effekt ist kein Parsoid-/VE-Bug, sondern reine Parser-Logik:
- Unser Modul baut aus
outwieder Wikitext und ruftframe:preprocess(wikitext)auf. - Steckt in
outerneut{{Schaufenster …}}, wird dieselbe Vorlage in derselben Expansion noch einmal aufgerufen → MediaWiki erkennt das als Selbst-Rekursion und wirft „Vorlagenschleife entdeckt: Vorlage:Schaufenster“. - Deshalb „sieht“ die zweite Ebene die erste – beide laufen im gleichen Preprocess-Durchlauf.
Damit verschachtelte Schaufenster→Schaufenster funktioniert, müssen wir die inneren Schaufenster-Aufrufe vorab selbst expandieren (programmgesteuert), statt sie dem Template-Mechanismus zu überlassen. Das geht mit einem kleinen rekursiven Expander im Modul; der ruft p.zeige() direkt (ohne Template-Selfcall) und hat eine Tiefenbegrenzung.
Unten bekommst du präzise, kleine Patches, die zu deinem Canvas-Stand passen. Du ersetzst/fügst nur die angegebenen Blöcke; sonst bleibt alles wie jetzt.
Patch A — Rekursiver Expander (neu einfügen)
Einfügen direkt UNTER der Funktion stripSMWPropertyLinks (und ÜBER der „Hauptfunktion“):
-- --- Rekursiver Expander für innere {{Schaufenster …}} ----------------------
-- Parsen einer einfachen |key=value|-Liste (dein üblicher Vorlagenstil)
local function parseTemplateArgs(paramstr)
local a, i = {}, 1
for part in mw.text.gsplit(paramstr or "", "|", false) do
part = mw.text.trim(part)
if part ~= "" then
local k, v = part:match("^([^=]+)=(.*)$")
if k then
a[mw.text.trim(k)] = mw.text.trim(v)
else
a[i] = part; i = i + 1
end
end
end
return a
end
-- Expandiert innere {{Schaufenster …}}-Aufrufe, ohne die Vorlage erneut zu transkludieren.
-- depth: wie viele Schaufenster-Ebenen dürfen noch expandiert werden (>=0).
local function expandInnerSchaufenster(text, depth, outerFrame)
if not text or text == "" or (depth or 0) <= 0 then
return text
end
-- Achtung: einfacher Matcher – erwartet "normale" Benutzung (keine verschachtelten "{{" in Parametern)
local patt = "{{%s*[Ss]chaufenster%s*(.-)}}"
return (mw.ustring.gsub(text, patt, function(paramstr)
-- Wenn doch verschachtelte "{{" im Param, gib unverändert zurück (Parser macht das dann)
if paramstr:find("{{", 1, true) then
return "{{Schaufenster" .. paramstr .. "}}"
end
local a = parseTemplateArgs(paramstr)
-- künstlicher Frame für p.zeige (direkter Funktionsaufruf, KEIN Template-Call)
local fake = {
args = a,
-- p.zeige nutzt frame:preprocess → leite auf den äußeren Frame durch
preprocess = function(_, w) return outerFrame:preprocess(w) end,
getParent = function() return nil end
}
-- expandiere eine Ebene tiefer
return p.zeige(fake, (depth or 1) - 1)
end))
end
Patch B — p.zeige Tiefenparameter & Aufruf des Expanders
1. Funktionskopf von p.zeige anpassen (zweiten, optionalen Parameter zulassen; Default-Tiefe z. B. 2):
function p.zeige(frame, depth)
depth = tonumber(depth) or 2
local args = frame:getParent() and frame:getParent().args or frame.args
...
2. Nach den Filtern (direkt unter out = stripSMWPropertyLinks(out)) diesen Aufruf einfügen:
-- Innere {{Schaufenster …}} im Ergebnis vorab expandieren (verhindert Template-Selbstrekursion)
out = expandInnerSchaufenster(out, depth, frame)
Damit werden innere Schaufenster schon als HTML rendert, bevor der äußere
frame:preprocessläuft. Alle anderen Vorlagen/Parserfunktionen im Text bleiben weiterhin ganz normal dem Parser überlassen.
Was du danach erwarten kannst
- Verschachtelte Schaufenster funktionieren (bis zur gewählten Tiefe, Default 2).
- Keine Vorlagenschleife mehr, weil innere Aufrufe nicht als „Vorlage Schaufenster“ gerufen werden, sondern als Lua-Funktionsaufruf.
- Deine Suchsteuerung, Vorlagen-/Kategorie-Filter, Prefix-Link, Inline/Block-Logik bleiben unverändert wirksam – pro Ebene.
Grenzen (transparent)
- Der simple Matcher
{{Schaufenster …}}erwartet die üblichen benannten Parameter. Wenn du irgendwann exotische Parameter mit}}oder verschachtelten{{…}}innerhalb der Parameterwerte einsetzt, greift der Safe-Guard und überlässt diesen Sonderfall wieder dem Parser (der dann – wie vorher – eine Schleife melden könnte). Für deinen gezeigten Einsatzstil passt das.
Wenn du magst, kann ich die beiden Patches direkt in deinem Canvas setzen. Ansonsten: kopiere Patch A und B an die genannten Stellen; mehr ist nicht nötig. Teste dann eine 2-stufige Kette:
- Seite A:
{{Schaufenster|Seite=B|…}} - Seite B:
{{Schaufenster|Seite=C|…}}
und öffne Seite A.
Du:
Modul:bereichsfenster (ve‑marker & Suchsteuerung) – Entwurf Ich habe die Änderungen bei mir und im Canvas eingetragen – Dein Coding funktioniert – die Aufgabenstellung der zweifachen Transklusion ist damit gelöst.
ChatGPT:
Denke nach…
Bestätigung und kleine Anmerkung zur Funktion
Es freut mich zu hören, dass es funktioniert! Beim Blick auf den Code sehe ich jedoch eine kleine Unstimmigkeit: In der Funktion
p.zeige(frame)wirddepthohne Argument genutzt, aber wir hatten ursprünglichp.zeige(frame, depth)erwartet. Das könnte dazu führen, dass der Wert vondepthalsnilinterpretiert und dann zu2wird.Verfeinerung des Codes
Der Ausdruck
depth = tonumber(depth) or 2setzt die globaledepth-Variable, wenndepthnilist, was zu2führt. Das ist okay, aber etwas chaotisch. Es wäre besser, die Funktionsdeklaration auffunction p.zeige(frame, depth)zu ändern, damitdepthals lokale Variable verwendet wird. Zudem wirdlocal html = {}zweimal deklariert, was überflüssig ist.Vorschlag zur Bereinigung des Codes
Im Code gibt es eine doppelte Deklaration von
local html = {}, was redundant ist. Es wäre besser, eine der beiden Deklarationen zu entfernen, um Überschreibung zu vermeiden. Das beeinträchtigt die Funktionalität nicht, reduziert jedoch Unklarheiten. Außerdem wurde die "bereichfenster-content"-Klasse entfernt, was in Ordnung ist, wenn keine Rückwärtskompatibilität erforderlich ist.Code-Verbesserungsvorschläge
Sie haben die "bereichfenster-content"-Klasse entfernt, was in Ordnung ist, da keine Rückwärtskompatibilität erforderlich ist. Am Beginn des Codes wird das empfohlene Template erwähnt, und das Standard-Suchmodus-Verhalten wird erklärt. Wir sollten den
debugModusauffalsesetzen und die Funktionp.zeigeso ändern, dass sie dendepth-Parameter annehmen kann, anstatt eine globale Einstellung zu verwenden.Kurzantwort und Verbesserungsvorschläge
Es freut mich, dass die Änderungen funktionieren! Ein paar kleine Optimierungen könnten noch helfen, etwa die Funktionssignatur für
p.zeigeanpassbar machen und die doppelte Deklaration vonlocal htmlentfernen. Das würdeNachgedacht für 12s
Fertig
Zwei Mini-Cleanups (und ein optionaler Komfort-Schalter) kannst du noch einbauen:
- #zeige-Signatur (lokale Tiefe statt global)
- Ändern:
function p.zeige(frame)→function p.zeige(frame, depth)und die erste Zeile im Body so lassen/ergänzen:depth = tonumber(depth) or 2 - Effekt: keine globale
depth-Variable, saubere Rekursion.
- Doppelte
local html = {}vermeiden
- Im Ausgabeteil steht
local html = {}zweimal (einmal direkt vor dem „Prefix-Link“-Block und einmal im Block). Lösche die frühere Zeile und lasse nur die im „Prefix-Link“-Block stehen.
- (Optional) Tiefe per Vorlagen-Parameter
- Direkt nach
args = …ergänzen:
local depthArg = tonumber(args.tiefe or args.depth)
if depthArg then depth = depthArg end
- Dann kannst du in der Vorlage bei Bedarf
|tiefe=3setzen.
Alles andere im Canvas sieht stimmig aus: Fallback „ganze Seite“, SMW-Link-Strip immer aktiv, Vorlagenfilter-Fallback, Block-Wrapper für VE-Grenzen, Prefix-Link inline.
Du:
Modul:bereichsfenster (ve‑marker & Suchsteuerung)
OK – habe ich im Canvas so ausgeführt – überprüfe bitte, ob ich dies richtig ausgeführt habe, vor allem "local depthArg …"
ChatGPT:
Denke nach…
Prüfung der Benutzeranfrage zu Änderungen und Code
Die Benutzeranfrage dreht sich darum, ob Änderungen erfolgreich durchgeführt wurden, insbesondere zum lokalen
depthArg. Die Codezeile zeigt eine mögliche Fehlausrichtung beimif-Befehl, aber in Lua ist das irrelevant. Es ist jedoch wichtig, zu prüfen, ob die VariabledepthArgdie vorherige Zuweisung vondepthüberschreibt. Andernfalls scheint alles in Ordnung zu sein.Überprüfung der Lua-Muster und möglicher Probleme
Die Lua-Muster verwenden
==+und%-, was korrekt ist, wobei%einen Literalbindestrich darstellt. Das Muster fürnextPosscheint zu funktionieren, um Überschriften zu identifizieren. Beim Muster fürSchaufensterkönnte es eine kleine Herausforderung geben, da es minimalistisch ist und eventuell unerwartete Ergebnisse liefern könnte.Überprüfung der Codeänderungen und Stabilität
Die Änderungen zeigen, dass die Nutzung von
frame:preprocessweiterhin funktioniert, während innere "schaufenster"-Elemente korrekt vorab expandiert werden. Auch die Klassenbenennung ist konsistent, es wurde auf Rückwärtskompatibilität verzichtet. Weitere nützliche Anpassungen wie die Handhabung von Referenzen und Kategorientexten wurden gut umgesetzt.Überprüfung der Codeänderungen und Funktionsweise
Die Nutzung von
\n-Escape-Sequenzen in den Strings ist in Ordnung. Bei der FunktionladeListeVonSeite, diemw.text.gsplitverwendet, wurde der neueste Parameter korrekt gesetzt, um das Muster als normalen String zu behandeln. Auch bei den anderen Anpassungen gibt es keine größeren Probleme, die Änderungen stimmen.Überprüfung der Codeoptimierung und Details
Die Verwendung von 'ignore' oder einem leeren Standardwert für "navigation-not-searchable" ist korrekt. Die Handhabung der Tiefe (
depthArg) sieht gut aus, obwohl beiNachgedacht für 18s
Fertig
Sieht sehr gut aus. Ich bin deinen Canvas durchgegangen – speziell um depth / depthArg – und das passt:
- Funktionskopf:
function p.zeige(frame, depth)✔️ - Default:
depth = tonumber(depth) or 2✔️ - Override per Vorlagen-Parameter:
local depthArg = tonumber(args.tiefe or args.depth)
if depthArg then depth = depthArg end
- ✔️ (Einrückung spielt in Lua keine Rolle.)
- Einsatz des Rekursions-Expanders direkt nach den Filtern:
out = expandInnerSchaufenster(out, depth, frame)
Weitere kurze Checks (alles ok):
- Fallback „ganze Seite“, wenn weder
MarkenochAbschnittgreift. - SMW-Linkannotation wird immer entschärft (Property-Links → normale Links).
- Vorlagenfilter mit Fallback auf
MediaWiki:Vorlagenfilter. - VE-freundlicher Block-Wrapper (verhindert zusammengefasste Transklusionsblöcke).
- Prefix-Link im Wrapper (inline), Suffix-Link separat – beides sauber.
- Newlines als
\n(keine sichtbaren\nmehr).
Zwei kleine Hinweise (optional):
extrahiereLeadist jetzt ungenutzt – kann bleiben oder entfernt werden (reiner Kosmetikpunkt).- Der einfache Matcher für innere
{{Schaufenster …}}ignoriert Fälle, in denen in Parametern verschachtelte{{…}}vorkommt. Dann lässt er die Stelle absichtlich dem Parser – das ist der gewünschte „Safe-Guard“. Wenn du später wirklich solche Spezialfälle brauchst, kann man den Parseraufruf noch gezielter kapseln.
Fazit: Deine Umsetzung ist korrekt, inklusive depthArg. Wenn du magst, können wir als Nächstes noch ein kurzes TemplateData für „Schaufenster“ ergänzen (mit tiefe als optionalem Feld), damit der VE-Dialog komplett ist.
Du:
Weitere kurze Checks (alles ok):
- Fallback „ganze Seite“, wenn weder
MarkenochAbschnittgreift. - SMW-Linkannotation wird immer entschärft (Property-Links → normale Links).
- Vorlagenfilter mit Fallback auf
MediaWiki:Vorlagenfilter. - VE-freundlicher Block-Wrapper (verhindert zusammengefasste Transklusionsblöcke).
- Prefix-Link im Wrapper (inline), Suffix-Link separat – beides sauber.
- Newlines als
\n(keine sichtbaren\nmehr).
Zwei kleine Hinweise (optional):
extrahiereLeadist jetzt ungenutzt – kann bleiben oder entfernt werden (reiner Kosmetikpunkt).- Der einfache Matcher für innere
{{Schaufenster …}}ignoriert Fälle, in denen in Parametern verschachtelte{{…}}vorkommt. Dann lässt er die Stelle absichtlich dem Parser – das ist der gewünschte „Safe-Guard“. Wenn du später wirklich solche Spezialfälle brauchst, kann man den Parseraufruf noch gezielter kapseln.
Fazit: Deine Umsetzung ist korrekt, inklusive depthArg. Wenn du magst, können wir als Nächstes noch ein kurzes TemplateData für „Schaufenster“ ergänzen (mit tiefe als optionalem Feld), damit der VE-Dialog komplett ist.
ChatGPT:
Denke nach…
Bestätigung zur Löschung von Modul:Linkaufbereitung
Ja, es ist sicher, Modul:Linkaufbereitung zu löschen, wenn keine anderen Module oder Templates davon abhängen. Um dies zu überprüfen, kannst du "Special:WhatLinksHere" verwenden, um Transklusionen zu finden. Ein weiterer Ansatz wäre, nach "require('Modul:Linkaufbereitung')" im Moduls-Namespace zu suchen.
Vorschläge zur Löschung von Modul:Linkaufbereitung
Um sicherzustellen, dass das Modul nicht mehr verwendet wird, kann der Nutzer eine "WhatLinksHere"-Suche sowie eine Insourcing-Suche durchführen. Wenn das Modul behalten werden soll, könnte eine Umleitung oder Deprecation-Durchsage hinzugefügt werden. Zudem kann der Nutzer einen minimalen Wrapper verwenden, um die Kompatibilität zu gewährleisten.
Vorschläge zur Beibehaltung der Kompatibilität bei Löschung
In Schaufenster wird das Strippen von SMW immer angewendet, daher ist keine zusätzliche Linkaufbereitung erforderlich. Falls Nutzer ältere Tests nicht brechen wollen, können sie ein minimales Modul erstellen, das die Funktion
saeubernzurückgibt, wobei die Logik manuell dupliziert wird, da sie nicht direkt in Schaufenster verfügbar ist.Zusammenfassung der Löschung von Modul:Linkaufbereitung
Es wird empfohlen, das Modul zu
Nachgedacht für 13s
Fertig
Ja — Modul:Linkaufbereitung kannst du löschen.
Begründung kurz & klar:
- In Modul:Schaufenster ist
stripSMWPropertyLinks(..)bereits enthalten und wird immer angewendet (vorexpandInnerSchaufensterund vor der Ausgabe). Damit entstehen auf der Zielseite keine SMW-Annotationenmehr aus transkludierten Property-Links.
Sichere Vorgehensweise (2 Minuten):
- Prüfe, ob es noch Verwendungen gibt:
- Spezial:„Links auf diese Seite“ →
Modul:Linkaufbereitung - Code-Suche im Modul-Namensraum:
insource:/require\\(['"]Modul:Linkaufbereitung['"]\\)/ prefix:Modul:
- Spezial:„Links auf diese Seite“ →
- Nichts gefunden → Modul löschen. Wenn du ganz konservativ sein willst, ersetze den Inhalt vorher für 1–2 Wochen durch einen Stub, der weiterhin funktioniert, aber eine Notiz hinterlässt:
-- Modul:Linkaufbereitung (veraltet) – delegiert auf die in Schaufenster genutzte Logik
local p = {}
function p.saeubern(w)
if not w or w == "" then return "" end
w = mw.ustring.gsub(w, "%[%[%s*[%w_]+::([^|%]]+)%|([^%]]+)%]%]", "[[%1|%2]]")
w = mw.ustring.gsub(w, "%[%[%s*[%w_]+::([^%]]+)%]%]", "[[%1]]")
return w
end
return p
- (So bricht garantiert nichts, falls irgendwo doch noch ein alter Testfall darauf zeigt.)
Damit sparst du dir das Doppel-Warten und hältst die Logik an einem Ort (Schaufenster).
Du:
Modul:bereichsfenster (ve‑marker & Suchsteuerung) – Entwurf
Wenn ich ein Modul oder eine Vorlage versuche zu löschen, die noch in Verwendung ist, bekomme ich eine MediaWiki Warnmeldung. Ich habe bereits alle Seiten mit den alten Vorlagen und Modulen durch Schaufenster ersetzt und brauche keinen Fallback.
Wir lassen Modul:Schaufenster nun beim gegenwärtigen Stand und ich werde im Anschluß den Gebrauch von Vorlage:Schaufenster an einigen Seiten Testen bei denen ich bislang nur {{:Seitenname}}verwendet habe.
Ich habe einige Seiten inzwischen getestet. Wenn ich mittels Vorlage:Schaufenster eine Seite trankludiere, die es gar nicht gibt, erhalte ich die Fehlermeldung "Lua-Fehler in Modul:Schaufenster, Zeile 252: attempt to call field 'escape' (a nil value)"
In Zeile 252 ist die dritte Zeile im folgenden Block:
local t = mw.title.new(seitentitel) if not t or not t.exists then return string.format("<strong class=\"error\">Schaufenster: Seite '%s' existiert nicht.</strong>", mw.html.escape(seitentitel)) end
Am liebsten wäre mit das Modul:Schaufenster sich im Fall einer fehlenden Seite wie MediaWiki verhält und nur einfach den roten Link zur Zeite anzeigt, sodaß man diese Seite gleich anlegen kann, oder anhand des roten Link erkennt, daß man den Seitennamen falsch geschrieben hat. Eine Meldung wie vergleichsweise "Seite nicht vorhanden" brauche ich nicht wirklich.
Wie bekommen wir den roten Link bei fehlender Seite hin?
ChatGPT:
-- Modul:Schaufenster (VE‑Marker & Suchsteuerung)
-- Zweck:
-- * Transklusion von Quellseiten-Text (komplett, Einleitung, Abschnitt, markierte Spanne)
-- * Optionales Strippen von Kategorien und bestimmten Vorlagen
-- * Steuerung des Suchverhaltens für Zielseiten (CirrusSearch):
-- - "navigation-not-searchable" → Transklusionsinhalt wird nicht indiziert
-- - "searchaux" → Transklusionsinhalt wird nur schwach gewichtet
-- * VE‑taugliche Marker: {{SchaufensterBegin|Label}} … {{SchaufensterEnde|Label}}
-- (kompatibel: {{SchaufensterBeginn|…}}, {{SchaufensterBegin(n)|…}}, {{SchaufensterEnde|…}})
-- * Zusätzlich Erkennung von LST‑Markern: <section begin="Label"/> … <section end="Label"/>
--
-- Aufruf (empfohlen über eine Vorlage, z. B. {{ZitatTransklusion}}):
-- {{#invoke:Schaufenster|zeige
-- | Seite = Werk:Beispiel
-- | Abschnitt = Ein Abschnittstitel (optional)
-- | Marke = Zitat-001 (optional; dominiert gegenüber Abschnitt/Lead)
-- | suche = ignorieren | abwerten | (leer) (optional; Default: ignorieren)
-- | ohneKat = 1/0 (Default 1)
-- | ohneVorlagen = 1/0 (Default 1)
-- | link = 1 / eigener Linktext (optional: Quelle-Link unterhalb)
-- | refs = 1 (optional: <references/> am Ende)
-- }}
local p = {}
local debugModus = false
-- Utils ----------------------------------------------------------------------
local u = {}
function u.trim(s)
if not s then return "" end
return (mw.text.trim(tostring(s)))
end
function u.esc(s)
-- Escape für Lua-Pattern
return (mw.ustring.gsub(s, "([%(%)%.%%%+%-%*%?%[%^%$])", "%%%1"))
end
-- Einfache Listenlese-Funktion: jede nicht-leere Zeile = Eintrag
local function ladeListeVonSeite(titel)
local t = mw.title.new(titel)
if not t or not t.exists then return {} end
local text = t:getContent() or ""
-- Zeilenenden vereinheitlichen: \r\n und \r -> \n
text = mw.ustring.gsub(text, "\r\n?", "\n")
-- (optional) UTF-8-BOM entfernen
text = mw.ustring.gsub(text, "^\239\187\191", "")
local out = {}
for line in mw.text.gsplit(text, "\n", true) do
line = mw.text.trim(line)
if line ~= "" and not line:match("^%-%-") and not line:match("^//") and not line:match("^#") then
table.insert(out, line)
end
end
return out
end
-- Kategorien entfernen ([[Kategorie:…]])
local function stripKategorien(text)
-- grob, aber effektiv; mehrfach ausführen ist ok
text = mw.ustring.gsub(text, "%[%[%s*[Kk]ategorie:%s*[^%]]+%]%]%s*", "")
return text
end
-- Ausgewählte Vorlagen entfernen (Namen werden aus einer Liste geladen)
local function stripVorlagen(text, namen)
for _, name in ipairs(namen or {}) do
local patt = u.esc(name)
-- Ohne Namensraumpräfix
text = mw.ustring.gsub(text, "{{%s*" .. patt .. "%s*}}", "")
text = mw.ustring.gsub(text, "{{%s*" .. patt .. "[^}]*}}", "")
-- Mit Namensraumpräfix (Vorlage:/Template:)
text = mw.ustring.gsub(text, "{{%s*[Vv]orlage:%s*" .. patt .. "%s*}}", "")
text = mw.ustring.gsub(text, "{{%s*[Vv]orlage:%s*" .. patt .. "[^}]*}}", "")
text = mw.ustring.gsub(text, "{{%s*[Tt]emplate:%s*" .. patt .. "%s*}}", "")
text = mw.ustring.gsub(text, "{{%s*[Tt]emplate:%s*" .. patt .. "[^}]*}}", "")
end
return text
end
-- Abschnitt per Überschrift extrahieren (einfacher Parser)
local function extrahiereBereich(text, heading)
if not heading or u.trim(heading) == "" then return nil end
local H = u.esc(heading)
-- Finde erste Überschrift mit diesem Titel
local startPos = mw.ustring.find(text, "==+%s*" .. H .. "%s*==+")
if not startPos then return nil end
-- Finde nächste Überschrift nach startPos
local nextPos = mw.ustring.find(text, "\n==+%s*[^=\n].-==+", startPos + 1)
local seg
if nextPos then
seg = mw.ustring.sub(text, startPos, nextPos - 1)
else
seg = mw.ustring.sub(text, startPos)
end
-- schneide die Überschriftenzeile selbst ab
local body = seg:gsub("^.-\n", "")
return body
end
-- Einleitung (vor erster Überschrift)
local function extrahiereLead(text)
local firstH = mw.ustring.find(text, "==+")
if firstH then
return mw.ustring.sub(text, 1, firstH - 1)
end
return text
end
-- Markenspannen extrahieren ---------------------------------------------------
local function extrahiereMarke(text, label)
label = u.trim(label)
if label == "" then return nil end
local L = u.esc(label)
-- (a) VE‑Marker via Vorlagen: {{SchaufensterBegin|Label}} ... {{SchaufensterEnde|Label}}
local function find_any(txt, patterns, init)
for _, patt in ipairs(patterns) do
local s, e = mw.ustring.find(txt, patt, init)
if e then return s, e end
end
return nil, nil
end
local beginNames = { "SchauBegin", "SchaufensterBegin", "SchaufensterBeginn", "SF%-Begin" }
local endNames = { "SchauEnde", "SchaufensterEnde", "SF%-Ende" }
local beginPats = {}
for _, name in ipairs(beginNames) do
table.insert(beginPats, "{{%s*" .. name .. "%s*|%s*" .. L .. "%s*}}")
end
local b1s, b1e = find_any(text, beginPats)
if b1e then
local endPats = {}
for _, name in ipairs(endNames) do
table.insert(endPats, "{{%s*" .. name .. "%s*|%s*" .. L .. "%s*}}")
end
local e2s = select(1, find_any(text, endPats, b1e + 1))
if e2s then
return mw.ustring.sub(text, b1e + 1, e2s - 1)
end
end
-- (b) LST‑Marker: <section begin="Label"/> ... <section end="Label"/>
do
local lb1s, lb1e = mw.ustring.find(text, "<%s*[Ss]ection%s+[Bb]egin%s*=%s*[\"']" .. L .. "[\"']%s*/%s*>")
if lb1e then
local le2s = mw.ustring.find(text, "<%s*[Ss]ection%s+[Ee]nd%s*=%s*[\"']" .. L .. "[\"']%s*/%s*>", lb1e + 1)
if le2s then
return mw.ustring.sub(text, lb1e + 1, le2s - 1)
end
end
end
-- (c) Kommentar‑Marker (optional): <!-- BF:BEGIN Label --> ... <!-- BF:END Label -->
do
local cb1s, cb1e = mw.ustring.find(text, "<!%-%-%s*[BbSs][Ff]%s*:%s*[Bb][Ee][Gg][Ii][Nn]%s+" .. L .. "%s*%-%->")
if cb1e then
local ce2s = mw.ustring.find(text, "<!%-%-%s*[BbSs][Ff]%s*:%s*[Ee][Nn][Dd]%s+" .. L .. "%s*%-%->", cb1e + 1)
if ce2s then
return mw.ustring.sub(text, cb1e + 1, ce2s - 1)
end
end
end
return nil
end
-- SMW-Property-Links in normale Links umwandeln (immer anwenden)
local function stripSMWPropertyLinks(text)
if not text or text == "" then return text end
-- [[Property::Wert|Label]] -> [[Wert|Label]]
text = mw.ustring.gsub(text, "%[%[%s*[%w_]+::([^|%]]+)%|([^%]]+)%]%]", "[[%1|%2]]")
-- [[Property::Wert]] -> [[Wert]]
text = mw.ustring.gsub(text, "%[%[%s*[%w_]+::([^%]]+)%]%]", "[[%1]]")
return text
end
-- --- Rekursiver Expander für innere {{Schaufenster …}} ----------------------
-- Parsen einer einfachen |key=value|-Liste (dein üblicher Vorlagenstil)
local function parseTemplateArgs(paramstr)
local a, i = {}, 1
for part in mw.text.gsplit(paramstr or "", "|", false) do
part = mw.text.trim(part)
if part ~= "" then
local k, v = part:match("^([^=]+)=(.*)$")
if k then
a[mw.text.trim(k)] = mw.text.trim(v)
else
a[i] = part; i = i + 1
end
end
end
return a
end
-- Expandiert innere {{Schaufenster …}}-Aufrufe, ohne die Vorlage erneut zu transkludieren.
-- depth: wie viele Schaufenster-Ebenen dürfen noch expandiert werden (>=0).
local function expandInnerSchaufenster(text, depth, outerFrame)
if not text or text == "" or (depth or 0) <= 0 then
return text
end
-- Achtung: einfacher Matcher – erwartet "normale" Benutzung (keine verschachtelten "{{" in Parametern)
-- Match NUR echte {{Schaufenster|...}}-Aufrufe (Pipe nach dem Namen zwingend),
-- vermeidet false positives bei {{SchaufensterBeginn}} / {{SchaufensterEnde}}
local patt = "{{%s*[Ss]chaufenster%s*(|[^{}]-)}}"
return (mw.ustring.gsub(text, patt, function(paramstr)
-- paramstr beginnt hier mit "|..."; führenden Pipe entfernen
paramstr = paramstr:gsub("^%s*|", "")
-- Falls verschachtelte Vorlagen im Parameter vorkommen, den Call unverändert lassen
if paramstr:find("{{", 1, true) then
return "{{Schaufenster|" .. paramstr .. "}}"
end
local a = parseTemplateArgs(paramstr)
local fake = {
args = a,
preprocess = function(_, w) return outerFrame:preprocess(w) end,
getParent = function() return nil end
}
-- expandiere eine Ebene tiefer
return p.zeige(fake, (depth or 1) - 1)
end))
end
-- Hauptfunktion --------------------------------------------------------------
function p.zeige(frame, depth)
depth = tonumber(depth) or 2
local args = frame:getParent() and frame:getParent().args or frame.args
local depthArg = tonumber(args.tiefe or args.depth)
if depthArg then depth = depthArg end
local seitentitel = u.trim(args.Seite or args.Seitenname or args[1] or "")
local bereich = u.trim(args.Abschnitt or args.Bereich or args[2] or "")
local marke = u.trim(args.Marke or args.label or "")
local suchmodus = (args.suche or args.modus or ""):lower() -- "ignorieren" | "abwerten" | ""
local ohneKat = tostring(args.ohneKat or "1") ~= "0"
local ohneVorlagen= tostring(args.ohneVorlagen or "1") ~= "0"
local linkParam = args.link
local link = not (linkParam == "0" or linkParam == 0 or linkParam == false)
local refs = tostring(args.refs or args.reflist or "0") ~= "0"
local inline = tostring(args.inline or args.zeilig or "0") ~= "0"
local linkpos = (args.linkpos or args.linkposition or "prefix"):lower()
if seitentitel == "" then
return "<strong class=\"error\">Schaufenster: Kein Seitentitel angegeben.</strong>"
end
local t = mw.title.new(seitentitel)
if not t or not t.exists then
-- Fehlende Seite: gib den roten Link zur Anlage/Prüfung des Titels aus (MediaWiki-Standardverhalten)
return string.format("[[%s]]", seitentitel)
end
local content = t:getContent() or ""
local debugText = ""
if debugModus then
debugText = debugText .. string.format("[Debug] Quelle geladen: %s (%d Zeichen)\n", t.prefixedText, mw.ustring.len(content))
end
-- 1) Vorrang: markierte Spanne
local out
if marke ~= "" then
out = extrahiereMarke(content, marke) or ""
if debugModus then debugText = debugText .. string.format("[Debug] Marke '%s' extrahiert.\n", marke) end
end
-- 2) Abschnitt
if not out or out == "" then
if bereich ~= "" then
out = extrahiereBereich(content, bereich) or ""
if debugModus then debugText = debugText .. string.format("[Debug] Abschnitt '%s' extrahiert.\n", bereich) end
else
-- 3) Fallback: ganze Seite (kein Marker/Abschnitt)
out = content
if debugModus then debugText = debugText .. "[Debug] Fallback: ganze Seite.\n" end
end
end
-- 4) Filter anwenden
if ohneKat then out = stripKategorien(out) end
if ohneVorlagen then
local namen = ladeListeVonSeite("Vorlage:Schaufenster/Vorlagenfilter")
if #namen == 0 then namen = ladeListeVonSeite("Template:Schaufenster/Vorlagenfilter") end
if #namen == 0 then namen = ladeListeVonSeite("MediaWiki:Vorlagenfilter") end
out = stripVorlagen(out, namen)
end
-- SMW-Property-Links immer entschärfen
out = stripSMWPropertyLinks(out)
-- Innere {{Schaufenster …}} im Ergebnis vorab expandieren (verhindert Template-Selbstrekursion)
out = expandInnerSchaufenster(out, depth, frame)
-- 5) Ausgabe verpacken (Suchsteuerung)
local cls
if suchmodus == "abwerten" or suchmodus == "aux" then
cls = "searchaux"
elseif suchmodus == "ignorieren" or suchmodus == "exclude" or suchmodus == "" then
cls = "navigation-not-searchable"
else
cls = nil
end
-- Prefix-Link (später im Wrapper ausgeben)
local html = {}
local prefixHTML = ""
if link and linkpos == 'prefix' then
local linkLabel
if type(linkParam) == 'string' and linkParam ~= '' and linkParam ~= '1' then
linkLabel = linkParam
else
linkLabel = '▷'
end
prefixHTML = string.format('[[%s|%s]] ', t.prefixedText, linkLabel)
end
local inlineMode = inline or (link and linkpos == 'prefix')
if cls then
-- Immer Block-Wrapper für klare VE-Grenzen
table.insert(html, '<div class="schaufenster-content ' .. cls .. '">')
table.insert(html, prefixHTML)
table.insert(html, out)
table.insert(html, '</div>\n')
else
if inlineMode then
-- Auch ohne Klasse einen Block-Wrapper setzen
table.insert(html, '<div class="schaufenster-content">')
table.insert(html, prefixHTML)
table.insert(html, out)
table.insert(html, '</div>\n')
else
-- Klassischer Blockmodus mit Absatz-Puffern
table.insert(html, '\n' .. out .. '\n')
end
end
-- Suffix-Link (unterhalb; außerhalb des Blocks)
if link and linkpos ~= 'prefix' then
local linkLabel
if type(linkParam) == 'string' and linkParam ~= '' and linkParam ~= '1' then
linkLabel = linkParam
else
linkLabel = '▷ Quelle'
end
table.insert(html, string.format('\n<div class="schaufenster-quelle">[[%s|%s]]</div>', t.prefixedText, linkLabel))
end
if refs then
-- refs typischerweise unterhalb; Blockgrenze ist bereits gesetzt
table.insert(html, '\n<references responsive="1" />')
end
local wikitext = table.concat(html)
local rendered = frame:preprocess(wikitext)
if debugModus then
return string.format("<pre>%s</pre>%s", debugText, rendered)
end
return rendered
end
return p
Denke nach…
Vorschlag für Codeänderung: Fehlende Seiten als rote Links anzeigen
Der Benutzer sieht einen Fehler, wenn er Schaufenster auf einer nicht existierenden Seite verwendet. Statt des Fehlers soll ein roter Link zur Seite angezeigt werden, der zur Erstellung auffordert. Wir könnten die Codeänderung so vornehmen, dass bei einer fehlenden Seite ein Wikitext-Link wie "[[Seitentitel]]" angezeigt wird.
Anpassung des roten Links für fehlende Seite
Beim fehlenden Inhalt möchten sie wahrscheinlich weiterhin den roten Link zur Seite anzeigen, wobei der Seitenname als Linktext erscheint, wie in MediaWiki üblich. Die Verwendung von '▷' vor dem Link könnte sich als unpassend herausstellen, daher sollten wir den Link mit dem Seitentitel ohne zusätzliche Textpräfixe anzeigen.
Vorschlag zur Codeanpassung für rote Links
Ich schlage vor, den bestehenden Code zu ändern, sodass bei einer nicht existierenden Seite statt einer Fehlermeldung einfach ein roter Link angezeigt wird:
[[Seitentitel]]. Dadurch wird ein direkt klickbarer Link zur Seite mit dem Titel als roten Link erstellt. Seitentitel können keine unsicheren Zeichen wie|oder]]enthalten, sodass dies sicher ist.Fix für Fehler mit mw.html.escape
Der Fehler tritt auf, weil
mw.html.escapein der aktuellen Umgebung nicht verfügbar ist. Stattdessen können wirmw.text.encodeodermw.text.nowikiverwenden, je nachdem, ob wir HTML oder Wikicode escapen wollen. Da wir jedoch nur einen Link anzeigen, könnte es auch ausreichen, keinen Escape zu verwenden, sodass keine zusätzlichen Wrapper notwendig sind.Codeanpassung und Implementierung von Änderungen
Die bevorzugte Lösung ist es, nur den roten Link zur nicht existierenden Seite anzuzeigen. Dafür werden wir den Code anpassen und den
mw.html.escape-Aufruf entfernen. Der Code wird so geändert, dass bei einer fehlenden Seite einfach[[seitentitel]]zurückgegeben wird. Wir müssen auch die richtige Anweisung in der Canvas aktualisieren, um diese Änderung vorzunehmen.Nachgedacht für 17s
Fertig
Erledigt: Ich habe den Block so angepasst, dass bei nicht vorhandener Quellseite kein Fehler mehr entsteht, sondern einfach ein roter Link auf den Seitennamen ausgegeben wird (MediaWiki-Standardverhalten).
Konkret geändert (im Canvas umgesetzt):
- Ersetzte den bisherigen Fehler-Return (mit
mw.html.escape, das bei dir nicht verfügbar ist) durch:→ Dadurch kannst du die Seite sofort anlegen, oder siehst Tippfehler am roten Link.return string.format("[[%s]]", seitentitel)
Wenn du stattdessen lieber den kleinen „▷“-Link (rot) sehen willst, ginge auch:
return string.format("[[%s|▷]] ", seitentitel)
Sag Bescheid, dann stelle ich das um.
Du:
Modul:bereichsfenster (ve‑marker & Suchsteuerung) – Entwurf
Ich habe den Block "local t = mw.title.new(seitentitel)…" ersetzt und es funktioniert nun.
Wir müssen noch den Default ändern. Wenn ich mittels RepkaceText nun in Wikiseiten lediglich "{{:" gegen "{{Schaufenster|Seite=" ersetze, so werden Modul:Schaufenster keine weiteren Parameter zu Link, Prefix … übermittelt.
Wenn keine Parameter übermittelt werden, dann soll nun per Fallback der Default des ▷-Link und der Prefix gesetzt werden, welches den Link an den Anfang setzt.
Gebe mir bitte dazu die zu ändernden Zeilen oder zu ersetzenden Blöcke aus, die ich dann erst beiu mir teste, bevor wir diese im Canvas einfügen – OK?
ChatGPT:
Denke nach…
Überprüfen der Standardwerte für Parameter
Die Benutzerin möchte, dass bei fehlenden Parametern der Link und der Prefix standardmäßig gesetzt werden. Der aktuelle Code setzt den Link standardmäßig auf "disabled", wenn der Parameter "link" nicht vorhanden oder leer ist. Ich muss den Code ändern, damit der Standard auf "enabled" und der Prefix auf den Anfang gesetzt wird.
Standardwerte für Link und Präfix anpassen
Die Standardeinstellung für "linkpos" ist bereits "prefix", was gut ist. Allerdings wird die "inline"-Variable standardmäßig auf "false" gesetzt. Wenn der Link aktiviert ist und der Link-Position "prefix" entspricht, wird "inlineMode" zu "true", was gewünscht ist. Ich muss also sicherstellen, dass der Link standardmäßig aktiviert wird, wenn der Parameter fehlt.
Verarbeitung der leerer Link-Parameter
Wenn der linkParam leer ist oder "0", wird der Link deaktiviert, andernfalls aktivieren wir ihn. Ein leerer String oder "1" signalisiert, dass wir den Standard-Label verwenden sollen – das bedeutet "▷". Wenn der linkParam leer ist, wird der Standardwert verwendet, andernfalls bleibt alles wie erwartet.
Vereinfachen der Link-Logik
Im Code prüfe ich, ob der "linkParam" leer oder falscher Wert ist und setze den Link entsprechend. Ich könnte den Code vereinfachen, indem ich den Link standardmäßig mit "true" setze, wenn der Parameter fehlt. Außerdem muss der Standardwert für den Link-Label als "▷" festgelegt werden.
Änderungen am Code vornehmen
Die Rückgabewerte für den Link bestimmen wir nach folgender Logik: Ist der Parameter 'nil' oder falsch, setzen wir den Standardwert. Ich werde die Zeilen zur Bestimmung von 'link' anpassen und sicherstellen, dass der Standardwert für 'linkpos' und 'suchmodus' beibehalten wird. Falls notwendig, könnte auch der Standard 'inline' überprüft werden.
Nachgedacht für 16s
Fertig
Alles klar — für deinen gewünschten Default (▷-Link an, Position prefix) reicht eine Code-Änderung.
Ersetze exakt diese beiden Zeilen
Finden:
local linkParam = args.link
local link = not (linkParam == nil or linkParam == "0" or linkParam == 0 or linkParam == false)
Ersetzen durch:
local linkParam = args.link
local link = not (linkParam == "0" or linkParam == 0 or linkParam == false)
Damit gilt:
- Kein Parameter →
link = true(Standard-Label „▷“, Position bleibt defaultprefix) link=0/link=false→ Link auslink=1→ Link an, Label „▷“link=Mein Label→ Link an, eigenes Label
Hinweis: Deine linkpos-Vorgabe steht bereits korrekt auf prefix:
local linkpos = (args.linkpos or args.linkposition or "prefix"):lower()
Kurztest
Nur mit Seitenangabe:
{{Schaufenster|Seite=Beispiel}}
→ sollte „▷ Beispiel …“ direkt am Anfang ausgeben, ohne Zusatzparameter.
Du:
Modul:bereichsfenster (ve‑marker & Suchsteuerung) – Entwurf
Ich habe die Änderung getestet. Wie kann es sein, daß nun die in der Quellseite verwendeten Marker {{SchaufensterBeginn|…}} und {{SchaufensterEnde|…}} in der Zielseite als "https://wiki.aewi.de/Beginn" und "https://wiki.aewi.de/Ende" rendern?
ChatGPT:
Aktivität
·55s
Denke nach…
Analyzing marker handling after change
The user's issue seems related to how the markers {{SchaufensterBeginn|…}} and {{SchaufensterEnde|…}}are rendering as external links instead of staying in template form. It looks like our extraction isn't fully stripping away markers after processing. After expanding inner content, I need to double-check if we're removing the markers properly post-extraction.
Tracking external link issue
The external link "https://wiki.aewi.de/Beginn" seems to be caused by the
[[Beginn]]pattern, which might appear in the output unexpectedly. It seems this could have come from text being transformed by a function likestripSMWPropertyLinks, though neither of these functions should turn it into a link like that. I need to investigate this further.Investigating changes and functions involved
The
stripVorlagenfunction should remove named templates, but "Beginn" and "Ende" are unlikely to be in the list. It seems the error could have arisen from our recent change to the link handling logic. I’ll double-check whether the link check is still using the old version on the current canvas.Checking for applied changes
It looks like the change to the link logic might not have been applied correctly. The canvas still shows the old version with
linkParam == nil, which doesn't match the updated code. The user mentioned making the change, so perhaps the update didn't get pasted or applied to the canvas here. I’ll verify this.Investigating marker rendering issue
It looks like the update didn't apply to the canvas. The issue with the markers
SchaufensterBeginnandSchaufensterEndelikely comes from non-recognition as templates, causing them to appear as links instead. This could be because the actual template names, like "BereichfensterBeginn," differ from what we assumed. I need to confirm this!Investigating template mismatch
It seems the user had a typo with "BreichfensterBeginn" instead of "BereichfensterBeginn," and then changed to "SchaufensterBeginn" and "SchaufensterEnde." But if their template pages don't exist, it could cause issues. The pattern in our filter might also be greedily matching, treating "SchaufensterBeginn" as a template when it's not. I'll need to cross-check the pattern and list names.
Investigating template processing and fallback behavior
It seems like a fallback is happening when
extrahiereMarkereturns nil, causing the entire content to be processed. The issue might be due to templates likeSchaufensterBeginnandSchaufensterEndenot being included in the filter list, resulting in them being processed incorrectly. I'll consider if redirects or other template behaviors could explain this.Examining issue with marker processing
It seems like the default change might have impacted the pattern for detecting the marker, but this should only affect prefix link insertion, not extraction. I'll look at the current implementation, where the label might have been stripped accidentally if
stripVorlagenhandled the curly braces incorrectly. Looks like the filter list could be missing a name.Addressing regex pattern issue with Schaufenster templates
It looks like the gsub pattern is picking up "SchaufensterBeginn" as part of a larger template string because it only requires optional whitespace between "Schaufenster" and the rest of the name. This might cause it to operate incorrectly, treating the param like "Beginn|Label" and attempting to transclude the page "Beginn."
Fixing regex for template detection
The problem arises when the
expandInnerSchaufensterpattern matches the "SchaufensterBeginn" and "SchaufensterEnde" templates due to the regex being too broad. To fix this, I need to ensure that the pattern strictly matches{{Schaufenster}}(case-insensitive) with appropriate boundaries, avoiding cases where extra parameters like "Beginn" or "Ende" appear. I'll update the regex to narrow this down.Nachgedacht für 55s
Fertig
Ja, das Verhalten ist erklärbar: unser Expander für innere {{Schaufenster …}} war zu großzügig und hat fälschlich auch {{SchaufensterBeginn|…}}/{{SchaufensterEnde|…}} als „Schaufenster“-Aufruf erkannt. Dann wurde Beginn/Ende als Positionsparameter 1 interpretiert ⇒ seitentitel="Beginn"/"Ende" ⇒ Ausgabe [[Beginn]]/[[Ende]].
Fix (gezielt, minimal)
Passe im expandInnerSchaufenster die Regex so an, dass NUR echte {{Schaufenster …}}-Aufrufe mit einem Pipenach dem Namen gematcht werden – nicht SchaufensterBeginn/SchaufensterEnde.
Ersetzen (nur diesen Block anpassen)
Suche im Modul nach:
local patt = "{{%s*[Ss]chaufenster%s*(.-)}}"
return (mw.ustring.gsub(text, patt, function(paramstr)
-- Wenn doch verschachtelte "{{" im Param, gib unverändert zurück (Parser macht das dann)
if paramstr:find("{{", 1, true) then
return "{{Schaufenster" .. paramstr .. "}}"
end
local a = parseTemplateArgs(paramstr)
...
Und ersetze durch:
-- Match NUR echte {{Schaufenster|...}}-Aufrufe (Pipe nach dem Namen zwingend),
-- vermeidet false positives bei {{SchaufensterBeginn}} / {{SchaufensterEnde}}
local patt = "{{%s*[Ss]chaufenster%s*(|[^{}]-)}}"
return (mw.ustring.gsub(text, patt, function(paramstr)
-- paramstr beginnt hier mit "|..."; führenden Pipe entfernen
paramstr = paramstr:gsub("^%s*|", "")
-- Falls verschachtelte Vorlagen im Parameter vorkommen, den Call unverändert lassen
if paramstr:find("{{", 1, true) then
return "{{Schaufenster|" .. paramstr .. "}}"
end
local a = parseTemplateArgs(paramstr)
local fake = {
args = a,
preprocess = function(_, w) return outerFrame:preprocess(w) end,
getParent = function() return nil end
}
return p.zeige(fake, (depth or 1) - 1)
end))
Wirkung
{{Schaufenster|…}}wird weiterhin rekursiv (sicher) expandiert.{{SchaufensterBeginn|…}}/{{SchaufensterEnde|…}}werden nicht mehr als Schaufenster interpretiert → deine Marker bleiben Marker; die Spanne wird korrekt erkannt; keine Links auf „Beginn/Ende“.
Das ist der einzige notwendige Patch für das geschilderte Phänomen.
Du:
So wie es aussieht, läuft alles – etwa 6000 Wikiseiten nutzen jertzt Modul:Schaufenster – Gratulation für das Coding und Danke für deine Unterstützung.
Bitte keine weiteren Anregungen und Hinweise in dieser Sache. Wir schließen dies hiernach ab.
An einem deartigen Modul haben wir seit Monaten immer wieder mal gearbeitet, noch nie sind wir so weit gelangt wie heute.
ChatGPT:
verstanden. Fall abgeschlossen.
Freut mich, dass Schaufenster jetzt stabil läuft und produktiv im Einsatz ist. Wenn du später wieder anknüpfen willst, bin ich bereit.