Serve every font from this server and surface open tasks in 1.14.0
Fonts were still reachable from Google in two places. The editor and area previews were handed `googleFonts` and no `localFonts`, so the screen used most of the day fetched Lato from fonts.googleapis.com on every open; the public page fell back to the same link whenever the files were missing. Neither path remains: the template has no Google branch, `googleFontsUrl()` is gone, and the policies name no foreign font host - `font-src 'self'` publicly, `style-src 'self'; font-src 'self'` in administration. Without local files a site now shows the theme's fallback and says so. Preloading took the first two weights per family. The Kant-IT theme names Lato 400, 700 and 900 and sets its headings on 800/900, so the one weight that carried them loaded after the stylesheet and `font-display:swap` swapped the heading in plain sight. Every weight of the theme is preloaded now, latin subset, and the links sit before the stylesheet: measured cold, all three files finish at 168 ms against a first paint at 292 ms. Open tasks no longer hide on the screen that owns them. A strip above every management screen names what needs a button and carries it: a new version leads to System, missing fonts to Design. Neither asks the network - the version comes from the daily update-check task, the fonts from a look in the folder. System and update was unusable on a phone: `.stack` is a grid whose automatic column grows to its widest content, and one long database path pushed the page sideways. It gets `minmax(0, 1fr)`, the backup table stacks below 620px, and the prose is 45% shorter with the fine print folded away. The device chips drew the current device with an outline, which lies outside the box, ran under its neighbour and was clipped by the sidebar - it read as a cut-off red frame. Used devices are filled in `#9d4e0d` now (5.6:1), the current one carries a border inside the chip. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
858b8c6de4
commit
a434e0cefc
19 files changed
+345
-126
No files matched your search
@@ -71,6 +71,15 @@
|
||||
<div class="shell-actions">{% block actions %}{% endblock %}</div>
|
||||
</div>
|
||||
<div class="shell-body stack">
|
||||
{# Offene Handlungen, auf jedem Bildschirm gleich: fehlende Schriften, eine neue Fassung.
|
||||
Sie stehen hier statt nur auf ihrer eigenen Seite - einen Hinweis findet nur, wer schon
|
||||
weiss, wo er steht. Jeder traegt den Knopf, der ihn erledigt. #}
|
||||
{% for hinweis in kant_admin_notices() %}{% if not hinweis.admin or is_granted('ROLE_ADMIN') %}
|
||||
<p class="shell-notice" role="status">
|
||||
<span>{{ hinweis.text }}</span>
|
||||
<a class="secondary" href="{{ path(hinweis.route) }}">{{ hinweis.action }} →</a>
|
||||
</p>
|
||||
{% endif %}{% endfor %}
|
||||
{% for type in ['error', 'success'] %}{% for message in app.flashes(type) %}
|
||||
<p class="notice {{ type == 'error' ? 'error' : 'ok' }}" role="{{ type == 'error' ? 'alert' : 'status' }}">{{ message }}</p>
|
||||
{% endfor %}{% endfor %}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{% set nav = 'system' %}
|
||||
{% block title %}System{% endblock %}
|
||||
{% block heading %}System und Update{% endblock %}
|
||||
{% block lead %}Welche Fassung läuft, ob ein Update möglich ist, und der Weg dorthin: sichern, Wartungszustand, Dateien tauschen, migrieren.{% endblock %}
|
||||
{% block lead %}Fassung, Updateweg und Sicherungen dieser Installation.{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
<div class="card">
|
||||
@@ -13,13 +13,13 @@
|
||||
<div class="card-body">
|
||||
<dl class="facts">
|
||||
<dt>Fassung</dt><dd><strong>{{ state.version }}</strong></dd>
|
||||
<dt>Adresse der Verwaltung</dt>
|
||||
<dt>Verwaltung</dt>
|
||||
<dd>
|
||||
<code>/{{ adminPath }}</code>
|
||||
{% if adminPath == 'admin' %}
|
||||
<span class="muted">– die Adresse, die jeder Scanner zuerst probiert. Ändern mit <code>php bin/console cms:admin:path <neu></code>; sie steht danach in <code>.env.local</code> und in keiner öffentlichen Datei.</span>
|
||||
<span class="muted">– Standardpfad, den jeder Scanner zuerst probiert. Ändern: <code>php bin/console cms:admin:path <neu></code>.</span>
|
||||
{% else %}
|
||||
<span class="muted">– geändert. Sie wird in der <code>robots.txt</code> nicht genannt; notiere sie dir an einem sicheren Ort. Zurück mit <code>php bin/console cms:admin:path admin</code>.</span>
|
||||
<span class="muted">– geändert; steht in keiner öffentlichen Datei. Zurück: <code>php bin/console cms:admin:path admin</code>.</span>
|
||||
{% endif %}
|
||||
</dd>
|
||||
<dt>Datenbank</dt>
|
||||
@@ -28,17 +28,17 @@
|
||||
{% if database.datei %}
|
||||
<code>{{ database.datei }}</code>
|
||||
{% if database.bytes %}<span class="muted">· {{ (database.bytes / 1048576)|number_format(1, ',', '.') }} MB</span>{% endif %}
|
||||
{% if not database.schreibbar %}<br><span class="check-bad"><strong>Nicht beschreibbar.</strong> Nach einem Upload per FTP gehört die Datei dem FTP-Benutzer; PHP läuft als ein anderer. SQLite braucht Schreibrechte auf die Datei <em>und</em> auf den Ordner darüber.</span>{% endif %}
|
||||
{% if not database.schreibbar %}<br><span class="check-bad"><strong>Nicht beschreibbar.</strong> SQLite braucht Schreibrechte auf die Datei <em>und</em> auf den Ordner darüber – nach einem FTP-Upload gehört sie dem FTP-Benutzer.</span>{% endif %}
|
||||
{% else %}
|
||||
<code>{{ database.adresse }}</code>
|
||||
{% endif %}
|
||||
<br><span class="muted">Eingestellt in <code>{{ database.quelle }}</code>. Die Installationskonfiguration steht in <code>.env</code>. Explizite Server-Umgebungsvariablen haben Vorrang.</span>
|
||||
<br><span class="muted">Eingestellt in <code>{{ database.quelle }}</code>; Server-Umgebungsvariablen haben Vorrang.</span>
|
||||
</dd>
|
||||
{% if state.worktree %}
|
||||
<dt>Stand</dt><dd><code>{{ state.describe }}</code>{% if state.commit != 'unbekannt' %} · Commit <code>{{ state.commit }}</code>{% endif %}</dd>
|
||||
{% else %}
|
||||
<dt>Eingerichtet über</dt>
|
||||
<dd>das <strong>Releasearchiv</strong> <span class="muted">– kein Git in diesem Verzeichnis, und dafür ist es auch nicht gedacht. Updates laufen über die Karte weiter unten.</span></dd>
|
||||
<dd><strong>Releasearchiv</strong> <span class="muted">– kein Git; Updates laufen über die Karte unten.</span></dd>
|
||||
{% endif %}
|
||||
{% if state.worktree %}
|
||||
<dt>Verfügbar</dt>
|
||||
@@ -55,7 +55,7 @@
|
||||
</dl>
|
||||
|
||||
{% if state.maintenance %}
|
||||
<p class="notice error" role="alert">Die Website antwortet Besuchern gerade mit 503. Wenn das nicht beabsichtigt ist, hebe den Wartungszustand auf – ein gescheitertes Update kann ihn eingeschaltet gelassen haben.</p>
|
||||
<p class="notice error" role="alert">Die Website antwortet Besuchern mit 503. Wenn das nicht beabsichtigt ist, hebe den Wartungszustand auf – ein gescheitertes Update kann ihn eingeschaltet gelassen haben.</p>
|
||||
{% endif %}
|
||||
|
||||
<div class="sheet-actions">
|
||||
@@ -74,7 +74,7 @@
|
||||
vollkommen in Ordnung ist. #}
|
||||
{% if state.worktree %}
|
||||
<div class="card">
|
||||
<div class="card-head"><h2>Vorprüfung</h2><span class="muted">Jede Bedingung wird geprüft, nicht angenommen</span></div>
|
||||
<div class="card-head"><h2>Vorprüfung</h2><span class="muted">{{ checks|length }} Bedingungen</span></div>
|
||||
<div class="card-body">
|
||||
<ul class="check-list">
|
||||
{% for check in checks %}
|
||||
@@ -97,9 +97,9 @@
|
||||
<span class="muted">{{ pendingMigrations|length }} Stück</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="notice">Der Code ist neuer als die Datenbank. Das passiert, wenn ein Update von Hand über FTP eingespielt wurde – dann fehlt der Schritt, den sonst der Updater übernimmt.</p>
|
||||
<p class="notice">Der Code ist neuer als die Datenbank – typisch nach einem Update von Hand über FTP.</p>
|
||||
<ul class="log-list">{% for name in pendingMigrations %}<li><code>{{ name }}</code></li>{% endfor %}</ul>
|
||||
<p class="field-help">Lege vorher eine Sicherung an: Migrationen sind nicht umkehrbar, der Rückweg ist die Sicherung.</p>
|
||||
<p class="field-help">Vorher sichern: Migrationen sind nicht umkehrbar, der Rückweg ist die Sicherung.</p>
|
||||
<form action="{{ path('admin_system_migrate') }}" method="post">
|
||||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('system') }}">
|
||||
<button class="primary" type="submit">Migrationen jetzt ausführen →</button>
|
||||
@@ -111,7 +111,7 @@
|
||||
<div class="card">
|
||||
<div class="card-head">
|
||||
<h2>{{ state.worktree ? 'Update aus dem Releasearchiv' : 'Update einspielen' }}</h2>
|
||||
<span class="muted">{{ state.worktree ? 'Alternative zum Weg über Git' : 'holt die neue Fassung und tauscht die Dateien' }}</span>
|
||||
<span class="muted">{{ state.worktree ? 'Alternative zum Weg über Git' : 'holt die neue Fassung' }}</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if archivePending %}
|
||||
@@ -122,14 +122,19 @@
|
||||
<button class="primary" type="submit">Migrationen ausführen und freigeben →</button>
|
||||
</form>
|
||||
{% else %}
|
||||
<p class="muted">Dieser Weg braucht kein Git: Er lädt das Archiv der neuen Fassung von der Releaseseite, vergleicht die Prüfsumme, sichert Datenbank und Medien, schaltet den Wartungszustand ein und ersetzt die Dateien der Anwendung. <strong>Unberührt bleiben <code>var/</code>, <code>.env</code>, <code>.env.local</code>, die geladenen Schriften und das erzeugte Stylesheet-Bündel.</strong> Der vorherige Stand wird beiseitegelegt, nicht gelöscht.</p>
|
||||
<p class="field-help">Danach folgt ein zweiter Knopf für die Migrationen. Das ist kein Umweg: Erst eine neue Anfrage startet mit dem Code der neuen Fassung – ein Prozess, der sich selbst ausgetauscht hat, arbeitet mit dem alten weiter.</p>
|
||||
<p class="muted">Ohne Git: Archiv laden, Prüfsumme vergleichen, Datenbank und Medien sichern, Wartungszustand ein, Dateien tauschen. Der vorherige Stand wird beiseitegelegt, nicht gelöscht.</p>
|
||||
{# Das Kleingedruckte steht zugeklappt: Wer aktualisiert, braucht zuerst den Knopf. #}
|
||||
<details class="hint">
|
||||
<summary>Was unberührt bleibt</summary>
|
||||
<p class="field-help"><code>var/</code>, <code>.env</code>, <code>.env.local</code>, die geladenen Schriften und das erzeugte Stylesheet-Bündel.</p>
|
||||
<p class="field-help">Danach folgt ein zweiter Knopf für die Migrationen. Das ist kein Umweg: Erst eine neue Anfrage startet mit dem Code der neuen Fassung.</p>
|
||||
</details>
|
||||
{% if archiveVersion %}
|
||||
<p class="notice done">Verfügbar: <strong>{{ archiveVersion }}</strong> (installiert: {{ state.version }}).</p>
|
||||
{% elseif asked %}
|
||||
<p class="field-help">Die Releaseseite nennt nichts Neueres als {{ state.version }}.</p>
|
||||
{% else %}
|
||||
<p class="field-help"><a href="{{ path('admin_system', {pruefen: 1}) }}">Nachsehen, ob es etwas Neues gibt</a> – das fragt die Releaseseite und dauert einen Moment.</p>
|
||||
<p class="field-help"><a href="{{ path('admin_system', {pruefen: 1}) }}">Nachsehen, ob es etwas Neues gibt</a> – dauert einen Moment.</p>
|
||||
{% endif %}
|
||||
<form action="{{ path('admin_system_archive') }}" method="post">
|
||||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('system') }}">
|
||||
@@ -150,9 +155,12 @@
|
||||
<div class="card">
|
||||
<div class="card-head"><h2>Update einspielen</h2><span class="muted">{{ ready ? 'Vorprüfung bestanden' : 'erst die Vorprüfung erfüllen' }}</span></div>
|
||||
<div class="card-body">
|
||||
<p class="muted">Der Updater sichert zuerst Datenbank und Umgebungsdateien, schaltet den Wartungszustand ein, wechselt auf den Tag, installiert Abhängigkeiten, migriert, räumt den Cache und prüft, ob die Installation antwortet. Scheitert ein Schritt, wird auf den vorherigen Stand zurückgesetzt – und nur wenn die Migration schon begonnen hatte, auch die Datenbank zurückgeschrieben.</p>
|
||||
<p class="field-help"><strong>Der Medienordner wird nicht gesichert.</strong> Er ist zu groß, und kein Update schreibt darin. Ein Update ist keine Datensicherung.</p>
|
||||
<p class="field-help">Auf manchen Hostings bricht ein Browseraufruf nach kurzer Zeit ab. Dann ist <code>php bin/console cms:update</code> der verlässliche Weg – dort gibt es dieselben Schritte mit <code>--check</code>, <code>--dry-run</code> und <code>--to=v1.2.0</code>.</p>
|
||||
<p class="muted">Sichern, Wartungszustand ein, auf den Tag wechseln, Abhängigkeiten, Migrationen, Cache, Antwortprüfung. Scheitert ein Schritt, wird zurückgesetzt – die Datenbank nur, wenn die Migration schon begonnen hatte.</p>
|
||||
<details class="hint">
|
||||
<summary>Zwei Hinweise vorab</summary>
|
||||
<p class="field-help"><strong>Der Medienordner wird nicht gesichert.</strong> Ein Update ist keine Datensicherung.</p>
|
||||
<p class="field-help">Bricht der Browseraufruf auf dem Hosting ab: <code>php bin/console cms:update</code> – dieselben Schritte mit <code>--check</code>, <code>--dry-run</code> und <code>--to=v1.2.0</code>.</p>
|
||||
</details>
|
||||
|
||||
<form action="{{ path('admin_system_update') }}" method="post">
|
||||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('system') }}">
|
||||
@@ -164,7 +172,7 @@
|
||||
</div>
|
||||
<div>
|
||||
<label class="check-label" for="dryRun"><input id="dryRun" name="dryRun" type="checkbox" value="1" checked> Nur Probelauf</label>
|
||||
<p class="field-help">Prüft alles und verändert nichts. Nimm das Häkchen weg, wenn es wirklich laufen soll.</p>
|
||||
<p class="field-help">Prüft alles und verändert nichts.</p>
|
||||
</div>
|
||||
</div>
|
||||
<button class="primary" type="submit"{{ ready ? '' : ' disabled' }}>Update ausführen</button>
|
||||
@@ -175,7 +183,7 @@
|
||||
|
||||
{% if steps is not empty %}
|
||||
<div class="card">
|
||||
<div class="card-head"><h2>Letzter Durchlauf</h2><span class="muted">Schritt für Schritt</span></div>
|
||||
<div class="card-head"><h2>Letzter Durchlauf</h2><span class="muted">{{ steps|length }} Schritte</span></div>
|
||||
<div class="card-body">
|
||||
<ol class="check-list">
|
||||
{% for step in steps %}
|
||||
@@ -197,31 +205,31 @@
|
||||
<div class="card">
|
||||
<div class="card-head"><h2>Sicherungen</h2><span class="muted">{{ backups|length }} vorhanden · var/backups</span></div>
|
||||
<div class="card-body">
|
||||
<p class="muted">Eine Sicherung enthält die Datenbank als vollständige Kopie – nicht als Dateikopie während des Schreibens, die unbrauchbar sein kann – und den Medienordner. <strong>Nicht enthalten sind <code>.env</code>, <code>vendor/</code> und der Quellcode</strong>: die kommen aus dem Repository, und <code>.env</code> enthält das Geheimnis dieser Installation.</p>
|
||||
<p class="field-help">Zurückspielen geht bewusst nur auf der Konsole: <code>php bin/console cms:restore <name></code>. Ein Knopf, der die ganze Datenbank ersetzt, gehört nicht neben einen, der eine Seite speichert. Die tägliche Sicherung erledigt der <a href="{{ path('admin_tasks') }}">Aufgabenplan</a> – auch ohne Cronjob.</p>
|
||||
<p class="muted">Eine Sicherung enthält die Datenbank als vollständige Kopie und den Medienordner – nicht <code>.env</code>, <code>vendor/</code> und den Quellcode.</p>
|
||||
<p class="field-help">Zurückspielen nur auf der Konsole: <code>php bin/console cms:restore <name></code>. Die tägliche Sicherung erledigt der <a href="{{ path('admin_tasks') }}">Aufgabenplan</a>.</p>
|
||||
<form action="{{ path('admin_system_backup') }}" method="post">
|
||||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('system') }}">
|
||||
<button class="primary" type="submit">Sicherung jetzt anlegen</button>
|
||||
</form>
|
||||
|
||||
{% if backups is not empty %}
|
||||
<table class="table">
|
||||
<table class="table table-stack">
|
||||
<caption class="visually-hidden">Vorhandene Sicherungen</caption>
|
||||
<thead><tr><th scope="col">Name</th><th scope="col">Erstellt</th><th scope="col">Fassung</th><th scope="col">Inhalt</th><th scope="col">Größe</th><th scope="col">Zustand</th></tr></thead>
|
||||
<tbody>
|
||||
{% for backup in backups %}
|
||||
<tr>
|
||||
<td><code>{{ backup.name }}</code></td>
|
||||
<td>{{ backup.manifest ? backup.manifest.erstellt|date('d.m.Y H:i') : '—' }}{% if backup.manifest %}<br><span class="muted">{{ backup.manifest.anlass }}</span>{% endif %}</td>
|
||||
<td>{{ backup.manifest ? backup.manifest.fassung : '—' }}</td>
|
||||
<td>{% if backup.manifest %}{{ backup.manifest.inhalt.seiten }} Seiten, {{ backup.manifest.medien.dateien }} Dateien{% else %}—{% endif %}</td>
|
||||
<td>{{ (backup.bytes / 1048576)|number_format(1, ',', '.') }} MB</td>
|
||||
<td>{% if backup.intact %}<span class="pill pill-live">unversehrt</span>{% else %}<span class="pill pill-off">Prüfsumme falsch</span>{% endif %}</td>
|
||||
<td data-label="Name"><code>{{ backup.name }}</code></td>
|
||||
<td data-label="Erstellt">{{ backup.manifest ? backup.manifest.erstellt|date('d.m.Y H:i') : '—' }}{% if backup.manifest %}<br><span class="muted">{{ backup.manifest.anlass }}</span>{% endif %}</td>
|
||||
<td data-label="Fassung">{{ backup.manifest ? backup.manifest.fassung : '—' }}</td>
|
||||
<td data-label="Inhalt">{% if backup.manifest %}{{ backup.manifest.inhalt.seiten }} Seiten, {{ backup.manifest.medien.dateien }} Dateien{% else %}—{% endif %}</td>
|
||||
<td data-label="Größe">{{ (backup.bytes / 1048576)|number_format(1, ',', '.') }} MB</td>
|
||||
<td data-label="Zustand">{% if backup.intact %}<span class="pill pill-live">unversehrt</span>{% else %}<span class="pill pill-off">Prüfsumme falsch</span>{% endif %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<p class="field-help">„Unversehrt“ heißt: die Prüfsumme der gesicherten Datenbank stimmt noch mit dem Manifest überein. Stimmt sie nicht, wird die Sicherung nicht eingespielt.</p>
|
||||
<p class="field-help">„Unversehrt“ heißt: die Prüfsumme stimmt noch. Stimmt sie nicht, wird die Sicherung nicht eingespielt.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
@@ -232,9 +240,19 @@
|
||||
{% if state.log is empty %}
|
||||
<p class="muted">Noch kein Update über diesen Weg eingespielt.</p>
|
||||
{% else %}
|
||||
{# Zwanzig Protokollzeilen sind auf einem Handy zwanzig Absätze. Die jüngsten fünf
|
||||
stehen offen, der Rest liegt eine Umdrehung dahinter. #}
|
||||
<ul class="log-list">
|
||||
{% for line in state.log %}<li><code>{{ line }}</code></li>{% endfor %}
|
||||
{% for line in state.log|slice(0, 5) %}<li><code>{{ line }}</code></li>{% endfor %}
|
||||
</ul>
|
||||
{% if state.log|length > 5 %}
|
||||
<details class="hint">
|
||||
<summary>Ältere Einträge ({{ state.log|length - 5 }})</summary>
|
||||
<ul class="log-list">
|
||||
{% for line in state.log|slice(5) %}<li><code>{{ line }}</code></li>{% endfor %}
|
||||
</ul>
|
||||
</details>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -129,22 +129,27 @@
|
||||
<button class="primary" type="submit">Design speichern</button>
|
||||
</form>
|
||||
|
||||
<div class="section-head"><h2>Schriften ausliefern</h2><span class="muted">Von Google oder vom eigenen Server</span></div>
|
||||
{% if fontsMissing is empty and not fontsLocal %}
|
||||
<p class="field-help">Dieses Design nutzt nur Systemschriften – es lädt ohnehin nichts von Google.</p>
|
||||
{% else %}
|
||||
<p class="field-help">
|
||||
{% if fontsLocal %}
|
||||
<strong>Die Schriften liegen auf diesem Server.</strong> Besucher laden nichts von Google, und die Seite baut sich schneller auf, weil eine Kette aus zwei fremden Verbindungen entfällt.
|
||||
<div class="card">
|
||||
<div class="card-head">
|
||||
<h2>Schriften ausliefern</h2>
|
||||
<span class="muted">{{ fontsMissing ? fontsMissing|length ~ ' fehlt noch' : 'immer vom eigenen Server' }}</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if fontsMissing is empty and not fontsLocal %}
|
||||
<p class="muted">Dieses Design nutzt nur Systemschriften – es lädt ohnehin nichts von Google.</p>
|
||||
{% else %}
|
||||
<strong>Die Schriften kommen zurzeit von Google.</strong> Damit erfährt Google die IP-Adresse jedes Besuchers – in Deutschland ein abmahnfähiger Mangel (LG München I, 3 O 17493/20) –, und der Seitenaufbau wartet auf zwei fremde Verbindungen nacheinander. Mit dem Knopf werden die Dateien einmalig hierher geholt; die Lizenz der Schriften erlaubt das ausdrücklich.
|
||||
{% if fontsLocal %}
|
||||
<p class="muted"><strong>Die Schriften liegen auf diesem Server.</strong> Besucher laden nichts von Google, und die Seite baut sich schneller auf.</p>
|
||||
{% else %}
|
||||
<p class="muted"><strong>Die Schriftdateien fehlen auf diesem Server.</strong> Bis sie hier liegen, zeigt die Website die eingestellte Ersatzschrift – von Google wird nichts geladen, weder hier noch beim Besucher.</p>
|
||||
{% endif %}
|
||||
{% if fontsMissing %}<p class="field-help">Noch nicht hier: {{ fontsMissing|join(', ') }}.</p>{% endif %}
|
||||
<form method="post" action="{{ path('admin_theme_fonts') }}">
|
||||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('theme') }}">
|
||||
<button class="{{ fontsLocal ? 'secondary' : 'primary' }}" type="submit">{{ fontsLocal ? 'Schriften erneut holen' : 'Schriften auf diesen Server holen' }}</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% if fontsMissing %}<br>Noch nicht hier: {{ fontsMissing|join(', ') }}.{% endif %}
|
||||
</p>
|
||||
<form method="post" action="{{ path('admin_theme_fonts') }}">
|
||||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('theme') }}">
|
||||
<button type="submit">{{ fontsLocal ? 'Schriften erneut holen' : 'Schriften auf diesen Server holen' }}</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<p class="footnote">KantSites · Arbeitsstand</p>
|
||||
{% endblock %}
|
||||
@@ -33,6 +33,13 @@
|
||||
drei Abfragen trifft zu - und zwar auf dieselbe Variante, die auch die Regel nimmt. #}
|
||||
{% for bild in heroBackground|default([]) %}<link rel="preload" as="image" href="{{ bild.src }}" media="{{ bild.media }}" fetchpriority="high">
|
||||
{% endfor %}
|
||||
{% if localFonts|default([]) %}
|
||||
{# Jeder Schnitt, den das Theme nennt, vorab - und zwar alle. Fehlt einer, laedt er erst,
|
||||
wenn das Stylesheet geparst ist, und die Ueberschrift springt sichtbar von der
|
||||
Ersatzschrift auf die richtige. Schriften kommen ausschliesslich vom eigenen Server;
|
||||
ein Stylesheet von fonts.googleapis.com wird nie verlinkt. #}
|
||||
{% for font in localFonts %}<link rel="preload" href="{{ font }}" as="font" type="font/woff2" crossorigin>{% endfor %}
|
||||
{% endif %}
|
||||
{% if styleBundle|default(null) %}
|
||||
<link rel="stylesheet" href="{{ styleBundle }}">
|
||||
{% else %}
|
||||
@@ -42,10 +49,6 @@
|
||||
{% if page.document.schemaVersion >= 2 %}<link rel="stylesheet" href="/assets/design.css?v={{ kant_version() }}">{% endif %}
|
||||
{% if page.document.schemaVersion >= 3 %}<link rel="stylesheet" href="/assets/enhancements.css?v={{ kant_version() }}">{% endif %}
|
||||
{% endif %}
|
||||
{% if localFonts|default([]) %}
|
||||
{# Die wichtigsten Schnitte vorab, damit die erste Zeile in der richtigen Schrift steht. #}
|
||||
{% for font in localFonts %}<link rel="preload" href="{{ font }}" as="font" type="font/woff2" crossorigin>{% endfor %}
|
||||
{% elseif googleFonts|default(null) %}<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link rel="stylesheet" href="{{ googleFonts }}">{% endif %}
|
||||
{% if hasPosts|default(false) %} <link rel="alternate" type="application/rss+xml" title="Beiträge" href="/feed.xml">
|
||||
{% endif %}
|
||||
{% if needsTabs|default(false) %}<script src="/assets/tabs.js?v={{ kant_version() }}" defer></script>{% endif %}
|
||||
|
||||
Reference in new issue
Block a user