note/note.cls

978 lines
21 KiB
OpenEdge ABL
Raw Normal View History

2023-08-15 19:52:29 +02:00
% vim: ft=tex ts=2 sts=2 sw=2 et:
\NeedsTeXFormat{LaTeX2e}
\ProvidesExplClass{note}{2023/07/15}{1.0}{Note}
%%% Class
\RequirePackage { l3keys2e }
\LoadClass [ english, french, 11pt ] { article }
%%% Error messages
% https://github.com/latex3/latex3/issues/887
\prop_gput:Nnn \g_msg_module_type_prop { note } { Class }
\msg_new:nnn { note } { Not~LuaLaTeX }
{ Please ~ use ~ LuaLaTeX. }
%%% Constants
%% Dimensions
% Height of the page header
\dim_const:Nn \c__note_head_height_dim { 6.5mm }
% Spacing between logos in the page header
\dim_const:Nn \c__note_logos_sep_dim
{ \c__note_head_height_dim / 2}
% Spacing between the page header and body
\dim_const:Nn \c__note_head_sep_dim { 8.5mm }
% Skip between the page footer and body
\dim_const:Nn \c__note_foot_skip_dim
{ \c__note_head_height_dim + \c__note_head_sep_dim }
% Margin around {body + footer + header}
\dim_const:Nn \c__note_margin_dim { 33mm }
% Left margin of list items
\dim_const:Nn \c__note_list_left_margin_dim
{ 8.5mm }
%% Skips
% Spacing between heading number and text
\skip_const:Nn \c__note_heading_sep_skip { .5em }
% Spacing between list item and label
\skip_const:Nn \c__note_list_label_sep_skip
{ \c__note_heading_sep_skip }
% Parskip
\skip_const:Nn \c__note_par_skip
{ 9pt plus 3pt minus 2pt }
% Parindent
\skip_const:Nn \c__note_par_indent_skip { 0pt }
% Section
\skip_const:Nn \c__note_section_skip
{ ( \c__note_par_skip * 150 ) / 100 }
% Subsection
\skip_const:Nn \c__note_subsection_skip
{ ( \c__note_par_skip * 135 ) / 100 }
% Subsubsection
\skip_const:Nn \c__note_subsubsection_skip
{ ( \c__note_par_skip * 120 ) / 100 }
% Total spacing between successive list items
\skip_const:Nn \c__note_list_total_item_sep_skip
{ \c__note_par_skip / 2 }
% Spacing between paragraphs inside a single list item
\skip_const:Nn \c__note_list_par_sep_skip
{ \c__note_par_skip / 4 }
% Spacing between footnote mark and text
\skip_const:Nn \c__note_footnote_mark_sep_skip
{ \c__note_par_skip / 4 }
%% Strings
% Separator between title and subtitle in PDF infos
\str_const:Nn \c__note_title_sep_str { ~ ~ }
%%% Declarations
\tl_new:N \g__note_subtitle_tl
\tl_new:N \g__note_date_tl
\tl_new:N \g__note_author_tl
\tl_new:N \g__note_reference_tl
\tl_new:N \g__note_place_tl
\tl_new:N \g__note_sender_title_tl
\tl_new:N \g__note_recipient_title_tl
\tl_new:N \g__note_plaintiff_tl
\tl_new:N \g__note_defendant_tl
\tl_new:N \g__note_court_prefix_tl
\tl_new:N \g__note_court_tl
\tl_new:N \l__note_meta_title_tl
\tl_new:N \l__note_meta_author_tl
\tl_new:N \l__note_sigs_flush_tl
\seq_new:N \g__note_logos_url_seq
\seq_new:N \g__note_logos_seq
\seq_new:N \g__note_sigs_name_seq
\seq_new:N \g__note_sigs_title_seq
\seq_new:N \g__note_sender_addr_seq
\seq_new:N \g__note_recipient_addr_seq
\int_new:N \g__note_logos_map_int
\int_new:N \g__note_sigs_map_int
\box_new:N \l__note_logos_box
\box_new:N \l__note_date_box
\bool_new:N \g__note_show_head_bool
%%% Common variants
\cs_generate_variant:Nn \exp_args:Nnnx { cnnx }
\cs_generate_variant:Nn \exp_args:Nnnn { cnnn }
%%% Basic checks
\sys_if_engine_luatex:F
{ \msg_fatal:nn { note } { Not ~ LuaLaTeX } }
%%% Options
\keys_define:nn { note/options }
{
nm .str_set:N = \g__note_mode_str,
nm .default:n = { note },
}
\ProcessKeysOptions { note/options }
\bool_gset:Nn \g__note_show_head_bool
{
\str_case:VnF \g__note_mode_str
{
{ letter } { \c_false_bool }
{ brief } { \c_false_bool }
}
{ \c_true_bool }
}
%%% Packages
\RequirePackage { fontspec }
\RequirePackage { xparse }
\RequirePackage [ latin, english, french ] { babel }
\RequirePackage [ babel ] { csquotes }
\RequirePackage { enumitem }
\RequirePackage { fancyhdr }
\RequirePackage [ explicit ] { titlesec }
\RequirePackage [ svgnames ] { xcolor }
\RequirePackage { graphicx }
\RequirePackage { acro }
\RequirePackage { geometry }
\RequirePackage { parskip }
\RequirePackage { tabularx }
\RequirePackage { siunitx }
\RequirePackage { booktabs }
\RequirePackage [ avoid-all ] { widows-and-orphans }
\RequirePackage [ babel = true ] { microtype }
\RequirePackage { hyperref }
%%% Colors
\definecolor { note/red } { HTML } { cd1e27 }
\definecolor { note/dark-blue } { HTML } { 44589f } %4e5368 }
\definecolor { note/light-blue } { HTML } { 729fcf }
%%% Geometry
\geometry
{
%showframe,
centering,
a4paper,
headheight = \c__note_head_height_dim,
headsep = \c__note_head_sep_dim,
footskip = \c__note_foot_skip_dim,
margin = \c__note_margin_dim,
includehead,
includefoot,
}
\bool_if:NF \g__note_show_head_bool
{
\geometry
{
headheight = 0pt,
headsep = 0pt,
}
}
%%% Paragraphs
\skip_set_eq:NN \parindent \c__note_par_indent_skip
\skip_set_eq:NN \parskip \c__note_par_skip
%%% Babel
\AddBabelHook { * } { foreign }
{ \em }
\frenchsetup
{
ListItemsAsPar = true,
FrenchFootnotes = true,
}
%%% Lists
% TODO fix the skip v. dim mess
\SetEnumitemKey { note/spacing }
{
itemsep =
\skip_eval:n
{
\c__note_list_total_item_sep_skip
- \c__note_list_par_sep_skip
},
parsep = \skip_use:N \c__note_list_par_sep_skip,
topsep = 0pt,
itemindent = 0pt,
listparindent = 0pt,
leftmargin = \skip_use:N \c__note_list_left_margin_dim,
labelsep = \skip_use:N \c__note_list_label_sep_skip,
}
\setlist [ enumerate ] { note/spacing }
\setlist [ enumerate, 1 ]
{
label = \textcolor { note/dark-blue } { \sffamily \arabic*. },
}
\setlist [ itemize ] { note/spacing }
\setlist [ itemize, 1 ]
{
label = \textcolor { note/dark-blue } { \sffamily \textbullet },
}
%%% Hyperref
\hypersetup
{
colorlinks,
urlcolor = RoyalBlue,
linkcolor = note/red ! 80 ! black, %VioletRed,
}
\AddToHook { begindocument/before }
{
\group_begin:
\tl_set:Nn \l__note_meta_title_tl
{
\@title
\tl_if_empty:NF \g__note_subtitle_tl
{
\str_use:N \c__note_title_sep_str
\tl_use:N \g__note_subtitle_tl
}
}
\tl_set:Nx \l__note_meta_author_tl
{
\tl_if_empty:NTF \g__note_author_tl
{ \seq_use:Nn \g__note_sigs_name_seq { , ~ } }
{ \g__note_author_tl }
}
\hypersetup
{
pdftitle = { \tl_use:N \l__note_meta_title_tl },
pdfauthor = { \tl_use:N \l__note_meta_author_tl },
}
\group_end:
}
%%% Headings
\setcounter { secnumdepth } { 5 }
%% Section
\titleformat { \section }
[ block ]
{
\sffamily \Large \bfseries
\color { note/dark-blue }
}
{ \Roman { section } . }
{ \skip_use:N \c__note_heading_sep_skip }
{#1}
\titlespacing \section
{ 0pt }
{ \skip_use:N \c__note_section_skip }
{ \skip_use:N \c__note_section_skip }
\tl_gset:Nn \thesection
{ \Roman { section } }
%% Subsection
\titleformat { \subsection }
[ block ]
{
\sffamily \large \bfseries
\color { note/dark-blue }
}
{ \Alph { subsection } . }
{ \skip_use:N \c__note_heading_sep_skip }
{#1}
\titlespacing \subsection
{ 0pt }
{ \skip_use:N \c__note_subsection_skip }
{ \skip_use:N \c__note_subsection_skip }
\tl_gset:Nn \thesubsection
{ \thesection . \Alph { subsection } }
%% Subsubsection
\titleformat { \subsubsection }
[ block ]
{
\sffamily \normalsize \bfseries
\color { note/dark-blue }
}
{ \arabic { subsubsection } . }
{ \skip_use:N \c__note_heading_sep_skip }
{#1}
\titlespacing \subsubsection
{ 0pt }
{ \skip_use:N \c__note_subsubsection_skip }
{ \skip_use:N \c__note_subsubsection_skip }
\tl_gset:Nn \thesubsubsection
{ \thesubsection . \arabic { subsubsection } }
%% Paragraph
\titleformat { \paragraph }
[ runin ]
{
\sffamily \normalsize %\bfseries
\color { note/dark-blue }
}
{}
{ 0pt }
%{ \alph { paragraph } . }
%{ \skip_use:N \c__note_heading_sep_skip }
{#1}
\titlespacing \paragraph
{ 0pt }
{ \skip_use:N \c__note_par_skip }
{ \skip_use:N \c__note_heading_sep_skip }
%%% Fonts
\setmainfont { Libertinus Serif }
\setsansfont { Libertinus Sans }
\setmonofont { Fira Mono }
[ Scale = 0.84 ]
%%% Siunitx
% TODO babel
\sisetup
{
detect-all,
locale = FR,
}
\DeclareSIUnit \euro {}
%%% Quotes FIXME
\cs_set:Npn \mktextquote #1#2#3#4#5#6
{ #1 { \em #2 } #3 #6 #4 #5 }
\cs_set:Npn \mktextins #1
{ { \em [ #1 ] } }
\cs_set:Npn \mkblockquote #1#2#3#4
{
\openautoquote { \em #1 } \closeautoquote #2 #4 #3
}
\cs_set:Npn \mktextelp
{ \mktextins { ... } }
\NewDocumentEnvironment { block } {}
{
\group_begin:
\begin { list } {}
{
\setlength{\topsep}{0pt}
\setlength{\leftmargin}{4.25mm}
\setlength{\rightmargin}{0pt}
\setlength{\listparindent}{\parindent}
\setlength{\itemindent}{\parindent}
\setlength{\parsep}{\parskip}
\@beginparpenalty=10000
}
\item[]
}
{
\end { list }
\group_end:
}
\SetBlockEnvironment { block }
\DeclareQuoteStyle [ guillemets ] { french }
[ \initfrenchquotes ]
{ \mkfrenchopenquote { \guillemotleft } }
[ { \em \mkfrenchopenquote { \guillemotleft } } ]
{ \mkfrenchclosequote { \guillemotright } }
{ \mkfrenchopenquote { \textquotedblleft } }
[ { \em \mkfrenchopenquote { \textquotedblleft } } ]
{ \mkfrenchclosequote { \textquotedblright } }
%%% Headers and footers
\cs_new:Nn \__note_logos_map_indexed_inline:n
{
\int_gincr:N \g__note_logos_map_int
\cs_gset:cn
{ __note_logos_map_ \int_use:N \g__note_logos_map_int :nnn }
{ #1 }
\seq_map_indexed_inline:Nn \g__note_logos_seq
{
\exp_args:cnnx
{ __note_logos_map_ \int_use:N \g__note_logos_map_int :nnn }
{##1} % index
{##2} % image path
{ \seq_item:Nn \g__note_logos_url_seq {##1} } % url
}
}
\cs_new:Nn \__note_logos_include:nn
{
\__note_logos_map_indexed_inline:n
{
\int_compare:nNnT {##1} > {1}
{ \skip_horizontal:n {#2} }
\tl_if_empty:nF {##3}
{ \href {##3} }
{ \includegraphics [ height = #1 ] {##2} }
}
}
\fancypagestyle { fancyplain }
{
\fancyhf {}
\bool_if:NT \g__note_show_head_bool
{
% TODO l3box
\fancyhead [R]
{
\parbox [] [ \headheight ] [c] { .5 \textwidth }
{
\raggedleft \sffamily
\tl_if_empty:NTF \g__note_date_tl
{ \today }
{ \tl_use:N \g__note_date_tl }
}
}
\fancyhead [L]
{
\parbox [] [ \headheight ] [c] { .5 \textwidth }
{
\__note_logos_include:nn
{ \c__note_head_height_dim }
{ \c__note_logos_sep_dim }
}
}
}
\fancyfoot [C] { \sffamily \thepage }
\tl_set:Nn \headrulewidth { 0pt }
\tl_set:Nn \footrulewidth { 0pt }
}
\pagestyle { fancyplain }
%%% Preamble
\cs_new:Nn \__note_undef_begin:N
{
\AddToHook { begindocument/before }
{ \cs_undefine:N #1 }
}
\DeclareDocumentCommand \author {m}
{ \tl_set:Nn \g__note_author_tl {#1} }
\__note_undef_begin:N \author
\DeclareDocumentCommand \reference {m}
{ \tl_set:Nn \g__note_reference_tl {#1} }
\__note_undef_begin:N \reference
\NewDocumentCommand \subtitle {m}
{ \tl_set:Nn \g__note_subtitle_tl {#1} }
\__note_undef_begin:N \subtitle
\NewDocumentCommand \place {m}
{ \tl_set:Nn \g__note_place_tl {#1} }
\__note_undef_begin:N \place
\NewDocumentCommand \plaintiff {m}
{ \tl_set:Nn \g__note_plaintiff_tl {#1} }
\__note_undef_begin:N \plaintiff
\NewDocumentCommand \defendant {m}
{ \tl_set:Nn \g__note_defendant_tl {#1} }
\__note_undef_begin:N \defendant
\NewDocumentCommand \court {O{}m}
{
\tl_set:Nn \g__note_court_prefix_tl {#1}
\tl_set:Nn \g__note_court_tl {#2}
}
\__note_undef_begin:N \court
\DeclareDocumentCommand \date {m}
{ \tl_set:Nn \g__note_date_tl {#1} }
\__note_undef_begin:N \date
\NewDocumentCommand \addlogo {O{}m}
{
\seq_put_right:Nn \g__note_logos_url_seq {#1}
\seq_put_right:Nn \g__note_logos_seq {#2}
}
\__note_undef_begin:N \addlogo
\cs_new:Nn \__note_sender_addr_add:n
{ \seq_put_right:Nn \g__note_sender_addr_seq {#1} }
\cs_new:Nn \__note_recipient_addr_add:n
{ \seq_put_right:Nn \g__note_recipient_addr_seq {#1} }
\NewDocumentCommand \sender {m>{\SplitList{,}}m}
{
\tl_set:Nn \g__note_sender_title_tl {#1}
\ProcessList {#2} { \__note_sender_addr_add:n }
}
\__note_undef_begin:N \sender
\NewDocumentCommand \recipient {m>{\SplitList{,}}m}
{
\tl_set:Nn \g__note_recipient_title_tl {#1}
\ProcessList {#2} { \__note_recipient_addr_add:n }
}
\__note_undef_begin:N \recipient
%%% Titlepage
\cs_new:Nn \__note_title_note_show:
{
\begin { center }
\vspace* { 2.65em }
{
\sffamily \LARGE \bfseries
\color { note/dark-blue }
\@title
}
\tl_if_empty:NF \g__note_subtitle_tl
{
\par
\sffamily \Large
\tl_use:N \g__note_subtitle_tl
}
\vspace* { 2.65em }
\end { center }
}
\cs_new:Nn \__note_title_letter_show:
{
\begin { flushleft }
\parbox { .40 \textwidth }
{
\flushleft \sffamily
\textbf { \tl_use:N \g__note_sender_title_tl }
\vspace* {.25em}
\par \seq_use:Nn \g__note_sender_addr_seq { \\ }
}
\end { flushleft }
\vspace* { 1em }
\begin { flushright }
\parbox { .45 \textwidth }
{
\flushleft \sffamily
\textbf { \tl_use:N \g__note_recipient_title_tl }
\vspace* {.25em}
\par \seq_use:Nn \g__note_recipient_addr_seq { \\ }
}
\end { flushright }
\vspace* { 2em }
\begin {flushright}
\parbox { .45 \textwidth }
{
\flushleft \sffamily
\tl_if_empty:NTF \g__note_place_tl
{ Le ~ }
{ \tl_use:N \g__note_place_tl , ~ le ~ }
\tl_if_empty:NTF \g__note_date_tl
{ \today }
{ \tl_use:N \g__note_date_tl }
}
\end { flushright }
\vspace* { 4.5em }
\group_begin:
\sffamily
\textcolor { note/dark-blue } { \bfseries Objet ~ : }
\hspace { 1em }
\@title \par
\tl_if_empty:NF \g__note_reference_tl
{
\textcolor { note/dark-blue } { \bfseries Réf. ~ : }
\hspace { 1em }
\tl_use:N \g__note_reference_tl
}
\group_end:
\vspace*{1.5em}
}
\cs_new:Nn \__note_title_brief_show:
{
\pagenumbering { Alph }
\begin { titlepage }
\vspace* { 13.5mm }
\begin { flushleft }
\begin { minipage } { .8 \textwidth }
\begin { flushleft }
\color { note/dark-blue }
\sffamily \bfseries \Huge \@title
\end { flushleft }
\tl_if_empty:NF \g__note_reference_tl
{
\vspace* { 2.5mm }
\begin { flushleft }
\LARGE \normalfont \sffamily
Dossier ~ \no \g__note_reference_tl
\end { flushleft }
}
\end { minipage }
\end { flushleft }
\vspace { 12.5mm }
\begin { flushright }
\tl_if_empty:NF \g__note_court_prefix_tl
{
\sffamily \large \g__note_court_prefix_tl
\par
}
\LARGE \g__note_court_tl
\end { flushright }
\vspace { \fill }
\begin { center }
\color { note/dark-blue }
\sffamily \bfseries \Large Pour
\vspace* { 2.5mm }
\end { center }
\begin { center }
\begin { minipage } { .8 \textwidth }
\large \sffamily \g__note_plaintiff_tl
\end { minipage }
\end { center }
\vspace { 11.5mm }
\begin { center }
\color { note/dark-blue }
\sffamily \bfseries \Large Contre
\vspace* { 2.5mm }
\end { center }
\begin { center }
\begin { minipage } { .8 \textwidth }
\large \sffamily \g__note_defendant_tl
\end { minipage }
\end { center }
\vspace* { 13.5mm }
\end { titlepage }
\pagenumbering { arabic }
}
\DeclareDocumentCommand \maketitle {}
{
\str_case:VnF \g__note_mode_str
{
{ letter } { \__note_title_letter_show: }
{ brief } { \__note_title_brief_show: }
}
{ \__note_title_note_show: }
}
%%% Mail
\NewDocumentCommand \email {m}
{ \href { mailto \c_colon_str #1 } { #1 } }
%%% Eur-Lex
\cs_new:Nn \__note_eurlex_lang:N
{
\str_case:VnF #1
{
{ french } { FR }
}
{ EN }
}
\cs_new:Nn \__note_eurlex_uri:Nn
{
% https://tex.stackexchange.com/q/384826
https \c_colon_str //eur-lex.europa.eu/legal-content/
\__note_eurlex_lang:N #1 /TXT/?uri = #2
}
\NewDocumentCommand \eurlex {mm}
{
\href
{ \__note_eurlex_uri:Nn \languagename {#1} }
{#2}
}
%%% JORF
\cs_new:Nn \__note_jorf_uri:n
{ https \c_colon_str //www.legifrance.gouv.fr/jorf/id/ #1 }
\NewDocumentCommand \jorf {mm}
{
\href
{ \__note_jorf_uri:n {#1} }
{#2}
}
%%% BOFiP
% TODO date
\cs_new:Nn \__note_bofip_uri:n
{ https \c_colon_str //bofip.impots.gouv.fr/doctrine/ #1 }
\NewDocumentCommand \bofip {m}
{ \href { \__note_bofip_uri:n {#1} } {#1} }
%%% Articles
\DeclareExpandableDocumentCommand \art {m}
{
\texorpdfstring { \nolinebreak } {}
\mbox {#1}
}
\clist_map_inline:nn
{
bis, ter, quater, quinquies,
sexies, septies, octies, nonies
}
{
\exp_args:Nc \DeclareExpandableDocumentCommand {#1} {m}
{ \art { ##1 ~ \lat {#1} } }
}
\DeclareExpandableDocumentCommand \para {m}
{ § \nobreakspace \mbox { #1 } }
\DeclareExpandableDocumentCommand \rn {m}
{ \art { \int_to_Roman:n {#1} } }
\DeclareExpandableDocumentCommand \ao {m}
{ \art { #1 \up { o } } }
\DeclareExpandableDocumentCommand \L {m}
{ \art { L. \, #1 } }
\DeclareExpandableDocumentCommand \R {m}
{ \art { R. \, #1 } }
%%% Names
\DeclareExpandableDocumentCommand \name {om}
{
\IfValueT {#1} { #1 ~ }
\textsc {#2}
}
\cs_new:Nn \__note_name_prefix_translate:n
{
\str_case:nnF {#1}
{
{ m } { M. }
{ mm } { MM. }
{ mme } { M \up { me } }
{ mmes } { M \up { mes } }
{ me } { M \up { e } }
}
{#1}
}
\clist_map_inline:nn { m, mm, mme, mmes }
{
\exp_args:Nc \DeclareExpandableDocumentCommand {#1} {om}
{
\__note_name_prefix_translate:n {#1}
\nobreakspace
\IfValueTF {##1}
{ \name [##1] {##2} }
{ \name {##2} }
}
}
%%% Todo
\NewDocumentCommand \todo {m}
{ \textcolor { note/red } { [ #1 ] } }
%%% Foreign language shortcuts
\NewExpandableDocumentCommand \en {m}
{ \foreignlanguage { english } {#1} }
\NewExpandableDocumentCommand \lat {m}
{ \foreignlanguage { latin } {#1} }
%%% End of page
\NewDocumentEnvironment { endofpage } {}
{ \vfill }
{}
%%% Footnotes
\AddToHook { begindocument }
{
\cs_gset:Npn \@makefntext #1
{
\textcolor { note/dark-blue } { \sffamily \@thefnmark . }
\skip_horizontal:N \c__note_footnote_mark_sep_skip
#1
}
% FIXME
\cs_gset:Npn \footnoterule
{
\kern -3pt
\textcolor { note/dark-blue }
{ \rule { .25 \textwidth } { .75pt } }
\vspace { .5em }
}
}
%%% Signatories
\cs_new:Nn \__note_sigs_add:nn
{
\seq_put_right:Nn \g__note_sigs_name_seq {#1}
\seq_put_right:Nn \g__note_sigs_title_seq {#2}
}
\cs_new:Nn \__note_sigs_map_indexed_inline:n
{
\int_gincr:N \g__note_sigs_map_int
\cs_gset:cn
{ __note_sigs_map_ \int_use:N \g__note_sigs_map_int :nnn }
{ #1 }
\seq_map_indexed_inline:Nn \g__note_sigs_name_seq
{
\exp_args:cnnx
{ __note_sigs_map_ \int_use:N \g__note_sigs_map_int :nnn }
{##1} % index
{##2} % name
{ \seq_item:Nn \g__note_sigs_title_seq {##1} } % title
}
}
\DeclareDocumentCommand \signature {O{}m}
{ \__note_sigs_add:nn {#2} {#1} }
\DeclareDocumentCommand \makesignatures {s}
{
\vspace* { 3em }
\IfBooleanT {#1}
{
\tl_if_empty:NTF \g__note_place_tl
{ Le ~ }
{ Fait ~ à ~ \tl_use:N \g__note_place_tl , ~ le ~ }
\tl_if_empty:NTF \g__note_date_tl
{ \today }
{ \tl_use:N \g__note_date_tl } .
\vspace* { 1em }
}
\__note_sigs_map_indexed_inline:n
{
\group_begin:
\tl_set:Nx \l__note_sigs_flush_tl
{
\int_compare:nNnTF { \int_mod:nn {##1} { 2 } } = { 1 }
{ flushright }
{ flushleft }
}
\begin { \tl_use:N \l__note_sigs_flush_tl }
\parbox { .5 \textwidth }
{
\centering
\textsc {##2}
\tl_if_empty:nF {##3}
{
, \\
\textit { ##3 }
}
}
\end { \tl_use:N \l__note_sigs_flush_tl }
\group_end:
}
}
\DeclareDocumentCommand \opening {m}
{
#1
\vspace* { 1em }
}
\DeclareDocumentCommand \closing {m}
{
\vspace* { 1em }
#1
}