From 878be656a1150bbeadad6c10c98f9a97914c1fcd Mon Sep 17 00:00:00 2001 From: ThomasAFink Date: Fri, 7 Aug 2026 21:23:30 +0200 Subject: [PATCH 1/4] fix(ZMSKVR-352): tighten mail template formatting Unbold service links, use a single em dash as separator, and reduce excess spacing in confirmation, reminder, and activation mails. --- ...rmat-mail-templates-spacing-and-dashes.sql | 249 ++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 zmsbackend/migrations/91785035201-format-mail-templates-spacing-and-dashes.sql diff --git a/zmsbackend/migrations/91785035201-format-mail-templates-spacing-and-dashes.sql b/zmsbackend/migrations/91785035201-format-mail-templates-spacing-and-dashes.sql new file mode 100644 index 0000000000..283e9c1ec4 --- /dev/null +++ b/zmsbackend/migrations/91785035201-format-mail-templates-spacing-and-dashes.sql @@ -0,0 +1,249 @@ +START TRANSACTION; + +-- ZMSKVR-352: Formatierung der Standard-E-Mail-Templates +-- +-- - Leistungen (Service-Links) nicht mehr bold +-- - Trennstriche einheitlich als einzelner Geviertstrich (—) statt —— +-- - Abstände um Trennstriche / unter "Termin aktivieren" / unter Ort / unter Bullet-Liste reduzieren +-- +-- Betrifft mail_confirmation, mail_preconfirmed und mail_reminder (global + customized). + +-- 1) Leistungen: remove around service info links +UPDATE `mailtemplate` +SET `value` = REPLACE( + `value`, + '{{ requestGroup[''request''].name }} ', + '{{ requestGroup[''request''].name }} ' +) +WHERE `name` IN ( + 'mail_confirmation.twig', + 'mail_preconfirmed.twig', + 'mail_reminder.twig' +) + AND `value` LIKE '%{{ requestGroup[''request''].name }} ', + '{{ requestGroup[''request''].name }} ' +) +WHERE `name` IN ( + 'mail_confirmation.twig', + 'mail_preconfirmed.twig', + 'mail_reminder.twig' +) + AND `value` LIKE '%%'; + +UPDATE `mailtemplate` +SET `value` = REPLACE( + `value`, + '{{ requestGroup[''request''].name }} ', + '{{ requestGroup[''request''].name }} ' +) +WHERE `name` IN ( + 'mail_confirmation.twig', + 'mail_preconfirmed.twig', + 'mail_reminder.twig' +) + AND `value` LIKE '%%'; + +-- 2) Aktivierung: tighten space below "Termin aktivieren" before separator (CRLF) +UPDATE `mailtemplate` +SET `value` = REPLACE( + `value`, + CONCAT( + 'Termin aktivieren

', + CHAR(13), CHAR(10), CHAR(13), CHAR(10), + '
', CHAR(13), CHAR(10), + '——', CHAR(13), CHAR(10), + '

' + ), + CONCAT( + 'Termin aktivieren', + CHAR(13), CHAR(10), + '
', CHAR(13), CHAR(10), + '—', CHAR(13), CHAR(10), + '
' + ) +) +WHERE `name` = 'mail_preconfirmed.twig' + AND `value` LIKE '%Termin aktivieren%


%'; + +-- LF variant +UPDATE `mailtemplate` +SET `value` = REPLACE( + `value`, + CONCAT( + 'Termin aktivieren

', + CHAR(10), CHAR(10), + '
', CHAR(10), + '——', CHAR(10), + '

' + ), + CONCAT( + 'Termin aktivieren', + CHAR(10), + '
', CHAR(10), + '—', CHAR(10), + '
' + ) +) +WHERE `name` = 'mail_preconfirmed.twig' + AND `value` LIKE '%Termin aktivieren%


%' + AND `value` LIKE '%——%'; + +-- 3) Bestätigung/Erinnerung: tighten space below Ort (hint endif) before separator (CRLF) +UPDATE `mailtemplate` +SET `value` = REPLACE( + `value`, + CONCAT( + '{% endif %}
', CHAR(13), CHAR(10), + '

', CHAR(13), CHAR(10), + '——', CHAR(13), CHAR(10), + '

' + ), + CONCAT( + '{% endif %}
', CHAR(13), CHAR(10), + '
', CHAR(13), CHAR(10), + '—', CHAR(13), CHAR(10), + '
' + ) +) +WHERE `name` IN ( + 'mail_confirmation.twig', + 'mail_reminder.twig' +) + AND `value` LIKE '%{% endif %}
%——%'; + +UPDATE `mailtemplate` +SET `value` = REPLACE( + `value`, + CONCAT( + '{% endif %}
', CHAR(10), + '

', CHAR(10), + '——', CHAR(10), + '

' + ), + CONCAT( + '{% endif %}
', CHAR(10), + '
', CHAR(10), + '—', CHAR(10), + '
' + ) +) +WHERE `name` IN ( + 'mail_confirmation.twig', + 'mail_reminder.twig' +) + AND `value` LIKE '%{% endif %}
%——%'; + +-- 4) Bestätigung/Erinnerung: tighten space below bullet list before separator (CRLF) +UPDATE `mailtemplate` +SET `value` = REPLACE( + `value`, + CONCAT( + '', CHAR(13), CHAR(10), + '
', CHAR(13), CHAR(10), + '——', CHAR(13), CHAR(10), + '

' + ), + CONCAT( + '', CHAR(13), CHAR(10), + '
', CHAR(13), CHAR(10), + '—', CHAR(13), CHAR(10), + '
' + ) +) +WHERE `name` IN ( + 'mail_confirmation.twig', + 'mail_reminder.twig' +) + AND `value` LIKE '%%——%'; + +UPDATE `mailtemplate` +SET `value` = REPLACE( + `value`, + CONCAT( + '', CHAR(10), + '
', CHAR(10), + '——', CHAR(10), + '

' + ), + CONCAT( + '', CHAR(10), + '
', CHAR(10), + '—', CHAR(10), + '
' + ) +) +WHERE `name` IN ( + 'mail_confirmation.twig', + 'mail_reminder.twig' +) + AND `value` LIKE '%%——%'; + +-- 5) Remaining double-br + double-em-dash blocks → single br + single em-dash (CRLF / LF) +UPDATE `mailtemplate` +SET `value` = REPLACE( + `value`, + CONCAT('

', CHAR(13), CHAR(10), '——', CHAR(13), CHAR(10), '

'), + CONCAT('
', CHAR(13), CHAR(10), '—', CHAR(13), CHAR(10), '
') +) +WHERE `name` IN ( + 'mail_confirmation.twig', + 'mail_preconfirmed.twig', + 'mail_reminder.twig' +) + AND `value` LIKE '%

%——%

%'; + +UPDATE `mailtemplate` +SET `value` = REPLACE( + `value`, + CONCAT('

', CHAR(10), '——', CHAR(10), '

'), + CONCAT('
', CHAR(10), '—', CHAR(10), '
') +) +WHERE `name` IN ( + 'mail_confirmation.twig', + 'mail_preconfirmed.twig', + 'mail_reminder.twig' +) + AND `value` LIKE '%

%——%

%'; + +-- Indented intro separators (confirmation/reminder opening block) +UPDATE `mailtemplate` +SET `value` = REPLACE( + `value`, + CONCAT('

', CHAR(13), CHAR(10), ' ——', CHAR(13), CHAR(10), '

'), + CONCAT('
', CHAR(13), CHAR(10), ' —', CHAR(13), CHAR(10), '
') +) +WHERE `name` IN ( + 'mail_confirmation.twig', + 'mail_reminder.twig' +) + AND `value` LIKE '% ——%'; + +UPDATE `mailtemplate` +SET `value` = REPLACE( + `value`, + CONCAT('

', CHAR(10), ' ——', CHAR(10), '

'), + CONCAT('
', CHAR(10), ' —', CHAR(10), '
') +) +WHERE `name` IN ( + 'mail_confirmation.twig', + 'mail_reminder.twig' +) + AND `value` LIKE '% ——%'; + +-- 6) Catch-all: any remaining double Geviertstrich → single +UPDATE `mailtemplate` +SET `value` = REPLACE(`value`, '——', '—') +WHERE `name` IN ( + 'mail_confirmation.twig', + 'mail_preconfirmed.twig', + 'mail_reminder.twig' +) + AND `value` LIKE '%——%'; + +COMMIT; From ccb6369684fbf1735c505fcf124c490a80d907ab Mon Sep 17 00:00:00 2001 From: ThomasAFink Date: Thu, 20 Aug 2026 19:52:59 +0200 Subject: [PATCH 2/4] fix(ZMSKVR-352): also convert ASCII --- separators in mail templates The first pass only matched double em-dashes, so zms-dev reminder and preconfirmed mails kept --- and the old spacing. Add an idempotent follow-up because 35201 already ran there. --- ...rmat-mail-templates-spacing-and-dashes.sql | 248 +++++------------- ...mail-templates-ascii-hyphen-separators.sql | 111 ++++++++ 2 files changed, 171 insertions(+), 188 deletions(-) create mode 100644 zmsbackend/migrations/91785035202-format-mail-templates-ascii-hyphen-separators.sql diff --git a/zmsbackend/migrations/91785035201-format-mail-templates-spacing-and-dashes.sql b/zmsbackend/migrations/91785035201-format-mail-templates-spacing-and-dashes.sql index 283e9c1ec4..268653467d 100644 --- a/zmsbackend/migrations/91785035201-format-mail-templates-spacing-and-dashes.sql +++ b/zmsbackend/migrations/91785035201-format-mail-templates-spacing-and-dashes.sql @@ -3,240 +3,112 @@ START TRANSACTION; -- ZMSKVR-352: Formatierung der Standard-E-Mail-Templates -- -- - Leistungen (Service-Links) nicht mehr bold --- - Trennstriche einheitlich als einzelner Geviertstrich (—) statt —— --- - Abstände um Trennstriche / unter "Termin aktivieren" / unter Ort / unter Bullet-Liste reduzieren +-- - Trennstriche einheitlich als einzelner Geviertstrich (—) +-- Live-Templates nutzen je nach Umgebung —— (doppelter Geviertstrich) +-- ODER --- (drei ASCII-Bindestriche); beides wird hier abgedeckt. +-- - Abstände um Trennstriche / unter "Termin aktivieren" reduzieren -- --- Betrifft mail_confirmation, mail_preconfirmed und mail_reminder (global + customized). - --- 1) Leistungen: remove around service info links -UPDATE `mailtemplate` -SET `value` = REPLACE( - `value`, - '{{ requestGroup[''request''].name }} ', - '{{ requestGroup[''request''].name }} ' -) -WHERE `name` IN ( - 'mail_confirmation.twig', - 'mail_preconfirmed.twig', - 'mail_reminder.twig' -) - AND `value` LIKE '%{{ requestGroup[''request''].name }} ', - '{{ requestGroup[''request''].name }} ' -) -WHERE `name` IN ( - 'mail_confirmation.twig', - 'mail_preconfirmed.twig', - 'mail_reminder.twig' -) - AND `value` LIKE '%%'; +-- REGEXP_REPLACE, damit Einrückung, CRLF/LF und optionale Leerzeilen +-- die Ersetzung nicht verhindern (das war der Fehlschlag auf zms-dev). +-- Idempotent: bereits umgestellte Templates bleiben unverändert. +-- +-- Betrifft mail_confirmation, mail_preconfirmed und mail_reminder +-- (global + customized). Lange Alt-Trenner (----------------------) +-- bleiben unangetastet. +-- 1) Leistungen: um Service-Links entfernen (beliebige href) UPDATE `mailtemplate` -SET `value` = REPLACE( +SET `value` = REGEXP_REPLACE( `value`, - '{{ requestGroup[''request''].name }} ', - '{{ requestGroup[''request''].name }} ' + '[[:space:]]*[[:space:]]*(\\{\\{ requestGroup\\[''request''\\]\\.name \\}\\})[[:space:]]*[[:space:]]*', + '\\2 ' ) WHERE `name` IN ( 'mail_confirmation.twig', 'mail_preconfirmed.twig', 'mail_reminder.twig' ) - AND `value` LIKE '%%'; - --- 2) Aktivierung: tighten space below "Termin aktivieren" before separator (CRLF) -UPDATE `mailtemplate` -SET `value` = REPLACE( - `value`, - CONCAT( - 'Termin aktivieren

', - CHAR(13), CHAR(10), CHAR(13), CHAR(10), - '
', CHAR(13), CHAR(10), - '——', CHAR(13), CHAR(10), - '

' - ), - CONCAT( - 'Termin aktivieren', - CHAR(13), CHAR(10), - '
', CHAR(13), CHAR(10), - '—', CHAR(13), CHAR(10), - '
' - ) -) -WHERE `name` = 'mail_preconfirmed.twig' - AND `value` LIKE '%Termin aktivieren%


%'; + AND `value` REGEXP '[[:space:]]*[[:space:]]*\\{\\{ requestGroup\\[''request''\\]\\.name'; --- LF variant +-- 2) Trennlinie aus genau drei ASCII-Bindestrichen → Geviertstrich +-- (nur ganze Zeile, nicht Teil von ----------------------) UPDATE `mailtemplate` -SET `value` = REPLACE( +SET `value` = REGEXP_REPLACE( `value`, CONCAT( - 'Termin aktivieren

', - CHAR(10), CHAR(10), - '
', CHAR(10), - '——', CHAR(10), - '

' + '(', CHAR(13), CHAR(10), '|', CHAR(10), ')', + '([[:blank:]]*)---([[:blank:]]*)', + '(', CHAR(13), CHAR(10), '|', CHAR(10), ')' ), - CONCAT( - 'Termin aktivieren', - CHAR(10), - '
', CHAR(10), - '—', CHAR(10), - '
' - ) -) -WHERE `name` = 'mail_preconfirmed.twig' - AND `value` LIKE '%Termin aktivieren%


%' - AND `value` LIKE '%——%'; - --- 3) Bestätigung/Erinnerung: tighten space below Ort (hint endif) before separator (CRLF) -UPDATE `mailtemplate` -SET `value` = REPLACE( - `value`, - CONCAT( - '{% endif %}
', CHAR(13), CHAR(10), - '

', CHAR(13), CHAR(10), - '——', CHAR(13), CHAR(10), - '

' - ), - CONCAT( - '{% endif %}
', CHAR(13), CHAR(10), - '
', CHAR(13), CHAR(10), - '—', CHAR(13), CHAR(10), - '
' - ) -) -WHERE `name` IN ( - 'mail_confirmation.twig', - 'mail_reminder.twig' -) - AND `value` LIKE '%{% endif %}
%——%'; - -UPDATE `mailtemplate` -SET `value` = REPLACE( - `value`, - CONCAT( - '{% endif %}
', CHAR(10), - '

', CHAR(10), - '——', CHAR(10), - '

' - ), - CONCAT( - '{% endif %}
', CHAR(10), - '
', CHAR(10), - '—', CHAR(10), - '
' - ) + CONCAT('\\1', '\\2', '—', '\\3', '\\4') ) WHERE `name` IN ( 'mail_confirmation.twig', + 'mail_preconfirmed.twig', 'mail_reminder.twig' ) - AND `value` LIKE '%{% endif %}
%——%'; + AND `value` REGEXP CONCAT( + '(', CHAR(13), CHAR(10), '|', CHAR(10), ')', + '[[:blank:]]*---[[:blank:]]*', + '(', CHAR(13), CHAR(10), '|', CHAR(10), ')' + ); --- 4) Bestätigung/Erinnerung: tighten space below bullet list before separator (CRLF) +-- 3) Trennlinie aus doppeltem Geviertstrich → einzelner Geviertstrich UPDATE `mailtemplate` -SET `value` = REPLACE( +SET `value` = REGEXP_REPLACE( `value`, CONCAT( - '', CHAR(13), CHAR(10), - '
', CHAR(13), CHAR(10), - '——', CHAR(13), CHAR(10), - '

' + '(', CHAR(13), CHAR(10), '|', CHAR(10), ')', + '([[:blank:]]*)——([[:blank:]]*)', + '(', CHAR(13), CHAR(10), '|', CHAR(10), ')' ), - CONCAT( - '', CHAR(13), CHAR(10), - '
', CHAR(13), CHAR(10), - '—', CHAR(13), CHAR(10), - '
' - ) + CONCAT('\\1', '\\2', '—', '\\3', '\\4') ) WHERE `name` IN ( 'mail_confirmation.twig', + 'mail_preconfirmed.twig', 'mail_reminder.twig' ) - AND `value` LIKE '%%——%'; + AND `value` LIKE '%——%'; +-- 4)

/ extra Leerzeilen um den Geviertstrich → je ein
UPDATE `mailtemplate` -SET `value` = REPLACE( +SET `value` = REGEXP_REPLACE( `value`, CONCAT( - '', CHAR(10), - '
', CHAR(10), - '——', CHAR(10), - '

' + '', + '([[:space:]]*)?', + '(', CHAR(13), CHAR(10), '|', CHAR(10), ')+', + '([[:blank:]]*)—([[:blank:]]*)', + '(', CHAR(13), CHAR(10), '|', CHAR(10), ')+', + '([[:blank:]]*)', + '([[:space:]]*)?' ), - CONCAT( - '', CHAR(10), - '
', CHAR(10), - '—', CHAR(10), - '
' - ) -) -WHERE `name` IN ( - 'mail_confirmation.twig', - 'mail_reminder.twig' -) - AND `value` LIKE '%%——%'; - --- 5) Remaining double-br + double-em-dash blocks → single br + single em-dash (CRLF / LF) -UPDATE `mailtemplate` -SET `value` = REPLACE( - `value`, - CONCAT('

', CHAR(13), CHAR(10), '——', CHAR(13), CHAR(10), '

'), - CONCAT('
', CHAR(13), CHAR(10), '—', CHAR(13), CHAR(10), '
') + CONCAT('
', CHAR(13), CHAR(10), '\\3—\\4', CHAR(13), CHAR(10), '\\6
') ) WHERE `name` IN ( 'mail_confirmation.twig', 'mail_preconfirmed.twig', 'mail_reminder.twig' ) - AND `value` LIKE '%

%——%

%'; + AND `value` LIKE '%—%' + AND ( + `value` LIKE '%

%—%' + OR `value` LIKE '%—%

%' + OR `value` LIKE '%

%—%' + ); +-- 5) Abstand unter "Termin aktivieren" reduzieren UPDATE `mailtemplate` -SET `value` = REPLACE( +SET `value` = REGEXP_REPLACE( `value`, - CONCAT('

', CHAR(10), '——', CHAR(10), '

'), - CONCAT('
', CHAR(10), '—', CHAR(10), '
') + 'Termin aktivieren
[[:space:]]*([[:space:]]*)?', + CONCAT('Termin aktivieren', CHAR(13), CHAR(10), '
') ) -WHERE `name` IN ( - 'mail_confirmation.twig', - 'mail_preconfirmed.twig', - 'mail_reminder.twig' -) - AND `value` LIKE '%

%——%

%'; - --- Indented intro separators (confirmation/reminder opening block) -UPDATE `mailtemplate` -SET `value` = REPLACE( - `value`, - CONCAT('

', CHAR(13), CHAR(10), ' ——', CHAR(13), CHAR(10), '

'), - CONCAT('
', CHAR(13), CHAR(10), ' —', CHAR(13), CHAR(10), '
') -) -WHERE `name` IN ( - 'mail_confirmation.twig', - 'mail_reminder.twig' -) - AND `value` LIKE '% ——%'; - -UPDATE `mailtemplate` -SET `value` = REPLACE( - `value`, - CONCAT('

', CHAR(10), ' ——', CHAR(10), '

'), - CONCAT('
', CHAR(10), ' —', CHAR(10), '
') -) -WHERE `name` IN ( - 'mail_confirmation.twig', - 'mail_reminder.twig' -) - AND `value` LIKE '% ——%'; +WHERE `name` = 'mail_preconfirmed.twig' + AND `value` LIKE '%Termin aktivieren%%
spacing. The first migration only matched double em-dashes (——). +-- +-- Same transforms as the updated 91785035201; idempotent so later +-- environments that run both files are unchanged the second time. + +-- 1) Leistungen: um Service-Links entfernen (beliebige href) +UPDATE `mailtemplate` +SET `value` = REGEXP_REPLACE( + `value`, + '[[:space:]]*[[:space:]]*(\\{\\{ requestGroup\\[''request''\\]\\.name \\}\\})[[:space:]]*[[:space:]]*', + '\\2 ' +) +WHERE `name` IN ( + 'mail_confirmation.twig', + 'mail_preconfirmed.twig', + 'mail_reminder.twig' +) + AND `value` REGEXP '[[:space:]]*[[:space:]]*\\{\\{ requestGroup\\[''request''\\]\\.name'; + +-- 2) Trennlinie aus genau drei ASCII-Bindestrichen → Geviertstrich +UPDATE `mailtemplate` +SET `value` = REGEXP_REPLACE( + `value`, + CONCAT( + '(', CHAR(13), CHAR(10), '|', CHAR(10), ')', + '([[:blank:]]*)---([[:blank:]]*)', + '(', CHAR(13), CHAR(10), '|', CHAR(10), ')' + ), + CONCAT('\\1', '\\2', '—', '\\3', '\\4') +) +WHERE `name` IN ( + 'mail_confirmation.twig', + 'mail_preconfirmed.twig', + 'mail_reminder.twig' +) + AND `value` REGEXP CONCAT( + '(', CHAR(13), CHAR(10), '|', CHAR(10), ')', + '[[:blank:]]*---[[:blank:]]*', + '(', CHAR(13), CHAR(10), '|', CHAR(10), ')' + ); + +-- 3) Trennlinie aus doppeltem Geviertstrich → einzelner Geviertstrich +UPDATE `mailtemplate` +SET `value` = REGEXP_REPLACE( + `value`, + CONCAT( + '(', CHAR(13), CHAR(10), '|', CHAR(10), ')', + '([[:blank:]]*)——([[:blank:]]*)', + '(', CHAR(13), CHAR(10), '|', CHAR(10), ')' + ), + CONCAT('\\1', '\\2', '—', '\\3', '\\4') +) +WHERE `name` IN ( + 'mail_confirmation.twig', + 'mail_preconfirmed.twig', + 'mail_reminder.twig' +) + AND `value` LIKE '%——%'; + +-- 4)

/ extra Leerzeilen um den Geviertstrich → je ein
+UPDATE `mailtemplate` +SET `value` = REGEXP_REPLACE( + `value`, + CONCAT( + '', + '([[:space:]]*)?', + '(', CHAR(13), CHAR(10), '|', CHAR(10), ')+', + '([[:blank:]]*)—([[:blank:]]*)', + '(', CHAR(13), CHAR(10), '|', CHAR(10), ')+', + '([[:blank:]]*)', + '([[:space:]]*)?' + ), + CONCAT('
', CHAR(13), CHAR(10), '\\3—\\4', CHAR(13), CHAR(10), '\\6
') +) +WHERE `name` IN ( + 'mail_confirmation.twig', + 'mail_preconfirmed.twig', + 'mail_reminder.twig' +) + AND `value` LIKE '%—%' + AND ( + `value` LIKE '%

%—%' + OR `value` LIKE '%—%

%' + OR `value` LIKE '%

%—%' + ); + +-- 5) Abstand unter "Termin aktivieren" reduzieren +UPDATE `mailtemplate` +SET `value` = REGEXP_REPLACE( + `value`, + 'Termin aktivieren
[[:space:]]*([[:space:]]*)?', + CONCAT('Termin aktivieren
', CHAR(13), CHAR(10), '
') +) +WHERE `name` = 'mail_preconfirmed.twig' + AND `value` LIKE '%Termin aktivieren%% Date: Fri, 28 Aug 2026 13:35:27 +0200 Subject: [PATCH 3/4] fix(ZMSKVR-352): restore double Geviertstrich with two breaks 35201 already ran, so add a follow-up: always

around a nowrap double em dash so the separator stays on one line. --- ...mail-templates-double-emdash-separator.sql | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 zmsbackend/migrations/91785035203-format-mail-templates-double-emdash-separator.sql diff --git a/zmsbackend/migrations/91785035203-format-mail-templates-double-emdash-separator.sql b/zmsbackend/migrations/91785035203-format-mail-templates-double-emdash-separator.sql new file mode 100644 index 0000000000..1797ddc4d2 --- /dev/null +++ b/zmsbackend/migrations/91785035203-format-mail-templates-double-emdash-separator.sql @@ -0,0 +1,47 @@ +START TRANSACTION; + +-- ZMSKVR-352 follow-up: use a double Geviertstrich with two
on each side: +-- a double Geviertstrich with two
on each side: +-- +--

+-- —— +--

+-- +-- 91785035201/35202 already ran on some envs and left a single — with one +--
. A lone —— can also wrap onto two lines in some clients, so wrap it +-- in nowrap. Idempotent: the canonical block matches itself. +-- +-- Does not touch long ASCII rules (----------------------). + +-- Standalone separator line (—, ——, ---, optional nowrap span) plus any +-- surrounding
tags → canonical two-break nowrap double Geviertstrich. +UPDATE `mailtemplate` +SET `value` = REGEXP_REPLACE( + `value`, + CONCAT( + '([[:space:]]*)*', + '(', CHAR(13), CHAR(10), '|', CHAR(10), ')+', + '[[:blank:]]*()?(——|—|---)()?[[:blank:]]*', + '(', CHAR(13), CHAR(10), '|', CHAR(10), ')+', + '([[:blank:]]*[[:space:]]*)*' + ), + CONCAT( + '

', + CHAR(13), CHAR(10), + '——', + CHAR(13), CHAR(10), + '

' + ) +) +WHERE `name` IN ( + 'mail_confirmation.twig', + 'mail_preconfirmed.twig', + 'mail_reminder.twig' +) + AND `value` REGEXP CONCAT( + '(', CHAR(13), CHAR(10), '|', CHAR(10), ')', + '[[:blank:]]*()?(——|—|---)()?[[:blank:]]*', + '(', CHAR(13), CHAR(10), '|', CHAR(10), ')' + ); + +COMMIT; From d3041dc896ff66ecccecd8ab21ed3ad1d4cf5494 Mon Sep 17 00:00:00 2001 From: ThomasAFink Date: Mon, 31 Aug 2026 11:33:37 +0200 Subject: [PATCH 4/4] fix(ZMSKVR-352): convert remaining mail separators and drop unused custom templates Normalize ---, long ASCII rules, and leftover Geviertstriche in delete/queued/admin templates to the nowrap double Geviertstrich; filesystem custom copies are unused now that templates live in the DB. --- ...at-mail-templates-remaining-separators.sql | 66 +++++++++++ .../fhrerscheinstelle/mail_confirmation.twig | 105 ------------------ .../custom/fhrerscheinstelle/mail_delete.twig | 48 -------- .../fhrerscheinstelle/mail_preconfirmed.twig | 55 --------- .../fhrerscheinstelle/mail_reminder.twig | 91 --------------- .../mail_confirmation.twig | 99 ----------------- .../kfz-zulassungsstelle/mail_delete.twig | 48 -------- .../mail_preconfirmed.twig | 55 --------- .../kfz-zulassungsstelle/mail_reminder.twig | 91 --------------- .../messaging/mail_confirmation.twig | 6 +- .../templates/messaging/mail_queued.twig | 6 +- .../templates/messaging/mail_reminder.twig | 6 +- 12 files changed, 75 insertions(+), 601 deletions(-) create mode 100644 zmsbackend/migrations/91785035204-format-mail-templates-remaining-separators.sql delete mode 100644 zmsentities/templates/messaging/custom/fhrerscheinstelle/mail_confirmation.twig delete mode 100644 zmsentities/templates/messaging/custom/fhrerscheinstelle/mail_delete.twig delete mode 100644 zmsentities/templates/messaging/custom/fhrerscheinstelle/mail_preconfirmed.twig delete mode 100644 zmsentities/templates/messaging/custom/fhrerscheinstelle/mail_reminder.twig delete mode 100644 zmsentities/templates/messaging/custom/kfz-zulassungsstelle/mail_confirmation.twig delete mode 100644 zmsentities/templates/messaging/custom/kfz-zulassungsstelle/mail_delete.twig delete mode 100644 zmsentities/templates/messaging/custom/kfz-zulassungsstelle/mail_preconfirmed.twig delete mode 100644 zmsentities/templates/messaging/custom/kfz-zulassungsstelle/mail_reminder.twig diff --git a/zmsbackend/migrations/91785035204-format-mail-templates-remaining-separators.sql b/zmsbackend/migrations/91785035204-format-mail-templates-remaining-separators.sql new file mode 100644 index 0000000000..0b0b59d1e0 --- /dev/null +++ b/zmsbackend/migrations/91785035204-format-mail-templates-remaining-separators.sql @@ -0,0 +1,66 @@ +START TRANSACTION; + +-- ZMSKVR-352 follow-up: remaining mail templates still use mixed +-- standalone separator lines that 91785035203 did not cover: +-- +--

(mail_delete.twig) +-- — +--

+-- +--

(mail_delete.twig) +-- --- +--

+-- +--

(mail_queued.twig and customized +-- ---------------------- mail_confirmation.twig; indented) +--

+-- +-- 35203 only matched (——|—|---) on confirmation/preconfirmed/reminder, +-- so long ASCII rules and delete/queued copies were left behind. +-- mail_admin_delete.twig is included so customized copies with dashes +-- are converted too (current dump rows have none). +-- +-- Same canonical block as 91785035203. Idempotent: that block matches +-- itself. Standalone line only (newline-bounded), so hyphens inside +-- URLs are not touched. +-- +-- Dash forms (longer first; no —+ because MariaDB REGEXP is byte-based): +-- —— double Geviertstrich +-- — single Geviertstrich +-- -{3,} ---, ----------------------, and any longer ASCII rule +-- –– double Halbgeviertstrich +-- – single Halbgeviertstrich + +UPDATE `mailtemplate` +SET `value` = REGEXP_REPLACE( + `value`, + CONCAT( + '([[:space:]]*)*', + '(', CHAR(13), CHAR(10), '|', CHAR(10), ')+', + '[[:blank:]]*()?(——|—|-{3,}|––|–)()?[[:blank:]]*', + '(', CHAR(13), CHAR(10), '|', CHAR(10), ')+', + '([[:blank:]]*[[:space:]]*)*' + ), + CONCAT( + '

', + CHAR(13), CHAR(10), + '——', + CHAR(13), CHAR(10), + '

' + ) +) +WHERE `name` IN ( + 'mail_confirmation.twig', + 'mail_preconfirmed.twig', + 'mail_reminder.twig', + 'mail_delete.twig', + 'mail_admin_delete.twig', + 'mail_queued.twig' +) + AND `value` REGEXP CONCAT( + '(', CHAR(13), CHAR(10), '|', CHAR(10), ')', + '[[:blank:]]*()?(——|—|-{3,}|––|–)()?[[:blank:]]*', + '(', CHAR(13), CHAR(10), '|', CHAR(10), ')' + ); + +COMMIT; diff --git a/zmsentities/templates/messaging/custom/fhrerscheinstelle/mail_confirmation.twig b/zmsentities/templates/messaging/custom/fhrerscheinstelle/mail_confirmation.twig deleted file mode 100644 index c5028242d8..0000000000 --- a/zmsentities/templates/messaging/custom/fhrerscheinstelle/mail_confirmation.twig +++ /dev/null @@ -1,105 +0,0 @@ -{% use "@zmsentities/messaging/snippets.twig" %} -{% block german %} -
- {{ block("autogenerated_top_german") }} - {{ block("salutation_german_neutral") }} - wir bestätigen Ihren Termin in der {{ process.scope.provider.displayName }}. -

- {#{{ process.scope.hint }} - {{ process.scope.shortName }} Die Variablen können für die Behördenspezifishe Texte verwendent verden #} - {# - ~ ", " ~ process.scope.provider.contact.street ~ " " ~ process.scope.provider.contact.streetNumber ~", " ~ process.scope.provider.contact.postalCode ~ " " ~ process.scope.provider.contact.city }}
- {% if process.scope.hint %} - ({{ process.scope.hint }})
- {% endif %}
- #} - Datum: {{ (date|default(getNow))|format_date(locale="de", pattern="EEEE, dd. MMMM y") }}
- Uhrzeit: {{ (date|default(getNow))|date("H:i") }} {% trans %}Uhr{% endtrans %}
-
- - Terminnummer: {{ process.id }}
- {% if process.scope.hint %} - Wartezone: {{ process.scope.hint }}
- {% endif %}
- Bitte gehen Sie rechtzeitig zur "{{ process.scope.provider.contact.street ~ " " ~ process.scope.provider.contact.streetNumber }}"
-
- - {#Ihre Vorgangsnummer ist die "{{ process.id }}"
-
#} - - {#{% if process.scope.provider.source == "dldb" and process.scope.provider.data.payment %} - Zahlungshinweis: {{ process.scope.provider.data.payment }}

- {% endif %}#} - {% if process.requests|length > 1 %} - {% set requestalias = "Dienstleistungen sind" %} - {% else %} - {% set requestalias = "Dienstleistung ist" %} - {% endif %} - {% if process.requests|length == 0 %} - Sie haben keine Dienstleistungen ausgewählt. - {% else %} - Folgende {{ requestalias }} für diesen Termin gebucht: -

- {% for requestGroup in requestGroups %} - {{ requestGroup['request'].name }} {#am Standort {{ process.scope.provider.displayName }}#}
- - Anzahl: {{ requestGroup['count'] }} - - {% if requestGroups|length > 1 and not loop.last %} -

- ---------------------- -

- {% endif %} - {% endfor %} - {% endif %} -

- Bitte informieren Sie sich vorab über oben genannte/n Link/s, welche Unterlagen Sie benötigen. -

- - Falls Sie diesen Termin nicht benötigen oder wahrnehmen können, stornieren Sie bitte umgehend Ihren Termin und reservieren einen neuen Termin. - Termin ändern/stornieren
-

- - Mit freundlichen Grüßen
- Ihre {{ process.scope.provider.displayName }} -

- -
- -{% endblock %} diff --git a/zmsentities/templates/messaging/custom/fhrerscheinstelle/mail_delete.twig b/zmsentities/templates/messaging/custom/fhrerscheinstelle/mail_delete.twig deleted file mode 100644 index 35a88d1a57..0000000000 --- a/zmsentities/templates/messaging/custom/fhrerscheinstelle/mail_delete.twig +++ /dev/null @@ -1,48 +0,0 @@ -{% use "@zmsentities/messaging/snippets.twig" %} -{% block german %} -
-{{ block("autogenerated_top_german") }} -{{ block("salutation_german_neutral") }} -Ihr Termin am {{ (date|default(getNow))|format_date(locale="de", pattern="EEEE, dd. MMMM y") }} {% trans %}um{% endtrans %} {{ (date|default(getNow))|date("H:i") }} {% trans %}Uhr{% endtrans %} wurde gelöscht.
-
-Mit freundlichen Grüßen
-Ihre {{ process.scope.provider.displayName }} -

- -
- -{% endblock %} diff --git a/zmsentities/templates/messaging/custom/fhrerscheinstelle/mail_preconfirmed.twig b/zmsentities/templates/messaging/custom/fhrerscheinstelle/mail_preconfirmed.twig deleted file mode 100644 index 6d5a9323de..0000000000 --- a/zmsentities/templates/messaging/custom/fhrerscheinstelle/mail_preconfirmed.twig +++ /dev/null @@ -1,55 +0,0 @@ -{% use "@zmsentities/messaging/snippets.twig" %} -{% block german %} -
-{{ block("autogenerated_top_german") }} -{{ block("salutation_german_neutral") }} -{% set confirmLink = config.appointments.urlAppointments ~ '#/appointment/confirm/' ~ appointmentLink %} -vielen Dank für die Terminanfrage.

-Klicken Sie bitte auf den unten stehenden Link, um den Termin am {{ (date|default(getNow))|format_date(locale="de", pattern="EEEE, dd. MMMM y") }}{% if not isQueued %} um {{ (date|default(getNow))|date("H:i") }} Uhr{% endif %} verbindlich zu reservieren.

-Termin bestätigen

-Bitte beachten Sie, dass Ihre Terminanfrage ohne eine Bestätigung nach Ablauf von einer Stunde gelöscht wird.

-Nach Aktivierung des Termins erhalten Sie eine Bestätigung mit der Terminnummer und weiteren Einzelheiten, die Sie für Ihre Vorsprache benötigen.

- -Mit freundlichen Grüßen
-Ihre {{ process.scope.provider.displayName }} -

- -
- -{% endblock %} diff --git a/zmsentities/templates/messaging/custom/fhrerscheinstelle/mail_reminder.twig b/zmsentities/templates/messaging/custom/fhrerscheinstelle/mail_reminder.twig deleted file mode 100644 index caef9cffbb..0000000000 --- a/zmsentities/templates/messaging/custom/fhrerscheinstelle/mail_reminder.twig +++ /dev/null @@ -1,91 +0,0 @@ -{% use "@zmsentities/messaging/snippets.twig" %} -{% block german %} -
-{{ block("autogenerated_top_german") }} -{{ block("salutation_german_neutral") }} -wir erinnern Sie an Ihren Termin am {{ (date|default(getNow))|format_date(locale="de", pattern="EEEE, dd. MMMM y") }} {% trans %}um{% endtrans %} {{ (date|default(getNow))|date("H:i") }} {% trans %}Uhr{% endtrans %}.
-Terminnummer: {{ process.id }}
-{% if process.scope.hint %} -Wartezone: {{ process.scope.hint }}
-{% endif %}
-Bitte gehen Sie rechtzeitig zur "{{ process.scope.provider.contact.street ~ " " ~ process.scope.provider.contact.streetNumber }}"
-
-Der Einlass ins Gebäude ist frühestens 10 Minuten vor Ihrem Termin möglich. Bitte erscheinen Sie rechtzeitig zu Ihrem Termin und zeigen diese Terminerinnerung beim Einlass vor. -

-Ihre Terminnummer wird im oben genannten Bereich auf dem Bildschirm bei Aufruf angezeigt. -

- {% if process.requests|length > 1 %} - {% set requestalias = "Dienstleistungen sind" %} - {% else %} - {% set requestalias = "Dienstleistung ist" %} - {% endif %} - {% if process.requests|length == 0 %} - Sie haben keine Dienstleistungen ausgewählt. - {% else %} - Folgende {{ requestalias }} für diesen Termin gebucht: -

- {% for requestGroup in requestGroups %} - {{ requestGroup['request'].name }} {#am Standort {{ process.scope.provider.displayName }}#}
- - Anzahl: {{ requestGroup['count'] }} - - {% if requestGroups|length > 1 and not loop.last %} -

- ---------------------- -

- {% endif %} - {% endfor %} - {% endif %} -

- Bitte vergewissern Sie sich über oben genannte/n Link/s, welche Unterlagen Sie benötigen und halten Sie diese für Ihren Termin bereit. -

- Hinweise: -

- Bei erhöhtem Kundenaufkommen können wir leider nicht ausschließen, dass Sie trotz Termins mit einer geringen Wartezeit rechnen müssen. Wir bitten Sie hierfür um Verständnis. -

- Falls Sie diesen Termin nicht benötigen oder wahrnehmen können, stornieren Sie bitte umgehend Ihren Termin und reservieren einen neuen Termin. - Termin ändern/stornieren
-

- - Mit freundlichen Grüßen
- Ihre {{ process.scope.provider.displayName }} -

-
- -{% endblock %} diff --git a/zmsentities/templates/messaging/custom/kfz-zulassungsstelle/mail_confirmation.twig b/zmsentities/templates/messaging/custom/kfz-zulassungsstelle/mail_confirmation.twig deleted file mode 100644 index e5e57bb02a..0000000000 --- a/zmsentities/templates/messaging/custom/kfz-zulassungsstelle/mail_confirmation.twig +++ /dev/null @@ -1,99 +0,0 @@ -{% use "@zmsentities/messaging/snippets.twig" %} -{% block german %} -
- {{ block("autogenerated_top_german") }} - {{ block("salutation_german_neutral") }} - wir bestätigen Ihren Termin in der {{ process.scope.provider.displayName }}. -

- {#{{ process.scope.hint }} - {{ process.scope.shortName }} Die Variablen können für die Behördenspezifishe Texte verwendent verden #} - {# - ~ ", " ~ process.scope.provider.contact.street ~ " " ~ process.scope.provider.contact.streetNumber ~", " ~ process.scope.provider.contact.postalCode ~ " " ~ process.scope.provider.contact.city }}
- {% if process.scope.hint %} - ({{ process.scope.hint }})
- {% endif %}
- #} - Datum: {{ (date|default(getNow))|format_date(locale="de", pattern="EEEE, dd. MMMM y") }}
- Uhrzeit: {{ (date|default(getNow))|date("H:i") }} {% trans %}Uhr{% endtrans %}
-

- {#Ihre Vorgangsnummer ist die "{{ process.id }}"
-
#} - - {#{% if process.scope.provider.source == "dldb" and process.scope.provider.data.payment %} - Zahlungshinweis: {{ process.scope.provider.data.payment }}

- {% endif %}#} - {% if process.requests|length > 1 %} - {% set requestalias = "Dienstleistungen sind" %} - {% else %} - {% set requestalias = "Dienstleistung ist" %} - {% endif %} - {% if process.requests|length == 0 %} - Sie haben keine Dienstleistungen ausgewählt. - {% else %} - Folgende {{ requestalias }} für diesen Termin gebucht: -

- {% for requestGroup in requestGroups %} - {{ requestGroup['request'].name }} {#am Standort {{ process.scope.provider.displayName }}#}
- - Anzahl: {{ requestGroup['count'] }} - - {% if requestGroups|length > 1 and not loop.last %} -

- ---------------------- -

- {% endif %} - {% endfor %} - {% endif %} -

- Bitte informieren Sie sich vorab über oben genannte/n Link/s, welche Unterlagen Sie benötigen. -

- Hinweis:
- Ein Einlass ins Gebäude ist frühestens 10 Minuten vor Ihrem Termin möglich. Bitte erscheinen Sie rechtzeitig zu Ihrem Termin. -

- Falls Sie diesen Termin nicht benötigen oder wahrnehmen können, stornieren Sie bitte umgehend Ihren Termin und reservieren einen neuen Termin. - Termin ändern/stornieren
-


- - Mit freundlichen Grüßen
- Ihre {{ process.scope.provider.displayName }} -

- -
- -{% endblock %} diff --git a/zmsentities/templates/messaging/custom/kfz-zulassungsstelle/mail_delete.twig b/zmsentities/templates/messaging/custom/kfz-zulassungsstelle/mail_delete.twig deleted file mode 100644 index 35a88d1a57..0000000000 --- a/zmsentities/templates/messaging/custom/kfz-zulassungsstelle/mail_delete.twig +++ /dev/null @@ -1,48 +0,0 @@ -{% use "@zmsentities/messaging/snippets.twig" %} -{% block german %} -
-{{ block("autogenerated_top_german") }} -{{ block("salutation_german_neutral") }} -Ihr Termin am {{ (date|default(getNow))|format_date(locale="de", pattern="EEEE, dd. MMMM y") }} {% trans %}um{% endtrans %} {{ (date|default(getNow))|date("H:i") }} {% trans %}Uhr{% endtrans %} wurde gelöscht.
-
-Mit freundlichen Grüßen
-Ihre {{ process.scope.provider.displayName }} -

- -
- -{% endblock %} diff --git a/zmsentities/templates/messaging/custom/kfz-zulassungsstelle/mail_preconfirmed.twig b/zmsentities/templates/messaging/custom/kfz-zulassungsstelle/mail_preconfirmed.twig deleted file mode 100644 index 6d5a9323de..0000000000 --- a/zmsentities/templates/messaging/custom/kfz-zulassungsstelle/mail_preconfirmed.twig +++ /dev/null @@ -1,55 +0,0 @@ -{% use "@zmsentities/messaging/snippets.twig" %} -{% block german %} -
-{{ block("autogenerated_top_german") }} -{{ block("salutation_german_neutral") }} -{% set confirmLink = config.appointments.urlAppointments ~ '#/appointment/confirm/' ~ appointmentLink %} -vielen Dank für die Terminanfrage.

-Klicken Sie bitte auf den unten stehenden Link, um den Termin am {{ (date|default(getNow))|format_date(locale="de", pattern="EEEE, dd. MMMM y") }}{% if not isQueued %} um {{ (date|default(getNow))|date("H:i") }} Uhr{% endif %} verbindlich zu reservieren.

-Termin bestätigen

-Bitte beachten Sie, dass Ihre Terminanfrage ohne eine Bestätigung nach Ablauf von einer Stunde gelöscht wird.

-Nach Aktivierung des Termins erhalten Sie eine Bestätigung mit der Terminnummer und weiteren Einzelheiten, die Sie für Ihre Vorsprache benötigen.

- -Mit freundlichen Grüßen
-Ihre {{ process.scope.provider.displayName }} -

- -
- -{% endblock %} diff --git a/zmsentities/templates/messaging/custom/kfz-zulassungsstelle/mail_reminder.twig b/zmsentities/templates/messaging/custom/kfz-zulassungsstelle/mail_reminder.twig deleted file mode 100644 index caef9cffbb..0000000000 --- a/zmsentities/templates/messaging/custom/kfz-zulassungsstelle/mail_reminder.twig +++ /dev/null @@ -1,91 +0,0 @@ -{% use "@zmsentities/messaging/snippets.twig" %} -{% block german %} -
-{{ block("autogenerated_top_german") }} -{{ block("salutation_german_neutral") }} -wir erinnern Sie an Ihren Termin am {{ (date|default(getNow))|format_date(locale="de", pattern="EEEE, dd. MMMM y") }} {% trans %}um{% endtrans %} {{ (date|default(getNow))|date("H:i") }} {% trans %}Uhr{% endtrans %}.
-Terminnummer: {{ process.id }}
-{% if process.scope.hint %} -Wartezone: {{ process.scope.hint }}
-{% endif %}
-Bitte gehen Sie rechtzeitig zur "{{ process.scope.provider.contact.street ~ " " ~ process.scope.provider.contact.streetNumber }}"
-
-Der Einlass ins Gebäude ist frühestens 10 Minuten vor Ihrem Termin möglich. Bitte erscheinen Sie rechtzeitig zu Ihrem Termin und zeigen diese Terminerinnerung beim Einlass vor. -

-Ihre Terminnummer wird im oben genannten Bereich auf dem Bildschirm bei Aufruf angezeigt. -

- {% if process.requests|length > 1 %} - {% set requestalias = "Dienstleistungen sind" %} - {% else %} - {% set requestalias = "Dienstleistung ist" %} - {% endif %} - {% if process.requests|length == 0 %} - Sie haben keine Dienstleistungen ausgewählt. - {% else %} - Folgende {{ requestalias }} für diesen Termin gebucht: -

- {% for requestGroup in requestGroups %} - {{ requestGroup['request'].name }} {#am Standort {{ process.scope.provider.displayName }}#}
- - Anzahl: {{ requestGroup['count'] }} - - {% if requestGroups|length > 1 and not loop.last %} -

- ---------------------- -

- {% endif %} - {% endfor %} - {% endif %} -

- Bitte vergewissern Sie sich über oben genannte/n Link/s, welche Unterlagen Sie benötigen und halten Sie diese für Ihren Termin bereit. -

- Hinweise: -

- Bei erhöhtem Kundenaufkommen können wir leider nicht ausschließen, dass Sie trotz Termins mit einer geringen Wartezeit rechnen müssen. Wir bitten Sie hierfür um Verständnis. -

- Falls Sie diesen Termin nicht benötigen oder wahrnehmen können, stornieren Sie bitte umgehend Ihren Termin und reservieren einen neuen Termin. - Termin ändern/stornieren
-

- - Mit freundlichen Grüßen
- Ihre {{ process.scope.provider.displayName }} -

-
- -{% endblock %} diff --git a/zmsentities/templates/messaging/mail_confirmation.twig b/zmsentities/templates/messaging/mail_confirmation.twig index f54f6c79f1..d0b9c33ad4 100644 --- a/zmsentities/templates/messaging/mail_confirmation.twig +++ b/zmsentities/templates/messaging/mail_confirmation.twig @@ -46,9 +46,9 @@ Anzahl: {{ requestGroup['count'] }} {% if requestGroups|length > 1 and not loop.last %} -

- ---------------------- -

+

+ —— +

{% endif %} {% endfor %} {% endif %} diff --git a/zmsentities/templates/messaging/mail_queued.twig b/zmsentities/templates/messaging/mail_queued.twig index 3ce6ee7dc3..128b22715f 100644 --- a/zmsentities/templates/messaging/mail_queued.twig +++ b/zmsentities/templates/messaging/mail_queued.twig @@ -36,9 +36,9 @@ Sie haben folgende {{ requestalias }} ausgewählt: {% endif %} {% if process.requests|length > 1 and not loop.last %} -

- ---------------------- -

+

+ —— +

{% endif %} {% endfor %} {% endif %} diff --git a/zmsentities/templates/messaging/mail_reminder.twig b/zmsentities/templates/messaging/mail_reminder.twig index 2815b81dff..8f3a585eac 100644 --- a/zmsentities/templates/messaging/mail_reminder.twig +++ b/zmsentities/templates/messaging/mail_reminder.twig @@ -30,9 +30,9 @@ Ihre Terminnummer wird im oben genannten Bereich auf dem Bildschirm bei Aufruf a Anzahl: {{ requestGroup['count'] }} {% if requestGroups|length > 1 and not loop.last %} -

- ---------------------- -

+

+ —— +

{% endif %} {% endfor %} {% endif %}