% \iffalse meta-comment % A LaTeX Class and Package for OMDoc Document Structures % Copyright (c) 2019 Michael Kohlhase, all rights reserved % this file is released under the % LaTeX Project Public License (LPPL) % % The original of this file is in the public repository at % http://github.com/sLaTeX/sTeX/ % % %<*driver> \def\bibfolder#1{../../lib/bib/#1} \input{../../doc/stex-docheader} \begin{document} \DocInput{\jobname.dtx} \end{document} % % \fi % % \title{document-structure: Semantic Markup for Open Mathematical Documents in {\LaTeX} % \thanks{Version {\fileversion} (last revised {\filedate})} % } % % \author{Michael Kohlhase, Dennis Müller\\ % FAU Erlangen-Nürnberg\\ % \url{http://kwarc.info/} % } % % \maketitle % % \ifinfulldoc\else % \begin{abstract} % This is the documentation for the \pkg{document-structure} package from \sTeX % collection, a version of {\TeX/\LaTeX} that allows to markup {\TeX/\LaTeX} documents % semantically without leaving the document format, essentially turning {\TeX/\LaTeX} % into a document format for mathematical knowledge management (MKM). % % For a more high-level introduction, see \href{\basedocurl/manual.pdf}{the \sTeX % Manual} or the \href{\basedocurl/stex.pdf}{full \sTeX documentation}. % \end{abstract} % % \tableofcontents % % \input{../../doc/packages/stex-document-structure} % \fi % % % \begin{documentation}\label{pkg:documentstructure:doc} % % \end{documentation} % % \begin{implementation}\label{pkg:documentstructure:impl} % % \begin{sfragment}{document-structure.sty Implementation} % % \begin{macrocode} %<*package> %<@@=document_structure> \ProvidesExplPackage{document-structure}{2022/05/24}{3.1.0}{Modular Document Structure} \RequirePackage{l3keys2e} % \end{macrocode} % % \begin{sfragment}[id=sec:impl:options]{Package Options} % % We declare some switches which will modify the behavior according to the package % options. Generally, an option |xxx| will just set the appropriate switches to true % (otherwise they stay false). % % % \begin{macrocode} \keys_define:nn{ document-structure }{ class .str_set_x:N = \c_document_structure_class_str, topsect .str_set_x:N = \c_document_structure_topsect_str,, unknown .code:n = { \PassOptionsToClass{\CurrentOption}{stex} \PassOptionsToClass{\CurrentOption}{tikzinput} } % showignores .bool_set:N = \c_document_structure_showignores_bool, } \ProcessKeysOptions{ document-structure } \str_if_empty:NT \c_document_structure_class_str { \str_set:Nn \c_document_structure_class_str {article} } \str_if_empty:NT \c_document_structure_topsect_str { \str_set:Nn \c_document_structure_topsect_str {section} } % \end{macrocode} % % Then we need to set up the packages by requiring the |sref| package to be loaded, % and set up triggers for other languages % % \begin{macrocode} \RequirePackage{xspace} \RequirePackage{comment} \RequirePackage{stex} \AddToHook{begindocument}{ \ltx@ifpackageloaded{babel}{ \clist_set:Nx \l_tmpa_clist {\bbl@loaded} \clist_if_in:NnT \l_tmpa_clist {ngerman}{ \makeatletter\input{document-structure-ngerman.ldf}\makeatother } }{} } % \end{macrocode} % % Finally, we set the \DescribeMacro{\section@level}|\section@level| macro that governs % sectioning. The default is two (corresponding to the |article| class), then we set the % defaults for the standard classes |book| and |report| and then we take care of the % levels passed in via the |topsect| option. % % \begin{macrocode} \int_new:N \l_document_structure_section_level_int \str_case:VnF \c_document_structure_topsect_str { {part}{ \int_set:Nn \l_document_structure_section_level_int {0} } {chapter}{ \int_set:Nn \l_document_structure_section_level_int {1} } }{ \str_case:VnF \c_document_structure_class_str { {book}{ \int_set:Nn \l_document_structure_section_level_int {0} } {report}{ \int_set:Nn \l_document_structure_section_level_int {0} } }{ \int_set:Nn \l_document_structure_section_level_int {2} } } % \end{macrocode} % % \end{sfragment} % % \begin{sfragment}[id=sec:impl:struct]{Document Structure} % % The structure of the document is given by the |sfragment| environment. The hierarchy % is adjusted automatically according to the {\LaTeX} class in effect. % \begin{macro}{\currentsectionlevel} % For the |\currentsectionlevel| and |\Currentsectionlevel| macros we use an internal % macro |\current@section@level| that only contains the keyword (no markup). We % initialize it with ``document'' as a default. In the generated OMDoc, we only generate % a text element of class |omdoc_currentsectionlevel|, wich will be instantiated by CSS % later.\ednote{MK: we may have to experiment with the more powerful uppercasing macro % from \texttt{mfirstuc.sty} once we internationalize.} % \begin{macrocode} \def\current@section@level{document}% \newcommand\currentsectionlevel{\lowercase\expandafter{\current@section@level}\xspace}% \newcommand\Currentsectionlevel{\expandafter\MakeUppercase\current@section@level\xspace}% % \end{macrocode} % \end{macro} % % \begin{macro}{\skipfragment} % \begin{macrocode} \cs_new_protected:Npn \skipfragment { \ifcase\l_document_structure_section_level_int \or\stepcounter{part} \or\stepcounter{chapter} \or\stepcounter{section} \or\stepcounter{subsection} \or\stepcounter{subsubsection} \or\stepcounter{paragraph} \or\stepcounter{subparagraph} \fi } % \end{macrocode} % \end{macro} % % \begin{environment}{blindfragment} % \begin{macrocode} \newcommand\at@begin@blindsfragment[1]{} \newenvironment{blindfragment} { \int_incr:N\l_document_structure_section_level_int \at@begin@blindsfragment\l_document_structure_section_level_int }{} % \end{macrocode} % \end{environment} % % \begin{macro}{\sfragment@nonum} % convenience macro: |\sfragment@nonum{|\meta{level}|}{|\meta{title}|}| makes an unnumbered % sectioning with title \meta{title} at level \meta{level}. % \begin{macrocode} \newcommand\sfragment@nonum[2]{ \ifx\hyper@anchor\@undefined\else\phantomsection\fi \addcontentsline{toc}{#1}{#2}\@nameuse{#1}*{#2} } % \end{macrocode} % \end{macro} % % \begin{macro}{\sfragment@num} % convenience macro: |\sfragment@nonum{|\meta{level}|}{|\meta{title}|}| makes numbered % sectioning with title \meta{title} at level \meta{level}. We have to check the |short| % key was given in the |sfragment| environment and -- if it is use it. But how to do that % depends on whether the |rdfmeta| package has been loaded. In the end we call % |\sref@label@id| to enable crossreferencing. % \begin{macrocode} \newcommand\sfragment@num[2]{ \tl_if_empty:NTF \l_@@_sfragment_short_tl { \@nameuse{#1}{#2} }{ \cs_if_exist:NTF\rdfmeta@sectioning{ \@nameuse{rdfmeta@#1@old}[\l_@@_sfragment_short_tl]{#2} }{ \@nameuse{#1}[\l_@@_sfragment_short_tl]{#2} } } %\sref@label@id@arg{\omdoc@sect@name~\@nameuse{the#1}}\sfragment@id } % \end{macrocode} % \end{macro} % % \begin{environment}{sfragment} % \begin{macrocode} \keys_define:nn { document-structure / sfragment }{ id .str_set_x:N = \l_@@_sfragment_id_str, date .str_set_x:N = \l_@@_sfragment_date_str, creators .clist_set:N = \l_@@_sfragment_creators_clist, contributors .clist_set:N = \l_@@_sfragment_contributors_clist, srccite .tl_set:N = \l_@@_sfragment_srccite_tl, type .tl_set:N = \l_@@_sfragment_type_tl, short .tl_set:N = \l_@@_sfragment_short_tl, display .tl_set:N = \l_@@_sfragment_display_tl, intro .tl_set:N = \l_@@_sfragment_intro_tl, imports .tl_set:N = \l_@@_sfragment_imports_tl, loadmodules .bool_set:N = \l_@@_sfragment_loadmodules_bool } \cs_new_protected:Nn \_@@_sfragment_args:n { \str_clear:N \l_@@_sfragment_id_str \str_clear:N \l_@@_sfragment_date_str \clist_clear:N \l_@@_sfragment_creators_clist \clist_clear:N \l_@@_sfragment_contributors_clist \tl_clear:N \l_@@_sfragment_srccite_tl \tl_clear:N \l_@@_sfragment_type_tl \tl_clear:N \l_@@_sfragment_short_tl \tl_clear:N \l_@@_sfragment_display_tl \tl_clear:N \l_@@_sfragment_imports_tl \tl_clear:N \l_@@_sfragment_intro_tl \bool_set_false:N \l_@@_sfragment_loadmodules_bool \keys_set:nn { document-structure / sfragment } { #1 } } % \end{macrocode} % we define a switch for numbering lines and a hook for the beginning of groups: The % \DescribeMacro{\at@begin@sfragment}|\at@begin@sfragment| macro allows customization. It is % run at the beginning of the |sfragment|, i.e. after the section heading. % \begin{macrocode} \newif\if@mainmatter\@mainmattertrue \newcommand\at@begin@sfragment[3][]{} % \end{macrocode} % % Then we define a helper macro that takes care of the sectioning magic. It comes with its % own key/value interface for customization. % % \begin{macrocode} \keys_define:nn { document-structure / sectioning }{ name .str_set_x:N = \l_@@_sect_name_str , ref .str_set_x:N = \l_@@_sect_ref_str , clear .bool_set:N = \l_@@_sect_clear_bool , clear .default:n = {true} , num .bool_set:N = \l_@@_sect_num_bool , num .default:n = {true} } \cs_new_protected:Nn \_@@_sect_args:n { \str_clear:N \l_@@_sect_name_str \str_clear:N \l_@@_sect_ref_str \bool_set_false:N \l_@@_sect_clear_bool \bool_set_false:N \l_@@_sect_num_bool \keys_set:nn { document-structure / sectioning } { #1 } } \newcommand\omdoc@sectioning[3][]{ \_@@_sect_args:n {#1 } \let\omdoc@sect@name\l_@@_sect_name_str \bool_if:NT \l_@@_sect_clear_bool { \cleardoublepage } \if@mainmatter% numbering not overridden by frontmatter, etc. \bool_if:NTF \l_@@_sect_num_bool { \sfragment@num{#2}{#3} }{ \sfragment@nonum{#2}{#3} } \def\current@section@level{\omdoc@sect@name} \else \sfragment@nonum{#2}{#3} \fi }% if@mainmatter % \end{macrocode} % and another one, if redefines the |\addtocontentsline| macro of {\LaTeX} to import the % respective macros. It takes as an argument a list of module names. % \begin{macrocode} \newcommand\sfragment@redefine@addtocontents[1]{% %\edef\@@import{#1}% %\@for\@I:=\@@import\do{% %\edef\@path{\csname module@\@I @path\endcsname}% %\@ifundefined{tf@toc}\relax% % {\protected@write\tf@toc{}{\string\@requiremodules{\@path}}}} %\ifx\hyper@anchor\@undefined% hyperref.sty loaded? %\def\addcontentsline##1##2##3{% %\addtocontents{##1}{\protect\contentsline{##2}{\string\withusedmodules{#1}{##3}}{\thepage}}} %\else% hyperref.sty not loaded %\def\addcontentsline##1##2##3{% %\addtocontents{##1}{\protect\contentsline{##2}{\string\withusedmodules{#1}{##3}}{\thepage}{\@currentHref}}}% %\fi }% hypreref.sty loaded? % \end{macrocode} % now the |sfragment| environment itself. This takes care of the table of contents via the % helper macro above and then selects the appropriate sectioning command from % |article.cls|. It also registeres the current level of sfragments in the |\sfragment@level| % counter. % \begin{macrocode} \newenvironment{sfragment}[2][]% keys, title { \_@@_sfragment_args:n { #1 }%\sref@target% % \end{macrocode} % If the |loadmodules| key is set on |\begin{sfragment}|, we redefine the |\addcontetsline| % macro that determines how the sectioning commands below construct the entries for the % table of contents. % \begin{macrocode} \stex_csl_to_imports:No \usemodule \l_@@_sfragment_imports_tl \bool_if:NT \l_@@_sfragment_loadmodules_bool { \sfragment@redefine@addtocontents{ %\@ifundefined{module@id}\used@modules% %{\@ifundefined{module@\module@id @path}{\used@modules}\module@id} } } % \end{macrocode} % now we only need to construct the right sectioning depending on the value of % |\section@level|. % \begin{macrocode} \stex_document_title:n { #2 } \int_incr:N\l_document_structure_section_level_int \ifcase\l_document_structure_section_level_int \or\omdoc@sectioning[name=\omdoc@part@kw,clear,num]{part}{#2} \or\omdoc@sectioning[name=\omdoc@chapter@kw,clear,num]{chapter}{#2} \or\omdoc@sectioning[name=\omdoc@section@kw,num]{section}{#2} \or\omdoc@sectioning[name=\omdoc@subsection@kw,num]{subsection}{#2} \or\omdoc@sectioning[name=\omdoc@subsubsection@kw,num]{subsubsection}{#2} \or\omdoc@sectioning[name=\omdoc@paragraph@kw,ref=this \omdoc@paragraph@kw]{paragraph}{#2} \or\omdoc@sectioning[name=\omdoc@subparagraph@kw,ref=this \omdoc@subparagraph@kw]{paragraph}{#2} \fi \at@begin@sfragment[#1]\l_document_structure_section_level_int{#2} \str_if_empty:NF \l_@@_sfragment_id_str { \stex_ref_new_doc_target:n\l_@@_sfragment_id_str } }% for customization {} % \end{macrocode} % \end{environment} % % and finally, we localize the sections % \begin{macrocode} \newcommand\omdoc@part@kw{Part} \newcommand\omdoc@chapter@kw{Chapter} \newcommand\omdoc@section@kw{Section} \newcommand\omdoc@subsection@kw{Subsection} \newcommand\omdoc@subsubsection@kw{Subsubsection} \newcommand\omdoc@paragraph@kw{paragraph} \newcommand\omdoc@subparagraph@kw{subparagraph} % \end{macrocode} % % \end{sfragment} % % \begin{sfragment}[id=sec:user:docmatter]{Front and Backmatter} % % Index markup is provided by the |omtext| package~\cite{Kohlhase:smmtf:git}, so in the % |document-structure| package we only need to supply the corresponding |\printindex| command, if it % is not already defined % \begin{macro}{\printindex} % \begin{macrocode} \providecommand\printindex{\IfFileExists{\jobname.ind}{\input{\jobname.ind}}{}} % \end{macrocode} % \end{macro} % % some classes (e.g. |book.cls|) already have |\frontmatter|, |\mainmatter|, and % |\backmatter| macros. As we want to define |frontmatter| and |backmatter| environments, % we save their behavior (possibly defining it) in |orig@*matter| macros and make them % undefined (so that we can define the environments). % \begin{macrocode} \cs_if_exist:NTF\frontmatter{ \let\_@@_orig_frontmatter\frontmatter \let\frontmatter\relax }{ \tl_set:Nn\_@@_orig_frontmatter{ \clearpage \@mainmatterfalse \pagenumbering{roman} } } \cs_if_exist:NTF\backmatter{ \let\_@@_orig_backmatter\backmatter \let\backmatter\relax }{ \tl_set:Nn\_@@_orig_backmatter{ \clearpage \@mainmatterfalse \pagenumbering{roman} } } % \end{macrocode} % % Using these, we can now define the |frontmatter| and |backmatter| environments % % \begin{environment}{frontmatter} % we use the |\orig@frontmatter| macro defined above and |\mainmatter| if it exists, % otherwise we define it. % \begin{macrocode} \newenvironment{frontmatter}{ \_@@_orig_frontmatter }{ \cs_if_exist:NTF\mainmatter{ \mainmatter }{ \clearpage \@mainmattertrue \pagenumbering{arabic} } } % \end{macrocode} % \end{environment} % % \begin{environment}{backmatter} % As backmatter is at the end of the document, we do nothing for |\endbackmatter|. % \begin{macrocode} \newenvironment{backmatter}{ \_@@_orig_backmatter }{ \cs_if_exist:NTF\mainmatter{ \mainmatter }{ \clearpage \@mainmattertrue \pagenumbering{arabic} } } % \end{macrocode} % % finally, we make sure that page numbering is arabic and we have main matter as the default % % \begin{macrocode} \@mainmattertrue\pagenumbering{arabic} % \end{macrocode} % \end{environment} % \end{sfragment} % % \begin{macro}{\prematurestop} % We initialize |\afterprematurestop|, and provide % |\prematurestop@endsfragment| which looks up |\sfragment@level| and recursively ends % enough |{sfragment}|s. % \begin{macrocode} \def \c_@@_document_str{document} \newcommand\afterprematurestop{} \def\prematurestop@endsfragment{ \unless\ifx\@currenvir\c_@@_document_str \expandafter\expandafter\expandafter\end\expandafter\expandafter\expandafter{\expandafter\@currenvir\expandafter} \expandafter\prematurestop@endsfragment \fi } \providecommand\prematurestop{ \message{Stopping~sTeX~processing~prematurely} \prematurestop@endsfragment \afterprematurestop \end{document} } % \end{macrocode} % \end{macro} % % \begin{sfragment}[id=sec:impl:gvars]{Global Variables} % % \begin{macro}{\setSGvar} % set a global variable % \begin{macrocode} \RequirePackage{etoolbox} \newcommand\setSGvar[1]{\@namedef{sTeX@Gvar@#1}} % \end{macrocode} % \end{macro} % % \begin{macro}{\useSGvar} % use a global variable % \begin{macrocode} \newrobustcmd\useSGvar[1]{% \@ifundefined{sTeX@Gvar@#1} {\PackageError{document-structure} {The sTeX Global variable #1 is undefined} {set it with \protect\setSGvar}} \@nameuse{sTeX@Gvar@#1}} % \end{macrocode} % \end{macro} % % \begin{macro}{\ifSGvar} % execute something conditionally based on the state of the global variable. % \begin{macrocode} \newrobustcmd\ifSGvar[3]{\def\@test{#2}% \@ifundefined{sTeX@Gvar@#1} {\PackageError{document-structure} {The sTeX Global variable #1 is undefined} {set it with \protect\setSGvar}} {\expandafter\ifx\csname sTeX@Gvar@#1\endcsname\@test #3\fi}} % \end{macrocode} % \end{macro} % % \end{sfragment} % \end{sfragment} % % \end{implementation} % \ifinfulldoc\else\printbibliography\fi \endinput %%% Local Variables: %%% mode: doctex %%% TeX-master: t %%% End: