From e81168f70ae0cc998671cbc6133dbb3c07dca77b Mon Sep 17 00:00:00 2001 From: Peter Murphy Date: Thu, 21 Mar 2024 23:29:42 -0400 Subject: [PATCH 1/3] fix: Codec for article slugs Allow for non-alphanumeric and non-lower-case characters in slugs. Fixes #127. --- src/Api/Endpoint.purs | 2 +- src/Capability/Resource/Article.purs | 2 +- src/Capability/Resource/Comment.purs | 2 +- src/Component/Part/FavoriteButton.purs | 2 +- src/Data/Article.purs | 4 +- src/Data/Route.purs | 4 +- src/Data/Slug.purs | 120 +++++++++++++++++++++++++ src/Page/Editor.purs | 2 +- src/Page/ViewArticle.purs | 2 +- 9 files changed, 130 insertions(+), 10 deletions(-) create mode 100644 src/Data/Slug.purs diff --git a/src/Api/Endpoint.purs b/src/Api/Endpoint.purs index d1aa2cf9..c925b67f 100644 --- a/src/Api/Endpoint.purs +++ b/src/Api/Endpoint.purs @@ -19,10 +19,10 @@ import Conduit.Data.Username (Username) import Data.Generic.Rep (class Generic) import Data.Lens.Iso.Newtype (_Newtype) import Data.Maybe (Maybe(..)) +import Data.Slug (Slug) import Routing.Duplex (RouteDuplex', int, optional, prefix, root, segment, string) import Routing.Duplex.Generic (noArgs, sum) import Routing.Duplex.Generic.Syntax ((/), (?)) -import Slug (Slug) -- | First, let's define a few types necessary for our larger `Endpoint` type. diff --git a/src/Capability/Resource/Article.purs b/src/Capability/Resource/Article.purs index 70e545f1..f1f7dbc7 100644 --- a/src/Capability/Resource/Article.purs +++ b/src/Capability/Resource/Article.purs @@ -17,8 +17,8 @@ import Conduit.Api.Endpoint (ArticleParams, Pagination) import Conduit.Data.Article (Article, ArticleWithMetadata) import Conduit.Data.PaginatedArray (PaginatedArray) import Data.Maybe (Maybe) +import Data.Slug (Slug) import Halogen (HalogenM, lift) -import Slug (Slug) -- | This capability represents the ability to manage articles in our system. Each function -- | represents a simple process to read, write, update, delete, favorite, or take some other action diff --git a/src/Capability/Resource/Comment.purs b/src/Capability/Resource/Comment.purs index b40d9d94..0d53a1ef 100644 --- a/src/Capability/Resource/Comment.purs +++ b/src/Capability/Resource/Comment.purs @@ -15,8 +15,8 @@ import Prelude import Conduit.Data.Comment (Comment, CommentId, CommentWithMetadata) import Data.Maybe (Maybe) +import Data.Slug (Slug) import Halogen (HalogenM, lift) -import Slug (Slug) -- | This capability represents the ability to manage comments in our system. Currently we only -- | need to get all comments, create a comment, or delete a comment, all of which must be diff --git a/src/Component/Part/FavoriteButton.purs b/src/Component/Part/FavoriteButton.purs index fbf33264..8af1dd86 100644 --- a/src/Component/Part/FavoriteButton.purs +++ b/src/Component/Part/FavoriteButton.purs @@ -20,10 +20,10 @@ import Conduit.Data.Article (ArticleWithMetadata) import Data.Foldable (for_) import Data.Lens (Traversal', preview, set) import Data.Maybe (Maybe) +import Data.Slug (Slug) import Halogen as H import Halogen.HTML as HH import Halogen.HTML.Events as HE -import Slug (Slug) -- A simple way to control button sizes diff --git a/src/Data/Article.purs b/src/Data/Article.purs index e39e04d6..b2610243 100644 --- a/src/Data/Article.purs +++ b/src/Data/Article.purs @@ -24,8 +24,8 @@ import Data.Codec.Argonaut.Migration as CAM import Data.Codec.Argonaut.Record as CAR import Data.Maybe (Maybe) import Data.PreciseDateTime (PreciseDateTime) -import Slug (Slug) -import Slug as Slug +import Data.Slug (Slug) +import Data.Slug as Slug import Type.Row (type (+)) -- | First, we'll describe the core fields that are always present when we have an `Article`. In diff --git a/src/Data/Route.purs b/src/Data/Route.purs index 5b5f2606..4776d20f 100644 --- a/src/Data/Route.purs +++ b/src/Data/Route.purs @@ -17,11 +17,11 @@ import Conduit.Data.Username (Username) import Conduit.Data.Username as Username import Data.Either (note) import Data.Generic.Rep (class Generic) +import Data.Slug (Slug) +import Data.Slug as Slug import Routing.Duplex (RouteDuplex', as, root, segment) import Routing.Duplex.Generic (noArgs, sum) import Routing.Duplex.Generic.Syntax ((/)) -import Slug (Slug) -import Slug as Slug -- | We'll represent routes in our application with a simple sum type. As the application grows, -- | you might want to swap this out with an extensible sum type with `Variant` and have several diff --git a/src/Data/Slug.purs b/src/Data/Slug.purs new file mode 100644 index 00000000..4681f121 --- /dev/null +++ b/src/Data/Slug.purs @@ -0,0 +1,120 @@ +module Data.Slug + ( Slug + , generate + , parse + , toString + , truncate + ) where + +import Prelude + +import Data.Argonaut.Decode (class DecodeJson, JsonDecodeError(..), decodeJson) +import Data.Argonaut.Encode (class EncodeJson, encodeJson) +import Data.Array as Array +import Data.CodePoint.Unicode (isLatin1) +import Data.Either (note) +import Data.Maybe (Maybe(..)) +import Data.String as String +import Data.String.CodePoints (codePointFromChar, fromCodePointArray, toCodePointArray) +import Data.String.Pattern (Pattern(..), Replacement(..)) + +-- | A `Slug` represents a string value which is guaranteed to have the +-- | following qualities: +-- | +-- | - it is not empty +-- | - it consists of groups of characters separated by `-` dashes, +-- | where the slug cannot begin or end with a dash, and there can +-- | never be two dashes in a row. +-- | +-- | Example: `Slug "this-is-an-article-slug"` +newtype Slug = Slug String + +derive newtype instance Eq Slug +derive newtype instance Ord Slug +derive newtype instance Semigroup Slug + +instance Show Slug where + show (Slug str) = "(Slug " <> str <> ")" + +instance EncodeJson Slug where + encodeJson (Slug s) = encodeJson s + +instance DecodeJson Slug where + decodeJson = note (TypeMismatch "Slug") <<< parse <=< decodeJson + +-- | Create a `Slug` from a string. This will transform the input string +-- | to be a valid slug (if it is possible to do so) by separating words +-- | with `-` dashes, ensuring the string does not begin or end with a +-- | dash, and ensuring there are never two dashes in a row. +-- | +-- | Slugs are usually created for article titles and other resources +-- | which need a human-readable resource name in a URL. +-- | +-- | ```purescript +-- | > Slug.generate "My article title!" +-- | > Just (Slug "My-article-title") +-- | +-- | > Slug.generate "¬¬¬{}¬¬¬" +-- | > Nothing +-- | ``` +generate :: String -> Maybe Slug +generate s = do + let arr = words $ onlyLatin1 $ stripApostrophes s + if Array.null arr then + Nothing + else + Just $ Slug $ String.joinWith "-" arr + where + -- Strip apostrophes to avoid unnecessary word breaks + stripApostrophes = String.replaceAll (Pattern "'") (Replacement "") + + -- Replace non-Latin 1 characters with spaces to be stripped later. + onlyLatin1 = + fromCodePointArray + <<< map (\x -> if isLatin1 x then x else codePointFromChar ' ') + <<< toCodePointArray + + -- Split on whitespace + words = Array.filter (not String.null) <<< String.split (Pattern " ") + +-- | Parse a valid slug (as a string) into a `Slug`. This will fail if the +-- | string is not a valid slug and does not provide the same behavior as +-- | `generate`. +-- | +-- | ```purescript +-- | > Slug.parse "my-article-title" +-- | > Just (Slug "my-article-title") +-- | +-- | > Slug.parse "My article" +-- | > Nothing +-- | ``` +parse :: String -> Maybe Slug +parse str = generate str >>= check + where + check slug@(Slug s) + | s == str = Just slug + | otherwise = Nothing + +-- | Unwrap a `Slug` into the string contained within, without performing +-- | any transformations. +-- | +-- | ```purescript +-- | > Slug.toString (mySlug :: Slug) +-- | > "my-slug-i-generated" +-- | ``` +toString :: Slug -> String +toString (Slug s) = s + +-- | Ensure a `Slug` is no longer than a given number of characters. If the last +-- | character is a dash, it will also be removed. Providing a non-positive +-- | number as the length will return `Nothing`. +-- | +-- | ```purescript +-- | > Slug.create "My article title is long!" >>= Slug.truncate 3 +-- | > Just (Slug "My") +-- | ``` +truncate :: Int -> Slug -> Maybe Slug +truncate n (Slug s) + | n < 1 = Nothing + | n >= String.length s = Just (Slug s) + | otherwise = generate $ String.take n s \ No newline at end of file diff --git a/src/Page/Editor.purs b/src/Page/Editor.purs index 5b34cd53..2d3d9f92 100644 --- a/src/Page/Editor.purs +++ b/src/Page/Editor.purs @@ -23,6 +23,7 @@ import Data.Either (either) import Data.Foldable (for_) import Data.Maybe (Maybe(..)) import Data.Set as Set +import Data.Slug (Slug) import Effect.Aff.Class (class MonadAff) import Formless as F import Halogen as H @@ -34,7 +35,6 @@ import Halogen.Store.Monad (class MonadStore) import Halogen.Store.Select (selectEq) import Network.RemoteData (RemoteData(..), fromMaybe, toMaybe) import Safe.Coerce (coerce) -import Slug (Slug) import Type.Proxy (Proxy(..)) type Input = Maybe Slug diff --git a/src/Page/ViewArticle.purs b/src/Page/ViewArticle.purs index 8d766847..431010a4 100644 --- a/src/Page/ViewArticle.purs +++ b/src/Page/ViewArticle.purs @@ -30,6 +30,7 @@ import Data.Lens (Traversal', preview) import Data.Lens.Record (prop) import Data.Maybe (Maybe(..)) import Data.Maybe as Maybe +import Data.Slug (Slug) import Effect.Aff.Class (class MonadAff) import Halogen as H import Halogen.HTML as HH @@ -39,7 +40,6 @@ import Halogen.Store.Connect (Connected, connect) import Halogen.Store.Monad (class MonadStore) import Halogen.Store.Select (selectEq) import Network.RemoteData (RemoteData(..), _Success, fromMaybe) -import Slug (Slug) import Type.Proxy (Proxy(..)) import Web.Event.Event (Event) import Web.Event.Event as Event From a978d5cdb976c7d88b4e8414150611ce50469516 Mon Sep 17 00:00:00 2001 From: Peter Murphy <26548438+ptrfrncsmrph@users.noreply.github.com> Date: Sat, 23 Mar 2024 10:22:56 -0400 Subject: [PATCH 2/3] fix: PR feedback Removing unused `Semigroup`, `Show`, `EncodeJson`, and `DecodeJson` instances from `Slug` module, adding newline at end of file, and removing unused `slug` dependency from `spago.yaml`. --- spago.yaml | 1 - src/Data/Slug.purs | 17 ++--------------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/spago.yaml b/spago.yaml index 11859ce6..6a3181a2 100644 --- a/spago.yaml +++ b/spago.yaml @@ -36,7 +36,6 @@ package: - routing - routing-duplex - safe-coerce - - slug - strings - transformers - tuples diff --git a/src/Data/Slug.purs b/src/Data/Slug.purs index 4681f121..2d68d5d5 100644 --- a/src/Data/Slug.purs +++ b/src/Data/Slug.purs @@ -8,11 +8,8 @@ module Data.Slug import Prelude -import Data.Argonaut.Decode (class DecodeJson, JsonDecodeError(..), decodeJson) -import Data.Argonaut.Encode (class EncodeJson, encodeJson) import Data.Array as Array import Data.CodePoint.Unicode (isLatin1) -import Data.Either (note) import Data.Maybe (Maybe(..)) import Data.String as String import Data.String.CodePoints (codePointFromChar, fromCodePointArray, toCodePointArray) @@ -26,21 +23,11 @@ import Data.String.Pattern (Pattern(..), Replacement(..)) -- | where the slug cannot begin or end with a dash, and there can -- | never be two dashes in a row. -- | --- | Example: `Slug "this-is-an-article-slug"` +-- | Example: `Slug "This-is-an-article-slug"` newtype Slug = Slug String derive newtype instance Eq Slug derive newtype instance Ord Slug -derive newtype instance Semigroup Slug - -instance Show Slug where - show (Slug str) = "(Slug " <> str <> ")" - -instance EncodeJson Slug where - encodeJson (Slug s) = encodeJson s - -instance DecodeJson Slug where - decodeJson = note (TypeMismatch "Slug") <<< parse <=< decodeJson -- | Create a `Slug` from a string. This will transform the input string -- | to be a valid slug (if it is possible to do so) by separating words @@ -117,4 +104,4 @@ truncate :: Int -> Slug -> Maybe Slug truncate n (Slug s) | n < 1 = Nothing | n >= String.length s = Just (Slug s) - | otherwise = generate $ String.take n s \ No newline at end of file + | otherwise = generate $ String.take n s From ced03b5d2ddc0fc32fdf072f585ddcf543ca18e7 Mon Sep 17 00:00:00 2001 From: Peter Murphy <26548438+ptrfrncsmrph@users.noreply.github.com> Date: Sat, 23 Mar 2024 10:25:53 -0400 Subject: [PATCH 3/3] chore: Commit spago.lock --- .gitignore | 3 + spago.lock | 1353 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1356 insertions(+) create mode 100644 spago.lock diff --git a/.gitignore b/.gitignore index 5779f9ec..8b9de113 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,6 @@ output-es # Dist dist/*.js + +# Keep spago.lock +!spago.lock diff --git a/spago.lock b/spago.lock new file mode 100644 index 00000000..bb22d49c --- /dev/null +++ b/spago.lock @@ -0,0 +1,1353 @@ +workspace: + packages: + halogen-realworld: + path: ./ + dependencies: + - aff + - affjax + - affjax-web + - argonaut-core + - arrays + - bifunctors + - codec + - codec-argonaut + - console + - const + - datetime + - dom-indexed + - effect + - either + - enums + - foldable-traversable + - formatters + - halogen + - halogen-formless + - halogen-store + - http-methods + - lists + - maybe + - newtype + - now + - ordered-collections + - parallel + - precise-datetime + - prelude + - profunctor + - profunctor-lenses + - remotedata + - routing + - routing-duplex + - safe-coerce + - strings + - transformers + - tuples + - typelevel-prelude + - web-events + - web-html + - web-storage + - web-uievents + test_dependencies: [] + build_plan: + - aff + - affjax + - affjax-web + - argonaut-core + - arraybuffer-types + - arrays + - assert + - avar + - bifunctors + - catenable-lists + - codec + - codec-argonaut + - console + - const + - contravariant + - control + - convertable-options + - datetime + - decimals + - distributive + - dom-indexed + - effect + - either + - enums + - exceptions + - exists + - fixed-points + - foldable-traversable + - foreign + - foreign-object + - fork + - form-urlencoded + - formatters + - free + - freeap + - functions + - functors + - gen + - halogen + - halogen-formless + - halogen-hooks + - halogen-store + - halogen-subscriptions + - halogen-vdom + - heterogeneous + - http-methods + - identity + - integers + - invariant + - js-date + - js-uri + - lazy + - lcg + - lists + - maybe + - media-types + - newtype + - nonempty + - now + - nullable + - numbers + - ordered-collections + - orders + - parallel + - parsing + - partial + - precise-datetime + - prelude + - profunctor + - profunctor-lenses + - quickcheck + - random + - record + - refs + - remotedata + - routing + - routing-duplex + - safe-coerce + - semirings + - st + - strings + - tailrec + - transformers + - tuples + - type-equality + - typelevel-prelude + - unfoldable + - unicode + - unsafe-coerce + - unsafe-reference + - validation + - variant + - web-clipboard + - web-dom + - web-events + - web-file + - web-html + - web-pointerevents + - web-promise + - web-storage + - web-touchevents + - web-uievents + - web-xhr + extra_packages: {} +packages: + aff: + type: registry + version: 7.1.0 + integrity: sha256-7hOC6uQO9XBAI5FD8F33ChLjFAiZVfd4BJMqlMh7TNU= + dependencies: + - arrays + - bifunctors + - control + - datetime + - effect + - either + - exceptions + - foldable-traversable + - functions + - maybe + - newtype + - parallel + - prelude + - refs + - tailrec + - transformers + - unsafe-coerce + affjax: + type: registry + version: 13.0.0 + integrity: sha256-blYfaoW4FYIrIdvmT4sB7nN7BathFaEfZuiVLPmHJOo= + dependencies: + - aff + - argonaut-core + - arraybuffer-types + - foreign + - form-urlencoded + - http-methods + - integers + - media-types + - nullable + - refs + - unsafe-coerce + - web-xhr + affjax-web: + type: registry + version: 1.0.0 + integrity: sha256-n/yJUk1wMxMN7fJ2TJ+fELgieomy29N617yOshAnrc0= + dependencies: + - aff + - affjax + - either + - maybe + - prelude + argonaut-core: + type: registry + version: 7.0.0 + integrity: sha256-RC82GfAjItydxrO24cdX373KHVZiLqybu19b5X8u7B4= + dependencies: + - arrays + - control + - either + - foreign-object + - functions + - gen + - maybe + - nonempty + - prelude + - strings + - tailrec + arraybuffer-types: + type: registry + version: 3.0.2 + integrity: sha256-mQKokysYVkooS4uXbO+yovmV/s8b138Ws3zQvOwIHRA= + dependencies: [] + arrays: + type: registry + version: 7.3.0 + integrity: sha256-tmcklBlc/muUtUfr9RapdCPwnlQeB3aSrC4dK85gQlc= + dependencies: + - bifunctors + - control + - foldable-traversable + - functions + - maybe + - nonempty + - partial + - prelude + - safe-coerce + - st + - tailrec + - tuples + - unfoldable + - unsafe-coerce + assert: + type: registry + version: 6.0.0 + integrity: sha256-hCSYcCw9kj3qujoDcriWhCdmrpPZoguSPDZhEMnTl3A= + dependencies: + - console + - effect + - prelude + avar: + type: registry + version: 5.0.0 + integrity: sha256-e7hf0x4hEpcygXP0LtvfvAQ49Bbj2aWtZT3gqM///0A= + dependencies: + - aff + - effect + - either + - exceptions + - functions + - maybe + bifunctors: + type: registry + version: 6.0.0 + integrity: sha256-/gZwC9YhNxZNQpnHa5BIYerCGM2jeX9ukZiEvYxm5Nw= + dependencies: + - const + - either + - newtype + - prelude + - tuples + catenable-lists: + type: registry + version: 7.0.0 + integrity: sha256-76vYENhwF4BWTBsjeLuErCH2jqVT4M3R1HX+4RwSftA= + dependencies: + - control + - foldable-traversable + - lists + - maybe + - prelude + - tuples + - unfoldable + codec: + type: registry + version: 6.1.0 + integrity: sha256-6vMLNlsJxQarVQ9cn1FYfl5x6opfzxAza15SzRdxFxQ= + dependencies: + - bifunctors + - profunctor + codec-argonaut: + type: registry + version: 10.0.0 + integrity: sha256-n80U8KiBk333qfQwDobSZWiyNg9BA3CL/EwFznIdRwI= + dependencies: + - argonaut-core + - codec + - foreign-object + - ordered-collections + - type-equality + - variant + console: + type: registry + version: 6.1.0 + integrity: sha256-CxmAzjgyuGDmt9FZW51VhV6rBPwR6o0YeKUzA9rSzcM= + dependencies: + - effect + - prelude + const: + type: registry + version: 6.0.0 + integrity: sha256-tNrxDW8D8H4jdHE2HiPzpLy08zkzJMmGHdRqt5BQuTc= + dependencies: + - invariant + - newtype + - prelude + contravariant: + type: registry + version: 6.0.0 + integrity: sha256-TP+ooAp3vvmdjfQsQJSichF5B4BPDHp3wAJoWchip6c= + dependencies: + - const + - either + - newtype + - prelude + - tuples + control: + type: registry + version: 6.0.0 + integrity: sha256-sH7Pg9E96JCPF9PIA6oQ8+BjTyO/BH1ZuE/bOcyj4Jk= + dependencies: + - newtype + - prelude + convertable-options: + type: registry + version: 1.0.0 + integrity: sha256-IFsYp0rXyzUtjoi3jed6yFYAVM+NhfgSn2j/zkjpccM= + dependencies: + - console + - effect + - maybe + - record + datetime: + type: registry + version: 6.1.0 + integrity: sha256-g/5X5BBegQWLpI9IWD+sY6mcaYpzzlW5lz5NBzaMtyI= + dependencies: + - bifunctors + - control + - either + - enums + - foldable-traversable + - functions + - gen + - integers + - lists + - maybe + - newtype + - numbers + - ordered-collections + - partial + - prelude + - tuples + decimals: + type: registry + version: 7.1.0 + integrity: sha256-DriR6lPEfFpjVv7e4JAQkr3ZLf0h17Qg2cAIrhxWV7w= + dependencies: + - maybe + distributive: + type: registry + version: 6.0.0 + integrity: sha256-HTDdmEnzigMl+02SJB88j+gAXDx9VKsbvR4MJGDPbOQ= + dependencies: + - identity + - newtype + - prelude + - tuples + - type-equality + dom-indexed: + type: registry + version: 11.0.0 + integrity: sha256-asNUditTILJdNGS7xxFFkm6TrxC0hykoZUII3aTi5Q4= + dependencies: + - media-types + - prelude + - web-clipboard + - web-pointerevents + - web-touchevents + effect: + type: registry + version: 4.0.0 + integrity: sha256-eBtZu+HZcMa5HilvI6kaDyVX3ji8p0W9MGKy2K4T6+M= + dependencies: + - prelude + either: + type: registry + version: 6.1.0 + integrity: sha256-6hgTPisnMWVwQivOu2PKYcH8uqjEOOqDyaDQVUchTpY= + dependencies: + - control + - invariant + - maybe + - prelude + enums: + type: registry + version: 6.0.1 + integrity: sha256-HWaD73JFLorc4A6trKIRUeDMdzE+GpkJaEOM1nTNkC8= + dependencies: + - control + - either + - gen + - maybe + - newtype + - nonempty + - partial + - prelude + - tuples + - unfoldable + exceptions: + type: registry + version: 6.0.0 + integrity: sha256-y/xTAEIZIARCE+50/u1di0ncebJ+CIwNOLswyOWzMTw= + dependencies: + - effect + - either + - maybe + - prelude + exists: + type: registry + version: 6.0.0 + integrity: sha256-A0JQHpTfo1dNOj9U5/Fd3xndlRSE0g2IQWOGor2yXn8= + dependencies: + - unsafe-coerce + fixed-points: + type: registry + version: 7.0.0 + integrity: sha256-hTl5fzeG4mzAOFzEzAeNH7kJvJgYCH7x3v2NdX9pOE4= + dependencies: + - exists + - newtype + - prelude + - transformers + foldable-traversable: + type: registry + version: 6.0.0 + integrity: sha256-fLeqRYM4jUrZD5H4WqcwUgzU7XfYkzO4zhgtNc3jcWM= + dependencies: + - bifunctors + - const + - control + - either + - functors + - identity + - maybe + - newtype + - orders + - prelude + - tuples + foreign: + type: registry + version: 7.0.0 + integrity: sha256-1ORiqoS3HW+qfwSZAppHPWy4/6AQysxZ2t29jcdUMNA= + dependencies: + - either + - functions + - identity + - integers + - lists + - maybe + - prelude + - strings + - transformers + foreign-object: + type: registry + version: 4.1.0 + integrity: sha256-q24okj6mT+yGHYQ+ei/pYPj5ih6sTbu7eDv/WU56JVo= + dependencies: + - arrays + - foldable-traversable + - functions + - gen + - lists + - maybe + - prelude + - st + - tailrec + - tuples + - typelevel-prelude + - unfoldable + fork: + type: registry + version: 6.0.0 + integrity: sha256-X7u0SuCvFbLbzuNEKLBNuWjmcroqMqit4xEzpQwAP7E= + dependencies: + - aff + form-urlencoded: + type: registry + version: 7.0.0 + integrity: sha256-WUzk8DTjrbPVHKZ5w7XpPBO6ci6xFhvYguHp6RvX+18= + dependencies: + - foldable-traversable + - js-uri + - maybe + - newtype + - prelude + - strings + - tuples + formatters: + type: registry + version: 7.0.0 + integrity: sha256-5JaC9d2p0xoqJWjWxlHH19R4iJwFTBr4j7SlYcLgicE= + dependencies: + - datetime + - fixed-points + - lists + - numbers + - parsing + - prelude + - transformers + free: + type: registry + version: 7.1.0 + integrity: sha256-JAumgEsGSzJCNLD8AaFvuX7CpqS5yruCngi6yI7+V5k= + dependencies: + - catenable-lists + - control + - distributive + - either + - exists + - foldable-traversable + - invariant + - lazy + - maybe + - prelude + - tailrec + - transformers + - tuples + - unsafe-coerce + freeap: + type: registry + version: 7.0.0 + integrity: sha256-T1VbmNxdNSKEgV4p8uFFv0F16cz+Xx1BkfF64etSdNI= + dependencies: + - const + - exists + - gen + - lists + functions: + type: registry + version: 6.0.0 + integrity: sha256-adMyJNEnhGde2unHHAP79gPtlNjNqzgLB8arEOn9hLI= + dependencies: + - prelude + functors: + type: registry + version: 5.0.0 + integrity: sha256-zfPWWYisbD84MqwpJSZFlvM6v86McM68ob8p9s27ywU= + dependencies: + - bifunctors + - const + - contravariant + - control + - distributive + - either + - invariant + - maybe + - newtype + - prelude + - profunctor + - tuples + - unsafe-coerce + gen: + type: registry + version: 4.0.0 + integrity: sha256-f7yzAXWwr+xnaqEOcvyO3ezKdoes8+WXWdXIHDBCAPI= + dependencies: + - either + - foldable-traversable + - identity + - maybe + - newtype + - nonempty + - prelude + - tailrec + - tuples + - unfoldable + halogen: + type: registry + version: 7.0.0 + integrity: sha256-aAE8oW32YiDdA3oQZxPbFkK4n31paT4JL6pvzOe47YE= + dependencies: + - aff + - avar + - console + - const + - dom-indexed + - effect + - foreign + - fork + - free + - freeap + - halogen-subscriptions + - halogen-vdom + - media-types + - nullable + - ordered-collections + - parallel + - profunctor + - transformers + - unsafe-coerce + - unsafe-reference + - web-file + - web-uievents + halogen-formless: + type: registry + version: 4.0.3 + integrity: sha256-HqNk/2CT01NPn1HVzAHCsnJ0K56tgtoBcVvKpRww5jo= + dependencies: + - convertable-options + - effect + - either + - foldable-traversable + - foreign-object + - halogen + - heterogeneous + - maybe + - prelude + - record + - safe-coerce + - type-equality + - unsafe-coerce + - unsafe-reference + - variant + - web-events + - web-uievents + halogen-hooks: + type: registry + version: 0.6.3 + integrity: sha256-r3Win1phxy3TCxuS6Ws2lrkQxpPZ8U1CPWcgdXj9qq8= + dependencies: + - aff + - arrays + - bifunctors + - effect + - exceptions + - foldable-traversable + - foreign-object + - free + - freeap + - halogen + - halogen-subscriptions + - maybe + - newtype + - ordered-collections + - parallel + - partial + - prelude + - refs + - tailrec + - transformers + - tuples + - unsafe-coerce + - unsafe-reference + - web-dom + - web-html + halogen-store: + type: registry + version: 0.5.4 + integrity: sha256-Mew74D5iJkh/tZ1JhCE4qKgv1Iv/nnhD3yMQphFTd4k= + dependencies: + - aff + - distributive + - effect + - fork + - halogen + - halogen-hooks + - halogen-subscriptions + - maybe + - prelude + - refs + - tailrec + - transformers + - tuples + - unsafe-reference + halogen-subscriptions: + type: registry + version: 2.0.0 + integrity: sha256-8/BPME/sC/kWMDxp0+n4k09gA1IIedXn2yUJ4pCH5xw= + dependencies: + - arrays + - effect + - foldable-traversable + - functors + - refs + - safe-coerce + - unsafe-reference + halogen-vdom: + type: registry + version: 8.0.0 + integrity: sha256-5UMDekaYNSM3jtpfWoWTbmZ38rIcnguzGRW3z+IQgV4= + dependencies: + - bifunctors + - effect + - foreign + - foreign-object + - maybe + - prelude + - refs + - tuples + - unsafe-coerce + - web-html + heterogeneous: + type: registry + version: 0.6.0 + integrity: sha256-cfNYSK6yYmjTrkzk95Otpv6TUUkeBreexwqG/tBvUyg= + dependencies: + - either + - functors + - prelude + - record + - tuples + - variant + http-methods: + type: registry + version: 6.0.0 + integrity: sha256-Orr7rbDGcp7qoqmUMXPRMjBx+C4jqOQcFe9+gE3nMgU= + dependencies: + - either + - prelude + - strings + identity: + type: registry + version: 6.0.0 + integrity: sha256-4wY0XZbAksjY6UAg99WkuKyJlQlWAfTi2ssadH0wVMY= + dependencies: + - control + - invariant + - newtype + - prelude + integers: + type: registry + version: 6.0.0 + integrity: sha256-sf+sK26R1hzwl3NhXR7WAu9zCDjQnfoXwcyGoseX158= + dependencies: + - maybe + - numbers + - prelude + invariant: + type: registry + version: 6.0.0 + integrity: sha256-RGWWyYrz0Hs1KjPDA+87Kia67ZFBhfJ5lMGOMCEFoLo= + dependencies: + - control + - prelude + js-date: + type: registry + version: 8.0.0 + integrity: sha256-6TVF4DWg5JL+jRAsoMssYw8rgOVALMUHT1CuNZt8NRo= + dependencies: + - datetime + - effect + - exceptions + - foreign + - integers + - now + js-uri: + type: registry + version: 3.1.0 + integrity: sha256-3p0ynHveCJmC2CXze+eMBdW/2l5e953Q8XMAKz+jxUo= + dependencies: + - functions + - maybe + lazy: + type: registry + version: 6.0.0 + integrity: sha256-lMsfFOnlqfe4KzRRiW8ot5ge6HtcU3Eyh2XkXcP5IgU= + dependencies: + - control + - foldable-traversable + - invariant + - prelude + lcg: + type: registry + version: 4.0.0 + integrity: sha256-h7ME5cthLfbgJOJdsZcSfFpwXsx4rf8YmhebU+3iSYg= + dependencies: + - effect + - integers + - maybe + - partial + - prelude + - random + lists: + type: registry + version: 7.0.0 + integrity: sha256-EKF15qYqucuXP2lT/xPxhqy58f0FFT6KHdIB/yBOayI= + dependencies: + - bifunctors + - control + - foldable-traversable + - lazy + - maybe + - newtype + - nonempty + - partial + - prelude + - tailrec + - tuples + - unfoldable + maybe: + type: registry + version: 6.0.0 + integrity: sha256-5cCIb0wPwbat2PRkQhUeZO0jcAmf8jCt2qE0wbC3v2Q= + dependencies: + - control + - invariant + - newtype + - prelude + media-types: + type: registry + version: 6.0.0 + integrity: sha256-n/4FoGBasbVSYscGVRSyBunQ6CZbL3jsYL+Lp01mc9k= + dependencies: + - newtype + - prelude + newtype: + type: registry + version: 5.0.0 + integrity: sha256-gdrQu8oGe9eZE6L3wOI8ql/igOg+zEGB5ITh2g+uttw= + dependencies: + - prelude + - safe-coerce + nonempty: + type: registry + version: 7.0.0 + integrity: sha256-54ablJZUHGvvlTJzi3oXyPCuvY6zsrWJuH/dMJ/MFLs= + dependencies: + - control + - foldable-traversable + - maybe + - prelude + - tuples + - unfoldable + now: + type: registry + version: 6.0.0 + integrity: sha256-xZ7x37ZMREfs6GCDw/h+FaKHV/3sPWmtqBZRGTxybQY= + dependencies: + - datetime + - effect + nullable: + type: registry + version: 6.0.0 + integrity: sha256-yiGBVl3AD+Guy4kNWWeN+zl1gCiJK+oeIFtZtPCw4+o= + dependencies: + - effect + - functions + - maybe + numbers: + type: registry + version: 9.0.1 + integrity: sha256-/9M6aeMDBdB4cwYDeJvLFprAHZ49EbtKQLIJsneXLIk= + dependencies: + - functions + - maybe + ordered-collections: + type: registry + version: 3.1.1 + integrity: sha256-boSYHmlz4aSbwsNN4VxiwCStc0t+y1F7BXmBS+1JNtI= + dependencies: + - arrays + - foldable-traversable + - gen + - lists + - maybe + - partial + - prelude + - st + - tailrec + - tuples + - unfoldable + orders: + type: registry + version: 6.0.0 + integrity: sha256-nBA0g3/ai0euH8q9pSbGqk53W2q6agm/dECZTHcoink= + dependencies: + - newtype + - prelude + parallel: + type: registry + version: 6.0.0 + integrity: sha256-VJbkGD0rAKX+NUEeBJbYJ78bEKaZbgow+QwQEfPB6ko= + dependencies: + - control + - effect + - either + - foldable-traversable + - functors + - maybe + - newtype + - prelude + - profunctor + - refs + - transformers + parsing: + type: registry + version: 10.2.0 + integrity: sha256-ZDIdMFAKkst57x6BVa1aUWJnS8smoZnXsZ339Aq1mPA= + dependencies: + - arrays + - control + - effect + - either + - enums + - foldable-traversable + - functions + - identity + - integers + - lazy + - lists + - maybe + - newtype + - nullable + - numbers + - partial + - prelude + - st + - strings + - tailrec + - transformers + - tuples + - unfoldable + - unicode + - unsafe-coerce + partial: + type: registry + version: 4.0.0 + integrity: sha256-fwXerld6Xw1VkReh8yeQsdtLVrjfGiVuC5bA1Wyo/J4= + dependencies: [] + precise-datetime: + type: registry + version: 7.0.0 + integrity: sha256-F7tzZ7++Ihtg3xjumzwaHQvGQg61UtEAe5MWeOlTzRY= + dependencies: + - arrays + - datetime + - decimals + - either + - enums + - foldable-traversable + - formatters + - integers + - js-date + - lists + - maybe + - newtype + - numbers + - prelude + - strings + - tuples + - unicode + prelude: + type: registry + version: 6.0.1 + integrity: sha256-o8p6SLYmVPqzXZhQFd2hGAWEwBoXl1swxLG/scpJ0V0= + dependencies: [] + profunctor: + type: registry + version: 6.0.0 + integrity: sha256-99NzxFgTr4CGlCSRYG1kShL+JhYbihhHtbOk1/0R5zI= + dependencies: + - control + - distributive + - either + - exists + - invariant + - newtype + - prelude + - tuples + profunctor-lenses: + type: registry + version: 8.0.0 + integrity: sha256-K7f29rHRHgVSb2Y/PaSKtfYPriP6n87BJNO7EhsZHas= + dependencies: + - arrays + - bifunctors + - const + - control + - distributive + - either + - foldable-traversable + - foreign-object + - functors + - identity + - lists + - maybe + - newtype + - ordered-collections + - partial + - prelude + - profunctor + - record + - transformers + - tuples + quickcheck: + type: registry + version: 8.0.1 + integrity: sha256-ZvpccKQCvgslTXZCNmpYW4bUsFzhZd/kQUr2WmxFTGY= + dependencies: + - arrays + - console + - control + - effect + - either + - enums + - exceptions + - foldable-traversable + - gen + - identity + - integers + - lazy + - lcg + - lists + - maybe + - newtype + - nonempty + - numbers + - partial + - prelude + - record + - st + - strings + - tailrec + - transformers + - tuples + - unfoldable + random: + type: registry + version: 6.0.0 + integrity: sha256-CJ611a35MPCE7XQMp0rdC6MCn76znlhisiCRgboAG+Q= + dependencies: + - effect + - integers + record: + type: registry + version: 4.0.0 + integrity: sha256-Za5U85bTRJEfGK5Sk4hM41oXy84YQI0I8TL3WUn1Qzg= + dependencies: + - functions + - prelude + - unsafe-coerce + refs: + type: registry + version: 6.0.0 + integrity: sha256-Vgwne7jIbD3ZMoLNNETLT8Litw6lIYo3MfYNdtYWj9s= + dependencies: + - effect + - prelude + remotedata: + type: registry + version: 5.0.0 + integrity: sha256-s+Udq18AZgZC/88P4ER3w9ur5WPchvPTiEp8zDttSCc= + dependencies: + - bifunctors + - either + - profunctor-lenses + routing: + type: registry + version: 11.0.0 + integrity: sha256-h2ZehllxQlfJDYh6Rlj0VySlJwqJvY4LMkb7p8cjxLs= + dependencies: + - aff + - console + - control + - effect + - either + - foldable-traversable + - integers + - js-uri + - lists + - maybe + - numbers + - partial + - prelude + - semirings + - tuples + - validation + - web-html + routing-duplex: + type: registry + version: 0.7.0 + integrity: sha256-hgWzZPft6067zYvoZ1n0y/dSz4H2jBNREwfC3qC/s8Y= + dependencies: + - arrays + - assert + - control + - effect + - either + - foldable-traversable + - integers + - js-uri + - lazy + - maybe + - newtype + - prelude + - profunctor + - quickcheck + - record + - strings + - tuples + safe-coerce: + type: registry + version: 2.0.0 + integrity: sha256-a1ibQkiUcbODbLE/WAq7Ttbbh9ex+x33VCQ7GngKudU= + dependencies: + - unsafe-coerce + semirings: + type: registry + version: 7.0.0 + integrity: sha256-2qGNMxVYns7RJxZd1uGtJbGTeVl/6Ozsz9OM5gRM61A= + dependencies: + - foldable-traversable + - lists + - newtype + - prelude + st: + type: registry + version: 6.2.0 + integrity: sha256-z9X0WsOUlPwNx9GlCC+YccCyz8MejC8Wb0C4+9fiBRY= + dependencies: + - partial + - prelude + - tailrec + - unsafe-coerce + strings: + type: registry + version: 6.0.1 + integrity: sha256-WssD3DbX4OPzxSdjvRMX0yvc9+pS7n5gyPv5I2Trb7k= + dependencies: + - arrays + - control + - either + - enums + - foldable-traversable + - gen + - integers + - maybe + - newtype + - nonempty + - partial + - prelude + - tailrec + - tuples + - unfoldable + - unsafe-coerce + tailrec: + type: registry + version: 6.1.0 + integrity: sha256-Xx19ECVDRrDWpz9D2GxQHHV89vd61dnXxQm0IcYQHGk= + dependencies: + - bifunctors + - effect + - either + - identity + - maybe + - partial + - prelude + - refs + transformers: + type: registry + version: 6.0.0 + integrity: sha256-Pzw40HjthX77tdPAYzjx43LK3X5Bb7ZspYAp27wksFA= + dependencies: + - control + - distributive + - effect + - either + - exceptions + - foldable-traversable + - identity + - lazy + - maybe + - newtype + - prelude + - tailrec + - tuples + - unfoldable + tuples: + type: registry + version: 7.0.0 + integrity: sha256-1rXgTomes9105BjgXqIw0FL6Fz1lqqUTLWOumhWec1M= + dependencies: + - control + - invariant + - prelude + type-equality: + type: registry + version: 4.0.1 + integrity: sha256-Hs9D6Y71zFi/b+qu5NSbuadUQXe5iv5iWx0226vOHUw= + dependencies: [] + typelevel-prelude: + type: registry + version: 7.0.0 + integrity: sha256-uFF2ph+vHcQpfPuPf2a3ukJDFmLhApmkpTMviHIWgJM= + dependencies: + - prelude + - type-equality + unfoldable: + type: registry + version: 6.0.0 + integrity: sha256-JtikvJdktRap7vr/K4ITlxUX1QexpnqBq0G/InLr6eg= + dependencies: + - foldable-traversable + - maybe + - partial + - prelude + - tuples + unicode: + type: registry + version: 6.0.0 + integrity: sha256-QJnTVZpmihEAUiMeYrfkusVoziJWp2hJsgi9bMQLue8= + dependencies: + - foldable-traversable + - maybe + - strings + unsafe-coerce: + type: registry + version: 6.0.0 + integrity: sha256-IqIYW4Vkevn8sI+6aUwRGvd87tVL36BBeOr0cGAE7t0= + dependencies: [] + unsafe-reference: + type: registry + version: 5.0.0 + integrity: sha256-zU7BhfJU14nXQRZG9iADsp0mSiKhz07OcKyjRB2YT+Y= + dependencies: + - prelude + validation: + type: registry + version: 6.0.0 + integrity: sha256-kfFailaIW4spGxbRk4261z/RGT0Sb7Dx5f3qihy0MTw= + dependencies: + - bifunctors + - control + - either + - foldable-traversable + - newtype + - prelude + variant: + type: registry + version: 8.0.0 + integrity: sha256-SR//zQDg2dnbB8ZHslcxieUkCeNlbMToapvmh9onTtw= + dependencies: + - enums + - lists + - maybe + - partial + - prelude + - record + - tuples + - unsafe-coerce + web-clipboard: + type: registry + version: 4.1.0 + integrity: sha256-BKWPF2VptPv3bf3c327NL7RwAW1jK7ggppwbOU1yrnY= + dependencies: + - web-html + - web-promise + web-dom: + type: registry + version: 6.0.0 + integrity: sha256-1kSKWFDI4LupdmpjK01b1MMxDFW7jvatEgPgVmCmSBQ= + dependencies: + - web-events + web-events: + type: registry + version: 4.0.0 + integrity: sha256-YDt8b6u1tzGtnWyNRodne57iO8FNSGPaTCVzBUyUn4k= + dependencies: + - datetime + - enums + - foreign + - nullable + web-file: + type: registry + version: 4.0.0 + integrity: sha256-1h5jPBkvjY71jLEdwVadXCx86/2inNoMBO//Rd3eCSU= + dependencies: + - foreign + - media-types + - web-dom + web-html: + type: registry + version: 4.1.0 + integrity: sha256-ByqS/h1/yG+hjCOnOQp7L1QpIWzQENNKB1kaHtpEhlE= + dependencies: + - js-date + - web-dom + - web-file + - web-storage + web-pointerevents: + type: registry + version: 1.0.0 + integrity: sha256-I3OGc4gVslh2QsH8QUTeihKCIpFwv4t3RoycZB9ITOs= + dependencies: + - effect + - maybe + - prelude + - web-dom + - web-uievents + web-promise: + type: registry + version: 3.2.0 + integrity: sha256-MttTUDEgrR2HvDxhdeHMHLAcLJQNYJnMDDitCLQrmcA= + dependencies: + - effect + - exceptions + - foldable-traversable + - functions + - maybe + - prelude + web-storage: + type: registry + version: 5.0.0 + integrity: sha256-q+6lxcnfWxus0/nDeFVtF1V+tLehZvvXQ0cduYPLksY= + dependencies: + - nullable + - web-events + web-touchevents: + type: registry + version: 4.0.0 + integrity: sha256-nDHMyXbkDfCEp299RLHCqj5HCDgWXFFy80lGoGjSzms= + dependencies: + - web-uievents + web-uievents: + type: registry + version: 4.1.0 + integrity: sha256-NLadhdaqqK0L9tVQREznam7wrIpcosvHsFVAK5Tf+gE= + dependencies: + - web-html + web-xhr: + type: registry + version: 5.0.1 + integrity: sha256-3dbIPVG66S+hPrgEVnpD78hrGjE7qlBbsReWOz89Ios= + dependencies: + - arraybuffer-types + - datetime + - http-methods + - web-dom + - web-file + - web-html