% \iffalse %<*driver> \documentclass{ltxdoc} \usepackage{fontspec} \AtBeginDocument{\RequirePackage{luabreakurl}} \EnableCrossrefs \CodelineIndex \RecordChanges \begin{document} \DocInput{luabreakurl.dtx} \end{document} % % \fi % % \GetFileInfo{luabreakurl.sty} % % \title{\textsf{luabreakurl}: Breakable URLs with visible continuation marks} % \author{Klaus Rindfrey} % \date{Version \fileversion\ (\filedate)} % % \maketitle % % \begin{abstract} % The \textsf{luabreakurl} package typesets long, clickable URLs and URIs with % flexible line breaking under Lua\LaTeX. It keeps the URI scheme intact and % can display a configurable continuation mark whenever a URL is continued on % the following line. % \end{abstract} % % \tableofcontents % % \section{Introduction} % % Long URLs can cause overfull lines, especially in narrow columns, footnotes, % bibliographies, and technical documentation. The standard \cs{url} command % and packages such as \textsf{xurl} provide useful line-breaking facilities. % % The particular aim of \textsf{luabreakurl} is to combine very frequent break % opportunities with a visible indication that the URL continues on the next % line. % % The package follows a deliberately simple approach: % % \begin{itemize} % \item it inserts a possible break after almost every character; % \item it keeps the URI scheme and a following |//| together; % \item it preserves the URL as a clickable hyperlink; % \item it prints a continuation mark only when a break is actually taken; % \item it does not change the hyphenation of ordinary text. % \end{itemize} % % \section{Requirements} % % The package is intended for Lua\LaTeX. It loads \textsf{hyperref}, which is % used to create the clickable hyperlink. % % \section{Installation} % % For a local installation, run % % \begin{verbatim} % lualatex luabreakurl.ins % \end{verbatim} % % This extracts |luabreakurl.sty| from the documented source. Place the % generated file in the same directory as your document or in a directory % searched by \TeX. % % Once the package is distributed through \TeX\ Live or MiK\TeX, it can be % installed with the package manager of the respective distribution. % % \section{Quick start} % % Load the package in the document preamble: % % \begin{verbatim} % \usepackage{luabreakurl} % \end{verbatim} % % Then use \cs{breakurl} for a URL or URI: % % \begin{verbatim} % \breakurl{https://www.example.org/a/very/long/url} % \end{verbatim} % % The result is typeset in a typewriter font and remains clickable. % % \section{User interface} % % \subsection{\cs{breakurl}} % % \DescribeMacro{\breakurl} % The command % % \begin{verbatim} % \breakurl{} % \end{verbatim} % % typesets its argument as a clickable hyperlink and inserts line-break % opportunities after almost every character. % % The argument is read verbatim, so characters such as |_| may be used without % escaping. % % The URI scheme is protected. For example, \texttt{https://}, % \texttt{mailto:}, and \texttt{git+ssh://} are kept together at the beginning % of the URI. % % \subsection{\cs{luabreakurlsetup}} % % \DescribeMacro{\luabreakurlsetup} % Package settings are changed with % % \begin{verbatim} % \luabreakurlsetup{ % continuation={\tiny$\Rightarrow$} % } % \end{verbatim} % % The only setting currently available is |continuation|. Its default value is % |\tiny$\hookrightarrow$|. The value is printed only when a line break is % actually taken. % % To disable the continuation mark, use an empty value: % % \begin{verbatim} % \luabreakurlsetup{ % continuation={} % } % \end{verbatim} % % Settings obey normal \TeX\ grouping. A temporary setting can therefore be % limited to a group: % % \begin{verbatim} % \begingroup % \luabreakurlsetup{ % continuation={\tiny$\Rightarrow$} % } % \breakurl{https://www.example.org/a/very/long/url} % \endgroup % \end{verbatim} % % \section{Examples} % % The following narrow block deliberately forces line breaks: % % \begin{center} % \begin{minipage}{0.48\linewidth} % \breakurl{https://www.example.org/documentation/releases/2026/07/20/a/very/long/path/with/query/parameters?language=en&format=pdf&download=true} % \end{minipage} % \end{center} % % A different continuation mark can be selected: % % \begingroup % \luabreakurlsetup{ % continuation={\tiny$\Rightarrow$} % } % \begin{center} % \begin{minipage}{0.48\linewidth} % \breakurl{git+ssh://git.example.org/repositories/latex/luabreakurl/branches/feature/documentation/index.html} % \end{minipage} % \end{center} % \endgroup % % Other URI schemes work in the same way: % % \begin{center} % \begin{minipage}{0.48\linewidth} % \breakurl{mailto:someone.with.a.very.long.name+latex-package@example.org?subject=Question-about-luabreakurl} % % \medskip % % \breakurl{doi:10.1000/abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ} % \end{minipage} % \end{center} % % \section{URI scheme recognition} % % A URI scheme is recognized according to the RFC~3986 form % % \begin{verbatim} % ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) ":" % \end{verbatim} % % If the colon is followed immediately by |//|, the two slashes are protected % as part of the prefix. Consequently prefixes such as |https://|, |ftp://|, % |file://|, |git+ssh://|, |mailto:|, and |doi:| remain intact. % % \section{Comparison with other packages} % % The standard \cs{url} command and the \textsf{xurl} package are suitable for % many documents and provide established URL-breaking behaviour. % % \textsf{luabreakurl} is intended for the more specific case in which breaks % should be permitted after almost every character and a visible continuation % mark is desired. % % It is therefore not intended as a general replacement for \textsf{xurl}. % % \section{Limitations} % % \begin{itemize} % \item The package is intended for Lua\LaTeX. % \item \cs{breakurl} is intended for URLs and URIs, not for arbitrary text. % \item The command takes a verbatim argument and therefore cannot be used in % every moving argument. % \item Break opportunities are intentionally very frequent. Applications % requiring conventional URL-breaking rules may prefer \textsf{xurl}. % \end{itemize} % % \section{Building the package and documentation} % % A complete build of the package documentation is simply: % % \begin{verbatim} % make % \end{verbatim} % % To build the documentation and the demonstration document, run: % % \begin{verbatim} % make check % \end{verbatim} % % Internally, the documentation build performs the following steps: % % \begin{verbatim} % lualatex luabreakurl.dtx % makeindex -s gind.ist -o luabreakurl.ind luabreakurl.idx % makeindex -s gglo.ist -o luabreakurl.gls luabreakurl.glo % lualatex luabreakurl.dtx % lualatex luabreakurl.dtx % \end{verbatim} % % The resulting |luabreakurl.pdf| serves both as the user manual and as the % documented implementation. % % \section{License} % % The package is distributed under the MIT License. % % \section{Change history} % % \changes{v0.01}{2026-07-01}{Initial implementation.} % \changes{v0.02}{2026-07-10}{Internal improvements.} % \changes{v0.03}{2026-07-18}{General URI scheme detection and configurable % continuation mark.} % \changes{v1.0}{2026-07-20}{Renamed the package to % \textsf{luabreakurl} and prepared the first public release.} % % \StopEventually{ % \clearpage % \PrintChanges % \clearpage % \PrintIndex % } % % \section{Implementation} % % \subsection{Package declaration} % % \begin{macrocode} %<*package> \NeedsTeXFormat{LaTeX2e} \ProvidesExplPackage {luabreakurl} {2026-07-19} {1.00} {Breakable URLs with visible continuation marks} \RequirePackage{hyperref} \ExplSyntaxOn % \end{macrocode} % % \subsection{Variables} % % \begin{macrocode} \tl_new:N \l_luabreakurl_url_tl \tl_new:N \l_luabreakurl_continuation_tl \seq_new:N \l_luabreakurl_scheme_match_seq \int_new:N \l_luabreakurl_url_len_int \int_new:N \l_luabreakurl_scheme_len_int \int_new:N \l_luabreakurl_position_int % \end{macrocode} % % \subsection{Configuration} % % \begin{macrocode} \keys_define:nn { luabreakurl } { continuation .tl_set:N = \l_luabreakurl_continuation_tl, continuation .initial:n = { \tiny $\hookrightarrow$ } } % \end{macrocode} % % \subsection{URI scheme detection} % % Determine the length of the initial URI scheme, including a following |//|. % \begin{macrocode} \cs_new_protected:Npn \luabreakurl_set_scheme_length:n #1 { \int_zero:N \l_luabreakurl_scheme_len_int \seq_clear:N \l_luabreakurl_scheme_match_seq \regex_extract_once:nnNT { \A [A-Za-z] [-A-Za-z0-9+.]* : (//)? } { #1 } \l_luabreakurl_scheme_match_seq { \int_set:Nn \l_luabreakurl_scheme_len_int { \tl_count:e { \seq_item:Nn \l_luabreakurl_scheme_match_seq { 1 } } } } } % \end{macrocode} % % \subsection{Insertion of a break point} % % \begin{macrocode} \cs_new_protected:Npn \luabreakurl_insert_breakpoint: { \nobreak \hskip 0pt plus .5pt \discretionary { \hbox to 0pt { \tl_use:N \l_luabreakurl_continuation_tl \hss } } { } { } } % \end{macrocode} % % \subsection{Typesetting} % % \begin{macrocode} \cs_new_protected:Npn \luabreakurl_typeset:n #1 { \group_begin: \ttfamily \tl_set:Nn \l_luabreakurl_url_tl { #1 } \int_set:Nn \l_luabreakurl_url_len_int { \tl_count:N \l_luabreakurl_url_tl } \luabreakurl_set_scheme_length:n { #1 } \href{#1} { \int_zero:N \l_luabreakurl_position_int \tl_map_inline:Nn \l_luabreakurl_url_tl { \int_incr:N \l_luabreakurl_position_int ##1 \int_compare:nNnT { \l_luabreakurl_position_int } > { 1 } { \int_compare:nT { \l_luabreakurl_position_int >= \l_luabreakurl_scheme_len_int } { \int_compare:nNnT { \l_luabreakurl_position_int } < { \l_luabreakurl_url_len_int - 1 } { \luabreakurl_insert_breakpoint: } } } } } \group_end: } % \end{macrocode} % % \subsection{Public commands} % % \begin{macrocode} \NewDocumentCommand \luabreakurlsetup { m } { \keys_set:nn { luabreakurl } { #1 } } % \end{macrocode} % % \begin{macrocode} \NewDocumentCommand \breakurl { v } { \luabreakurl_typeset:n { #1 } } % \end{macrocode} % % \begin{macrocode} \ExplSyntaxOff % % \end{macrocode} % % \Finale