packages feed

shortcut-links 0.1.0.0 → 0.2.0.0

raw patch · 3 files changed

+981/−693 lines, 3 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

CHANGELOG.md view
@@ -1,3 +1,11 @@+# 0.2.0.0++* Descriptions of shortcuts look much better now.+* “sublime” was renamed to “sublimepc”, since it's possible that some other package manager for Sublime Text would emerge in the future.+* Shortcut “tvt” for TV Tropes was removed – it's just “tvtropes” now.+* “facebook” can link to profiles by their ID.+* “tvtropes” properly capitalises names of categories (if given as an option) – previously you needed to write e.g. “SugarWiki”, now “sugar wiki” works too.+ # 0.1.0.0  First release.
shortcut-links.cabal view
@@ -1,9 +1,9 @@ name:                shortcut-links-version:             0.1.0.0+version:             0.2.0.0 synopsis:            Link shortcuts for use in text markup description:   This package is a database of link shortcuts. A Markdown example: -  @[Google](\@w)@ turns into <http://en.wikipedia.org/wiki/Google Google>.+  @\[Google\](\@w)@ turns into <http://en.wikipedia.org/wiki/Google Google>. homepage:            http://github.com/aelve/shortcut-links bug-reports:         http://github.com/aelve/shortcut-links/issues license:             BSD3
src/ShortcutLinks/All.hs view
@@ -90,697 +90,977 @@  type Shortcut = Maybe Text -> Text -> Result Text --- | A list of all functions included in this module, together with suggested--- names for them.-allShortcuts :: [([Text], Shortcut)]-allShortcuts =-  let (.=) names func = (T.words names, func)-  in [-  -- encyclopedias-  "w wikipedia"             .= wikipedia,-  "tvt tvtropes"            .= tvtropes,-  -- social networks-  "fb facebook"             .= facebook,-  "vk vkontakte"            .= vk,-  "gp gplus googleplus"     .= googleplus,-  -- microblogs-  "t twitter"               .= twitter,-  "juick"                   .= juick,-  -- search engines-  "google"                  .= google,-  "ddg duckduckgo"          .= duckduckgo,-  "yandex"                  .= yandex,-  "baidu"                   .= baidu,-  -- programming language libraries-  "npm"                     .= npm,-  "jam"                     .= jam,-  "gem"                     .= rubygems,-  "pypi"                    .= pypi,-  "cpan"                    .= metacpanPod,-  "cpan-r"                  .= metacpanRelease,-  "hackage"                 .= hackage,-  "cargo"                   .= cargo,-  "pub"                     .= pub,-  "hex"                     .= hex,-  "cran"                    .= cran,-  "swiprolog"               .= swiprolog,-  "dub"                     .= dub,-  "bpkg"                    .= bpkg,-  "pear"                    .= pear,-  -- code hosting-  "gh github"               .= github,-  "gitlab"                  .= gitlab,-  "bitbucket"               .= bitbucket,-  -- OS-  "gplay googleplay"        .= googleplay,-  "chocolatey"              .= chocolatey,-  "brew"                    .= braumeister,-  -- OS – Linux-  "debian"                  .= debian,-  "aur"                     .= aur,-  "mint"                    .= mint,-  "fedora"                  .= fedora,-  "gentoo"                  .= gentoo,-  "opensuse"                .= opensuse,-  -- text editors-  "marmalade"               .= marmalade,-  "melpa"                   .= melpa,-  "elpa"                    .= elpa,-  "sublime"                 .= packagecontrol,-  "atom"                    .= atomPackage,-  "atom-theme"              .= atomTheme,-  "jedit"                   .= jedit,-  "vim"                     .= vim,-  -- browsers-  "opera"                   .= operaExt,-  "opera-theme"             .= operaTheme,-  "firefox"                 .= firefox,-  "chrome"                  .= chrome,-  -- manuals-  "ghc-ext"                 .= ghcExt,-  -- standards and databases-  "rfc"                     .= rfc,-  "ecma"                    .= ecma,-  "cve"                     .= cve ]---- | <https://facebook.com Facebook>------ Link example:--- @[green](\@fb)@ →--- <https://facebook.com/green>-facebook :: Shortcut-facebook _ q = return $ "https://facebook.com/" <> q---- | <https://vk.com Vkontakte> (Вконтакте)------ Link example (username):--- @[green](\@vk)@ →--- <https://vk.com/green>------ Link example (ID):------ @[1337](\@vk)@ →--- <https://vk.com/id1337>-vk :: Shortcut-vk _ q = return $ "https://vk.com/" <> q'-  where q' = if not (T.null q) && isDigit (T.head q) then "id" <> q else q---- | <https://plus.google.com Google+>------ Link example (username):--- @[SergeyBrin](\@gp)@ →--- <https://plus.google.com/+SergeyBrin SergeyBrin>--- --- Link example (username with @+@):--- @[+SergeyBrin](\@gp)@ →--- <https://plus.google.com/+SergeyBrin +SergeyBrin>------ Link example (full name – will just be concatenated):--- @[Sergey Brin](\@gp)@ →--- <https://plus.google.com/+SergeyBrin Sergey Brin>------ Link example (ID):--- @[Sergey Brin](\@gp:109813896768294978296)@ →--- <https://plus.google.com/109813896768294978296 Sergey Brin>------ Link example (hashtag):--- @[#Australia](\@gp)@ →--- <https://plus.google.com/explore/Australia #Australia>-googleplus :: Shortcut-googleplus _ q-  | T.null q        = return $ url-  | T.head q == '#' = return $ format "{}/explore/{}" url (T.tail q)-  | T.head q == '+' = return $ format "{}/{}" url q-  | T.all isDigit q = return $ format "{}/{}" url q-  | otherwise       = return $ format "{}/+{}" url (T.concat (T.words q))-  where url = "https://plus.google.com"---- | <https://twitter.com Twitter>------ Link example (username):--- @[kmett](\@t)@ →--- <https://twitter.com/kmett kmett>--- --- Link example (username with @\@@):--- @[\@kmett](\@t)@ →--- <https://twitter.com/kmett \@kmett>------ Link example (hashtag):--- @[#haskell](\@t)@ →--- <https://twitter.com/hashtag/haskell #haskell>-twitter :: Shortcut-twitter _ q-  | T.null q        = return $ url-  | T.head q == '#' = return $ format "{}/hashtag/{}" url (T.tail q)-  | T.head q == '@' = return $ format "{}/{}" url (T.tail q)-  | otherwise       = return $ format "{}/{}" url q-  where url = "https://twitter.com"---- | <https://juick.com Juick>------ Link example (username):--- @[thefish](\@juick)@ →--- <https://juick.com/thefish/ thefish>--- --- Link example (username with @\@@):--- @[\@thefish](\@juick)@ →--- <https://juick.com/thefish/ \@thefish>------ Link example (tag):--- @[*Haskell](\@juick)@ →--- <https://juick.com/tag/Haskell *Haskell>-juick :: Shortcut-juick _ q-  | T.null q        = return $ url-  | T.head q == '*' = return $ format "{}/tag/{}" url (T.tail q)-  | T.head q == '@' = return $ format "{}/{}" url (T.tail q)-  | otherwise       = return $ format "{}/{}" url q-  where url = "https://juick.com"---- | <https://google.com Google>------ Link example:--- @[random query](\@google)@ →--- <https://www.google.com/search?nfpr=1&q=random+query random query>-google :: Shortcut-google _ q = return $-  "https://google.com/search?nfpr=1&q=" <> replaceSpaces '+' q---- | <https://duckduckgo.com Duckduckgo>------ Link example:--- @[random query](\@ddg)@ →--- <https://duckduckgo.com/?q=random+query random query>-duckduckgo :: Shortcut-duckduckgo _ q = return $ "https://duckduckgo.com/?q=" <> replaceSpaces '+' q---- | <http://yandex.ru Yandex> (Russian search engine)------ Link example:--- @[random query](\@yandex)@ →--- <http://yandex.ru/search/?noreask=1&text=random+query random query>-yandex :: Shortcut-yandex _ q = return $-  "http://yandex.ru/search/?noreask=1&text=" <> replaceSpaces '+' q---- | <http://baidu.com Baidu> (Chinese search engine)------ Link example:--- @[random query](\@baidu)@ →--- <http://baidu.com/s?nojc=1&wd=random+query random query>-baidu :: Shortcut-baidu _ q = return $ "http://baidu.com/s?nojc=1&wd=" <> replaceSpaces '+' q---- | __Node.js__ – <https://npmjs.com NPM>------ Link example:--- @[markdown](\@npm)@ →--- <https://www.npmjs.com/package/markdown markdown>-npm :: Shortcut-npm _ q = return $ "https://npmjs.com/package/" <> q---- | __Javascript__ – <http://jamjs.org/packages/#/ Jam>------ Link example:--- @[pagedown](\@jam)@ →--- <http://jamjs.org/packages/#/details/pagedown pagedown>-jam :: Shortcut-jam _ q = return $ "http://jamjs.org/packages/#/details/" <> q---- | __Ruby__ – <https://rubygems.org RubyGems.org>------ Link example:--- @[github-markdown](\@gem)@ →--- <https://rubygems.org/gems/github-markdown github-markdown>-rubygems :: Shortcut-rubygems _ q = return $ "https://rubygems.org/gems/" <> q---- | __Python__ – <https://pypi.python.org/pypi PyPI>------ Link example:--- @[Markdown](\@pypi)@ →--- <https://pypi.python.org/pypi/Markdown Markdown>-pypi :: Shortcut-pypi _ q = return $ "https://pypi.python.org/pypi/" <> q---- | __Perl__ – <https://metacpan.org MetaCPAN> (by module)------ Link example:--- @[Text::Markdown](\@cpan)@ →--- <https://metacpan.org/pod/Text::Markdown Text::Markdown>-metacpanPod :: Shortcut-metacpanPod _ q = return $ "https://metacpan.org/pod/" <> q---- | __Perl__ – <https://metacpan.org MetaCPAN> (by release)------ Link example:--- @[Text-Markdown](\@cpan-r)@ →--- <https://metacpan.org/release/Text-Markdown Text-Markdown>-metacpanRelease :: Shortcut-metacpanRelease _ q = return $ "https://metacpan.org/release/" <> q---- | __Haskell__ – <https://hackage.haskell.org Hackage>------ Link example:--- @[cmark](\@hackage)@ →--- <https://hackage.haskell.org/package/cmark cmark>-hackage :: Shortcut-hackage _ q = return $ "https://hackage.haskell.org/package/" <> q---- | __Rust__ – <https://crates.io Cargo>------ Link example:--- @[hoedown](\@cargo)@ →--- <https://crates.io/crates/hoedown hoedown>-cargo :: Shortcut-cargo _ q = return $ "https://crates.io/crates/" <> q---- | __PHP__ – <http://pear.php.net PEAR>------ Link example:--- @[Text_Wiki_Doku](\@pear)@ →--- <http://pear.php.net/package/Text_Wiki_Doku Text_Wiki_Doku>-pear :: Shortcut-pear _ q = return $ "http://pear.php.net/package/" <> q---- | __Dart__ – <https://pub.dartlang.org pub>------ Link example:--- @[md_proc](\@pub)@ →--- <https://pub.dartlang.org/packages/md_proc md_proc>-pub :: Shortcut-pub _ q = return $ "https://pub.dartlang.org/packages/" <> q---- | __R__ – <http://cran.r-project.org/web/packages/ CRAN>------ Link example:--- @[markdown](\@cran)@ →--- <http://cran.r-project.org/web/packages/markdown markdown>-cran :: Shortcut-cran _ q = return $ "http://cran.r-project.org/web/packages/" <> q---- | __Erlang__ – <https://hex.pm Hex>------ Link example:--- @[earmark](\@hex)@ →--- <https://hex.pm/packages/earmark earmark>-hex :: Shortcut-hex _ q = return $ "https://hex.pm/packages/" <> q---- | __SWI-Prolog__ – <http://www.swi-prolog.org/pack/list packages>------ Link example:--- @[markdown](\@swiprolog)@ →--- <http://www.swi-prolog.org/pack/list?p=markdown markdown>-swiprolog :: Shortcut-swiprolog _ q = return $ "http://www.swi-prolog.org/pack/list?p=" <> q---- | __D__ – <http://code.dlang.org DUB>------ Link example:--- @[dmarkdown](\@dub)@ →--- <http://code.dlang.org/packages/dmarkdown dmarkdown>-dub :: Shortcut-dub _ q = return $ "http://code.dlang.org/packages/" <> q---- | __Bash__ – <http://bpkg.io bpkg>------ Link example:--- @[markdown](\@bpkg)@ →--- <http://www.bpkg.io/pkg/markdown markdown>-bpkg :: Shortcut-bpkg _ q = return $ "http://bpkg.io/pkg/" <> q---- | <https://github.com Github>------ Link example:--- @[aelve/shortcut-links](\@gh)@ →--- <https://github.com/aelve/shortcut-links aelve/shortcut-links>------ The repository owner can also be given as an option:------ @[shortcut-links](\@gh(aelve))@ →--- <https://github.com/aelve/shortcut-links shortcut-links>-github :: Shortcut-github mbOwner q = case mbOwner of-  Nothing    -> return $ format "https://github.com/{}" q-  Just owner -> return $ format "https://github.com/{}/{}" owner q---- | <https://bitbucket.org Bitbucket>------ Link example:--- @[bos/text](\@bitbucket)@ →--- <https://bitbucket.org/bos/text bos/text>------ The repository owner can also be given as an option:------ @[text](\@bitbucket(bos))@ →--- <https://bitbucket.org/bos/text text>-bitbucket :: Shortcut-bitbucket mbOwner q = case mbOwner of-  Nothing    -> return $ format "https://bitbucket.org/{}" q-  Just owner -> return $ format "https://bitbucket.org/{}/{}" owner q---- | <https://gitlab.com Gitlab>------ Link example:--- @[learnyou/lysa](\@gitlab)@ →--- <https://gitlab.com/learnyou/lysa learnyou/lysa>------ The repository owner can also be given as an option:------ @[lysa](\@gitlab(learnyou))@ →--- <https://gitlab.com/learnyou/lysa lysa>------ Note that links like <https://gitlab.com/owner> work but are going to be--- automatically redirected to either <https://gitlab.com/u/owner> or--- <https://gitlab.com/groups/owner>, depending on whether it's a user or a--- team. So, it's a case when the “links have to look as authentic as--- possible” principle is violated (but c'mon, this “u” thing looks ugly--- anyway).-gitlab :: Shortcut-gitlab mbOwner q = case mbOwner of-  Nothing    -> return $ format "https://gitlab.com/{}" q-  Just owner -> return $ format "https://gitlab.com/{}/{}" owner q---- | __Android__ – <https://play.google.com Google Play> (formerly Play Market)------ Link example:--- @[Opera Mini](\@gplay:com.opera.mini.native)@ →--- <https://play.google.com/store/apps/details?id=com.opera.mini.native Opera Mini>-googleplay :: Shortcut-googleplay _ q = return $ "https://play.google.com/store/apps/details?id=" <> q---- | <http://braumeister.org Braumeister> (Homebrew formulas)------ Link example:--- @[multimarkdown](\@brew)@ →--- <http://braumeister.org/formula/multimarkdown multimarkdown>-braumeister :: Shortcut-braumeister _ q = return $ "http://braumeister.org/formula/" <> q---- | <https://chocolatey.org Chocolatey>------ Link example:--- @[Opera](\@chocolatey)@ →--- <https://chocolatey.org/packages/Opera Opera>-chocolatey :: Shortcut-chocolatey _ q = return $ "https://chocolatey.org/packages/" <> q---- | __Debian__ – <https://debian.org/distrib/packages packages>------ Link example (stable distribution):--- @[ghc](\@debian)@ →--- <https://packages.debian.org/stable/ghc ghc>--- --- Link example (experimental distribution, but could be any other):--- @[ghc](\@debian(experimental))@ →--- <https://packages.debian.org/experimental/ghc ghc>-debian :: Shortcut-debian mbDist q = return $ format "https://packages.debian.org/{}/{}" dist q-  where-    dist = fromMaybe "stable" mbDist---- | __Arch Linux__ – <https://aur.archlinux.org AUR> (“user repository”)------ Link example:--- @[ghc-git](\@aur)@ →--- <https://aur.archlinux.org/packages/ghc-git ghc-git>-aur :: Shortcut-aur _ q = return $ "https://aur.archlinux.org/packages/" <> q---- | __Gentoo__ – <https://packages.gentoo.org packages>------ Link example:--- @[dev-lang/ghc](\@gentoo)@ →--- <https://packages.gentoo.org/package/dev-lang/ghc dev-lang/ghc>--- --- Link example (category as an option):--- @[ghc](\@gentoo(dev-lang))@ →--- <https://packages.gentoo.org/package/dev-lang/ghc ghc>------ Note that if you don't specify any category, the link would still work –--- but there are a lot of packages with overlapping names (like “ace”, “csv”,--- “http”), and such links would lead to search pages listing several--- packages. So, it's better to include categories.-gentoo :: Shortcut-gentoo mbCat q = return $ "https://packages.gentoo.org/package/" <> pkg-  where-    pkg = case mbCat of-      Nothing  -> q-      Just cat -> cat <> "/" <> q---- | __openSUSE__ – <http://software.opensuse.org packages>------ Link example:--- @[ghc](\@opensuse)@ →--- <http://software.opensuse.org/package/ghc ghc>-opensuse :: Shortcut-opensuse _ q = return $ "http://software.opensuse.org/package/" <> q---- | __Linux Mint__ – <http://community.linuxmint.com/software/browse packages>------ Link example:--- @[ghc](\@mint)@ →--- <http://community.linuxmint.com/software/view/ghc ghc>-mint :: Shortcut-mint _ q = return $ "http://community.linuxmint.com/software/view/" <> q---- | __Fedora__ – <https://admin.fedoraproject.org/pkgdb packages>------ Link example:--- @[ghc](\@fedora)@ →--- <https://admin.fedoraproject.org/pkgdb/package/ghc ghc>-fedora :: Shortcut-fedora _ q = return $ "https://admin.fedoraproject.org/pkgdb/package/" <> q---- | __Emacs__ – <https://marmalade-repo.org Marmalade>------ Link example:--- @[markdown-mode](\@marmalade)@ →--- <https://marmalade-repo.org/packages/markdown-mode markdown-mode>-marmalade :: Shortcut-marmalade _ q = return $ "https://marmalade-repo.org/packages/" <> q---- | __Emacs__ – <http://melpa.org MELPA>------ Link example:--- @[markdown-mode](\@melpa)@ →--- <http://melpa.org/#/markdown-mode markdown-mode>-melpa :: Shortcut-melpa _ q = return $ "http://melpa.org/#/" <> q---- | __Emacs__ – <https://elpa.gnu.org ELPA>------ Link example:--- @[undo-tree](\@elpa)@ →--- <https://elpa.gnu.org/packages/undo-tree.html undo-tree>-elpa :: Shortcut-elpa _ q = return $ format "https://elpa.gnu.org/packages/{}.html" q---- | __Sublime Text__ – <https://packagecontrol.io Package Control>------ Link example:--- @[MarkdownEditing](\@sublime)@ →--- <https://packagecontrol.io/packages/MarkdownEditing MarkdownEditing>-packagecontrol :: Shortcut-packagecontrol _ q = return $ "https://packagecontrol.io/packages/" <> q---- | __Atom__ – <https://atom.io/packages packages>------ Link example:--- @[tidy-markdown](\@atom)@ →--- <https://atom.io/packages/tidy-markdown tidy-markdown>-atomPackage :: Shortcut-atomPackage _ q = return $ "https://atom.io/packages/" <> q---- | __Atom__ – <https://atom.io/themes themes>------ Link example:--- @[atom-material-ui](\@atom-theme)@ →--- <https://atom.io/themes/atom-material-ui atom-material-ui>-atomTheme :: Shortcut-atomTheme _ q = return $ "https://atom.io/themes/" <> q---- | __jEdit__ – <http://plugins.jedit.org packages>------ Link example:--- @[MarkdownPlugin](\@jedit)@ →--- <http://plugins.jedit.org/plugins/?MarkdownPlugin MarkdownPlugin>-jedit :: Shortcut-jedit _ q = return $ "http://plugins.jedit.org/plugins/?" <> q---- | __Vim__ – <http://www.vim.org/scripts/ scripts>------ Link example (ID):--- @[haskell.vim](\@vim:2062)@ →--- <http://www.vim.org/scripts/script.php?script_id=2062 haskell.vim>-vim :: Shortcut-vim _ q = return $ "http://www.vim.org/scripts/script.php?script_id=" <> q---- | __Opera__ – <https://addons.opera.com/extensions/ extensions>------ Link example:--- @[Amazon](\@opera:amazon-for-opera)@ →--- <https://addons.opera.com/extensions/details/amazon-for-opera Amazon>-operaExt :: Shortcut-operaExt _ q = return $ "https://addons.opera.com/extensions/details/" <> q---- | __Opera__ – <https://addons.opera.com/themes/ themes>------ Link example:--- @[Space theme](\@opera-theme:space-15)@ →--- <https://addons.opera.com/en/themes/details/space-15 Space theme>-operaTheme :: Shortcut-operaTheme _ q = return $ "https://addons.opera.com/themes/details/" <> q---- | __Firefox__ – <https://addons.mozilla.org/firefox Add-ons> (extensions, themes)------ Link example:--- @[tree-style-tab]@ →--- <https://addons.mozilla.org/firefox/addon/tree-style-tab Tree Style Tab>-firefox :: Shortcut-firefox _ q = return $ "https://addons.mozilla.org/firefox/addon/" <> q---- | __Chrome__ – <https://chrome.google.com/webstore Chrome Web Store> (extensions, apps, themes)------ Link example:--- @[hdokiejnpimakedhajhdlcegeplioahd]@ →--- <https://chrome.google.com/webstore/detail/hdokiejnpimakedhajhdlcegeplioahd LastPass>-chrome :: Shortcut-chrome _ q = return $ "https://chrome.google.com/webstore/detail/" <> q---- | <https://www.haskell.org/ghc/ GHC> (Glasgow Haskell Compiler) extensions------ Link example:--- @[ViewPatterns](\@ghc-ext)@ →--- <https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/syntax-extns.html#view-patterns ViewPatterns>-ghcExt :: Shortcut-ghcExt _ ext = case lookup ext ghcExtsList of-  Nothing   -> fail (format "unknown GHC extension '{}'" ext)-  Just link -> return link---- | <https://www.ietf.org/rfc.html RFCs>------ Link example:--- @[RFC 2026](\@rfc)@ →--- <https://tools.ietf.org/html/rfc2026 RFC 2026>------ Precise format of recognised text: optional “rfc” (case-insensitive), then--- arbitrary amount of spaces and punctuation (or nothing), then the--- number. Examples: “RFC 2026”, “RFC-2026”, “rfc2026”, “rfc #2026”, “2026”,--- “#2026”.-rfc :: Shortcut-rfc _ x = do-  let n = T.dropWhile (not . isAlphaNum) (tryStripPrefixCI "rfc" x)-  -- We don't use 'readMaybe' here because 'readMaybe' isn't available in GHC-  -- 7.4, which Pandoc has to be compatible with.-  unless (T.all isDigit n) $-    warn "non-digits in RFC number"-  when (T.null n) $-    warn "no RFC number"-  let n' = T.dropWhile (== '0') n `orElse` "0"-  return ("https://tools.ietf.org/html/rfc" <> n')---- | <http://ecma-international.org/publications/index.html Ecma standards and technical reports>------ Link example (standard):--- @[ECMA-262](\@ecma)@ →--- <http://www.ecma-international.org/publications/standards/Ecma-262.htm ECMA-262>------ Link example (technical report):--- @[TR/71](\@ecma)@ →--- <http://ecma-international.org/publications/techreports/E-TR-071.htm TR/71>------ Precise format of recognised text for standards: optional “ECMA”--- (case-insensitive), then arbitrary amount of spaces and punctuation (or--- nothing), then the number. Examples: “ECMA-262”, “ECMA 262”, “ecma262”,--- “ECMA #262”, “262”, “#262”.------ Format for technical reports is the same, except that “TR” (instead of--- “ECMA”) is not optional (so, if there's only a number given, it's--- considered a standard and not a technical report).-ecma :: Shortcut-ecma _ q = do-  -- TODO: move dropSeparators to Utils and use it in 'rfc' and 'cve'-  let dropSeparators = T.dropWhile (not . isAlphaNum)-  let (dropSeparators -> mbNum, isTR) = case stripPrefixCI "tr" q of-        Nothing -> (tryStripPrefixCI "ecma" q, False)-        Just q' -> (q', True)-  -- We don't use 'readMaybe' here because 'readMaybe' isn't available in GHC-  -- 7.4, which Pandoc has to be compatible with.-  unless (T.all isDigit mbNum) $-    warn "non-digits in ECMA standard number"-  when (T.null mbNum) $-    warn "no ECMA standard number"-  -- The number has to have at least 3 digits.-  let num = T.justifyRight 3 '0' mbNum-      url = "http://ecma-international.org/publications" :: Text-  return $ if isTR-    then format "{}/techreports/E-TR-{}.htm" url num-    else format "{}/standards/Ecma-{}.htm" url num---- | <http://cve.mitre.org CVEs> (Common Vulnerabilities and Exposures)------ Link example:--- @[CVE-2014-10001](\@cve)@ →--- <http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-10001>------ Precise format of recognised text: optional “cve” (case-insensitive), then--- arbitrary amount of spaces and punctuation (or nothing), then the year,--- ‘-’, and a number. Examples: “CVE-2014-10001”, “cve 2014-10001”,--- “2014-10001”.-cve :: Shortcut-cve _ x = do-  let n = T.dropWhile (not . isAlphaNum) (tryStripPrefixCI "cve" x)-  unless (T.length n >= 9) $-    warn "CVE-ID is too short"-  let isValid = and [-        T.length n >= 9,-        T.all isDigit (T.take 4 n),-        T.index n 4 == '-',-        T.all isDigit (T.drop 5 n) ]-  unless isValid $-    warn "CVE-ID doesn't follow the <year>-<digits> format"-  return ("http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-" <> n)---- | <https://wikipedia.org/ Wikipedia>------ Link example (English Wikipedia):--- @[grey-headed flying fox](\@w)@ →--- <https://en.wikipedia.org/wiki/Grey-headed_flying_fox>--- --- Link example (Russian Wikipedia, but any language code can be used):--- @[Haskell](\@w(ru))@ →--- <https://ru.wikipedia.org/wiki/Haskell>-wikipedia :: Shortcut-wikipedia mbLang q = return $-  format "https://{}.wikipedia.org/wiki/{}" lang q'-  where-    lang = fromMaybe "en" mbLang-    q'   = titleFirst (replaceSpaces '_' q)---- | <http://tvtropes.org TV Tropes>------ Link example (trope):--- @[so bad, it's good](\@tvtropes)@ →--- <http://tvtropes.org/pmwiki/pmwiki.php/Main/SoBadItsGood>------ Link example (series):--- @[Elementary](\@tvtropes(series))@ →--- <http://tvtropes.org/pmwiki/pmwiki.php/Series/Elementary>------ You can give anything as a category instead of “series”, it'll be--- capitalised but nothing else.-tvtropes :: Shortcut-tvtropes mbCat q = return $-  format "http://tvtropes.org/pmwiki/pmwiki.php/{}/{}" cat q'-  where-    cat = maybe "Main" titleFirst mbCat-    isSep c = (isSpace c || isPunctuation c) && c /= '\''-    -- Break into words, transform each word like “it's” → “Its”, and concat.-    -- Note that e.g. “man-made” is considered 2 separate words.-    q' = T.concat $ map (titleFirst . T.filter isAlphaNum) (T.split isSep q)+{- |+A list of all functions included in this module, together with suggested names for them.+-}+allShortcuts :: [([Text], Shortcut)]+allShortcuts =+  let (.=) names func = (T.words names, func)+  in [+  -- encyclopedias+  "w wikipedia"             .= wikipedia,+  "tvtropes"                .= tvtropes,+  -- social networks+  "fb facebook"             .= facebook,+  "vk vkontakte"            .= vk,+  "gp gplus googleplus"     .= googleplus,+  -- microblogs+  "t twitter"               .= twitter,+  "juick"                   .= juick,+  -- search engines+  "google"                  .= google,+  "ddg duckduckgo"          .= duckduckgo,+  "yandex"                  .= yandex,+  "baidu"                   .= baidu,+  -- programming language libraries+  "npm"                     .= npm,+  "jam"                     .= jam,+  "gem"                     .= rubygems,+  "pypi"                    .= pypi,+  "cpan"                    .= metacpanPod,+  "cpan-r"                  .= metacpanRelease,+  "hackage"                 .= hackage,+  "cargo"                   .= cargo,+  "pub"                     .= pub,+  "hex"                     .= hex,+  "cran"                    .= cran,+  "swiprolog"               .= swiprolog,+  "dub"                     .= dub,+  "bpkg"                    .= bpkg,+  "pear"                    .= pear,+  -- code hosting+  "gh github"               .= github,+  "gitlab"                  .= gitlab,+  "bitbucket"               .= bitbucket,+  -- OS+  "gplay googleplay"        .= googleplay,+  "chocolatey"              .= chocolatey,+  "brew"                    .= braumeister,+  -- OS – Linux+  "debian"                  .= debian,+  "aur"                     .= aur,+  "mint"                    .= mint,+  "fedora"                  .= fedora,+  "gentoo"                  .= gentoo,+  "opensuse"                .= opensuse,+  -- text editors+  "marmalade"               .= marmalade,+  "melpa"                   .= melpa,+  "elpa"                    .= elpa,+  "sublimepc"               .= packagecontrol,+  "atom"                    .= atomPackage,+  "atom-theme"              .= atomTheme,+  "jedit"                   .= jedit,+  "vim"                     .= vim,+  -- browsers+  "opera"                   .= operaExt,+  "opera-theme"             .= operaTheme,+  "firefox"                 .= firefox,+  "chrome"                  .= chrome,+  -- manuals+  "ghc-ext"                 .= ghcExt,+  -- standards and databases+  "rfc"                     .= rfc,+  "ecma"                    .= ecma,+  "cve"                     .= cve ]++{- | <https://facebook.com Facebook>++Link by username:++@+\[green\](\@fb)+<https://facebook.com/green>+@++Or by profile ID (are there still people without usernames, actually?):++@+\[someone something\](\@fb:164680686880529)+<https://facebook.com/profile.php?id=164680686880529>+@+-}+facebook :: Shortcut+facebook _ q+  | T.all isDigit q = return $ "https://facebook.com/profile.php?id=" <> q+  | otherwise       = return $ "https://facebook.com/" <> q++{- | <https://vk.com Vkontakte> (Вконтакте)++Link by username:++@+\[green\](\@vk)+<https://vk.com/green>+@++Or by ID:++@+\[Durov\](\@vk:1)+<https://vk.com/id1>+@+-}+vk :: Shortcut+vk _ q+  | T.all isDigit q = return $ "https://vk.com/id" <> q+  | otherwise       = return $ "https://vk.com/" <> q++{- | <https://plus.google.com Google+>++Link by username:++@+\[SergeyBrin\](\@gp)+<https://plus.google.com/+SergeyBrin>+@++It's alright if the username already starts with a “+”:++@+\[+SergeyBrin\](\@gp)+<https://plus.google.com/+SergeyBrin>+@++Since many usernames are just “your full name without spaces”, in many cases you can give a name and it's easy to make a username from it:++@+\[Sergey Brin\](\@gp)+<https://plus.google.com/+SergeyBrin>+@++You can also link by ID:++@+\[Sergey Brin\](\@gp:109813896768294978296)+<https://plus.google.com/109813896768294978296>+@++Finally, there are different links for hashtags:++@+\[#Australia\](\@gp)+<https://plus.google.com/explore/Australia>+@+-}+googleplus :: Shortcut+googleplus _ q+  | T.null q        = return $ url+  | T.head q == '#' = return $ format "{}/explore/{}" url (T.tail q)+  | T.head q == '+' = return $ format "{}/{}" url q+  | T.all isDigit q = return $ format "{}/{}" url q+  | otherwise       = return $ format "{}/+{}" url (T.concat (T.words q))+  where url = "https://plus.google.com"++{- | <https://twitter.com Twitter>++Link by username:++@+\[Edward Kmett\](\@t:kmett)+<https://twitter.com/kmett>+@++It's alright if the username already starts with a “\@”:++@+\[\@kmett\](\@t)+<https://twitter.com/kmett>+@++There are different links for hashtags:++@+\[#haskell\](\@t)+<https://twitter.com/hashtag/haskell>+@+-}+twitter :: Shortcut+twitter _ q+  | T.null q        = return $ url+  | T.head q == '#' = return $ format "{}/hashtag/{}" url (T.tail q)+  | T.head q == '@' = return $ format "{}/{}" url (T.tail q)+  | otherwise       = return $ format "{}/{}" url q+  where url = "https://twitter.com"++{- | <https://juick.com Juick>++Link by username:++@+\[thefish\](\@juick)+<https://juick.com/thefish>+@++It's alright if the username already starts with a “\@”:++@+\[\@thefish\](\@juick)+<https://juick.com/thefish>+@++There are different links for tags (which start with “\*” and not with “#”, by the way):++@+\[*Haskell\](\@juick)+<https://juick.com/tag/Haskell>+@+-}+juick :: Shortcut+juick _ q+  | T.null q        = return $ url+  | T.head q == '*' = return $ format "{}/tag/{}" url (T.tail q)+  | T.head q == '@' = return $ format "{}/{}" url (T.tail q)+  | otherwise       = return $ format "{}/{}" url q+  where url = "https://juick.com"++{- | <https://google.com Google>++Search results:++@+\[random query\](\@google)+<https://www.google.com/search?nfpr=1&q=random+query>+@+-}+google :: Shortcut+google _ q = return $+  "https://google.com/search?nfpr=1&q=" <> replaceSpaces '+' q++{- | <https://duckduckgo.com Duckduckgo>++Search results:++@+\[random query\](\@ddg)+<https://duckduckgo.com/?q=random+query>+@+-}+duckduckgo :: Shortcut+duckduckgo _ q = return $ "https://duckduckgo.com/?q=" <> replaceSpaces '+' q++{- | <http://yandex.ru Yandex> (Russian search engine)++Search results:++@+\[random query\](\@yandex)+<http://yandex.ru/search/?noreask=1&text=random+query>+@+-}+yandex :: Shortcut+yandex _ q = return $+  "http://yandex.ru/search/?noreask=1&text=" <> replaceSpaces '+' q++{- | <http://baidu.com Baidu> (Chinese search engine)++Search results:++@+\[random query\](\@baidu)+<http://baidu.com/s?nojc=1&wd=random+query>+@+-}+baidu :: Shortcut+baidu _ q = return $ "http://baidu.com/s?nojc=1&wd=" <> replaceSpaces '+' q++{- | __Node.js__ – <https://npmjs.com NPM>++Link to a package:++@+\[markdown\](\@npm)+<https://www.npmjs.com/package/markdown>+@+-}+npm :: Shortcut+npm _ q = return $ "https://npmjs.com/package/" <> q++{- | __Javascript__ – <http://jamjs.org/packages/#/ Jam>++Link to a package:++@+\[pagedown\](\@jam)+<http://jamjs.org/packages/#/details/pagedown>+@+-}+jam :: Shortcut+jam _ q = return $ "http://jamjs.org/packages/#/details/" <> q++{- | __Ruby__ – <https://rubygems.org RubyGems.org>++Link to a package:++@+\[github-markdown\](\@gem)+<https://rubygems.org/gems/github-markdown>+@+-}+rubygems :: Shortcut+rubygems _ q = return $ "https://rubygems.org/gems/" <> q++{- | __Python__ – <https://pypi.python.org/pypi PyPI>++Link to a package:++@+\[Markdown\](\@pypi)+<https://pypi.python.org/pypi/Markdown>+@+-}+pypi :: Shortcut+pypi _ q = return $ "https://pypi.python.org/pypi/" <> q++{- | __Perl__ – <https://metacpan.org MetaCPAN> (by module)++Link to a module:++@+\[Text::Markdown\](\@cpan)+<https://metacpan.org/pod/Text::Markdown>+@++To link to a release, look at 'metacpanRelease'.+-}+metacpanPod :: Shortcut+metacpanPod _ q = return $ "https://metacpan.org/pod/" <> q++{- | __Perl__ – <https://metacpan.org MetaCPAN> (by release)++Link to a release:++@+\[Text-Markdown\](\@cpan-r)+<https://metacpan.org/release/Text-Markdown>+@+-}+metacpanRelease :: Shortcut+metacpanRelease _ q = return $ "https://metacpan.org/release/" <> q++{- | __Haskell__ – <https://hackage.haskell.org Hackage>++Link to a package:++@+\[cmark\](\@hackage)+<https://hackage.haskell.org/package/cmark>+@+-}+hackage :: Shortcut+hackage _ q = return $ "https://hackage.haskell.org/package/" <> q++{- | __Rust__ – <https://crates.io Cargo>++Link to a package:++@+\[hoedown\](\@cargo)+<https://crates.io/crates/hoedown>+@+-}+cargo :: Shortcut+cargo _ q = return $ "https://crates.io/crates/" <> q++{- | __PHP__ – <http://pear.php.net PEAR>++Link to a package:++@+\[Text_Wiki_Doku\](\@pear)+<http://pear.php.net/package/Text_Wiki_Doku>+@+-}+pear :: Shortcut+pear _ q = return $ "http://pear.php.net/package/" <> q++{- | __Dart__ – <https://pub.dartlang.org pub>++Link to a package:++@+\[md_proc\](\@pub)+<https://pub.dartlang.org/packages/md_proc>+@+-}+pub :: Shortcut+pub _ q = return $ "https://pub.dartlang.org/packages/" <> q++{- | __R__ – <http://cran.r-project.org/web/packages/ CRAN>++Link to a package:++@+\[markdown\](\@cran)+<http://cran.r-project.org/web/packages/markdown>+@+-}+cran :: Shortcut+cran _ q = return $ "http://cran.r-project.org/web/packages/" <> q++{- | __Erlang__ – <https://hex.pm Hex>++Link to a package:++@+\[earmark\](\@hex)+<https://hex.pm/packages/earmark>+@+-}+hex :: Shortcut+hex _ q = return $ "https://hex.pm/packages/" <> q++{- | __SWI-Prolog__ – <http://www.swi-prolog.org/pack/list packages>++Link to a package:++@+\[markdown\](\@swiprolog)+<http://www.swi-prolog.org/pack/list?p=markdown>+@+-}+swiprolog :: Shortcut+swiprolog _ q = return $ "http://www.swi-prolog.org/pack/list?p=" <> q++{- | __D__ – <http://code.dlang.org DUB>++Link to a package:++@+\[dmarkdown\](\@dub)+<http://code.dlang.org/packages/dmarkdown>+@+-}+dub :: Shortcut+dub _ q = return $ "http://code.dlang.org/packages/" <> q++{- | __Bash__ – <http://bpkg.io bpkg>++Link to a package:++@+\[markdown\](\@bpkg)+<http://www.bpkg.io/pkg/markdown>+@+-}+bpkg :: Shortcut+bpkg _ q = return $ "http://bpkg.io/pkg/" <> q++{- | <https://github.com Github>++Link to a user:++@+\[Aelve\](\@gh:aelve)+<https://github.com/aelve>+@++Link to a repository:++@+\[aelve/shortcut-links\](\@gh)+<https://github.com/aelve/shortcut-links>+@++The repository owner can also be given as an option (to avoid mentioning nem in the link text):++@+\[shortcut-links\](\@gh(aelve))+<https://github.com/aelve/shortcut-links>+@+-}+github :: Shortcut+github mbOwner q = case mbOwner of+  Nothing    -> return $ format "https://github.com/{}" q+  Just owner -> return $ format "https://github.com/{}/{}" owner q++{- | <https://bitbucket.org Bitbucket>++Link to a user:++@+\[Bryan\](\@bitbucket:bos)+<https://bitbucket.org/bos>+@++Link to a repository:++@+\[bos/text\](\@bitbucket)+<https://bitbucket.org/bos/text>+@++The repository owner can also be given as an option (to avoid mentioning nem in the link text):++@+\[text\](\@bitbucket(bos))+<https://bitbucket.org/bos/text>+@+-}+bitbucket :: Shortcut+bitbucket mbOwner q = case mbOwner of+  Nothing    -> return $ format "https://bitbucket.org/{}" q+  Just owner -> return $ format "https://bitbucket.org/{}/{}" owner q++{- | <https://gitlab.com Gitlab>++Link to a user or a team (note that links like <https://gitlab.com/owner> work but are going to be automatically redirected to either <https://gitlab.com/u/owner> or <https://gitlab.com/groups/owner>, depending on whether it's a user or a team – so, it's a case when the “links have to look as authentic as possible” principle is violated, but nothing can be done with that):++@+\[CyanogenMod\](\@bitbucket)+<https://gitlab.com/CyanogenMod>+@++Link to a repository:++@+\[learnyou/lysa\](\@gitlab)+<https://gitlab.com/learnyou/lysa>+@++The repository owner can also be given as an option (to avoid mentioning nem in the link text):++@+\[lysa\](\@gitlab(learnyou))+<https://gitlab.com/learnyou/lysa>+@+-}+gitlab :: Shortcut+gitlab mbOwner q = case mbOwner of+  Nothing    -> return $ format "https://gitlab.com/{}" q+  Just owner -> return $ format "https://gitlab.com/{}/{}" owner q++{- | __Android__ – <https://play.google.com Google Play> (formerly Play Market)++Link to an app:++@+\[Opera Mini\](\@gplay:com.opera.mini.native)+<https://play.google.com/store/apps/details?id=com.opera.mini.native>+@+-}+googleplay :: Shortcut+googleplay _ q = return $ "https://play.google.com/store/apps/details?id=" <> q++{- | <http://braumeister.org Braumeister> (Homebrew formulas)++Link to a formula:++@+\[multimarkdown\](\@brew)+<http://braumeister.org/formula/multimarkdown>+@+-}+braumeister :: Shortcut+braumeister _ q = return $ "http://braumeister.org/formula/" <> q++{- | <https://chocolatey.org Chocolatey>++Link to a package:++@+\[Opera\](\@chocolatey)+<https://chocolatey.org/packages/Opera>+@+-}+chocolatey :: Shortcut+chocolatey _ q = return $ "https://chocolatey.org/packages/" <> q++{- | __Debian__ – <https://debian.org/distrib/packages packages>++Link to a package in stable distribution:++@+\[ghc\](\@debian)+<https://packages.debian.org/stable/ghc>+@++Distribution can be given as an option:++@+\[ghc\](\@debian(experimental))+<https://packages.debian.org/experimental/ghc>+@+-}+debian :: Shortcut+debian mbDist q = return $ format "https://packages.debian.org/{}/{}" dist q+  where+    dist = fromMaybe "stable" mbDist++{- | __Arch Linux__ – <https://aur.archlinux.org AUR> (“user repository”)++Link to a package:++@+\[ghc-git\](\@aur)+<https://aur.archlinux.org/packages/ghc-git>+@+-}+aur :: Shortcut+aur _ q = return $ "https://aur.archlinux.org/packages/" <> q++{- | __Gentoo__ – <https://packages.gentoo.org packages>++Link to a package:++@+\[dev-lang/ghc\](\@gentoo)+<https://packages.gentoo.org/package/dev-lang/ghc>+@++Category can be given as an option, to avoid cluttering link text:++@+\[ghc\](\@gentoo(dev-lang))+<https://packages.gentoo.org/package/dev-lang/ghc>+@++Note that if you don't specify any category, the link would still work – but there are a lot of packages with overlapping names (like “ace”, “csv”, “http”), and such links would lead to search pages listing several packages. So, it's better to include categories.+-}+gentoo :: Shortcut+gentoo mbCat q = return $ "https://packages.gentoo.org/package/" <> pkg+  where+    pkg = case mbCat of+      Nothing  -> q+      Just cat -> cat <> "/" <> q++{- | __openSUSE__ – <http://software.opensuse.org packages>++Link to a package:++@+\[ghc\](\@opensuse)+<http://software.opensuse.org/package/ghc>+@+-}+opensuse :: Shortcut+opensuse _ q = return $ "http://software.opensuse.org/package/" <> q++{- | __Linux Mint__ – <http://community.linuxmint.com/software/browse packages>++Link to a package:++@+\[ghc\](\@mint)+<http://community.linuxmint.com/software/view/ghc>+@+-}+mint :: Shortcut+mint _ q = return $ "http://community.linuxmint.com/software/view/" <> q++{- | __Fedora__ – <https://admin.fedoraproject.org/pkgdb packages>++Link to a package:++@+\[ghc\](\@fedora)+<https://admin.fedoraproject.org/pkgdb/package/ghc>+@+-}+fedora :: Shortcut+fedora _ q = return $ "https://admin.fedoraproject.org/pkgdb/package/" <> q++{- | __Emacs__ – <https://marmalade-repo.org Marmalade>++Link to a package:++@+\[markdown-mode\](\@marmalade)+<https://marmalade-repo.org/packages/markdown-mode>+@+-}+marmalade :: Shortcut+marmalade _ q = return $ "https://marmalade-repo.org/packages/" <> q++{- | __Emacs__ – <http://melpa.org MELPA>++Link to a package:++@+\[markdown-mode\](\@melpa)+<http://melpa.org/#/markdown-mode>+@+-}+melpa :: Shortcut+melpa _ q = return $ "http://melpa.org/#/" <> q++{- | __Emacs__ – <https://elpa.gnu.org ELPA>++Link to a package:++@+\[undo-tree\](\@elpa)+<https://elpa.gnu.org/packages/undo-tree.html>+@+-}+elpa :: Shortcut+elpa _ q = return $ format "https://elpa.gnu.org/packages/{}.html" q++{- | __Sublime Text__ – <https://packagecontrol.io Package Control>++Link to a package:++@+\[MarkdownEditing\](\@sublimepc)+<https://packagecontrol.io/packages/MarkdownEditing>+@+-}+packagecontrol :: Shortcut+packagecontrol _ q = return $ "https://packagecontrol.io/packages/" <> q++{- | __Atom__ – <https://atom.io/packages packages>++Link to a package:++@+\[tidy-markdown\](\@atom)+<https://atom.io/packages/tidy-markdown>+@+-}+atomPackage :: Shortcut+atomPackage _ q = return $ "https://atom.io/packages/" <> q++{- | __Atom__ – <https://atom.io/themes themes>++Link to a theme:++@+\[atom-material-ui\](\@atom-theme)+<https://atom.io/themes/atom-material-ui>+@+-}+atomTheme :: Shortcut+atomTheme _ q = return $ "https://atom.io/themes/" <> q++{- | __jEdit__ – <http://plugins.jedit.org plugins>++Link to a plugin:++@+\[MarkdownPlugin\](\@jedit)+<http://plugins.jedit.org/plugins/?MarkdownPlugin>+@+-}+jedit :: Shortcut+jedit _ q = return $ "http://plugins.jedit.org/plugins/?" <> q++{- | __Vim__ – <http://www.vim.org/scripts/ scripts>++Link to a script (by ID):++@+\[haskell.vim\](\@vim:2062)+<http://www.vim.org/scripts/script.php?script_id=2062>+@+-}+vim :: Shortcut+vim _ q = return $ "http://www.vim.org/scripts/script.php?script_id=" <> q++{- | __Opera__ – <https://addons.opera.com/extensions/ extensions>++Link to an extension:++@+\[Amazon\](\@opera:amazon-for-opera)+<https://addons.opera.com/extensions/details/amazon-for-opera>+@+-}+operaExt :: Shortcut+operaExt _ q = return $ "https://addons.opera.com/extensions/details/" <> q++{- | __Opera__ – <https://addons.opera.com/themes/ themes>++Link to a theme:++@+\[Space theme\](\@opera-theme:space-15)+<https://addons.opera.com/en/themes/details/space-15>+@+-}+operaTheme :: Shortcut+operaTheme _ q = return $ "https://addons.opera.com/themes/details/" <> q++{- | __Firefox__ – <https://addons.mozilla.org/firefox add-ons>++Link to an extension (or a theme):++@+\[tree-style-tab](\@firefox)+<https://addons.mozilla.org/firefox/addon/tree-style-tab>+@+-}+firefox :: Shortcut+firefox _ q = return $ "https://addons.mozilla.org/firefox/addon/" <> q++{- | __Chrome__ – <https://chrome.google.com/webstore Chrome Web Store>++Link to an extension, app, or theme (using that weird random-looking ID):++@+\[hdokiejnpimakedhajhdlcegeplioahd](\@chrome)+<https://chrome.google.com/webstore/detail/hdokiejnpimakedhajhdlcegeplioahd>+@+-}+chrome :: Shortcut+chrome _ q = return $ "https://chrome.google.com/webstore/detail/" <> q++{- | <https://www.haskell.org/ghc/ GHC> (Glasgow Haskell Compiler) extensions++Link to an extension's description in the user manual:++@+\[ViewPatterns\](\@ghc-ext)+<https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/syntax-extns.html#view-patterns>+@+-}+ghcExt :: Shortcut+ghcExt _ ext = case lookup ext ghcExtsList of+  Nothing   -> fail (format "unknown GHC extension '{}'" ext)+  Just link -> return link++{- | <https://www.ietf.org/rfc.html RFCs>++Link to an RFC:++@+\[RFC 2026\](\@rfc)+<https://tools.ietf.org/html/rfc2026>+@++Precise format of recognised text: optional “rfc” (case-insensitive), then arbitrary amount of spaces and punctuation (or nothing), then the number. Examples: “RFC 2026”, “RFC-2026”, “rfc2026”, “rfc #2026”, “2026”, “#2026”.+-}+rfc :: Shortcut+rfc _ x = do+  let n = T.dropWhile (not . isAlphaNum) (tryStripPrefixCI "rfc" x)+  -- We don't use 'readMaybe' here because 'readMaybe' isn't available in GHC+  -- 7.4, which Pandoc has to be compatible with.+  unless (T.all isDigit n) $+    warn "non-digits in RFC number"+  when (T.null n) $+    warn "no RFC number"+  let n' = T.dropWhile (== '0') n `orElse` "0"+  return ("https://tools.ietf.org/html/rfc" <> n')++{- | <http://ecma-international.org/publications/index.html Ecma standards and technical reports>++Link to a standard:++@+\[ECMA-262\](\@ecma)+<http://www.ecma-international.org/publications/standards/Ecma-262.htm>+@++Link to a technical report:++@+\[TR/71\](\@ecma)+<http://ecma-international.org/publications/techreports/E-TR-071.htm>+@++Precise format of recognised text for standards: optional “ECMA” (case-insensitive), then arbitrary amount of spaces and punctuation (or nothing), then the number. Examples: “ECMA-262”, “ECMA 262”, “ecma262”, “ECMA #262”, “262”, “#262”.++Format for technical reports is the same, except that “TR” (instead of “ECMA”) is not optional (so, if there's only a number given, it's considered a standard and not a technical report).+-}+ecma :: Shortcut+ecma _ q = do+  -- TODO: move dropSeparators to Utils and use it in 'rfc' and 'cve'+  let dropSeparators = T.dropWhile (not . isAlphaNum)+  let (dropSeparators -> mbNum, isTR) = case stripPrefixCI "tr" q of+        Nothing -> (tryStripPrefixCI "ecma" q, False)+        Just q' -> (q', True)+  -- We don't use 'readMaybe' here because 'readMaybe' isn't available in GHC+  -- 7.4, which Pandoc has to be compatible with.+  unless (T.all isDigit mbNum) $+    warn "non-digits in ECMA standard number"+  when (T.null mbNum) $+    warn "no ECMA standard number"+  -- The number has to have at least 3 digits.+  let num = T.justifyRight 3 '0' mbNum+      url = "http://ecma-international.org/publications" :: Text+  return $ if isTR+    then format "{}/techreports/E-TR-{}.htm" url num+    else format "{}/standards/Ecma-{}.htm" url num++{- | <http://cve.mitre.org CVEs> (Common Vulnerabilities and Exposures)++Link to a CVE:++@+\[CVE-2014-10001\](\@cve)+<http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-10001>+@++Precise format of recognised text: optional “cve” (case-insensitive), then arbitrary amount of spaces and punctuation (or nothing), then the year, “-”, and a number. Examples: “CVE-2014-10001”, “cve 2014-10001”, “2014-10001”.+-}+cve :: Shortcut+cve _ x = do+  let n = T.dropWhile (not . isAlphaNum) (tryStripPrefixCI "cve" x)+  unless (T.length n >= 9) $+    warn "CVE-ID is too short"+  let isValid = and [+        T.length n >= 9,+        T.all isDigit (T.take 4 n),+        T.index n 4 == '-',+        T.all isDigit (T.drop 5 n) ]+  unless isValid $+    warn "CVE-ID doesn't follow the <year>-<digits> format"+  return ("http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-" <> n)++{- | <https://wikipedia.org/ Wikipedia>++Link to an article in English Wikipedia:++@+\[grey-headed flying fox\](\@w)+<https://en.wikipedia.org/wiki/Grey-headed_flying_fox>+@++You can link to Wikipedia-in-another-language if you give language code as an option:++@+\[Haskell\](\@w(ru))+<https://ru.wikipedia.org/wiki/Haskell>+@+-}+wikipedia :: Shortcut+wikipedia mbLang q = return $+  format "https://{}.wikipedia.org/wiki/{}" lang q'+  where+    lang = fromMaybe "en" mbLang+    q'   = titleFirst (replaceSpaces '_' q)++{- | <http://tvtropes.org TV Tropes>++Link to a trope:++@+\[so bad, it's good\](\@tvtropes)+<http://tvtropes.org/pmwiki/pmwiki.php/Main/SoBadItsGood>+@++Link to anything else (a series, for example):++@+\[Elementary\](\@tvtropes(series))+<http://tvtropes.org/pmwiki/pmwiki.php/Series/Elementary>+@++Or something on Sugar Wiki:++@+\[awesome music\](\@tvtropes(sugar wiki))+<http://tvtropes.org/pmwiki/pmwiki.php/SugarWiki/AwesomeMusic>+@+-}+tvtropes :: Shortcut+tvtropes mbCat q = return $+  format "http://tvtropes.org/pmwiki/pmwiki.php/{}/{}" cat (camel q)+  where+    isSep c = (isSpace c || isPunctuation c) && c /= '\''+    -- Break into words, transform each word like “it's” → “Its”, and concat.+    -- Note that e.g. “man-made” is considered 2 separate words.+    camel = T.concat . map (titleFirst . T.filter isAlphaNum) . T.split isSep+    cat = maybe "Main" camel mbCat  ghcExtsList :: [(Text, Text)] ghcExtsList = do