git.iko.soy/typeable/compaREST
on master help sign in
GHC 9.6 support and CSS fixes (#139)

* Port to GHC 9.6 * Fix CSS paths.

commitfbd027d530f2ec35a559a7303b15db326974ee55 authorNick <nick@typeable.io> dateTue 28 May 2024, 07:01 (2 years ago) parentf0f24ad
16 files changed+44−27
.gitmodules−3 app/Data/OpenApi/Compare/Options.hs+1 app/Main.hs+1 awsm-css−1 compaREST.cabal+5−3 css/awsm.min.css+1 default.nix+1−1 src/Data/OpenApi/Compare/PathsPrefixTree.hs+5−4 src/Data/OpenApi/Compare/Report.hs+1−1 src/Data/OpenApi/Compare/Report/Html/Template.hs+1−1 src/Data/OpenApi/Compare/Validate/OpenApi.hs+2−1 src/Data/OpenApi/Compare/Validate/Schema.hs+1−1 src/Data/OpenApi/Compare/Validate/Schema/JsonFormula.hs+7−6 src/Data/OpenApi/Compare/Validate/Schema/Partition.hs+4−1 src/Data/OpenApi/Compare/Validate/Schema/Process.hs+2 stack.yaml+12−4
.gitmodulesdeleted−3
@@ -1,3 +0,0 @@
1−[submodule "awsm-css"]
2− path = awsm-css
3− url = https://github.com/igoradamenko/awsm.css.git
app/Data/OpenApi/Compare/Options.hs+1
@@ -9,6 +9,7 @@ import Data.OpenApi.Compare.Report
99import GHC.Generics (Generic)
1010import Options.Applicative
1111import Options.Applicative.Help hiding (fullDesc)
12+import Text.PrettyPrint.ANSI.Leijen ((<$$>),string)
1213
1314parseOptions :: IO Options
1415parseOptions = customExecParser (prefs $ showHelpOnError) optionsParserInfo
app/Main.hs+1
@@ -2,6 +2,7 @@ module Main (main) where
22
33import Control.Monad
44import Control.Monad.Except
5+import Control.Monad.Trans (lift)
56import Data.Aeson
67import qualified Data.ByteString.Lazy as BSL
78import Data.Default
awsm-cssdeleted−1

Submodule changed.

compaREST.cabal+5−3
@@ -12,8 +12,8 @@ category: Web
1212build-type: Simple
1313extra-doc-files: README.md
1414 CHANGELOG.md
15−tested-with: GHC == 8.10.4
16−extra-source-files: awsm-css/dist/awsm.min.css
15+tested-with: GHC == 9.6
16+extra-source-files: css/awsm.min.css
1717extra-source-files:
1818 test/golden/**/*.yaml
1919 test/golden/**/*.md
@@ -26,13 +26,14 @@ common common-options
2626 -Wno-safe
2727 -Wno-prepositive-qualified-module
2828 -Wno-missing-import-lists
29+ -Wno-missing-kind-signatures
2930 -Wno-partial-fields
3031 -Wno-all-missed-specialisations
3132 -Wno-missing-local-signatures
3233 -Wno-unsafe
3334 -fconstraint-solver-iterations=0
3435 default-language: Haskell2010
35− build-depends: base >= 4.12.0.0 && < 4.16
36+ build-depends: base >= 4.12.0.0 && < 5
3637 , text
3738
3839
@@ -165,6 +166,7 @@ executable compaREST
165166 , containers
166167 , doctemplates
167168 , pandoc-types
169+ , prettyprinter-compat-ansi-wl-pprint
168170 ghc-options: -threaded
169171 -rtsopts
170172 -with-rtsopts=-N
css/awsm.min.cssnew file+1
@@ -0,0 +1 @@
1+@charset "UTF-8";html{font-family:"PT Serif",Georgia,serif;font-size:100%;line-height:1.6;background:#fff;color:#000;-webkit-overflow-scrolling:touch}body{margin:1em;font-size:1rem}@media (min-width:20rem){body{font-size:calc(1rem + .0125*(100vw - 20rem))}}@media (min-width:40rem){body{font-size:1.25rem}}body article,body footer,body header,body main{position:relative;max-width:40rem;margin:0 auto}body>header{margin-bottom:3.5em}body>header h1{margin:0;font-size:1.5em}body>header p{margin:0;font-size:.85em}body>footer{margin-top:4.5em;padding-bottom:1.5em;text-align:center;font-size:.8rem;color:#aaa}details,nav,p{margin:1em 0}nav ul{list-style:none;margin:0;padding:0}nav li{display:inline-block;margin-right:1em;margin-bottom:.25em}nav a:visited{color:#0064c1}article header h1 a:visited:hover,article header h2 a:visited:hover,nav a:hover{color:#3000c1}ol,ul{margin-top:0;padding-top:0;padding-left:2.5em}p{-webkit-hyphens:auto;-ms-hyphens:auto;hyphens:auto}aside:first-child,p:first-child{margin-top:0}aside:last-child,p:last-child{margin-bottom:0}p+ol,p+ul{margin-top:-.75em}p img,p picture{float:right;margin-bottom:.5em;margin-left:.5em}p picture img{float:none;margin:0}blockquote,dd{padding-left:2.5em}dd{margin-bottom:1em;margin-left:0}dt{font-weight:700}blockquote{margin:0}aside{margin:.5em 0;font-style:italic;color:#aaa}@media (min-width:65rem){aside{position:absolute;right:-12.5rem;width:9.375rem;max-width:9.375rem;margin:0;padding-left:.5em;font-size:.8em;border-left:1px solid #f2f2f2}}section+section{margin-top:2em}h1,h2,h3,h4,h5,h6{margin:1.25em 0 0;line-height:1.2}h1:focus>a[href^="#"][id],h1:hover>a[href^="#"][id],h2:focus>a[href^="#"][id],h2:hover>a[href^="#"][id],h3:focus>a[href^="#"][id],h3:hover>a[href^="#"][id],h4:focus>a[href^="#"][id],h4:hover>a[href^="#"][id],h5:focus>a[href^="#"][id],h5:hover>a[href^="#"][id],h6:focus>a[href^="#"][id],h6:hover>a[href^="#"][id]{opacity:1;transition:opacity 0s,color 300ms ease-out}figure+p,h1+details,h1+p,h2+details,h2+p,h3+details,h3+p,h4+details,h4+p,h5+details,h5+p,h6+details,h6+p{margin-top:.5em}h1>a[href^="#"][id],h2>a[href^="#"][id],h3>a[href^="#"][id],h4>a[href^="#"][id],h5>a[href^="#"][id],h6>a[href^="#"][id]{position:absolute;left:-.5em;opacity:0;background:0 0;color:rgba(0,0,0,.5);transition:opacity 300ms ease-out}h1>a[href^="#"][id]:focus,h1>a[href^="#"][id]:hover,h1>a[href^="#"][id]:target,h2>a[href^="#"][id]:focus,h2>a[href^="#"][id]:hover,h2>a[href^="#"][id]:target,h3>a[href^="#"][id]:focus,h3>a[href^="#"][id]:hover,h3>a[href^="#"][id]:target,h4>a[href^="#"][id]:focus,h4>a[href^="#"][id]:hover,h4>a[href^="#"][id]:target,h5>a[href^="#"][id]:focus,h5>a[href^="#"][id]:hover,h5>a[href^="#"][id]:target,h6>a[href^="#"][id]:focus,h6>a[href^="#"][id]:hover,h6>a[href^="#"][id]:target{opacity:1;box-shadow:none;color:#000;transition:opacity 0s,color 0s}h1>a[href^="#"][id]:target:focus,h2>a[href^="#"][id]:target:focus,h3>a[href^="#"][id]:target:focus,h4>a[href^="#"][id]:target:focus,h5>a[href^="#"][id]:target:focus,h6>a[href^="#"][id]:target:focus{outline:0}h1>a[href^="#"][id]::before,h2>a[href^="#"][id]::before,h3>a[href^="#"][id]::before,h4>a[href^="#"][id]::before,h5>a[href^="#"][id]::before,h6>a[href^="#"][id]::before{content:"•"}h1{font-size:2em}h2{font-size:1.75em}h3{font-size:1.25em}h4{font-size:1.15em}h5,h6{font-size:1em}h6{margin-top:1em;color:#aaa}article+article{margin-top:5em}article header p{font-family:system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:.6em;color:#aaa}article header p+h1,article header p+h2{margin-top:-.25em}article header h1+p,article header h2+p{margin-top:.25em}article header h1 a,article header h2 a{color:#000;background:url('data:image/svg+xml;charset=utf8,%3Csvg xmlns="http://www.w3.org/2000/svg" width="1" height="1"%3E%3Crect x="0" y="0.5" width="1" height="0.5" fill="rgba(0, 0, 0, 0.35)"/%3E%3C/svg%3E') left bottom repeat-x}@media screen and (-ms-high-contrast:active),(-ms-high-contrast:none){article header h1 a,article header h2 a{background:url('data:image/svg+xml;charset=utf8,%3Csvg xmlns="http://www.w3.org/2000/svg" width="1" height="2"%3E%3Crect x="0" y="1" width="1" height="1" fill="rgba(0, 0, 0, 0.35)"/%3E%3C/svg%3E') left bottom repeat-x}}article header h1 a:visited,article header h2 a:visited{color:#aaa;background:url('data:image/svg+xml;charset=utf8,%3Csvg xmlns="http://www.w3.org/2000/svg" width="1" height="1"%3E%3Crect x="0" y="0.5" width="1" height="0.5" fill="rgba(170, 170, 170, 0.35)"/%3E%3C/svg%3E') left bottom repeat-x}@media screen and (-ms-high-contrast:active),(-ms-high-contrast:none){article header h1 a:visited,article header h2 a:visited{background:url('data:image/svg+xml;charset=utf8,%3Csvg xmlns="http://www.w3.org/2000/svg" width="1" height="2"%3E%3Crect x="0" y="1" width="1" height="1" fill="rgba(170, 170, 170, 0.35)"/%3E%3C/svg%3E') left bottom repeat-x}}article>footer{margin-top:1.5em;font-size:.85em}a,abbr{text-decoration:none}a{color:#0064c1;transition:color 300ms ease-out,box-shadow 300ms ease-out;background:url('data:image/svg+xml;charset=utf8,%3Csvg xmlns="http://www.w3.org/2000/svg" width="1" height="1"%3E%3Crect x="0" y="0.5" width="1" height="0.5" fill="rgba(0, 100, 193, 0.35)"/%3E%3C/svg%3E') left bottom repeat-x}@media screen and (-ms-high-contrast:active),(-ms-high-contrast:none){a{background:url('data:image/svg+xml;charset=utf8,%3Csvg xmlns="http://www.w3.org/2000/svg" width="1" height="2"%3E%3Crect x="0" y="1" width="1" height="1" fill="rgba(0, 100, 193, 0.35)"/%3E%3C/svg%3E') left bottom repeat-x}}a:visited{color:#80b2e0}a:active,a:hover{outline-width:0}a:hover{box-shadow:inset 0 -1px #3000c1;color:#3000c1;transition:color 0s,box-shadow 0s}abbr{margin-right:-.075em;-webkit-hyphens:none;-ms-hyphens:none;hyphens:none;letter-spacing:.075em;font-size:.9em;border-bottom:1px dotted}img,picture{display:block;max-width:100%;margin:0 auto}audio,video{width:100%;max-width:100%}video{-o-object-position:0 -1px;object-position:0 -1px}figure{margin:1em 0 .5em;padding:0}figure figcaption{opacity:.65;font-size:.85em}table{display:inline-block;border-spacing:0;border-collapse:collapse;overflow-x:auto;max-width:100%;text-align:left;vertical-align:top;background:linear-gradient(rgba(0,0,0,.15) 0%,rgba(0,0,0,.15) 100%) 0 0,linear-gradient(rgba(0,0,0,.15) 0%,rgba(0,0,0,.15) 100%) 100% 0;background-attachment:scroll,scroll;background-size:1px 100%,1px 100%;background-repeat:no-repeat,no-repeat}table caption{font-size:.9em;background:#fff}table td,table th{padding:.35em .75em;vertical-align:top;font-size:.9em;border:1px solid #f2f2f2;border-top:0;border-left:0}table td:first-child,table th:first-child{padding-left:0;background-image:linear-gradient(to right,#fff 50%,rgba(255,255,255,0) 100%);background-size:2px 100%;background-repeat:no-repeat}table td:last-child,table th:last-child{padding-right:0;border-right:0;background-image:linear-gradient(to left,#fff 50%,rgba(255,255,255,0) 100%);background-position:100% 0;background-size:2px 100%;background-repeat:no-repeat}table td:only-child,table th:only-child{background-image:linear-gradient(to right,#fff 50%,rgba(255,255,255,0) 100%),linear-gradient(to left,#fff 50%,rgba(255,255,255,0) 100%);background-position:0 0,100% 0;background-size:2px 100%,2px 100%;background-repeat:no-repeat,no-repeat}table th{line-height:1.2}code,kbd,samp,var{font-family:Consolas,"Lucida Console",Monaco,monospace;font-style:normal}pre{overflow-x:auto;font-size:.8em;background:linear-gradient(rgba(0,0,0,.15) 0%,rgba(0,0,0,.15) 100%) 0 0,linear-gradient(rgba(0,0,0,.15) 0%,rgba(0,0,0,.15) 100%) 100% 0;background-attachment:scroll,scroll;background-size:1px 100%,1px 100%;background-repeat:no-repeat,no-repeat}pre>code,summary{display:inline-block}pre>code{overflow-x:visible;box-sizing:border-box;min-width:100%;border-right:3px solid #fff;border-left:1px solid #fff}hr{height:1px;margin:2em 0;border:0;background:#f2f2f2}details[open]{padding-bottom:.5em;border-bottom:1px solid #f2f2f2}summary{font-weight:700;border-bottom:1px dashed;cursor:pointer}summary::-webkit-details-marker{display:none}noscript{color:#d00000}::selection{background:rgba(0,100,193,.15)}
default.nix+1−1
@@ -38,7 +38,7 @@ let
3838 (inDirectory ./src)
3939 (inDirectory ./app)
4040 (inDirectory ./github-action)
41− ./awsm-css/dist/awsm.min.css
41+ ./css/awsm.min.css
4242 ./LICENSE
4343 ];
4444 };
src/Data/OpenApi/Compare/PathsPrefixTree.hs+5−4
@@ -23,7 +23,8 @@ where
2323import Control.Monad
2424import Data.Aeson
2525import Data.Foldable hiding (null, toList)
26−import qualified Data.HashMap.Strict as HM
26+import qualified Data.Aeson.Key as Key
27+import qualified Data.Aeson.KeyMap as KeyMap
2728import Data.Kind
2829import qualified Data.Map as M
2930import Data.Monoid
@@ -256,7 +257,7 @@ newtype MergableObject = MergableObject {getMergableObject :: Object}
256257
257258instance Semigroup MergableObject where
258259 (MergableObject x) <> (MergableObject y) =
259− MergableObject $ HM.unionWith mergeValue x y
260+ MergableObject $ KeyMap.unionWith mergeValue x y
260261 where
261262 mergeValue :: Value -> Value -> Value
262263 mergeValue (Object a) (Object b) =
@@ -271,6 +272,6 @@ instance Monoid MergableObject where
271272
272273traceObject :: Paths q r a -> Value -> Object
273274traceObject Root (Object o) = o
274−traceObject Root v = HM.singleton "root" v
275+traceObject Root v = KeyMap.singleton "root" v
275276traceObject (root `Snoc` s) v =
276− traceObject root . Object $ HM.singleton (T.pack . show $ s) v
277+ traceObject root . Object $ KeyMap.singleton (Key.fromText . T.pack . show $ s) v
src/Data/OpenApi/Compare/Report.hs+1−1
@@ -198,7 +198,7 @@ showErrs x@(P.PathsPrefixNode currentIssues _) =
198198 let -- Extract this pattern if more cases like this arise
199199 ( removedPaths :: Maybe (Orientation, [Issue 'APILevel])
200200 , otherIssues :: Set (AnIssue a)
201− ) = case eqT @a @ 'APILevel of
201+ ) = case eqT @a @'APILevel of
202202 Just Refl
203203 | (S.toList -> p@((AnIssue ori _) : _), o) <-
204204 S.partition
src/Data/OpenApi/Compare/Report/Html/Template.hs+1−1
@@ -36,4 +36,4 @@ template =
3636 \</html>"
3737
3838awsmCss :: ByteString
39−awsmCss = $(makeRelativeToProject "awsm-css/dist/awsm.min.css" >>= embedFile)
39+awsmCss = $(makeRelativeToProject "css/awsm.min.css" >>= embedFile)
src/Data/OpenApi/Compare/Validate/OpenApi.hs+2−1
@@ -38,7 +38,8 @@ tracedSecuritySchemes :: Traced OpenApi -> Traced (Definitions SecurityScheme)
3838tracedSecuritySchemes oa =
3939 traced
4040 (ask oa >>> step ComponentsSecurityScheme)
41− (_componentsSecuritySchemes . _openApiComponents . extract $ oa)
41+ (unSecurityDefinitions . _componentsSecuritySchemes . _openApiComponents . extract $ oa)
42+ where unSecurityDefinitions (SecurityDefinitions ds) = ds
4243
4344tracedResponses :: Traced OpenApi -> Traced (Definitions Response)
4445tracedResponses oa =
src/Data/OpenApi/Compare/Validate/Schema.hs+1−1
@@ -5,7 +5,7 @@ module Data.OpenApi.Compare.Validate.Schema
55 )
66where
77
8−import Control.Monad.Writer
8+import Control.Monad (when,unless)
99import qualified Data.Aeson as A
1010import Data.Coerce
1111import Data.Foldable (for_, toList)
src/Data/OpenApi/Compare/Validate/Schema/JsonFormula.hs+7−6
@@ -18,10 +18,11 @@ where
1818
1919import Algebra.Lattice
2020import qualified Data.Aeson as A
21+import qualified Data.Aeson.Key as Key
22+import qualified Data.Aeson.KeyMap as KeyMap
2123import qualified Data.ByteString.Lazy as BSL
2224import qualified Data.Foldable as F
2325import Data.Functor
24−import qualified Data.HashMap.Strict as HM
2526import Data.Int
2627import Data.Kind
2728import qualified Data.Map as M
@@ -39,7 +40,7 @@ import Data.Text (Text)
3940import qualified Data.Text as T
4041import qualified Data.Text.Encoding as T
4142import Data.Typeable
42−import Text.Pandoc.Builder hiding (Format, Null)
43+import Text.Pandoc.Builder hiding (Format)
4344import Text.Regex.Pcre2
4445
4546data Bound a = Exclusive !a | Inclusive !a
@@ -177,10 +178,10 @@ satisfiesTyped (TArray a) (MaxItems m) = fromIntegral (F.length a) <= m
177178satisfiesTyped (TArray a) (MinItems m) = fromIntegral (F.length a) >= m
178179satisfiesTyped (TArray a) UniqueItems = S.size (S.fromList $ F.toList a) == F.length a -- TODO: could be better #36
179180satisfiesTyped (TObject o) (Properties props additional _) =
180− all (`HM.member` o) (M.keys (M.filter propRequired props))
181− && all (\(k, v) -> satisfies v $ maybe additional propFormula $ M.lookup k props) (HM.toList o)
182−satisfiesTyped (TObject o) (MaxProperties m) = fromIntegral (HM.size o) <= m
183−satisfiesTyped (TObject o) (MinProperties m) = fromIntegral (HM.size o) >= m
181+ all (`KeyMap.member` o) (map Key.fromText $ M.keys (M.filter propRequired props))
182+ && all (\(k, v) -> satisfies v $ maybe additional propFormula $ M.lookup (Key.toText k) props) (KeyMap.toList o)
183+satisfiesTyped (TObject o) (MaxProperties m) = fromIntegral (KeyMap.size o) <= m
184+satisfiesTyped (TObject o) (MinProperties m) = fromIntegral (KeyMap.size o) >= m
184185
185186checkNumberFormat :: Format -> Scientific -> Bool
186187checkNumberFormat "int32" (toRational -> n) =
src/Data/OpenApi/Compare/Validate/Schema/Partition.hs+4−1
@@ -16,6 +16,7 @@ where
1616import Algebra.Lattice
1717import Algebra.Lattice.Lifted
1818import Control.Applicative
19+import Control.Monad (when)
1920import Control.Monad.Reader hiding (ask)
2021import qualified Control.Monad.Reader as R
2122import Control.Monad.State
@@ -31,6 +32,7 @@ import qualified Data.List as L
3132import qualified Data.List.NonEmpty as NE
3233import qualified Data.Map as M
3334import Data.Maybe
35+import Data.Monoid
3436import Data.OpenApi
3537import Data.OpenApi.Compare.Memo
3638import Data.OpenApi.Compare.References
@@ -43,7 +45,8 @@ import Data.Ord
4345import qualified Data.Set as S
4446import Data.Text (Text)
4547import qualified Data.Text as T
46−import Text.Pandoc.Builder hiding (Format, Null)
48+import Data.Traversable (forM)
49+import Text.Pandoc.Builder hiding (Format)
4750
4851data PartitionData
4952 = DByEnumValue (DNF (S.Set A.Value))
src/Data/OpenApi/Compare/Validate/Schema/Process.hs+2
@@ -13,6 +13,7 @@ import Data.Functor.Identity
1313import qualified Data.HashMap.Strict.InsOrd as IOHM
1414import qualified Data.Map as M
1515import Data.Maybe
16+import Data.Monoid
1617import Data.OpenApi hiding (get)
1718import Data.OpenApi.Compare.Behavior
1819import Data.OpenApi.Compare.Memo
@@ -28,6 +29,7 @@ import Data.OpenApi.Compare.Validate.Schema.Traced
2829import Data.OpenApi.Compare.Validate.Schema.TypedJson
2930import Data.Ord
3031import qualified Data.Set as S
32+import Data.Traversable (forM)
3133
3234-- | A fake writer monad that doesn't actually record anything and allows lazy recursion.
3335newtype Silent w a = Silent {runSilent :: a}
stack.yaml+12−4
@@ -1,11 +1,19 @@
1−resolver: lts-18.27
1+resolver: lts-22.17
22
33packages:
44 - .
55
66extra-deps:
7+ - base16-bytestring-1.0.2.0
8+ - freer-simple-1.2.1.2
9+ - github-0.29
10+ - http-link-header-1.2.1
711 - open-union-0.4.0.0
812 - type-fun-0.1.3
9− - github-0.26
10− - base16-bytestring-0.1.1.7
11− - http-link-header-1.0.3.1
13+ - typerep-map-0.6.0.0
14+
15+# Required for freer-simple and typerep-map
16+allow-newer: true
17+
18+nix:
19+ packages: [pkg-config zlib]