From 03b8a435219b7720b5210c7cba5a2114672d2fb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Dobrowolski?= Date: Mon, 15 Sep 2025 01:05:58 +0200 Subject: [PATCH] Rework \social command --- moderncv.cls | 132 ++++++++++++++++++++------------------------ moderncvfooti.sty | 4 +- moderncvheadi.sty | 4 +- moderncvheadiii.sty | 4 +- moderncvheadiv.sty | 4 +- moderncvheadv.sty | 4 +- moderncvheadvi.sty | 2 +- moderncvheadvii.sty | 2 +- 8 files changed, 72 insertions(+), 84 deletions(-) diff --git a/moderncv.cls b/moderncv.cls index 3756507..3a2f2dd 100644 --- a/moderncv.cls +++ b/moderncv.cls @@ -256,80 +256,68 @@ % http://latex.org/forum/viewtopic.php?t=12239 \def\SplitMyMacro#1/#2{#2} +% Define links for different social networks +\newcommand{\linkedinlink}[2]{\protect\httpslink[#1]{www.linkedin.com/in/#2}} +\newcommand{\xinglink}[2]{\protect\httpslink[#1]{www.xing.com/profile/#2}} +\newcommand{\twitterlink}[2]{\protect\httpslink[#1]{twitter.com/#2}} +\newcommand{\mastodonlink}[2]{\protect\httpslink[#1]{#2}} +\newcommand{\githublink}[2]{\protect\httpslink[#1]{github.com/#2}} +\newcommand{\gitlablink}[2]{\protect\httpslink[#1]{gitlab.com/#2}} +\newcommand{\stackoverflowlink}[2]{\protect\httpslink[#1]{stackoverflow.com/users/#2}} +\newcommand{\bitbucketlink}[2]{\protect\httpslink[#1]{bitbucket.org/#2}} +\newcommand{\skypelink}[2]{\ifthenelse{\equal{#1}{}}{#1}{#2}} +\newcommand{\orcidlink}[2]{\protect\httpslink[#1]{orcid.org/#2}} +\newcommand{\researchgatelink}[2]{\protect\httpslink[#1]{www.researchgate.net/profile/#2}} +\newcommand{\researcheridlink}[2]{\protect\httpslink[#1]{www.researcherid.com/rid/#2}} +\newcommand{\telegramlink}[2]{\protect\httpslink[#1]{t.me/#2}} +\newcommand{\whatsapplink}[2]{\protect\httpslink[#1]{wa.me/#2}} +\newcommand{\signallink}[2]{\ifthenelse{\equal{#1}{}}{#1}{#2}} +\newcommand{\matrixlink}[2]{\protect\httpslink[#1]{matrix.to/\#/#2}} +\newcommand{\googlescholarlink}[2]{\protect\httpslink[#1]{scholar.google.com/citations?user=#2}} +\newcommand{\codeberglink}[2]{\protect\httpslink[#1]{codeberg.org/#2}} +\newcommand{\discordlink}[2]{\ifthenelse{\equal{#1}{}}{#1}{#2}} +\newcommand{\twitchlink}[2]{\protect\httpslink[#1]{twitch.tv/#2}} +\newcommand{\youtubelink}[2]{\protect\httpslink[#1]{youtube.com/#2}} +\newcommand{\tiktoklink}[2]{\protect\httpslink[#1]{tiktok.com/@#2}} +\newcommand{\instagramlink}[2]{\protect\httpslink[#1]{instagram.com/#2}} +\newcommand{\soundcloudlink}[2]{\protect\httpslink[#1]{soundcloud.com/#2}} +\newcommand{\steamlink}[2]{\protect\httpslink[#1]{steamcommunity.com/id/#2}} +\newcommand{\xboxlink}[2]{\protect\httpslink[#1]{account.xbox.com/profile?gamertag=#2}} +\newcommand{\playstationlink}[2]{\ifthenelse{\equal{#1}{}}{#1}{#2}} +\newcommand{\battlenetlink}[2]{\ifthenelse{\equal{#1}{}}{#1}{#2}} +\newcommand{\arxivlink}[2]{\protect\httpslink[#1]{arxiv.org/a/#2}} +\newcommand{\inspirelink}[2]{\protect\httpslink[#1]{inspirehep.net/authors/#2}} +\newcommand{\simplexlink}[2]{\protect\httpslink[#1]{simplex.chat/#2}} +\newcommand{\threemalink}[2]{\protect\httpslink[#1]{threema.id/#2}} -% adds a social link to one's personal information (optional) -% usage: \social[][]{} -% where should be either: -% - "linkedin" -% - "xing" -% - "twitter" -% - "mastodon" -% - "github" -% - "gitlab" -% - "stackoverflow" -% - "bitbucket" -% - "skype" -% - "orcid" -% - "researchgate" -% - "researcherid" -% - "telegram" -% - "whatsapp" -% - "signal" -% - "matrix" -% - "googlescholar" -% - "codeberg" -% - "discord" -% - "twitch" -% - "youtube" -% - "tiktok" -% - "instagram" -% - "soundcloud" -% - "steam -% - "xbox" -% - "playstation" -% - "battlenet" -% - "arxiv" -% - "inspire" -% - "simplex" -% - "threema" +\NewDocumentCommand{\socialIconLink}{m}{ + \ifx\previtem\empty + % Do nothing on first iteration. This way we 'shift' the whole list by one. + \else % The actual work happens here. + \unskip\unskip\unskip~% Get rid of a glue space inserted by \ProcessList + \expandafter\expandafter\csname\previtem link\endcsname{\csname\previtem socialsymbol\endcsname}{\username} + % Eg for (linkedin, username) -> \linkedinlink{\linkedinsocialsymbol}{username} + \fi + \def\previtem{#1} % Update previtem +} + +% Adds a links to social networks +% usage: \social[,]{} +% If you have the same username you can specify multiple networks separating them by commas. +% The entries are shown in order they are added. +% To be supported network needs a \networknamelink and \networknamesocialsymbol commands. \collectionnew{socials} -\NewDocumentCommand{\social}{O{}O{}m}{% - \ifthenelse{\equal{#2}{}}% - {% - \ifthenelse{\equal{#1}{linkedin}} {\collectionadd[linkedin]{socials} {\protect\httpslink[#3]{www.linkedin.com/in/#3}}} {}% - \ifthenelse{\equal{#1}{xing}} {\collectionadd[xing]{socials} {\protect\httpslink[#3]{www.xing.com/profile/#3}}} {}% - \ifthenelse{\equal{#1}{twitter}} {\collectionadd[twitter]{socials} {\protect\httpslink[#3]{twitter.com/#3}}} {}% - \ifthenelse{\equal{#1}{mastodon}} {\collectionadd[mastodon]{socials} {\protect\httpslink[#3]{#3}}} {}% - \ifthenelse{\equal{#1}{github}} {\collectionadd[github]{socials} {\protect\httpslink[#3]{github.com/#3}}} {}% - \ifthenelse{\equal{#1}{gitlab}} {\collectionadd[gitlab]{socials} {\protect\httpslink[#3]{gitlab.com/#3}}} {}% - \ifthenelse{\equal{#1}{stackoverflow}}{\collectionadd[stackoverflow]{socials}{\protect\httpslink[#3]{stackoverflow.com/users/#3}}} {}% - \ifthenelse{\equal{#1}{bitbucket}} {\collectionadd[bitbucket]{socials} {\protect\httpslink[#3]{bitbucket.org/#3}}} {}% - \ifthenelse{\equal{#1}{skype}} {\collectionadd[skype]{socials} {#3}} {}% - \ifthenelse{\equal{#1}{orcid}} {\collectionadd[orcid]{socials} {\protect\httpslink[#3]{orcid.org/#3}}} {}% - \ifthenelse{\equal{#1}{researchgate}} {\collectionadd[researchgate]{socials} {\protect\httpslink[#3]{www.researchgate.net/profile/#3}}} {}% - \ifthenelse{\equal{#1}{researcherid}} {\collectionadd[researcherid]{socials} {\protect\httpslink[#3]{www.researcherid.com/rid/#3}}} {}% - \ifthenelse{\equal{#1}{telegram}} {\collectionadd[telegram]{socials} {\protect\httpslink[#3]{t.me/#3}}} {}% - \ifthenelse{\equal{#1}{whatsapp}} {\collectionadd[whatsapp]{socials} {\protect\httpslink[#3]{wa.me/#3}}} {}% - \ifthenelse{\equal{#1}{signal}} {\collectionadd[signal]{socials} {#3}} {}% - \ifthenelse{\equal{#1}{matrix}} {\collectionadd[matrix]{socials} {\httpslink[#3]{matrix.to/\#/#3}}} {}% - \ifthenelse{\equal{#1}{googlescholar}}{\collectionadd[googlescholar]{socials}{\protect\httpslink[#3]{scholar.google.com/citations?user=#3}}} {}% - \ifthenelse{\equal{#1}{codeberg}} {\collectionadd[codeberg]{socials} {\protect\httpslink[#3]{codeberg.org/#3}}} {}% - \ifthenelse{\equal{#1}{discord}} {\collectionadd[discord]{socials} {#3}} {}% - \ifthenelse{\equal{#1}{twitch}} {\collectionadd[twitch]{socials} {\protect\httpslink[#3]{twitch.tv/#3}}} {}% - \ifthenelse{\equal{#1}{youtube}} {\collectionadd[youtube]{socials} {\protect\httpslink[#3]{youtube.com/#3}}} {}% - \ifthenelse{\equal{#1}{tiktok}} {\collectionadd[tiktok]{socials} {\protect\httpslink[#3]{tiktok.com/@#3}}} {}% - \ifthenelse{\equal{#1}{instagram}} {\collectionadd[instagram]{socials} {\protect\httpslink[#3]{instagram.com/#3}}} {}% - \ifthenelse{\equal{#1}{soundcloud}} {\collectionadd[soundcloud]{socials} {\protect\httpslink[#3]{soundcloud.com/#3}}} {}% - \ifthenelse{\equal{#1}{steam}} {\collectionadd[steam]{socials} {\protect\httpslink[#3]{steamcommunity.com/id/#3}}} {}% - \ifthenelse{\equal{#1}{xbox}} {\collectionadd[xbox]{socials} {\protect\httpslink[#3]{account.xbox.com/profile?gamertag=#3}}} {}% - \ifthenelse{\equal{#1}{playstation}} {\collectionadd[playstation]{socials} {#3}} {}% - \ifthenelse{\equal{#1}{battlenet}} {\collectionadd[battlenet]{socials} {#3}} {}% - \ifthenelse{\equal{#1}{arxiv}} {\collectionadd[arxiv]{socials} {\protect\httpslink[#3]{arxiv.org/a/#3}}} {}% - \ifthenelse{\equal{#1}{inspire}} {\collectionadd[inspire]{socials} {\protect\httpslink[#3]{inspirehep.net/authors/#3}}} {}% - \ifthenelse{\equal{#1}{simplex}} {\collectionadd[simplex]{socials} {\protect\httpslink[#3]{simplex.chat/#3}}} {}% - \ifthenelse{\equal{#1}{threema}} {\collectionadd[threema]{socials} {\protect\httpslink[#3]{threema.id/#3}}} {}% - } - {\collectionadd[#1]{socials}{\protect\httpslink[#3]{#2}}}}% +\NewDocumentCommand{\social}{>{\SplitList{,}}o m}{ + \collectionadd{socials}{ + \begingroup % Make sure \username does not leak outside + \def\username{#2} % \ProcessList can't handle multiple arguments. Work around it by defining a var. + \let\previtem\empty % Ugly hack to handle all but last element by acting on (i-1)th element + \ProcessList{#1}{\socialIconLink} % Common case handled here (all but last item) + \unskip\unskip\unskip~% Get rid of a glue space inserted by \ProcessList + \expandafter\expandafter\csname\previtem link\endcsname{\csname\previtem socialsymbol\endcsname~\username}{\username} % Last item + \endgroup + } +} % defines additional personal information (optional) % usage: \extrainfo{} diff --git a/moderncvfooti.sty b/moderncvfooti.sty index 92f9de7..842d8ea 100644 --- a/moderncvfooti.sty +++ b/moderncvfooti.sty @@ -92,7 +92,7 @@ \ifthenelse{\isundefined{\@homepage}}{}{\addtofoot{\homepagesymbol% \ifthenelse{\equal{\@homepageprotocol}{http}}{\httplink{\@homepage}}{\httpslink{\@homepage}}}}% \collectionloop{socials}{% the key holds the social type (=symbol command prefix), the item holds the link - \addtofoot{\csname\collectionloopkey socialsymbol\endcsname\collectionloopitem}}% + \addtofoot{\collectionloopitem}}% \ifthenelse{\isundefined{\@extrainfo}}{}{\addtofoot{\@extrainfo}}% \ifthenelse{\lengthtest{\footboxwidth=0pt}}{}{\flushfoot}% the lengthtest is required to avoid flushing an empty footer, which could cause a blank line due to the \\ after the address, if no other personal info is used }}}% @@ -125,7 +125,7 @@ \ifthenelse{\isundefined{\@homepage}}{}{\addtofoot{\homepagesymbol% \ifthenelse{\equal{\@homepageprotocol}{http}}{\httplink{\@homepage}}{\httpslink{\@homepage}}}}% \collectionloop{socials}{% the key holds the social type (=symbol command prefix), the item holds the link - \addtofoot{\csname\collectionloopkey socialsymbol\endcsname\collectionloopitem}}% + \addtofoot{\collectionloopitem}}% \ifthenelse{\isundefined{\@extrainfo}}{}{\addtofoot{\@extrainfo}}% \ifthenelse{\lengthtest{\footboxwidth=0pt}}{}{\flushfoot}% the lengthtest is required to avoid flushing an empty footer, which could cause a blank line due to the \\ after the address, if no other personal info is used }}}% diff --git a/moderncvheadi.sty b/moderncvheadi.sty index 930b1fd..9396c8d 100644 --- a/moderncvheadi.sty +++ b/moderncvheadi.sty @@ -77,7 +77,7 @@ \protected@edef\phonesdetails{\phonesdetails\protect\makenewline\csname\collectionloopkey phonesymbol\endcsname\collectionloopitem}}% \def\socialsdetails{}% \collectionloop{socials}{% the key holds the social type (=symbol command prefix), the item holds the link - \protected@edef\socialsdetails{\socialsdetails\protect\makenewline\csname\collectionloopkey socialsymbol\endcsname\collectionloopitem}}% + \protected@edef\socialsdetails{\socialsdetails\protect\makenewline\collectionloopitem}}% \savebox{\makecvheaddetailsbox}{% \addressfont\color{addresscolor}% \if@left\begin{tabular}[b]{@{}r@{}}\fi% @@ -181,7 +181,7 @@ \ifthenelse{\isundefined{\@homepage}}{}{\makenewline\homepagesymbol% \ifthenelse{\equal{\@homepageprotocol}{http}}{\httplink{\@homepage}}{\httpslink{\@homepage}}}% \collectionloop{socials}{% the key holds the social type (=symbol command prefix), the item holds the link - \makenewline\csname\collectionloopkey socialsymbol\endcsname\collectionloopitem}% + \makenewline\collectionloopitem}% \ifthenelse{\isundefined{\@extrainfo}}{}{\makenewline\@extrainfo}}\fi% \end{minipage}\\[2em] % recipient block diff --git a/moderncvheadiii.sty b/moderncvheadiii.sty index 6919dee..bbaad63 100644 --- a/moderncvheadiii.sty +++ b/moderncvheadiii.sty @@ -100,7 +100,7 @@ \ifthenelse{\isundefined{\@homepage}}{}{\addtomakeheaddetails{\homepagesymbol% \ifthenelse{\equal{\@homepageprotocol}{http}}{\httplink{\@homepage}}{\httpslink{\@homepage}}}}% \collectionloop{socials}{% the key holds the social type (=symbol command prefix), the item holds the link - \addtomakeheaddetails{\csname\collectionloopkey socialsymbol\endcsname\collectionloopitem}}% + \addtomakeheaddetails{\collectionloopitem}}% \ifthenelse{\isundefined{\@extrainfo}}{}{\addtomakeheaddetails{\@extrainfo}}% \flushmakeheaddetails}\fi}}% need to force a \par after this to avoid weird spacing bug at the first section if no blank line is left after \makehead @@ -160,7 +160,7 @@ \ifthenelse{\isundefined{\@homepage}}{}{\makenewline\homepagesymbol% \ifthenelse{\equal{\@homepageprotocol}{http}}{\httplink{\@homepage}}{\httpslink{\@homepage}}}% \collectionloop{socials}{% the key holds the social type (=symbol command prefix), the item holds the link - \makenewline\csname\collectionloopkey socialsymbol\endcsname\collectionloopitem}% + \makenewline\collectionloopitem}% \ifthenelse{\isundefined{\@extrainfo}}{}{\makenewline\@extrainfo}}\fi% \end{minipage}\\[2em] % recipient block diff --git a/moderncvheadiv.sty b/moderncvheadiv.sty index 0c9970a..5e39586 100644 --- a/moderncvheadiv.sty +++ b/moderncvheadiv.sty @@ -116,7 +116,7 @@ \ifthenelse{\isundefined{\@homepage}}{}{\makenewline\hbox to 1.0em{\homepagesymbol}~% \ifthenelse{\equal{\@homepageprotocol}{http}}{\httplink{\@homepage}}{\httpslink{\@homepage}}}% \collectionloop{socials}{% the key holds the social type (=symbol command prefix), the item holds the link - \makenewline\hbox to 1.0em{\csname\collectionloopkey socialsymbol\endcsname}~\collectionloopitem}% + \makenewline\collectionloopitem}% \ifthenelse{\isundefined{\@extrainfo}}{}{\makenewline\@extrainfo}}\fi} @@ -165,7 +165,7 @@ \ifthenelse{\isundefined{\@homepage}}{}{\makenewline\hbox to 1.0em{\homepagesymbol}~% \ifthenelse{\equal{\@homepageprotocol}{http}}{\httplink{\@homepage}}{\httpslink{\@homepage}}}% \collectionloop{socials}{% the key holds the social type (=symbol command prefix), the item holds the link - \makenewline\hbox to 1.0em{\csname\collectionloopkey socialsymbol\endcsname}~\collectionloopitem}% + \makenewline\collectionloopitem}% \ifthenelse{\isundefined{\@extrainfo}}{}{\makenewline\@extrainfo}}}% % ensure no extra spacing after \makelettertitle due to a possible blank line %\ignorespacesafterend% not working diff --git a/moderncvheadv.sty b/moderncvheadv.sty index 2431ab3..f95b5fc 100644 --- a/moderncvheadv.sty +++ b/moderncvheadv.sty @@ -88,7 +88,7 @@ \ifthenelse{\isundefined{\@homepage}}{}{\makenewline\homepagesymbol~% \ifthenelse{\equal{\@homepageprotocol}{http}}{\httplink{\@homepage}}{\httpslink{\@homepage}}}% \collectionloop{socials}{% the key holds the social type (=symbol command prefix), the item holds the link - \makenewline\csname\collectionloopkey socialsymbol\endcsname~\collectionloopitem}% + \makenewline\collectionloopitem}% \ifthenelse{\isundefined{\@extrainfo}}{}{\makenewline\@extrainfo}\fi}% {% % name and optional title @@ -161,7 +161,7 @@ \ifthenelse{\isundefined{\@homepage}}{}{\makenewline\homepagesymbol% \ifthenelse{\equal{\@homepageprotocol}{http}}{\httplink{\@homepage}}{\httpslink{\@homepage}}}% \collectionloop{socials}{% the key holds the social type (=symbol command prefix), the item holds the link - \makenewline\csname\collectionloopkey socialsymbol\endcsname\collectionloopitem}% + \makenewline\collectionloopitem}% \ifthenelse{\isundefined{\@extrainfo}}{}{\makenewline\@extrainfo}}\fi% \end{minipage}\\[2em] % recipient block diff --git a/moderncvheadvi.sty b/moderncvheadvi.sty index 405fdf2..2a5744e 100644 --- a/moderncvheadvi.sty +++ b/moderncvheadvi.sty @@ -121,7 +121,7 @@ \ifthenelse{\isundefined{\@homepage}}{}{\addtomakeheaddetails{\homepagesymbol% \ifthenelse{\equal{\@homepageprotocol}{http}}{\httplink{\@homepage}}{\httpslink{\@homepage}}}}% \collectionloop{socials}{% the key holds the social type (=symbol command prefix), the item holds the link - \addtomakeheaddetails{\csname\collectionloopkey socialsymbol\endcsname\collectionloopitem}}% + \addtomakeheaddetails{\collectionloopitem}}% \ifthenelse{\isundefined{\@extrainfo}}{}{\addtomakeheaddetails{\@extrainfo}}% \flushmakeheaddetails}\fi% need to force a \par after this to avoid weird spacing bug at the first section if no blank line is left after \makehead; not forcing it here because of the possible quote % optional quote diff --git a/moderncvheadvii.sty b/moderncvheadvii.sty index 6e6f1a1..d52ab0b 100644 --- a/moderncvheadvii.sty +++ b/moderncvheadvii.sty @@ -84,7 +84,7 @@ \protected@edef\phonesdetails{\phonesdetails\protect\makenewline\csname\collectionloopkey phonesymbol\endcsname\collectionloopitem}}% \def\socialsdetails{}% \collectionloop{socials}{% the key holds the social type (=symbol command prefix), the item holds the link - \protected@edef\socialsdetails{\socialsdetails\protect\makenewline\csname\collectionloopkey socialsymbol\endcsname\collectionloopitem}}% + \protected@edef\socialsdetails{\socialsdetails\protect\makenewline\collectionloopitem}}% \savebox{\makecvheaddetailsbox}{% \addressfont\color{headtext}% \if@left\begin{tabular}[b]{@{}r@{}}\fi%