Stadionzeitung: Live-Seiten (Tabellen, Ergebnisse, Vorschau, Termine, News, Kontakt, Historie, Sportheim, Partner, Momente, Impressum), automatisches Cover, Swipe-Viewer mit Vollbildmodus und die Druckfassung als Falt-Heft. Anzeigen kommen jetzt aus dem Bestand und werden gleichmäßig verteilt, nie mehr als zwei hintereinander (vorher vier Blöcke à fünf). Die Doppelseiten-Regel rechnet das Skript selbst, statt sie von Hand zu prüfen. Veranstaltungen: Bereich /veranstaltungen mit Detailseite pro Fest, Lebenszyklus über das Datum (Ankündigung vor dem Fest, Rückblick danach), Galerie mit Lightbox. veranstaltungen.json ist dritte Termin-Quelle, damit ein Fest nie doppelt gepflegt wird. News-Artikel als dritte dynamische Prefix-Route, gemeinsamer detail-head. Behobene Fehler: - Wappen-Kontexte setzten Zeilen-Layout auf .crest statt auf die Zeile; das Wappen wurde zum Grid, Vereinsname und Tore rutschten darunter zusammen (Ergebnis-Rückblick, Vorschau, Cover). - --header-h (60px) unterschätzt die Kopfleiste um 32px (Logo 72px + 20px Versatz): neues abgeleitetes --header-space, sonst klebten Zurück-Links unter dem Logo. - base_url in der Produktions-Config ohne www, während .htaccess auf www umleitet; preflight prüft das jetzt. - .lightbox brauchte display:none mit (0,2,0), sonst lag das Overlay offen. Neue Werkzeuge: bin/anzeige-add.php (Anzeigen-Bestand), bin/veranstaltung-bilder.php (Plakate und Galerien, Alt-Texte folgen der Quelldatei), bin/qr.php (Druck-QR mit Warnung, wenn base_url nicht auf die echte Domain zeigt). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NzeVVgMCrzCDJAKeLEdKr7
161 lines
3.7 KiB
JavaScript
161 lines
3.7 KiB
JavaScript
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
// Distributed under an MIT license: https://codemirror.net/5/LICENSE
|
|
|
|
(function(mod) {
|
|
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|
mod(require("../../lib/codemirror"));
|
|
else if (typeof define == "function" && define.amd) // AMD
|
|
define(["../../lib/codemirror"], mod);
|
|
else // Plain browser env
|
|
mod(CodeMirror);
|
|
})(function(CodeMirror) {
|
|
"use strict";
|
|
|
|
CodeMirror.defineMode("eiffel", function() {
|
|
function wordObj(words) {
|
|
var o = {};
|
|
for (var i = 0, e = words.length; i < e; ++i) o[words[i]] = true;
|
|
return o;
|
|
}
|
|
var keywords = wordObj([
|
|
'note',
|
|
'across',
|
|
'when',
|
|
'variant',
|
|
'until',
|
|
'unique',
|
|
'undefine',
|
|
'then',
|
|
'strip',
|
|
'select',
|
|
'retry',
|
|
'rescue',
|
|
'require',
|
|
'rename',
|
|
'reference',
|
|
'redefine',
|
|
'prefix',
|
|
'once',
|
|
'old',
|
|
'obsolete',
|
|
'loop',
|
|
'local',
|
|
'like',
|
|
'is',
|
|
'inspect',
|
|
'infix',
|
|
'include',
|
|
'if',
|
|
'frozen',
|
|
'from',
|
|
'external',
|
|
'export',
|
|
'ensure',
|
|
'end',
|
|
'elseif',
|
|
'else',
|
|
'do',
|
|
'creation',
|
|
'create',
|
|
'check',
|
|
'alias',
|
|
'agent',
|
|
'separate',
|
|
'invariant',
|
|
'inherit',
|
|
'indexing',
|
|
'feature',
|
|
'expanded',
|
|
'deferred',
|
|
'class',
|
|
'Void',
|
|
'True',
|
|
'Result',
|
|
'Precursor',
|
|
'False',
|
|
'Current',
|
|
'create',
|
|
'attached',
|
|
'detachable',
|
|
'as',
|
|
'and',
|
|
'implies',
|
|
'not',
|
|
'or'
|
|
]);
|
|
var operators = wordObj([":=", "and then","and", "or","<<",">>"]);
|
|
|
|
function chain(newtok, stream, state) {
|
|
state.tokenize.push(newtok);
|
|
return newtok(stream, state);
|
|
}
|
|
|
|
function tokenBase(stream, state) {
|
|
if (stream.eatSpace()) return null;
|
|
var ch = stream.next();
|
|
if (ch == '"'||ch == "'") {
|
|
return chain(readQuoted(ch, "string"), stream, state);
|
|
} else if (ch == "-"&&stream.eat("-")) {
|
|
stream.skipToEnd();
|
|
return "comment";
|
|
} else if (ch == ":"&&stream.eat("=")) {
|
|
return "operator";
|
|
} else if (/[0-9]/.test(ch)) {
|
|
stream.eatWhile(/[xXbBCc0-9\.]/);
|
|
stream.eat(/[\?\!]/);
|
|
return "ident";
|
|
} else if (/[a-zA-Z_0-9]/.test(ch)) {
|
|
stream.eatWhile(/[a-zA-Z_0-9]/);
|
|
stream.eat(/[\?\!]/);
|
|
return "ident";
|
|
} else if (/[=+\-\/*^%<>~]/.test(ch)) {
|
|
stream.eatWhile(/[=+\-\/*^%<>~]/);
|
|
return "operator";
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function readQuoted(quote, style, unescaped) {
|
|
return function(stream, state) {
|
|
var escaped = false, ch;
|
|
while ((ch = stream.next()) != null) {
|
|
if (ch == quote && (unescaped || !escaped)) {
|
|
state.tokenize.pop();
|
|
break;
|
|
}
|
|
escaped = !escaped && ch == "%";
|
|
}
|
|
return style;
|
|
};
|
|
}
|
|
|
|
return {
|
|
startState: function() {
|
|
return {tokenize: [tokenBase]};
|
|
},
|
|
|
|
token: function(stream, state) {
|
|
var style = state.tokenize[state.tokenize.length-1](stream, state);
|
|
if (style == "ident") {
|
|
var word = stream.current();
|
|
style = keywords.propertyIsEnumerable(stream.current()) ? "keyword"
|
|
: operators.propertyIsEnumerable(stream.current()) ? "operator"
|
|
: /^[A-Z][A-Z_0-9]*$/g.test(word) ? "tag"
|
|
: /^0[bB][0-1]+$/g.test(word) ? "number"
|
|
: /^0[cC][0-7]+$/g.test(word) ? "number"
|
|
: /^0[xX][a-fA-F0-9]+$/g.test(word) ? "number"
|
|
: /^([0-9]+\.[0-9]*)|([0-9]*\.[0-9]+)$/g.test(word) ? "number"
|
|
: /^[0-9]+$/g.test(word) ? "number"
|
|
: "variable";
|
|
}
|
|
return style;
|
|
},
|
|
lineComment: "--"
|
|
};
|
|
});
|
|
|
|
CodeMirror.defineMIME("text/x-eiffel", "eiffel");
|
|
|
|
});
|