link-relations (empty) → 0.1.0.0
raw patch · 12 files changed
+1836/−0 lines, 12 filesdep +basedep +bytestringdep +hashablesetup-changed
Dependencies added: base, bytestring, hashable, unordered-containers, uri-bytestring
Files
- AUTHORS +1/−0
- COPYING +121/−0
- ChangeLog +17/−0
- INSTALL +13/−0
- NEWS.md +23/−0
- README.md +77/−0
- Setup.hs +2/−0
- link-relations.cabal +49/−0
- src/Web/LinkRelations.hs +916/−0
- util/generate.hs +353/−0
- util/link-relations-1.csv +153/−0
- util/template.hs +111/−0
+ AUTHORS view
@@ -0,0 +1,1 @@+fr33domlover <fr33domlover@riseup.net>
+ COPYING view
@@ -0,0 +1,121 @@+Creative Commons Legal Code++CC0 1.0 Universal++ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE+ LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN+ ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS+ INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES+ REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS+ PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM+ THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED+ HEREUNDER.++Statement of Purpose++The laws of most jurisdictions throughout the world automatically confer+exclusive Copyright and Related Rights (defined below) upon the creator+and subsequent owner(s) (each and all, an "owner") of an original work of+authorship and/or a database (each, a "Work").++Certain owners wish to permanently relinquish those rights to a Work for+the purpose of contributing to a commons of creative, cultural and+scientific works ("Commons") that the public can reliably and without fear+of later claims of infringement build upon, modify, incorporate in other+works, reuse and redistribute as freely as possible in any form whatsoever+and for any purposes, including without limitation commercial purposes.+These owners may contribute to the Commons to promote the ideal of a free+culture and the further production of creative, cultural and scientific+works, or to gain reputation or greater distribution for their Work in+part through the use and efforts of others.++For these and/or other purposes and motivations, and without any+expectation of additional consideration or compensation, the person+associating CC0 with a Work (the "Affirmer"), to the extent that he or she+is an owner of Copyright and Related Rights in the Work, voluntarily+elects to apply CC0 to the Work and publicly distribute the Work under its+terms, with knowledge of his or her Copyright and Related Rights in the+Work and the meaning and intended legal effect of CC0 on those rights.++1. Copyright and Related Rights. A Work made available under CC0 may be+protected by copyright and related or neighboring rights ("Copyright and+Related Rights"). Copyright and Related Rights include, but are not+limited to, the following:++ i. the right to reproduce, adapt, distribute, perform, display,+ communicate, and translate a Work;+ ii. moral rights retained by the original author(s) and/or performer(s);+iii. publicity and privacy rights pertaining to a person's image or+ likeness depicted in a Work;+ iv. rights protecting against unfair competition in regards to a Work,+ subject to the limitations in paragraph 4(a), below;+ v. rights protecting the extraction, dissemination, use and reuse of data+ in a Work;+ vi. database rights (such as those arising under Directive 96/9/EC of the+ European Parliament and of the Council of 11 March 1996 on the legal+ protection of databases, and under any national implementation+ thereof, including any amended or successor version of such+ directive); and+vii. other similar, equivalent or corresponding rights throughout the+ world based on applicable law or treaty, and any national+ implementations thereof.++2. Waiver. To the greatest extent permitted by, but not in contravention+of, applicable law, Affirmer hereby overtly, fully, permanently,+irrevocably and unconditionally waives, abandons, and surrenders all of+Affirmer's Copyright and Related Rights and associated claims and causes+of action, whether now known or unknown (including existing as well as+future claims and causes of action), in the Work (i) in all territories+worldwide, (ii) for the maximum duration provided by applicable law or+treaty (including future time extensions), (iii) in any current or future+medium and for any number of copies, and (iv) for any purpose whatsoever,+including without limitation commercial, advertising or promotional+purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each+member of the public at large and to the detriment of Affirmer's heirs and+successors, fully intending that such Waiver shall not be subject to+revocation, rescission, cancellation, termination, or any other legal or+equitable action to disrupt the quiet enjoyment of the Work by the public+as contemplated by Affirmer's express Statement of Purpose.++3. Public License Fallback. Should any part of the Waiver for any reason+be judged legally invalid or ineffective under applicable law, then the+Waiver shall be preserved to the maximum extent permitted taking into+account Affirmer's express Statement of Purpose. In addition, to the+extent the Waiver is so judged Affirmer hereby grants to each affected+person a royalty-free, non transferable, non sublicensable, non exclusive,+irrevocable and unconditional license to exercise Affirmer's Copyright and+Related Rights in the Work (i) in all territories worldwide, (ii) for the+maximum duration provided by applicable law or treaty (including future+time extensions), (iii) in any current or future medium and for any number+of copies, and (iv) for any purpose whatsoever, including without+limitation commercial, advertising or promotional purposes (the+"License"). The License shall be deemed effective as of the date CC0 was+applied by Affirmer to the Work. Should any part of the License for any+reason be judged legally invalid or ineffective under applicable law, such+partial invalidity or ineffectiveness shall not invalidate the remainder+of the License, and in such case Affirmer hereby affirms that he or she+will not (i) exercise any of his or her remaining Copyright and Related+Rights in the Work or (ii) assert any associated claims and causes of+action with respect to the Work, in either case contrary to Affirmer's+express Statement of Purpose.++4. Limitations and Disclaimers.++ a. No trademark or patent rights held by Affirmer are waived, abandoned,+ surrendered, licensed or otherwise affected by this document.+ b. Affirmer offers the Work as-is and makes no representations or+ warranties of any kind concerning the Work, express, implied,+ statutory or otherwise, including without limitation warranties of+ title, merchantability, fitness for a particular purpose, non+ infringement, or the absence of latent or other defects, accuracy, or+ the present or absence of errors, whether or not discoverable, all to+ the greatest extent permissible under applicable law.+ c. Affirmer disclaims responsibility for clearing rights of other persons+ that may apply to the Work or any use thereof, including without+ limitation any person's Copyright and Related Rights in the Work.+ Further, Affirmer disclaims responsibility for obtaining any necessary+ consents, permissions or other rights required for any use of the+ Work.+ d. Affirmer understands and acknowledges that Creative Commons is not a+ party to this document and has no duty or obligation with respect to+ this CC0 or use of the Work.
+ ChangeLog view
@@ -0,0 +1,17 @@+The changes are recorded by the version control system, Darcs. To see a log+quickly from the terminal, run:++ $ darcs changes --repo http://hub.darcs.net/fr33domlover/link-relations++There is also a web interface at <http://hub.darcs.net> which, among other+things, can display the history log.++To see the log in a local clone, first get a copy of the repository if you+haven't yet:++ $ darcs get http://hub.darcs.net/fr33domlover/link-relations++Then move into the newly created directory and run darcs:++ $ cd link-relations+ $ darcs changes
+ INSTALL view
@@ -0,0 +1,13 @@+Install from Hackage:++ $ cabal install link-relations++Install from unpacked release tarball or source repo:++ $ cd link-relations+ $ cabal install++Just play with it without installing:++ $ cabal build+ $ cabal repl
+ NEWS.md view
@@ -0,0 +1,23 @@+This file lists the user-visible interesting changes between releases. For a+full list of changes to the source, see the ChangeLog.++++link-relations 0.1.0.0 -- 2015-12-15+====================================++General, build and documentation changes:++* (This is the first release, so everything is new)++New APIs, features and enhancements:++* (This is the first release, so everything is a new feature)++Bug fixes:++* (This is just the first release, many bugs haven't been discovered yet)++Dependency changes:++* (This is the first release)
+ README.md view
@@ -0,0 +1,77 @@+See the .cabal file for more info and link to project website the version+control.++The official download location is Hackage.++This library is free software, and is committed to software freedom. It is+released to the public domain using the CC0 Public Domain Dedication. For the+boring "legal" details see the file `COPYING`.++See the file `INSTALL` for hints on installation. The file `ChangeLog` explains+how to see the history log of the changes done in the code. `NEWS.md` provides+a friendly overview of the changes for each release.++# How to Release++This package's source code is auto-generated using 3 files:++1. A Haskell source file template+2. CSV file containing the IANA link relation registry data+3. A Haskell program which embeds the data into the template as Haskell code++All 3 files are found in the `util/` directory.++## (1) Update the source++- To update the non-generated part of the code, edit the template file.+- To update the CSV to a new version, download it from+ <https://www.iana.org/assignments/link-relations/link-relations-1.csv>+- To modify the source generation process, edit the generator program++## (2) Update version and date++If you downloaded a new CSV version, update the `lastUpdated` value in the+generator program. You can find that date at+<http://www.iana.org/assignments/link-relations/link-relations.xhtml>.++Update the package version number in the .cabal file. Use `darcs diff` to+examine the changes in the generated source and pick a version number according+to PVP. The most common change in the registry will probably be new link+relations added, which means new API functions and therefore an increase of the+minor version number (i.e. 3rd number, e.g. /0.1.5.3/ becomes /0.1.6.0/).+That's because the `LinkRelation` constructors themselves aren't exported.++## (3) Adjust other config++Near the top of the generator program file there is a configuration section+(e.g. the update date, file paths, etc.). If you made any changes which require+updates there, make the required modifications.++## (4) Build and test++The generator program depends on the `cassava` package. The other dependencies+are also dependencies of `cassava` (primarily `bytestring` and `vector`), which+means you can install the dependencies like this:++ $ cabal install cassava++Run the generator program from the package toplevel. Either using the+interpreter:++ $ runhaskell util/generate.hs++Or like this, if you installed `cassava` into a sandbox:++ $ cabal exec runhaskell util/generate.hs++Examine the result. Switch between the old generated source and the new one+(which is generated as a separate file in the same directory).++Build the library itself:++ $ cabal build++## (5) Record everything into the Darcs repo, make a tag, make a tarball etc.++As usual. Note that the 3 files in `util/` (i.e. including the CSV data) and+the generated source in `src/`, are all kept in the Darcs repo.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ link-relations.cabal view
@@ -0,0 +1,49 @@+name: link-relations+version: 0.1.0.0+synopsis: Use web link relation types (RFC 5988) in Haskell+description:+ This library provides access to the IANA registry of link relation types, for+ use in Haskell code in a type-safe manner.+ .+ The registry data can be found at+ <https://www.iana.org/assignments/link-relations>. This package is generated+ from that data.+ .+ To see to which revision of the registry this version of the package+ corresponds, look at the intro comment in "Web.LinkRelations".+homepage: http://hub.darcs.net/fr33domlover/link-relations+bug-reports: http://hub.darcs.net/fr33domlover/link-relations/issues+license: PublicDomain+license-file: COPYING+author: fr33domlover+maintainer: fr33domlover@riseup.net+copyright: ♡ Copying is an act of love. Please copy, reuse and share.+category: Data, Web+build-type: Simple+extra-source-files: AUTHORS+ ChangeLog+ COPYING+ INSTALL+ NEWS.md+ README.md+ util/template.hs+ util/link-relations-1.csv+ util/generate.hs+cabal-version: >=1.10++source-repository head+ type: darcs+ location: http://hub.darcs.net/fr33domlover/link-relations++library+ exposed-modules: Web.LinkRelations+ -- other-modules: + -- other-extensions: + build-depends: base >=4.7 && <5+ , bytestring+ , hashable+ , unordered-containers >=0.2.5+ , uri-bytestring >=0.1.7+ hs-source-dirs: src+ default-language: Haskell2010+ ghc-options: -Wall
+ src/Web/LinkRelations.hs view
@@ -0,0 +1,916 @@+{- This file is part of link-relations.+ -+ - Written in 2015 by fr33domlover <fr33domlover@riseup.net>.+ - Also includes parts generated from the IANA link relation registry.+ -+ - ♡ Copying is an act of love. Please copy, reuse and share.+ -+ - The author(s) have dedicated all copyright and related and neighboring+ - rights to this software to the public domain worldwide. This software is+ - distributed without any warranty.+ -+ - You should have received a copy of the CC0 Public Domain Dedication along+ - with this software. If not, see+ - <http://creativecommons.org/publicdomain/zero/1.0/>.+ -}++{-# LANGUAGE OverloadedStrings #-}++-- | A simple web link between two web resources, e.g. a hyperlink in a webpage+-- referring to another page, suggests that the resources are somehow related,+-- but it doesn't say /how/ they are related. For example, a blog post may link+-- to the author's main page (relation: author of the post) but also link to+-- the previous post (relation: previous post by chronological order).+--+-- Link relations provide a way to express the relation between resources+-- linked by a web link.+--+-- A link relation type may be represented by a URI, or by a registered link+-- relation name. IANA maintains a+-- <https://www.iana.org/assignments/link-relations registry> of link+-- relations. This module provides access to them through a dedicated+-- 'LinkRelation' datatype.+--+-- This version of the package corresponds to the+-- /2015-01-21/+-- version of the registry.+module Web.LinkRelations+ ( -- * Types and Conversions+ LinkRelation+ , fromURI+ , fromURIStr+ , fromName+ , fromByteString+ , isURI+ , isName+ , toByteString+ -- * Link Relation Identifiers+ , relAbout+ , relAlternate+ , relAppendix+ , relArchives+ , relAuthor+ , relBookmark+ , relCanonical+ , relChapter+ , relCollection+ , relContents+ , relCopyright+ , relCreateForm+ , relCurrent+ , relDerivedfrom+ , relDescribedby+ , relDescribes+ , relDisclosure+ , relDuplicate+ , relEdit+ , relEditForm+ , relEditMedia+ , relEnclosure+ , relFirst+ , relGlossary+ , relHelp+ , relHosts+ , relHub+ , relIcon+ , relIndex+ , relItem+ , relLast+ , relLatestVersion+ , relLicense+ , relLrdd+ , relMemento+ , relMonitor+ , relMonitorGroup+ , relNext+ , relNextArchive+ , relNofollow+ , relNoreferrer+ , relOriginal+ , relPayment+ , relPredecessorVersion+ , relPrefetch+ , relPrev+ , relPreview+ , relPrevious+ , relPrevArchive+ , relPrivacyPolicy+ , relProfile+ , relRelated+ , relReplies+ , relSearch+ , relSection+ , relSelf+ , relService+ , relStart+ , relStylesheet+ , relSubsection+ , relSuccessorVersion+ , relTag+ , relTermsOfService+ , relTimegate+ , relTimemap+ , relType+ , relUp+ , relVersionHistory+ , relVia+ , relWorkingCopy+ , relWorkingCopyOf+ )+where++import Control.Applicative ((<|>))+import URI.ByteString++import qualified Data.ByteString as B+import qualified Data.HashMap.Strict as M++-- | A web link relation type. Either a URI or a registered name.+data LinkRelation+ = FromURI URI+ | RelAbout+ | RelAlternate+ | RelAppendix+ | RelArchives+ | RelAuthor+ | RelBookmark+ | RelCanonical+ | RelChapter+ | RelCollection+ | RelContents+ | RelCopyright+ | RelCreateForm+ | RelCurrent+ | RelDerivedfrom+ | RelDescribedby+ | RelDescribes+ | RelDisclosure+ | RelDuplicate+ | RelEdit+ | RelEditForm+ | RelEditMedia+ | RelEnclosure+ | RelFirst+ | RelGlossary+ | RelHelp+ | RelHosts+ | RelHub+ | RelIcon+ | RelIndex+ | RelItem+ | RelLast+ | RelLatestVersion+ | RelLicense+ | RelLrdd+ | RelMemento+ | RelMonitor+ | RelMonitorGroup+ | RelNext+ | RelNextArchive+ | RelNofollow+ | RelNoreferrer+ | RelOriginal+ | RelPayment+ | RelPredecessorVersion+ | RelPrefetch+ | RelPrev+ | RelPreview+ | RelPrevious+ | RelPrevArchive+ | RelPrivacyPolicy+ | RelProfile+ | RelRelated+ | RelReplies+ | RelSearch+ | RelSection+ | RelSelf+ | RelService+ | RelStart+ | RelStylesheet+ | RelSubsection+ | RelSuccessorVersion+ | RelTag+ | RelTermsOfService+ | RelTimegate+ | RelTimemap+ | RelType+ | RelUp+ | RelVersionHistory+ | RelVia+ | RelWorkingCopy+ | RelWorkingCopyOf+ deriving (Eq, Show)++-- | A mapping from name string to identifiers, for parsing a link relation+-- name from a string.+hashmap :: M.HashMap B.ByteString LinkRelation+hashmap = M.fromList+ [ ("about", RelAbout)+ , ("alternate", RelAlternate)+ , ("appendix", RelAppendix)+ , ("archives", RelArchives)+ , ("author", RelAuthor)+ , ("bookmark", RelBookmark)+ , ("canonical", RelCanonical)+ , ("chapter", RelChapter)+ , ("collection", RelCollection)+ , ("contents", RelContents)+ , ("copyright", RelCopyright)+ , ("create-form", RelCreateForm)+ , ("current", RelCurrent)+ , ("derivedfrom", RelDerivedfrom)+ , ("describedby", RelDescribedby)+ , ("describes", RelDescribes)+ , ("disclosure", RelDisclosure)+ , ("duplicate", RelDuplicate)+ , ("edit", RelEdit)+ , ("edit-form", RelEditForm)+ , ("edit-media", RelEditMedia)+ , ("enclosure", RelEnclosure)+ , ("first", RelFirst)+ , ("glossary", RelGlossary)+ , ("help", RelHelp)+ , ("hosts", RelHosts)+ , ("hub", RelHub)+ , ("icon", RelIcon)+ , ("index", RelIndex)+ , ("item", RelItem)+ , ("last", RelLast)+ , ("latest-version", RelLatestVersion)+ , ("license", RelLicense)+ , ("lrdd", RelLrdd)+ , ("memento", RelMemento)+ , ("monitor", RelMonitor)+ , ("monitor-group", RelMonitorGroup)+ , ("next", RelNext)+ , ("next-archive", RelNextArchive)+ , ("nofollow", RelNofollow)+ , ("noreferrer", RelNoreferrer)+ , ("original", RelOriginal)+ , ("payment", RelPayment)+ , ("predecessor-version", RelPredecessorVersion)+ , ("prefetch", RelPrefetch)+ , ("prev", RelPrev)+ , ("preview", RelPreview)+ , ("previous", RelPrevious)+ , ("prev-archive", RelPrevArchive)+ , ("privacy-policy", RelPrivacyPolicy)+ , ("profile", RelProfile)+ , ("related", RelRelated)+ , ("replies", RelReplies)+ , ("search", RelSearch)+ , ("section", RelSection)+ , ("self", RelSelf)+ , ("service", RelService)+ , ("start", RelStart)+ , ("stylesheet", RelStylesheet)+ , ("subsection", RelSubsection)+ , ("successor-version", RelSuccessorVersion)+ , ("tag", RelTag)+ , ("terms-of-service", RelTermsOfService)+ , ("timegate", RelTimegate)+ , ("timemap", RelTimemap)+ , ("type", RelType)+ , ("up", RelUp)+ , ("version-history", RelVersionHistory)+ , ("via", RelVia)+ , ("working-copy", RelWorkingCopy)+ , ("working-copy-of", RelWorkingCopyOf)+ ]++-- | Create a link relation type from a URI.+fromURI :: URI -> LinkRelation+fromURI = FromURI++-- | Try to parse a string into a URI, returning a link relation if successful.+fromURIStr :: B.ByteString -> Maybe LinkRelation+fromURIStr s =+ case parseURI laxURIParserOptions s of+ Left _ -> Nothing+ Right u -> Just $ fromURI u++-- | Try to match a given link relation name against the registered names.+-- Return the matching link relation if successful.+fromName :: B.ByteString -> Maybe LinkRelation+fromName s = M.lookup s hashmap++-- | Try to parse the given string as a link relation, either as a registered+-- name or as a URI. If both fail, return 'Nothing'.+fromByteString :: B.ByteString -> Maybe LinkRelation+fromByteString s = fromName s <|> fromURIStr s++-- | Get the official registered name of a link relation (if it's a name) or+-- its URI string (if it's a URI).+toByteString :: LinkRelation -> B.ByteString+toByteString lr =+ case lr of+ FromURI u -> serializeURI' u+ RelAbout -> "about"+ RelAlternate -> "alternate"+ RelAppendix -> "appendix"+ RelArchives -> "archives"+ RelAuthor -> "author"+ RelBookmark -> "bookmark"+ RelCanonical -> "canonical"+ RelChapter -> "chapter"+ RelCollection -> "collection"+ RelContents -> "contents"+ RelCopyright -> "copyright"+ RelCreateForm -> "create-form"+ RelCurrent -> "current"+ RelDerivedfrom -> "derivedfrom"+ RelDescribedby -> "describedby"+ RelDescribes -> "describes"+ RelDisclosure -> "disclosure"+ RelDuplicate -> "duplicate"+ RelEdit -> "edit"+ RelEditForm -> "edit-form"+ RelEditMedia -> "edit-media"+ RelEnclosure -> "enclosure"+ RelFirst -> "first"+ RelGlossary -> "glossary"+ RelHelp -> "help"+ RelHosts -> "hosts"+ RelHub -> "hub"+ RelIcon -> "icon"+ RelIndex -> "index"+ RelItem -> "item"+ RelLast -> "last"+ RelLatestVersion -> "latest-version"+ RelLicense -> "license"+ RelLrdd -> "lrdd"+ RelMemento -> "memento"+ RelMonitor -> "monitor"+ RelMonitorGroup -> "monitor-group"+ RelNext -> "next"+ RelNextArchive -> "next-archive"+ RelNofollow -> "nofollow"+ RelNoreferrer -> "noreferrer"+ RelOriginal -> "original"+ RelPayment -> "payment"+ RelPredecessorVersion -> "predecessor-version"+ RelPrefetch -> "prefetch"+ RelPrev -> "prev"+ RelPreview -> "preview"+ RelPrevious -> "previous"+ RelPrevArchive -> "prev-archive"+ RelPrivacyPolicy -> "privacy-policy"+ RelProfile -> "profile"+ RelRelated -> "related"+ RelReplies -> "replies"+ RelSearch -> "search"+ RelSection -> "section"+ RelSelf -> "self"+ RelService -> "service"+ RelStart -> "start"+ RelStylesheet -> "stylesheet"+ RelSubsection -> "subsection"+ RelSuccessorVersion -> "successor-version"+ RelTag -> "tag"+ RelTermsOfService -> "terms-of-service"+ RelTimegate -> "timegate"+ RelTimemap -> "timemap"+ RelType -> "type"+ RelUp -> "up"+ RelVersionHistory -> "version-history"+ RelVia -> "via"+ RelWorkingCopy -> "working-copy"+ RelWorkingCopyOf -> "working-copy-of"++-- | Check whether a link relation is represented by a URI, i.e. is not a link+-- relation registered name.+isURI :: LinkRelation -> Bool+isURI (FromURI _) = True+isURI _ = False++-- | Check whether a link relation is represented by a registered name, i.e. is+-- not a URI.+isName :: LinkRelation -> Bool+isName = not . isURI++-- | Refers to a resource that is the subject of the link\'s context.+--+-- Reference: <https://www.iana.org/go/rfc6903 RFC 6903>, section 2+relAbout :: LinkRelation+relAbout = RelAbout++-- | Refers to a substitute for this context+--+-- Reference: <http://www.w3.org/TR/html5/links.html#link-type-alternate>+relAlternate :: LinkRelation+relAlternate = RelAlternate++-- | Refers to an appendix.+--+-- Reference: <http://www.w3.org/TR/1999/REC-html401-19991224>+relAppendix :: LinkRelation+relAppendix = RelAppendix++-- | Refers to a collection of records, documents, or other materials of+-- historical interest.+--+-- Reference:+-- <http://www.w3.org/TR/2011/WD-html5-20110113/links.html#rel-archives>+relArchives :: LinkRelation+relArchives = RelArchives++-- | Refers to the context\'s author.+--+-- Reference: <http://www.w3.org/TR/html5/links.html#link-type-author>+relAuthor :: LinkRelation+relAuthor = RelAuthor++-- | Gives a permanent link to use for bookmarking purposes.+--+-- Reference: <http://www.w3.org/TR/html5/links.html#link-type-bookmark>+relBookmark :: LinkRelation+relBookmark = RelBookmark++-- | Designates the preferred version of a resource (the IRI and its contents).+--+-- Reference: <https://www.iana.org/go/rfc6596 RFC 6596>+relCanonical :: LinkRelation+relCanonical = RelCanonical++-- | Refers to a chapter in a collection of resources.+--+-- Reference: <http://www.w3.org/TR/1999/REC-html401-19991224>+relChapter :: LinkRelation+relChapter = RelChapter++-- | The target IRI points to a resource which represents the collection+-- resource for the context IRI.+--+-- Reference: <https://www.iana.org/go/rfc6573 RFC 6573>+relCollection :: LinkRelation+relCollection = RelCollection++-- | Refers to a table of contents.+--+-- Reference: <http://www.w3.org/TR/1999/REC-html401-19991224>+relContents :: LinkRelation+relContents = RelContents++-- | Refers to a copyright statement that applies to the link\'s context.+--+-- Reference: <http://www.w3.org/TR/1999/REC-html401-19991224>+relCopyright :: LinkRelation+relCopyright = RelCopyright++-- | The target IRI points to a resource where a submission form can be+-- obtained.+--+-- Reference: <https://www.iana.org/go/rfc6861 RFC 6861>+relCreateForm :: LinkRelation+relCreateForm = RelCreateForm++-- | Refers to a resource containing the most recent item(s) in a collection of+-- resources.+--+-- Reference: <https://www.iana.org/go/rfc5005 RFC 5005>+relCurrent :: LinkRelation+relCurrent = RelCurrent++-- | The target IRI points to a resource from which this material was derived.+--+-- Reference:+-- <https://www.iana.org/go/draft-hoffman-xml2rfc draft-hoffman-xml2rfc>+relDerivedfrom :: LinkRelation+relDerivedfrom = RelDerivedfrom++-- | Refers to a resource providing information about the link\'s context.+--+-- Reference: <http://www.w3.org/TR/powder-dr/#assoc-linking>+relDescribedby :: LinkRelation+relDescribedby = RelDescribedby++-- | The relationship A \'describes\' B asserts that resource A provides a+-- description of resource B. There are no constraints on the format or+-- representation of either A or B, neither are there any further constraints+-- on either resource.+--+-- Reference: <https://www.iana.org/go/rfc6892 RFC 6892>+--+-- Note: This link relation type is the inverse of the \'describedby\' relation+-- type. While \'describedby\' establishes a relation from the described+-- resource back to the resource that describes it, \'describes\' established a+-- relation from the describing resource to the resource it describes. If B is+-- \'describedby\' A, then A \'describes\' B.+relDescribes :: LinkRelation+relDescribes = RelDescribes++-- | Refers to a list of patent disclosures made with respect to material for+-- which \'disclosure\' relation is specified.+--+-- Reference: <https://www.iana.org/go/rfc6579 RFC 6579>+relDisclosure :: LinkRelation+relDisclosure = RelDisclosure++-- | Refers to a resource whose available representations are byte-for-byte+-- identical with the corresponding representations of the context IRI.+--+-- Reference: <https://www.iana.org/go/rfc6249 RFC 6249>+--+-- Note: This relation is for static resources. That is, an HTTP GET request on+-- any duplicate will return the same representation. It does not make sense+-- for dynamic or POSTable resources and should not be used for them.+relDuplicate :: LinkRelation+relDuplicate = RelDuplicate++-- | Refers to a resource that can be used to edit the link\'s context.+--+-- Reference: <https://www.iana.org/go/rfc5023 RFC 5023>+relEdit :: LinkRelation+relEdit = RelEdit++-- | The target IRI points to a resource where a submission form for editing+-- associated resource can be obtained.+--+-- Reference: <https://www.iana.org/go/rfc6861 RFC 6861>+relEditForm :: LinkRelation+relEditForm = RelEditForm++-- | Refers to a resource that can be used to edit media associated with the+-- link\'s context.+--+-- Reference: <https://www.iana.org/go/rfc5023 RFC 5023>+relEditMedia :: LinkRelation+relEditMedia = RelEditMedia++-- | Identifies a related resource that is potentially large and might require+-- special handling.+--+-- Reference: <https://www.iana.org/go/rfc4287 RFC 4287>+relEnclosure :: LinkRelation+relEnclosure = RelEnclosure++-- | An IRI that refers to the furthest preceding resource in a series of+-- resources.+--+-- Reference: <https://www.iana.org/go/rfc5988 RFC 5988>+--+-- Note: This relation type registration did not indicate a reference.+-- Originally requested by Mark Nottingham in December 2004.+relFirst :: LinkRelation+relFirst = RelFirst++-- | Refers to a glossary of terms.+--+-- Reference: <http://www.w3.org/TR/1999/REC-html401-19991224>+relGlossary :: LinkRelation+relGlossary = RelGlossary++-- | Refers to context-sensitive help.+--+-- Reference: <http://www.w3.org/TR/html5/links.html#link-type-help>+relHelp :: LinkRelation+relHelp = RelHelp++-- | Refers to a resource hosted by the server indicated by the link context.+--+-- Reference: <https://www.iana.org/go/rfc6690 RFC 6690>+--+-- Note: This relation is used in CoRE where links are retrieved as a+-- \"\/.well-known\/core\" resource representation, and is the default relation+-- type in the CoRE Link Format.+relHosts :: LinkRelation+relHosts = RelHosts++-- | Refers to a hub that enables registration for notification of updates to+-- the context.+--+-- Reference: <http://pubsubhubbub.googlecode.com>+--+-- Note: This relation type was requested by Brett Slatkin.+relHub :: LinkRelation+relHub = RelHub++-- | Refers to an icon representing the link\'s context.+--+-- Reference: <http://www.w3.org/TR/html5/links.html#link-type-icon>+relIcon :: LinkRelation+relIcon = RelIcon++-- | Refers to an index.+--+-- Reference: <http://www.w3.org/TR/1999/REC-html401-19991224>+relIndex :: LinkRelation+relIndex = RelIndex++-- | The target IRI points to a resource that is a member of the collection+-- represented by the context IRI.+--+-- Reference: <https://www.iana.org/go/rfc6573 RFC 6573>+relItem :: LinkRelation+relItem = RelItem++-- | An IRI that refers to the furthest following resource in a series of+-- resources.+--+-- Reference: <https://www.iana.org/go/rfc5988 RFC 5988>+--+-- Note: This relation type registration did not indicate a reference.+-- Originally requested by Mark Nottingham in December 2004.+relLast :: LinkRelation+relLast = RelLast++-- | Points to a resource containing the latest (e.g., current) version of the+-- context.+--+-- Reference: <https://www.iana.org/go/rfc5829 RFC 5829>+relLatestVersion :: LinkRelation+relLatestVersion = RelLatestVersion++-- | Refers to a license associated with this context.+--+-- Reference: <https://www.iana.org/go/rfc4946 RFC 4946>+--+-- Note: For implications of use in HTML, see:+-- http:\/\/www.w3.org\/TR\/html5\/links.html#link-type-license+relLicense :: LinkRelation+relLicense = RelLicense++-- | Refers to further information about the link\'s context, expressed as a+-- LRDD (\"Link-based Resource Descriptor Document\") resource. See+-- <https://www.iana.org/go/rfc6415 RFC 6415> for information about processing+-- this relation type in host-meta documents. When used elsewhere, it refers to+-- additional links and other metadata. Multiple instances indicate additional+-- LRDD resources. LRDD resources MUST have an \"application\/xrd+xml\"+-- representation, and MAY have others.+--+-- Reference: <https://www.iana.org/go/rfc6415 RFC 6415>+relLrdd :: LinkRelation+relLrdd = RelLrdd++-- | The Target IRI points to a Memento, a fixed resource that will not change+-- state anymore.+--+-- Reference: <https://www.iana.org/go/rfc7089 RFC 7089>+--+-- Note: A Memento for an Original Resource is a resource that encapsulates a+-- prior state of the Original Resource.+relMemento :: LinkRelation+relMemento = RelMemento++-- | Refers to a resource that can be used to monitor changes in an HTTP+-- resource.+--+-- Reference: <https://www.iana.org/go/rfc5989 RFC 5989>+relMonitor :: LinkRelation+relMonitor = RelMonitor++-- | Refers to a resource that can be used to monitor changes in a specified+-- group of HTTP resources.+--+-- Reference: <https://www.iana.org/go/rfc5989 RFC 5989>+relMonitorGroup :: LinkRelation+relMonitorGroup = RelMonitorGroup++-- | Indicates that the link\'s context is a part of a series, and that the+-- next in the series is the link target.+--+-- Reference: <http://www.w3.org/TR/html5/links.html#link-type-next>+relNext :: LinkRelation+relNext = RelNext++-- | Refers to the immediately following archive resource.+--+-- Reference: <https://www.iana.org/go/rfc5005 RFC 5005>+relNextArchive :: LinkRelation+relNextArchive = RelNextArchive++-- | Indicates that the context’s original author or publisher does not+-- endorse the link target.+--+-- Reference: <http://www.w3.org/TR/html5/links.html#link-type-nofollow>+relNofollow :: LinkRelation+relNofollow = RelNofollow++-- | Indicates that no referrer information is to be leaked when following the+-- link.+--+-- Reference: <http://www.w3.org/TR/html5/links.html#link-type-noreferrer>+relNoreferrer :: LinkRelation+relNoreferrer = RelNoreferrer++-- | The Target IRI points to an Original Resource.+--+-- Reference: <https://www.iana.org/go/rfc7089 RFC 7089>+--+-- Note: An Original Resource is a resource that exists or used to exist, and+-- for which access to one of its prior states may be required.+relOriginal :: LinkRelation+relOriginal = RelOriginal++-- | Indicates a resource where payment is accepted.+--+-- Reference: <https://www.iana.org/go/rfc5988 RFC 5988>+--+-- Note: This relation type registration did not indicate a reference.+-- Requested by Joshua Kinberg and Robert Sayre. It is meant as a general way+-- to facilitate acts of payment, and thus this specification makes no+-- assumptions on the type of payment or transaction protocol. Examples may+-- include a web page where donations are accepted or where goods and services+-- are available for purchase. rel=\"payment\" is not intended to initiate an+-- automated transaction. In Atom documents, a link element with a+-- rel=\"payment\" attribute may exist at the feed\/channel level and\/or the+-- entry\/item level. For example, a rel=\"payment\" link at the feed\/channel+-- level may point to a \"tip jar\" URI, whereas an entry\/ item containing a+-- book review may include a rel=\"payment\" link that points to the location+-- where the book may be purchased through an online retailer.+relPayment :: LinkRelation+relPayment = RelPayment++-- | Points to a resource containing the predecessor version in the version+-- history.+--+-- Reference: <https://www.iana.org/go/rfc5829 RFC 5829>+relPredecessorVersion :: LinkRelation+relPredecessorVersion = RelPredecessorVersion++-- | Indicates that the link target should be preemptively cached.+--+-- Reference: <http://www.w3.org/TR/html5/links.html#link-type-prefetch>+relPrefetch :: LinkRelation+relPrefetch = RelPrefetch++-- | Indicates that the link\'s context is a part of a series, and that the+-- previous in the series is the link target.+--+-- Reference: <http://www.w3.org/TR/html5/links.html#link-type-prev>+relPrev :: LinkRelation+relPrev = RelPrev++-- | Refers to a resource that provides a preview of the link\'s context.+--+-- Reference: <https://www.iana.org/go/rfc6903 RFC 6903>, section 3+relPreview :: LinkRelation+relPreview = RelPreview++-- | Refers to the previous resource in an ordered series of resources. Synonym+-- for \"prev\".+--+-- Reference: <http://www.w3.org/TR/1999/REC-html401-19991224>+relPrevious :: LinkRelation+relPrevious = RelPrevious++-- | Refers to the immediately preceding archive resource.+--+-- Reference: <https://www.iana.org/go/rfc5005 RFC 5005>+relPrevArchive :: LinkRelation+relPrevArchive = RelPrevArchive++-- | Refers to a privacy policy associated with the link\'s context.+--+-- Reference: <https://www.iana.org/go/rfc6903 RFC 6903>, section 4+relPrivacyPolicy :: LinkRelation+relPrivacyPolicy = RelPrivacyPolicy++-- | Identifying that a resource representation conforms to a certain profile,+-- without affecting the non-profile semantics of the resource representation.+--+-- Reference: <https://www.iana.org/go/rfc6906 RFC 6906>+--+-- Note: Profile URIs are primarily intended to be used as identifiers, and+-- thus clients SHOULD NOT indiscriminately access profile URIs.+relProfile :: LinkRelation+relProfile = RelProfile++-- | Identifies a related resource.+--+-- Reference: <https://www.iana.org/go/rfc4287 RFC 4287>+relRelated :: LinkRelation+relRelated = RelRelated++-- | Identifies a resource that is a reply to the context of the link.+--+-- Reference: <https://www.iana.org/go/rfc4685 RFC 4685>+relReplies :: LinkRelation+relReplies = RelReplies++-- | Refers to a resource that can be used to search through the link\'s+-- context and related resources.+--+-- Reference: <http://www.opensearch.org/Specifications/OpenSearch/1.1>+relSearch :: LinkRelation+relSearch = RelSearch++-- | Refers to a section in a collection of resources.+--+-- Reference: <http://www.w3.org/TR/1999/REC-html401-19991224>+relSection :: LinkRelation+relSection = RelSection++-- | Conveys an identifier for the link\'s context.+--+-- Reference: <https://www.iana.org/go/rfc4287 RFC 4287>+relSelf :: LinkRelation+relSelf = RelSelf++-- | Indicates a URI that can be used to retrieve a service document.+--+-- Reference: <https://www.iana.org/go/rfc5023 RFC 5023>+--+-- Note: When used in an Atom document, this relation type specifies Atom+-- Publishing Protocol service documents by default. Requested by James Snell.+relService :: LinkRelation+relService = RelService++-- | Refers to the first resource in a collection of resources.+--+-- Reference: <http://www.w3.org/TR/1999/REC-html401-19991224>+relStart :: LinkRelation+relStart = RelStart++-- | Refers to a stylesheet.+--+-- Reference: <http://www.w3.org/TR/html5/links.html#link-type-stylesheet>+relStylesheet :: LinkRelation+relStylesheet = RelStylesheet++-- | Refers to a resource serving as a subsection in a collection of resources.+--+-- Reference: <http://www.w3.org/TR/1999/REC-html401-19991224>+relSubsection :: LinkRelation+relSubsection = RelSubsection++-- | Points to a resource containing the successor version in the version+-- history.+--+-- Reference: <https://www.iana.org/go/rfc5829 RFC 5829>+relSuccessorVersion :: LinkRelation+relSuccessorVersion = RelSuccessorVersion++-- | Gives a tag (identified by the given address) that applies to the current+-- document.+--+-- Reference: <http://www.w3.org/TR/html5/links.html#link-type-tag>+relTag :: LinkRelation+relTag = RelTag++-- | Refers to the terms of service associated with the link\'s context.+--+-- Reference: <https://www.iana.org/go/rfc6903 RFC 6903>, section 5+relTermsOfService :: LinkRelation+relTermsOfService = RelTermsOfService++-- | The Target IRI points to a TimeGate for an Original Resource.+--+-- Reference: <https://www.iana.org/go/rfc7089 RFC 7089>+--+-- Note: A TimeGate for an Original Resource is a resource that is capable of+-- datetime negotiation to support access to prior states of the Original+-- Resource.+relTimegate :: LinkRelation+relTimegate = RelTimegate++-- | The Target IRI points to a TimeMap for an Original Resource.+--+-- Reference: <https://www.iana.org/go/rfc7089 RFC 7089>+--+-- Note: A TimeMap for an Original Resource is a resource from which a list of+-- URIs of Mementos of the Original Resource is available.+relTimemap :: LinkRelation+relTimemap = RelTimemap++-- | Refers to a resource identifying the abstract semantic type of which the+-- link\'s context is considered to be an instance.+--+-- Reference: <https://www.iana.org/go/rfc6903 RFC 6903>, section 6+relType :: LinkRelation+relType = RelType++-- | Refers to a parent document in a hierarchy of documents.+--+-- Reference: <https://www.iana.org/go/rfc5988 RFC 5988>+--+-- Note: This relation type registration did not indicate a reference.+-- Requested by Noah Slater.+relUp :: LinkRelation+relUp = RelUp++-- | Points to a resource containing the version history for the context.+--+-- Reference: <https://www.iana.org/go/rfc5829 RFC 5829>+relVersionHistory :: LinkRelation+relVersionHistory = RelVersionHistory++-- | Identifies a resource that is the source of the information in the link\'s+-- context.+--+-- Reference: <https://www.iana.org/go/rfc4287 RFC 4287>+relVia :: LinkRelation+relVia = RelVia++-- | Points to a working copy for this resource.+--+-- Reference: <https://www.iana.org/go/rfc5829 RFC 5829>+relWorkingCopy :: LinkRelation+relWorkingCopy = RelWorkingCopy++-- | Points to the versioned resource from which this working copy was+-- obtained.+--+-- Reference: <https://www.iana.org/go/rfc5829 RFC 5829>+relWorkingCopyOf :: LinkRelation+relWorkingCopyOf = RelWorkingCopyOf
+ util/generate.hs view
@@ -0,0 +1,353 @@+{- This file is part of link-relations.+ -+ - Written in 2015 by fr33domlover <fr33domlover@riseup.net>.+ -+ - ♡ Copying is an act of love. Please copy, reuse and share.+ -+ - The author(s) have dedicated all copyright and related and neighboring+ - rights to this software to the public domain worldwide. This software is+ - distributed without any warranty.+ -+ - You should have received a copy of the CC0 Public Domain Dedication along+ - with this software. If not, see+ - <http://creativecommons.org/publicdomain/zero/1.0/>.+ -}++{-# LANGUAGE OverloadedStrings #-}++module Main where++import Control.Applicative+import Control.Monad (guard, liftM)+import Data.Char (toUpper)+import Data.Csv+import Data.Foldable (mapM_)+import Data.Int (Int64)+import Data.List (intercalate)+import Data.Maybe (fromMaybe)+import Data.Monoid ((<>), mconcat)+import Prelude hiding (mapM_)++import qualified Data.ByteString.Lazy as BL+import qualified Data.ByteString.Lazy.Char8 as BLC+import qualified Data.Vector as V (length, toList)++-------------------------------------------------------------------------------+-- Configuration+-------------------------------------------------------------------------------++-- | The IANA link relations registry data.+csvFile :: FilePath+csvFile = "util/link-relations-1.csv"++-- | Haskell source template into which the data needs to be inserted.+hsTemplateFile :: FilePath+hsTemplateFile = "util/template.hs"++-- | Where to write the result of writing formatted data into the template.+outputFile :: FilePath+outputFile = "src/Web/LinkRelations.hs.new"++-- | Y-M-D date specifying the time of the last update to the IANA registry.+lastUpdated :: BL.ByteString+lastUpdated = "2015-01-21"++-------------------------------------------------------------------------------+-- Types+-------------------------------------------------------------------------------++data LinkRelInfo = LinkRelInfo+ { lrName :: BL.ByteString+ , lrDescription :: BL.ByteString+ , lrReferences :: BL.ByteString+ , lrNotes :: BL.ByteString+ }+ deriving (Show)++instance FromRecord LinkRelInfo where+ parseRecord v =+ if V.length v == 4+ then LinkRelInfo <$>+ v .! 0 <*>+ v .! 1 <*>+ v .! 2 <*>+ v .! 3+ else empty++data TemplateLine = TemplText BL.ByteString | TemplVar BL.ByteString++-------------------------------------------------------------------------------+-- Utilities+-------------------------------------------------------------------------------++-- | Like 'map', but applies one function to the first element and a different+-- function to the rest of the elements.+mapSep :: (a -> b) -> (a -> b) -> [a] -> [b]+mapSep _ _ [] = []+mapSep f g (x:xs) = f x : map g xs++-- | Like 'BLC.map', but applies the function /only/ to the first byte.+mapFstB :: (Char -> Char) -> BL.ByteString -> BL.ByteString+mapFstB f s =+ case BLC.uncons s of+ Nothing -> s+ Just (c, r) -> f c `BLC.cons` r++--mapTail :: (a -> a) -> [a] -> [a]+--mapTail _ [] = []+--mapTail f (x:xs) = x : map f xs++-- | Convert @this-is-some-name@ to @ThisIsSomeName@.+toCamel :: BL.ByteString -> BL.ByteString+toCamel = mconcat . map (mapFstB toUpper) . BLC.split '-'++-- | Apply a function to the first element.+applyFst :: (a -> c) -> (a, b) -> (c, b)+applyFst f (x, y) = (f x, y)++-- | Break a list of words into two lists. The first is the maximal prefix+-- whose length (including spaces between words) is at most N (unless the first+-- word is longer than N, in which case that word is returned), and the second+-- list is the rest of the word list.+breakN :: Int64 -> [BL.ByteString] -> ([BL.ByteString], [BL.ByteString])+breakN len ws = applyFst reverse $ f 0 [] ws+ where+ f _ xs [] = (xs, [])+ f n [] (y:ys) =+ let l = n + BL.length y -- 'n' should be 0 here+ in if len <= l+ then ([y], ys)+ else f l [y] ys+ f n xs r@(y:ys) =+ let l = n + 1 + BL.length y+ in if len < l+ then (xs, r)+ else f l (y:xs) ys++-- | Apply 'breakN' repeatedly on a word list, splitting it into a list of+-- word-lists.+splitN :: Int64 -> [BL.ByteString] -> [[BL.ByteString]]+splitN len = f+ where+ f ws =+ case breakN len ws of+ (xs, []) -> [xs]+ (xs, ys) -> xs : f ys++-- | Read a text file into a list of lines.+readLines :: FilePath -> IO [BL.ByteString]+readLines = liftM BLC.lines . BL.readFile++-------------------------------------------------------------------------------+-- Haddock Comments+-------------------------------------------------------------------------------++-- | Try to detect a link by suffix. Return remaining prefix and a suffix to+-- append after link conversion.+stripLinkSuffix :: BL.ByteString -> Maybe (BL.ByteString, BL.ByteString)+stripLinkSuffix w =+ case BLC.unsnoc w of+ Just (t, ']') -> Just (t, BL.empty)+ Just (t, ',') ->+ case BLC.unsnoc t of+ Just (r, ']') -> Just (r, BLC.singleton ',')+ _ -> Nothing+ _ -> Nothing++-- | If the given word is a link, convert to haddock format.+detectLink :: BL.ByteString -> Maybe BL.ByteString+detectLink w =+ let rfcPrefix = "[RFC"+ rfcDrop = 4+ httpPrefix = "[http"+ httpDrop = 1+ otherPrefix = "["+ otherDrop = 1+ iana = "<https://www.iana.org/go/"+ in case stripLinkSuffix w of+ Just (t, r)+ | rfcPrefix `BL.isPrefixOf` t -> Just $+ let num = BL.drop rfcDrop t+ in iana <> "rfc" <> num <> " RFC " <> num <> ">" <> r+ | httpPrefix `BL.isPrefixOf` t -> Just $+ "<" <> BL.drop httpDrop t <> ">" <> r+ | otherPrefix `BL.isPrefixOf` t -> Just $+ let name = BL.drop otherDrop t+ in iana <> name <> " " <> name <> ">" <> r+ | otherwise -> Nothing+ Nothing -> Nothing++-- | Escape some formatting characters in a non-link word.+escapeWord :: BL.ByteString -> BL.ByteString+escapeWord = BLC.foldr f BL.empty+ where+ f c s =+ if c `elem` ['/', '"', '\'']+ then '\\' `BLC.cons` c `BLC.cons` s+ else c `BLC.cons` s++-- | Convert links, espcape characters, do some comment text processing.+processWords :: [BL.ByteString] -> [BL.ByteString]+processWords = map $ \ s -> fromMaybe (escapeWord s) $ detectLink s++-- | Format a paragraph as haddock identifier comment lines.+toComment :: BL.ByteString -> [BL.ByteString]+toComment s =+ let mkFirst = ("-- | " <>) . BLC.unwords+ mkRest = ("-- " <>) . BLC.unwords+ in case breakN 74 $ processWords $ BLC.words s of+ (xs, []) -> [mkFirst xs]+ (xs, ys) -> mkFirst xs : map mkRest (splitN 76 ys)++-- | Format a paragraph as haddock identifier non-first comment lines.+toCommentCont :: BL.ByteString -> [BL.ByteString]+toCommentCont =+ let mkline = ("-- " <>) . BLC.unwords+ in map mkline . splitN 76 . processWords . BLC.words++-------------------------------------------------------------------------------+-- Registry Data+-------------------------------------------------------------------------------++-- | Given the CSV file path, read it into a list of linkrel records.+readData :: FilePath -> IO [LinkRelInfo]+readData file = do+ csv <- BL.readFile file+ case decode HasHeader csv of+ Left err -> error $ "CSV parsing failed: " ++ err+ Right lrs -> return $ V.toList lrs++-------------------------------------------------------------------------------+-- Template+-------------------------------------------------------------------------------++-- | Detect whether a template line is literal text or a variable.+parseLine :: BL.ByteString -> TemplateLine+parseLine s = fromMaybe (TemplText s) $ do+ (h, t) <- BLC.uncons s+ guard $ h == '$'+ (h', t') <- BLC.uncons t+ guard $ h' == '{'+ (i, l) <- BLC.unsnoc t'+ guard $ l == '}'+ return $ TemplVar i++-- | Interpolate the variable values into a template.+render :: (BL.ByteString -> BL.ByteString) -> [TemplateLine] -> BL.ByteString+render f =+ let g (TemplText s) = s `BLC.snoc` '\n'+ g (TemplVar v) = f v+ in mconcat . map g++-- | Read and parse a template file.+readTemplate :: FilePath -> IO [TemplateLine]+readTemplate = liftM (map parseLine) . readLines++-------------------------------------------------------------------------------+-- Haskell Code Generation+-------------------------------------------------------------------------------++-- date -----------------------------------------------------------------------++-- | Registry revision date to insert into haddock comment.+varDate :: BL.ByteString+varDate = "-- /" <> lastUpdated <> "/\n"++-- exports --------------------------------------------------------------------++-- | Given a linkrel name, get a matching Haskell variable name.+toSymName :: BL.ByteString -> BL.ByteString+toSymName = ("rel" <>) . toCamel++-- | Given a linkrel name, format an export source line.+formatExport :: BL.ByteString -> BL.ByteString+formatExport = (" , " <>) . toSymName++-- | Given a list of linkrel names, get the exports text.+mkVarExports :: [BL.ByteString] -> BL.ByteString+mkVarExports = BLC.unlines . map formatExport++-- ctors ----------------------------------------------------------------------++-- | Given a linkrel name, get a matching data constructor name.+toCtorName :: BL.ByteString -> BL.ByteString+toCtorName = ("Rel" <>) . toCamel++-- | Given a linkrel name, format a data constructor source line.+formatCtor :: BL.ByteString -> BL.ByteString+formatCtor = (" | " <>) . toCtorName++-- | Given a list of linkrel names, get the constructors text.+mkVarCtors :: [BL.ByteString] -> BL.ByteString+mkVarCtors = BLC.unlines . map formatCtor++-- hashmap --------------------------------------------------------------------++-- | Given a linkrel name, format a hashmap pair source line.+formatPair :: Bool -> BL.ByteString -> BL.ByteString+formatPair first name =+ let c = if first then "[" else ","+ in " " <> c <> " (\"" <> name <> "\", " <> toCtorName name <> ")"++-- | Given a list of linkrel names, get the hashmap text.+mkVarHashmap :: [BL.ByteString] -> BL.ByteString+mkVarHashmap = BLC.unlines . mapSep (formatPair True) (formatPair False)++-- tostr ----------------------------------------------------------------------++-- | Given a linkrel name, format a to-string source line.+formatMatch :: BL.ByteString -> BL.ByteString+formatMatch name = " " <> toCtorName name <> " -> \"" <> name <> "\""++-- | Given a list of linkrel names, get the tostr text.+mkVarTostr :: [BL.ByteString] -> BL.ByteString+mkVarTostr = BLC.unlines . map formatMatch++-- rels -----------------------------------------------------------------------++-- | Given a linkrel, format a haddock comment.+formatRelComment :: LinkRelInfo -> [BL.ByteString]+formatRelComment lr =+ let fmt pref s =+ if BL.null s+ then []+ else "--" : toCommentCont (pref <> s)+ in toComment (lrDescription lr) +++ fmt "Reference: " (lrReferences lr) +++ fmt "Note: " (lrNotes lr)++-- | Given a linkrel, format relation symbol lines.+formatRel :: LinkRelInfo -> [BL.ByteString]+formatRel lr =+ let name = lrName lr+ sym = toSymName name+ ctor = toCtorName name+ in formatRelComment lr +++ [ sym <> " :: LinkRelation"+ , sym <> " = " <> ctor+ ]++-- | Given a list of linkrels , get the rels text.+mkVarRels :: [LinkRelInfo] -> BL.ByteString+mkVarRels = BLC.unlines . intercalate [BL.empty] . map formatRel++-------------------------------------------------------------------------------+-- Main+-------------------------------------------------------------------------------++main :: IO ()+main = do+ lrs <- readData csvFile+ templ <- readTemplate hsTemplateFile+ let lrNames = map lrName lrs+ getVar s+ | s == "date" = varDate+ | s == "exports" = mkVarExports lrNames+ | s == "ctors" = mkVarCtors lrNames+ | s == "hashmap" = mkVarHashmap lrNames+ | s == "tostr" = mkVarTostr lrNames+ | s == "rels" = mkVarRels lrs+ | otherwise =+ error $ "No value defined for variable " ++ show s+ BL.writeFile outputFile $ render getVar templ+ putStrLn "Done."
+ util/link-relations-1.csv view
@@ -0,0 +1,153 @@+Relation Name,Description,Reference,Notes +about,Refers to a resource that is the subject of the link's context.,"[RFC6903], section 2", +alternate,Refers to a substitute for this context,[http://www.w3.org/TR/html5/links.html#link-type-alternate], +appendix,Refers to an appendix.,[http://www.w3.org/TR/1999/REC-html401-19991224], +archives,"Refers to a collection of records, documents, or other+ materials of historical interest.",[http://www.w3.org/TR/2011/WD-html5-20110113/links.html#rel-archives], +author,Refers to the context's author.,[http://www.w3.org/TR/html5/links.html#link-type-author], +bookmark,Gives a permanent link to use for bookmarking purposes.,[http://www.w3.org/TR/html5/links.html#link-type-bookmark], +canonical,Designates the preferred version of a resource (the IRI and its contents).,[RFC6596], +chapter,Refers to a chapter in a collection of resources.,[http://www.w3.org/TR/1999/REC-html401-19991224], +collection,The target IRI points to a resource which represents the collection resource for the context IRI.,[RFC6573], +contents,Refers to a table of contents.,[http://www.w3.org/TR/1999/REC-html401-19991224], +copyright,"Refers to a copyright statement that applies to the+ link's context.",[http://www.w3.org/TR/1999/REC-html401-19991224], +create-form,The target IRI points to a resource where a submission form can be obtained.,[RFC6861], +current,"Refers to a resource containing the most recent+ item(s) in a collection of resources.",[RFC5005], +derivedfrom,The target IRI points to a resource from which this material was derived.,[draft-hoffman-xml2rfc], +describedby,"Refers to a resource providing information about the+ link's context.",[http://www.w3.org/TR/powder-dr/#assoc-linking], +describes,"The relationship A 'describes' B asserts that+ resource A provides a description of resource B. There are no+ constraints on the format or representation of either A or B,+ neither are there any further constraints on either resource.",[RFC6892],"This link relation type is the inverse of the 'describedby'+ relation type. While 'describedby' establishes a relation from+ the described resource back to the resource that describes it,+ 'describes' established a relation from the describing resource to+ the resource it describes. If B is 'describedby' A, then A+ 'describes' B." +disclosure,Refers to a list of patent disclosures made with respect to material for which 'disclosure' relation is specified.,[RFC6579], +duplicate,"Refers to a resource whose available representations+ are byte-for-byte identical with the corresponding representations of+ the context IRI.",[RFC6249],"This relation is for static resources. That is, an HTTP GET+ request on any duplicate will return the same representation. It+ does not make sense for dynamic or POSTable resources and should not+ be used for them." +edit,"Refers to a resource that can be used to edit the+ link's context.",[RFC5023], +edit-form,"The target IRI points to a resource where a submission form for+ editing associated resource can be obtained.",[RFC6861], +edit-media,"Refers to a resource that can be used to edit media+ associated with the link's context.",[RFC5023], +enclosure,"Identifies a related resource that is potentially+ large and might require special handling.",[RFC4287], +first,"An IRI that refers to the furthest preceding resource+ in a series of resources.",[RFC5988],"This relation type registration did not indicate a+ reference. Originally requested by Mark Nottingham in December+ 2004." +glossary,Refers to a glossary of terms.,[http://www.w3.org/TR/1999/REC-html401-19991224], +help,Refers to context-sensitive help.,[http://www.w3.org/TR/html5/links.html#link-type-help], +hosts,"Refers to a resource hosted by the server indicated by+ the link context.",[RFC6690],"This relation is used in CoRE where links are retrieved as a+ ""/.well-known/core"" resource representation, and is the default+ relation type in the CoRE Link Format." +hub,"Refers to a hub that enables registration for+ notification of updates to the context.",[http://pubsubhubbub.googlecode.com],This relation type was requested by Brett Slatkin. +icon,Refers to an icon representing the link's context.,[http://www.w3.org/TR/html5/links.html#link-type-icon], +index,Refers to an index.,[http://www.w3.org/TR/1999/REC-html401-19991224], +item,The target IRI points to a resource that is a member of the collection represented by the context IRI.,[RFC6573], +last,"An IRI that refers to the furthest following resource+ in a series of resources.",[RFC5988],"This relation type registration did not indicate a+ reference. Originally requested by Mark Nottingham in December+ 2004." +latest-version,"Points to a resource containing the latest (e.g.,+ current) version of the context.",[RFC5829], +license,Refers to a license associated with this context.,[RFC4946],"For implications of use in HTML, see: + http://www.w3.org/TR/html5/links.html#link-type-license" +lrdd,"Refers to further information about the link's context,+ expressed as a LRDD (""Link-based Resource Descriptor Document"")+ resource. See [RFC6415] for information about+ processing this relation type in host-meta documents. When used+ elsewhere, it refers to additional links and other metadata.+ Multiple instances indicate additional LRDD resources. LRDD+ resources MUST have an ""application/xrd+xml"" representation, and+ MAY have others.",[RFC6415], +memento,"The Target IRI points to a Memento, a fixed resource that will not change state anymore.",[RFC7089],"A Memento for an Original Resource is a resource that+ encapsulates a prior state of the Original Resource." +monitor,Refers to a resource that can be used to monitor changes in an HTTP resource.,[RFC5989], +monitor-group,Refers to a resource that can be used to monitor changes in a specified group of HTTP resources.,[RFC5989], +next,"Indicates that the link's context is a part of a series, and+ that the next in the series is the link target.",[http://www.w3.org/TR/html5/links.html#link-type-next], +next-archive,Refers to the immediately following archive resource.,[RFC5005], +nofollow,Indicates that the context’s original author or publisher does not endorse the link target.,[http://www.w3.org/TR/html5/links.html#link-type-nofollow], +noreferrer,Indicates that no referrer information is to be leaked when following the link.,[http://www.w3.org/TR/html5/links.html#link-type-noreferrer], +original,The Target IRI points to an Original Resource.,[RFC7089],"An Original Resource is a resource that exists or used to+ exist, and for which access to one of its prior states may be+ required." +payment,Indicates a resource where payment is accepted.,[RFC5988],"This relation type registration did not indicate a+ reference. Requested by Joshua Kinberg and Robert Sayre. It is+ meant as a general way to facilitate acts of payment, and thus+ this specification makes no assumptions on the type of payment or+ transaction protocol. Examples may include a web page where+ donations are accepted or where goods and services are available+ for purchase. rel=""payment"" is not intended to initiate an+ automated transaction. In Atom documents, a link element with a+ rel=""payment"" attribute may exist at the feed/channel level and/or+ the entry/item level. For example, a rel=""payment"" link at the+ feed/channel level may point to a ""tip jar"" URI, whereas an entry/+ item containing a book review may include a rel=""payment"" link+ that points to the location where the book may be purchased+ through an online retailer." +predecessor-version,"Points to a resource containing the predecessor+ version in the version history.",[RFC5829], +prefetch,Indicates that the link target should be preemptively cached.,[http://www.w3.org/TR/html5/links.html#link-type-prefetch], +prev,"Indicates that the link's context is a part of a series, and+ that the previous in the series is the link target.",[http://www.w3.org/TR/html5/links.html#link-type-prev], +preview,Refers to a resource that provides a preview of the link's context.,"[RFC6903], section 3", +previous,"Refers to the previous resource in an ordered series+ of resources. Synonym for ""prev"".",[http://www.w3.org/TR/1999/REC-html401-19991224], +prev-archive,Refers to the immediately preceding archive resource.,[RFC5005], +privacy-policy,Refers to a privacy policy associated with the link's context.,"[RFC6903], section 4", +profile,"Identifying that a resource representation conforms+to a certain profile, without affecting the non-profile semantics+of the resource representation.",[RFC6906],"Profile URIs are primarily intended to be used as+identifiers, and thus clients SHOULD NOT indiscriminately access+profile URIs." +related,Identifies a related resource.,[RFC4287], +replies,"Identifies a resource that is a reply to the context+ of the link.",[RFC4685], +search,"Refers to a resource that can be used to search through+ the link's context and related resources.",[http://www.opensearch.org/Specifications/OpenSearch/1.1], +section,Refers to a section in a collection of resources.,[http://www.w3.org/TR/1999/REC-html401-19991224], +self,Conveys an identifier for the link's context.,[RFC4287], +service,"Indicates a URI that can be used to retrieve a+ service document.",[RFC5023],"When used in an Atom document, this relation type specifies+ Atom Publishing Protocol service documents by default. Requested+ by James Snell." +start,"Refers to the first resource in a collection of+ resources.",[http://www.w3.org/TR/1999/REC-html401-19991224], +stylesheet,Refers to a stylesheet.,[http://www.w3.org/TR/html5/links.html#link-type-stylesheet], +subsection,"Refers to a resource serving as a subsection in a+ collection of resources.",[http://www.w3.org/TR/1999/REC-html401-19991224], +successor-version,"Points to a resource containing the successor version+ in the version history.",[RFC5829], +tag,"Gives a tag (identified by the given address) that applies to+ the current document.",[http://www.w3.org/TR/html5/links.html#link-type-tag], +terms-of-service,Refers to the terms of service associated with the link's context.,"[RFC6903], section 5", +timegate,The Target IRI points to a TimeGate for an Original Resource.,[RFC7089],"A TimeGate for an Original Resource is a resource that is+ capable of datetime negotiation to support access to prior states+ of the Original Resource." +timemap,The Target IRI points to a TimeMap for an Original Resource.,[RFC7089],"A TimeMap for an Original Resource is a resource from which+ a list of URIs of Mementos of the Original Resource is available." +type,Refers to a resource identifying the abstract semantic type of which the link's context is considered to be an instance.,"[RFC6903], section 6", +up,"Refers to a parent document in a hierarchy of+ documents.",[RFC5988],"This relation type registration did not indicate a+ reference. Requested by Noah Slater." +version-history,"Points to a resource containing the version history+ for the context.",[RFC5829], +via,"Identifies a resource that is the source of the+ information in the link's context.",[RFC4287], +working-copy,Points to a working copy for this resource.,[RFC5829], +working-copy-of,"Points to the versioned resource from which this+ working copy was obtained.",[RFC5829],
+ util/template.hs view
@@ -0,0 +1,111 @@+{- This file is part of link-relations.+ -+ - Written in 2015 by fr33domlover <fr33domlover@riseup.net>.+ - Also includes parts generated from the IANA link relation registry.+ -+ - ♡ Copying is an act of love. Please copy, reuse and share.+ -+ - The author(s) have dedicated all copyright and related and neighboring+ - rights to this software to the public domain worldwide. This software is+ - distributed without any warranty.+ -+ - You should have received a copy of the CC0 Public Domain Dedication along+ - with this software. If not, see+ - <http://creativecommons.org/publicdomain/zero/1.0/>.+ -}++{-# LANGUAGE OverloadedStrings #-}++-- | A simple web link between two web resources, e.g. a hyperlink in a webpage+-- referring to another page, suggests that the resources are somehow related,+-- but it doesn't say /how/ they are related. For example, a blog post may link+-- to the author's main page (relation: author of the post) but also link to+-- the previous post (relation: previous post by chronological order).+--+-- Link relations provide a way to express the relation between resources+-- linked by a web link.+--+-- A link relation type may be represented by a URI, or by a registered link+-- relation name. IANA maintains a+-- <https://www.iana.org/assignments/link-relations registry> of link+-- relations. This module provides access to them through a dedicated+-- 'LinkRelation' datatype.+--+-- This version of the package corresponds to the+${date}+-- version of the registry.+module Web.LinkRelations+ ( -- * Types and Conversions+ LinkRelation+ , fromURI+ , fromURIStr+ , fromName+ , fromByteString+ , isURI+ , isName+ , toByteString+ -- * Link Relation Identifiers+${exports}+ )+where++import Control.Applicative ((<|>))+import URI.ByteString++import qualified Data.ByteString as B+import qualified Data.HashMap.Strict as M++-- | A web link relation type. Either a URI or a registered name.+data LinkRelation+ = FromURI URI+${ctors}+ deriving (Eq, Show)++-- | A mapping from name string to identifiers, for parsing a link relation+-- name from a string.+hashmap :: M.HashMap B.ByteString LinkRelation+hashmap = M.fromList+${hashmap}+ ]++-- | Create a link relation type from a URI.+fromURI :: URI -> LinkRelation+fromURI = FromURI++-- | Try to parse a string into a URI, returning a link relation if successful.+fromURIStr :: B.ByteString -> Maybe LinkRelation+fromURIStr s =+ case parseURI laxURIParserOptions s of+ Left _ -> Nothing+ Right u -> Just $ fromURI u++-- | Try to match a given link relation name against the registered names.+-- Return the matching link relation if successful.+fromName :: B.ByteString -> Maybe LinkRelation+fromName s = M.lookup s hashmap++-- | Try to parse the given string as a link relation, either as a registered+-- name or as a URI. If both fail, return 'Nothing'.+fromByteString :: B.ByteString -> Maybe LinkRelation+fromByteString s = fromName s <|> fromURIStr s++-- | Get the official registered name of a link relation (if it's a name) or+-- its URI string (if it's a URI).+toByteString :: LinkRelation -> B.ByteString+toByteString lr =+ case lr of+ FromURI u -> serializeURI' u+${tostr}++-- | Check whether a link relation is represented by a URI, i.e. is not a link+-- relation registered name.+isURI :: LinkRelation -> Bool+isURI (FromURI _) = True+isURI _ = False++-- | Check whether a link relation is represented by a registered name, i.e. is+-- not a URI.+isName :: LinkRelation -> Bool+isName = not . isURI++${rels}