Badge Links

⭐ The code lives at github.com/alhassy/org-special-block-extras —star it, or discuss it there!
Badges provide a quick and colourful summary of key features of a project, such as whether it's maintained, its license, and if it's documented.
Figure 1: An Emacs interface to https://shields.io/
As people who are passionate about writing great code we display "badges" in our code repositories to signal to fellow developers that we set ourselves high standards for the code we write, think of them as the software-equivalent of the brand on your jeans or other reliable product. — repo-badges
﴾What You Write﴿
What are badges?
badge:Let_me_google_that|for_you!|orange|https://lmgtfy.app/?q=badge+shields.io&iie=1|Elixir
or
[[badge: Let me google that | for you! |orange|
https://lmgtfy.app/?q=badge+shields.io&iie=1 |Elixir]]
or
badge:Let_me_*not*_google_that|for_you Notice that the orange badge points to a URL and so is clickable, whereas the green one does not point to a URL and so is not clickable.
Automated Tests
Let's have some sanity tests…
(deftest "It works when all 5 arguments are provided"
[badge]
(⇝ (⟰ "badge:Let_me_google_that|for_you!|orange|https://lmgtfy.app/?q=badge+shields.io&iie=1|Elixir")
"<a href=\"https://lmgtfy.app/?q=badge+shields.io&iie=1\">"
"<img src=\"https://img.shields.io/badge/Let_me_google_that-for_you%21-orange?logo=Elixir\"></a>"))
(deftest "It works when we use [[link]] syntax with generous spaces and newlines"
[badge]
(⇝ (⟰ "[[badge: Let me google that | for you! | orange |
https://lmgtfy.app/?q=badge+shields.io&iie=1|Elixir]]")
"<a href=\"https://lmgtfy.app/?q=badge+shields.io&iie=1\">"
(* anything)
"<img src=\"https://img.shields.io/badge/Let%20me%20google%20that-for%20you%21-orange?logo=Elixir\">"))
(deftest "It works when only the first 2 arguments are provided; asterisks are passed unaltered into the first argument"
[badge]
(⇝ (⟰ "badge:Let_me_*not*_google_that|for_you")
"<img src=\"https://img.shields.io/badge/Let_me_%2Anot%2A_google_that-for_you-nil?logo=nil\">"))
(deftest "It works when all 5 arguments are provided - URL ‘here’ makes it a local link"
[badge]
(⇝ (⟰ "badge:key|value|informational||Elixir")
"<a id=\"key\" href=\"#key\">"
"<img src=\"https://img.shields.io/badge/key-value-informational?logo=Elixir\"></a>"))
(deftest "We can use spaces, commas, dashes, and percentage symbols in the first argument"
[badge]
(⇝ (⟰ "badge:example_with_spaces,_-,_and_%|points_right_here|orange")
"<a id=\"example_with_spaces,_-,_and_%\" href=\"#example_with_spaces,_-,_and_%\">"
"<img src=\"https://img.shields.io/badge/example_with_spaces%2C_--%2C_and_%25-points_right_here-orange?logo=nil\"></a>"))
(deftest "It works when only first 2 arguments are given: Default colour & logo are green & no logo shown"
[badge]
(⇝ (⟰ "badge:key|value")
"<img src=\"https://img.shields.io/badge/key-value-nil?logo=nil\">"))
(deftest "When only a key is provided, the value slot is shown as an empty green stub"
[badge]
(⇝ (⟰ "badge:key")
"<img src=\"https://img.shields.io/badge/key--nil?logo=nil\">"))
(deftest "When only a value is provided, only the value is shown in a default green ---no stub for the missing key, yay"
[badge]
(⇝ (⟰ "badge:|value")
"<img src=\"https://img.shields.io/badge/-value-nil?logo=nil\">"))
(deftest "It's only a green stub when provided with an empty key and empty value"
[badge]
(⇝ (⟰ "badge:||green")
"<img src=\"https://img.shields.io/badge/--green?logo=nil\">"))
(deftest "It's only a green stub when we use a totally [[badge:]]"
[badge]
(⇝ (⟰ "[[badge:]]")
"<img src=\"https://img.shields.io/badge/--nil?logo=nil\">"))
1. Example Badges
The general syntax is as follows, with only the first 2 are mandatory,
with the colour defaulting to green, and the url and logo both to nil.
We can thus have badge:label|message
-
⇐
<<key>> badge:key|value|informational||Elixir- Standard template; Org's own target beside it is a permalink to the current location, named
#key—click on it and look at your browser's URL ;-)
- Standard template; Org's own target beside it is a permalink to the current location, named
⇐
badge:example_with_spaces,_-,_and_%|points_right_here|orange⇐
badge:key|value.⇐
badge:empty_value||informational⇐
badge:|value⇐
badge:||green( No key; nor value! )Also:
⇐
[[badge:]].
General Syntax
badge:your_key|its_neato_value|some_url|a_logo_as_shown_below [[badge: your key | its neato value | some url | a logo as shown below]] reddit-subscribe-to:exact-name-of-a-subreddit github-stars:user-name/repository-name github-watchers:user-name/repository-name github-forks:user-name/repository-name github-followers:user-name tweet:url
For now, only badge: badges redirect to their URL, if any, upon a user's click.
Within Emacs, hovering over a badge displays a tooltip indicating which values
corresponds to which badge fields.
You can make your own badge types with
org-make-badgeMake a link NAME whose export is presented as an SVG badge.
If the link is intend to be a social badge, then, adhering to
shield.io conventions, the appropriate SOCIAL-SHIELDS-NAME must
be given.
The SOCIAL-URL is a URL that the badge points to and it should
have a single ‘%s’ where the link label argument will go.
Some social badges have a uniform URL, but otherwise, such as
twitter, deviate and so need their own SOCIAL-SHIELDS-URL,
which has a single ‘%s’ for the link’s label argument.
----------------------------------------------------------------------
E.g., to create a badge named “go”:
(org-make-badge "go")
Then the following exports nicely from an Org file:
go:key|value|blue||gnu-emacs
(fn NAME &optional SOCIAL-SHIELDS-NAME SOCIAL-URL SOCIAL-SHIELDS-URL).
org-make-badge
The implementation is a bit lengthy since it attempts to capture a useful portion of the shilelds.io badge interface.
(cl-defmacro org-make-badge
(name &optional social-shields-name social-url social-shields-url )
"Make a link NAME whose export is presented as an SVG badge.
If the link is intend to be a social badge, then, adhering to
shield.io conventions, the appropriate SOCIAL-SHIELDS-NAME must
be given.
The SOCIAL-URL is a URL that the badge points to and it should
have a single ‘%s’ where the link label argument will go.
Some social badges have a uniform URL, but otherwise, such as
twitter, deviate and so need their own SOCIAL-SHIELDS-URL,
which has a single ‘%s’ for the link's label argument.
----------------------------------------------------------------------
E.g., to create a badge named “go”:
(org-make-badge \"go\")
Then the following exports nicely from an Org file:
go:key|value|blue||gnu-emacs"
`(org-deflink ,(intern name) (label &optional _description backend)
"Export a Shields.io badge, with general Syntax: badge:key|value|colour|url|logo.
Precise details for each argument are shown in the Emacs tooltip for this badge."
[:display 'full
:follow (--> (s-split "|" path)
(or (nth 3 it) label)
(browse-url it))
:help-echo
(-let [ (key value color url logo) (mapcar #'s-trim (s-split "|" label)) ]
(lf-string "${label}
\nGeneral Syntax: badge:key|value|colour|url|logo
Key : ${key}
Value : ${(or value \"\")}
Colour : ${(or color \"green\")}
URL : ${(or url \"\")}
Logo : ${(or logo \"\")}
This results in an SVG badge “[key∣value]”, where the ‘key’
is coloured grey and the ‘value’ is coloured ‘color’;
for the HTML backend, and otherwise are silently omitted.
Descriptions are ignored; i.e., ‘[[badge:label][description]]’
is the same as ‘[[badge:label]]’.
► ‘key’ and ‘value’ have their underscores interpreted as spaces.
⇒ ‘__’ is interpreted as an underscore;
Of course, you can write ‘<badge: ⋯>’, then ‘⋯’ may have multiword, spaced, content.
⇒ ‘|’ is not a valid substring, but ‘-, %, ?’ are okay.
► ‘|color|url|logo’ are optional;
⇒ If ‘url’ is not present, the resulting badge is not a hyperlink.
⇒ if ‘url’ is ‘here’ then we have a local link;
i.e., the resulting badge behaves like <<key>>.
⇒ ‘color’ may be: ‘brightgreen’ or ‘success’,
‘red’ or ‘important’,
‘orange’ or ‘critical’,
‘lightgrey’ or ‘inactive’,
‘blue’ or ‘informational’,
or ‘green’, ‘yellowgreen’, ‘yellow’, ‘blueviolet’, ‘ff69b4’, etc.
Consult https://htmlcolorcodes.com/ to see the HEX codes of other colours.
⇒ ‘logo’ examples and how they look can be found at
https://alhassy.com/org-special-block-extras#Example-Badge-Icons
See also: https://alhassy.com/org-special-block-extras#Common-Project-Badges"))]
;; :export #'org--link--badge
(if (equal backend 'latex) ""
(-let [ (key value color url logo) (mapcar #'s-trim (s-split "|" label)) ]
(format
(pcase ,(if social-shields-name `(format ,social-url label) 'url)
("here" (format "<a id=\"%s\" href=\"#%s\">%%s</a>" (s-replace "%" "%%" key) (s-replace "%" "%%" key)))
("" "%s") ;; e.g., badge:key|value|color||logo
('nil "%s") ;; e.g., badge:key|value|color
(_ (format "<a href=\"%s\">%%s</a>"
(s-replace "%" "%%"
,(if social-shields-name
`(format ,social-url label)
'url)))))
,(if social-shields-name
(if social-shields-url
`(format ,social-shields-url label)
`(format "<img src=\"https://img.shields.io/%s/%s?style=social\">"
,social-shields-name label))
'(format "<img src=\"https://img.shields.io/badge/%s-%s-%s?logo=%s\">"
(url-hexify-string (s-replace "-" "--" key))
(url-hexify-string (s-replace "-" "--" (or value "")))
color
logo)))))))
Notice that we can have special %-HTML characters in URLs; e.g.,
<badge:my key|my value| my
colour|https://www.google.com/search?q=hello%20world|gnu-emacs>
⇒
.
Example: Derived Reddit/Github/Twitter social badges
For example, a super simple ‘badge’ link type
(org-make-badge "badge")
A more involved example.
;; Since we're invoking a macro, the twitter-excitement is used lazily; i.e.,
;; consulted when needed instead of being evaluated once.
(defvar org-link-twitter-excitement
"This looks super neat (•̀ᴗ•́)و:"
"The string prefixing the URL being shared.")
(org-make-badge
"tweet"
"twitter/url?=url="
(format
"https://twitter.com/intent/tweet?text=%s:&url=%%s"
org-link-twitter-excitement)
"<img src=\"https://img.shields.io/twitter/url?url=%s\">"
)
A few more in one, convoluted, go.
;; MA: I don't think this is ideal for long-term maintainability, see ‘:OLD’ below.
(cl-loop for (social url name)
in '(("reddit/subreddit-subscribers" "https://www.reddit.com/r/%s" "reddit")
("github" "https://www.github.com/%s")
("github/stars" "https://github.com/%s") ; Its Star button; /stars is no page
("github/watchers" "https://github.com/%s") ; Its Watch button; /watchers needs a login
("github/followers" "https://www.github.com/%s?tab=followers")
("github/forks" "https://www.github.com/%s/fork"))
for name′ = (or name (s-replace "/" "-" social))
do (eval `(org-make-badge ,name′ ,social ,url)))
Here are some examples.
2. Example Colours
﴾What You Write﴿
+ badge:|red|red badge:|critical|critical + badge:|blue|blue badge:|informational|informational + badge:|brightgreen|brightgreen badge:|success|success + badge:|orange|orange badge:|important|important + badge:|lightgrey|lightgrey badge:|inactive|inactive + badge:|green|green + badge:|yellowgreen|yellowgreen + badge:|yellow|yellow + badge:|blueviolet|blueviolet + badge:|ff69b4|ff69b4 + badge:|9cf|9cf + ... Consult https://htmlcolorcodes.com/ to see the HEX code of any other colour you wish to use; e.g., badge:|1d8348|1d8348
﴾What You Get﴿
- …
Consult https://htmlcolorcodes.com/ to see the HEX code of any other colour you
wish to use; e.g.,
3. Example Badge Icons
Here are a few free SVG icons for popular brands from https://simpleicons.org/.
To use any of the names below, just write, say,
badge:||grey||SVG-NAME-HERE.
- “Fire”
Elixir
tinder
codeigniter
prometheus
sparkpost
- “Messaging”
quip
WeChat
google-hangouts
hackhands
google-messages
Slack
- “Emacs”
gnu-emacs
spacemacs
vim
neovim
gnu
github
acm
wikipedia
microsoft-excel
microsoft-word
dropbox
google-scholar
google
google-translate
ghost
helm
apache-openoffice
buffer
adobe-fonts
google-calendar
- “Social”
google-cast
youtube
discord
facebook
google-hangouts
whatsapp
skype
reddit
stack-overflow
stack-exchange
linkedin
twitter
jabber
- “Lightbulb”
lighthouse
google-keep
minds
- “Programming”
git
ruby
scala
OCaml
javascript
gnu-bash
powershell
LaTeX
java
kotlin
haskell
coffeescript
purescript
rust
typescript
css3
python
c
clojure
lua
adobe-acrobat-reader
perl
- “Miscellaneous”
read-the-docs
buy-me-a-coffee
gimp
mega
nintendo-3ds
paypal
pinboard
mocha
Gitea
instacart
openStreetMap
amazon
svg
rss
swagger
pastebin
skyliner
iTunes
gulp
leaflet
youtube-gaming
GIMP
atom
4. Common Project Badges —with copyable source
src
badge:Emacs|23/26/28|green|https://www.gnu.org/software/emacs|gnu-emacssrc
badge:Org|9.3.6|blue|https://orgmode.org|gnusrc
[[badge:org-special-block-extras|1.0|informational|https://alhassy.com/org-special-block-extras|Gnu-Emacs][org-special-block-extras badge]]src
[[badge:melpa|pending|critical|https://github.com/alhassy/emacs.d#use-package-the-start-of-initel|github][melpa badge]]src
[[badge:docs|literate|success|https://github.com/alhassy/emacs.d#what-does-literate-programming-look-like|read-the-docs][read-the-docs badge]]src
badge:wiki|github|informational||wikipediasrc
badge:code_coverage|88%|green||codecovsrc
badge:build|passing|success||azure-pipelinessrc
badge:author|musa_al-hassy|purple|https://alhassy.github.io/|nintendo-3dssrc
badge:author|musa_al-hassy|purple|https://alhassy.github.io/|gimpsrc
[[badge:license|GNU_3|informational|https://www.gnu.org/licenses/gpl-3.0.en.html|read-the-docs][gnu 3 license badge]]src
badge:issue_tracking|github|informational||githubsrc
badge:help_forum|discourse|informational||discoursesrc
badge:social_chat|gitter|informational|https://gitter.im/explore|gittersrc
badge:Maintained?|yes|successsrc
badge:Maintained?|no|criticalsrc
badge:No_Maintenance_Intended|×|critical|http://unmaintained.tech/src
badge:website|up|successsrc
badge:website|down|criticalsrc
badge:Ask_me|anything|1abc9csrc
badge:contributions|welcome|green|https://github.com/alhassy/org-special-block-extras/issuessrc
badge:Made_with|Python,_LaTeX,_MathJax,_and_Emacs_Org-mode|1f425
5. Next Steps
Going forward, it would be desirable to provide non-whitespace alternatives for the LaTeX backend.
[Author: That is why no examples are shown in the PDF ]
It may be useful to colour the|-separated fields of a badge link.
Life & Computing Science by Musa Al-hassy is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License