Add basic JSON docs explorer webpage

json-docs
Bram 2024-01-23 13:41:19 +01:00
parent acd13ac67a
commit 779bb2d5e2
6 changed files with 1027 additions and 0 deletions

497
dev/Colors.elm Normal file
View File

@ -0,0 +1,497 @@
module Colors exposing (..)
{-| This module aims to create color palettes that fit the Noordstar color scheme.
-}
import Color exposing (rgb255)
import Element
import Element.Background
import Element.Font
import Svg
import Svg.Attributes exposing (fill)
import Widget.Material exposing (Palette)
type alias Color =
Color.Color
type alias AllColors a =
AllBlindnesses (AllModes (AllShades (AllNames a)))
allColors : AllColors Color
allColors =
allBlindnesses
(\blindness ->
allModes
(\mode ->
allShades
(\shade ->
allNames
(\name ->
get blindness mode shade name
)
)
)
)
stdPicker : Picker
stdPicker =
allColors.trichromatic.lightMode
type Name
= Primary
| Secondary
| Tertiary
| Quaternary
| Extra
| Black
| White
type alias AllNames a =
{ primary : a
, secondary : a
, tertiary : a
, quaternary : a
, extra : a
, black : a
, white : a
}
allNames : (Name -> a) -> AllNames a
allNames builder =
{ primary = builder Primary
, secondary = builder Secondary
, tertiary = builder Tertiary
, quaternary = builder Quaternary
, extra = builder Extra
, black = builder Black
, white = builder White
}
type Shade
= Light
| Medium
| Dark
type alias AllShades a =
{ light : a
, medium : a
, dark : a
}
allShades : (Shade -> a) -> AllShades a
allShades builder =
{ light = builder Light
, medium = builder Medium
, dark = builder Dark
}
{-| Based on the user's preferences, the website can be displayed in light mode or dark mode.
-}
type Mode
= LightMode
| DarkMode
type alias AllModes a =
{ lightMode : a
, darkMode : a
}
allModes : (Mode -> a) -> AllModes a
allModes builder =
{ lightMode = builder LightMode
, darkMode = builder DarkMode
}
{-| The website supports color blindness friendly color palettes.
This way, everyone can enjoy the website's graphs without having to distinguish
colors that they cannot distinguish.
-}
type Blindness
= Trichromatic -- ALL THREE
| Protanomaly -- BARELY RED
| Deuteranomaly -- BARELY GREEN
| Tritanomaly -- BARELY BLUE
| Protanopia -- NO RED
| Deuteranopia -- NO GREEN
| Tritanopia -- NO BLUE
| Monochromacy -- NO COLOR
| BlueConeMonochromacy -- BARELY COLOR
type alias AllBlindnesses a =
{ trichromatic : a
, protanomaly : a
, deuteranomaly : a
, tritanomaly : a
, protanopia : a
, deuteranopia : a
, tritanopia : a
, monochromacy : a
, blueConeMonochromacy : a
}
allBlindnesses : (Blindness -> a) -> AllBlindnesses a
allBlindnesses builder =
{ trichromatic = builder Trichromatic
, protanomaly = builder Protanomaly
, deuteranomaly = builder Deuteranomaly
, tritanomaly = builder Tritanomaly
, protanopia = builder Protanopia
, deuteranopia = builder Deuteranopia
, tritanopia = builder Tritanopia
, monochromacy = builder Monochromacy
, blueConeMonochromacy = builder BlueConeMonochromacy
}
type alias Picker =
AllShades (AllNames Color)
{-| Get a color based on the right criteria.
-}
get : Blindness -> Mode -> Shade -> Name -> Color
get blindness mode shade name =
let
trueName : Name
trueName =
name |> flipName mode
trueShade : Shade
trueShade =
shade |> flipShade mode
in
toBlindnessPalette blindness
|> toColor blindness trueName
|> fromShade trueShade
|> (\( r, g, b ) -> rgb255 r g b)
defaultPalette : Picker -> Palette
defaultPalette p =
{ primary = p.medium.primary
, secondary = p.medium.secondary
, background = p.dark.white
, surface = p.light.white
, error = p.light.secondary
, on =
{ primary = p.light.white
, secondary = p.light.white
, background = p.light.black
, surface = p.dark.black
, error = p.medium.white
}
}
{-| Get a blindness color palette based on a blindness input.
-}
toBlindnessPalette : Blindness -> BlindnessPalette
toBlindnessPalette blindness =
case blindness of
Trichromatic ->
trichromatic
Protanomaly ->
protanomaly
Deuteranomaly ->
deuteranomaly
Tritanomaly ->
tritanomaly
Protanopia ->
protanopia
Deuteranopia ->
deuteranopia
Tritanopia ->
tritanopia
Monochromacy ->
monochromacy
BlueConeMonochromacy ->
blueConeMonochromacy
flipName : Mode -> Name -> Name
flipName mode name =
case mode of
LightMode ->
name
DarkMode ->
case name of
Black ->
White
White ->
Black
_ ->
name
flipShade : Mode -> Shade -> Shade
flipShade mode shade =
case ( mode, shade ) of
( LightMode, _ ) ->
shade
( DarkMode, Dark ) ->
Light
( DarkMode, Medium ) ->
Medium
( DarkMode, Light ) ->
Dark
{-| We distringuish the following colours:
| Protan | Deuter | Tritan | Mono |
- Blue | Blue | Blue | Blue | Blue |
- Green | Green | Green | Green | XXXXXX | [Orange]
- Yellow | Yellow | Yellow | XXXXXX | Yellow | [Orange]
- Orange | XXXXXX | XXXXXX | Orange | Orange | [Green,Red]
- Red | Red | Red | Red | Red |
- Black | Black | Black | Black | Black |
- White | White | White | White | White |
In other words:
Primary | Blue | Blue | Blue | Blue |
Secondary | Red | Red | Red | Red |
Tertiary | Yellow | Yellow | Orange | Yellow |
Quaternary | Green | Green | Green | Orange |
-----------|--------|--------|--------|--------|
Rest | Orange | Orange | Yellow | Green |
-}
toColor : Blindness -> Name -> (BlindnessPalette -> ColorPalette)
toColor blindness name =
case name of
Primary ->
.blue
Secondary ->
.red
Tertiary ->
case blindness of
Tritanopia ->
.orange
_ ->
.yellow
Quaternary ->
case blindness of
Monochromacy ->
.orange
_ ->
.green
Extra ->
case blindness of
Tritanopia ->
.yellow
Monochromacy ->
.green
_ ->
.orange
Black ->
.black
White ->
.white
fromShade : Shade -> ColorPalette -> ( Int, Int, Int )
fromShade shade =
case shade of
Light ->
.light
Medium ->
.medium
Dark ->
.dark
type alias ColorPalette =
{ light : ( Int, Int, Int )
, medium : ( Int, Int, Int )
, dark : ( Int, Int, Int )
}
type alias BlindnessPalette =
{ blue : ColorPalette
, green : ColorPalette
, yellow : ColorPalette
, orange : ColorPalette
, red : ColorPalette
, black : ColorPalette
, white : ColorPalette
}
{-| No color blindness
-}
trichromatic : BlindnessPalette
trichromatic =
{ blue = { light = ( 0x42, 0x87, 0xFF ), medium = ( 0x42, 0x7F, 0xF0 ), dark = ( 0x00, 0x54, 0xBD ) }
, green = { light = ( 0x86, 0xEA, 0xD1 ), medium = ( 0x5E, 0xA4, 0x93 ), dark = ( 0x3E, 0x6D, 0x62 ) }
, yellow = { light = ( 0xFC, 0xF9, 0x2B ), medium = ( 0xD2, 0xD0, 0x24 ), dark = ( 0xAF, 0xAD, 0x1E ) }
, orange = { light = ( 0xFF, 0xBB, 0x93 ), medium = ( 0xCC, 0x95, 0x75 ), dark = ( 0xA3, 0x77, 0x5E ) }
, red = { light = ( 0xDC, 0x00, 0x00 ), medium = ( 0xB0, 0x00, 0x00 ), dark = ( 0x8C, 0x00, 0x00 ) }
, black = { light = ( 0x2C, 0x2C, 0x48 ), medium = ( 0x1D, 0x1D, 0x30 ), dark = ( 0x00, 0x00, 0x00 ) }
, white = { light = ( 0xFF, 0xFF, 0xFF ), medium = ( 0xFE, 0xFA, 0xF5 ), dark = ( 0xF2, 0xEF, 0xEA ) }
}
{-| Weak red vision
-}
protanomaly : BlindnessPalette
protanomaly =
{ blue = { light = ( 0x49, 0x86, 0xFE ), medium = ( 0x46, 0x7E, 0xEF ), dark = ( 0x00, 0x55, 0xB9 ) }
, green = { light = ( 0xBE, 0xDD, 0xCA ), medium = ( 0x85, 0x9B, 0x8E ), dark = ( 0x58, 0x67, 0x5F ) }
, yellow = { light = ( 0xFE, 0xF4, 0x88 ), medium = ( 0xDD, 0xCC, 0x23 ), dark = ( 0xB8, 0xAA, 0x1D ) }
, orange = { light = ( 0xE6, 0xC4, 0x97 ), medium = ( 0xB8, 0x9D, 0x78 ), dark = ( 0x93, 0x7D, 0x61 ) }
, red = { light = ( 0x9F, 0x47, 0x12 ), medium = ( 0x7F, 0x39, 0x0F ), dark = ( 0x65, 0x2D, 0x0C ) }
, black = { light = ( 0x27, 0x2D, 0x49 ), medium = ( 0x1A, 0x1E, 0x31 ), dark = ( 0x00, 0x00, 0x00 ) }
, white = { light = ( 0xFF, 0xFF, 0xFF ), medium = ( 0xFF, 0xFA, 0xF6 ), dark = ( 0xF4, 0xEE, 0xEA ) }
}
{-| Weak green vision
-}
deuteranomaly : BlindnessPalette
deuteranomaly =
{ blue = { light = ( 0x18, 0x8A, 0xFA ), medium = ( 0x18, 0x82, 0xEC ), dark = ( 0x00, 0x59, 0xA9 ) }
, green = { light = ( 0xC6, 0xD9, 0xD5 ), medium = ( 0x8B, 0x98, 0x95 ), dark = ( 0x5C, 0x65, 0x64 ) }
, yellow = { light = ( 0xFE, 0xF3, 0x9C ), medium = ( 0xEE, 0xC5, 0x2B ), dark = ( 0xC6, 0xA4, 0x23 ) }
, orange = { light = ( 0xF5, 0xBF, 0x92 ), medium = ( 0xC4, 0x99, 0x74 ), dark = ( 0x9D, 0x7A, 0x5D ) }
, red = { light = ( 0xA9, 0x43, 0x00 ), medium = ( 0x87, 0x36, 0x00 ), dark = ( 0x6C, 0x2B, 0x00 ) }
, black = { light = ( 0x26, 0x2E, 0x48 ), medium = ( 0x19, 0x1E, 0x30 ), dark = ( 0x00, 0x00, 0x00 ) }
, white = { light = ( 0xFF, 0xFF, 0xFF ), medium = ( 0xFE, 0xFA, 0xF5 ), dark = ( 0xFA, 0xEC, 0xEC ) }
}
{-| Weak blue vision
-}
tritanomaly : BlindnessPalette
tritanomaly =
{ blue = { light = ( 0x18, 0x93, 0xC5 ), medium = ( 0x18, 0x8A, 0xBA ), dark = ( 0x00, 0x5E, 0x88 ) }
, green = { light = ( 0x8C, 0xE7, 0xE9 ), medium = ( 0x62, 0xA2, 0xA4 ), dark = ( 0x41, 0x6B, 0x6D ) }
, yellow = { light = ( 0xFE, 0xF1, 0xAC ), medium = ( 0xDA, 0xC7, 0x92 ), dark = ( 0xB6, 0xA5, 0x79 ) }
, orange = { light = ( 0xFF, 0xB8, 0xB2 ), medium = ( 0xCE, 0x92, 0x8D ), dark = ( 0xA5, 0x74, 0x71 ) }
, red = { light = ( 0xDB, 0x0D, 0x00 ), medium = ( 0xAF, 0x0A, 0x00 ), dark = ( 0x8B, 0x08, 0x00 ) }
, black = { light = ( 0x29, 0x2F, 0x3B ), medium = ( 0x1B, 0x1F, 0x27 ), dark = ( 0x00, 0x00, 0x00 ) }
, white = { light = ( 0xFF, 0xFF, 0xFF ), medium = ( 0xFD, 0xFA, 0xFB ), dark = ( 0xF4, 0xED, 0xF7 ) }
}
{-| Red-blind vision
-}
protanopia : BlindnessPalette
protanopia =
{ blue = { light = ( 0x4D, 0x86, 0xFE ), medium = ( 0x48, 0x7E, 0xEF ), dark = ( 0x00, 0x56, 0xB6 ) }
, green = { light = ( 0xDE, 0xD6, 0xC6 ), medium = ( 0x9C, 0x96, 0x8B ), dark = ( 0x67, 0x64, 0x5D ) }
, yellow = { light = ( 0xFF, 0xF2, 0xBE ), medium = ( 0xE3, 0xCA, 0x22 ), dark = ( 0xBD, 0xA8, 0x1D ) }
, orange = { light = ( 0xD8, 0xCA, 0x9A ), medium = ( 0xAD, 0xA1, 0x7A ), dark = ( 0x8A, 0x81, 0x62 ) }
, red = { light = ( 0x7D, 0x6F, 0x1C ), medium = ( 0x64, 0x59, 0x17 ), dark = ( 0x4F, 0x47, 0x12 ) }
, black = { light = ( 0x24, 0x2E, 0x4A ), medium = ( 0x18, 0x1E, 0x31 ), dark = ( 0x00, 0x00, 0x00 ) }
, white = { light = ( 0xFF, 0xFF, 0xFF ), medium = ( 0xFF, 0xFA, 0xF6 ), dark = ( 0xF5, 0xEE, 0xEA ) }
}
{-| Green-blind vision
-}
deuteranopia : BlindnessPalette
deuteranopia =
{ blue = { light = ( 0x00, 0x8C, 0xF8 ), medium = ( 0x00, 0x84, 0xEA ), dark = ( 0x00, 0x5B, 0x9D ) }
, green = { light = ( 0xEB, 0xD0, 0xD7 ), medium = ( 0xA5, 0x92, 0x97 ), dark = ( 0x6D, 0x61, 0x65 ) }
, yellow = { light = ( 0xFF, 0xEF, 0xDC ), medium = ( 0xFE, 0xBF, 0x2E ), dark = ( 0xD3, 0x9F, 0x26 ) }
, orange = { light = ( 0xF0, 0xC2, 0x92 ), medium = ( 0xBF, 0x9B, 0x74 ), dark = ( 0x99, 0x7B, 0x5D ) }
, red = { light = ( 0x8C, 0x69, 0x00 ), medium = ( 0x70, 0x54, 0x00 ), dark = ( 0x59, 0x43, 0x00 ) }
, black = { light = ( 0x23, 0x2F, 0x47 ), medium = ( 0x16, 0x1F, 0x30 ), dark = ( 0x00, 0x00, 0x00 ) }
, white = { light = ( 0xFF, 0xFF, 0xFF ), medium = ( 0xFF, 0xF9, 0xFA ), dark = ( 0xFF, 0xEA, 0xED ) }
}
{-| Blue-blind vision
-}
tritanopia : BlindnessPalette
tritanopia =
{ blue = { light = ( 0x00, 0x99, 0xA4 ), medium = ( 0x00, 0x90, 0x9B ), dark = ( 0x00, 0x63, 0x69 ) }
, green = { light = ( 0x90, 0xE5, 0xF7 ), medium = ( 0x65, 0xA0, 0xAD ), dark = ( 0x43, 0x6B, 0x73 ) }
, yellow = { light = ( 0xFF, 0xED, 0xF6 ), medium = ( 0xDF, 0xC2, 0xD1 ), dark = ( 0xBA, 0xA1, 0xAE ) }
, orange = { light = ( 0xFF, 0xB7, 0xC3 ), medium = ( 0xCF, 0x90, 0x9B ), dark = ( 0xA6, 0x73, 0x7C ) }
, red = { light = ( 0xDA, 0x14, 0x00 ), medium = ( 0xAF, 0x10, 0x00 ), dark = ( 0x8B, 0x0D, 0x00 ) }
, black = { light = ( 0x27, 0x30, 0x34 ), medium = ( 0x1A, 0x20, 0x22 ), dark = ( 0x00, 0x00, 0x00 ) }
, white = { light = ( 0xFF, 0xFF, 0xFF ), medium = ( 0xFC, 0xFA, 0xFF ), dark = ( 0xF5, 0xEC, 0xFE ) }
}
{-| Color-less vision
-}
monochromacy : BlindnessPalette
monochromacy =
{ blue = { light = ( 0x80, 0x80, 0x80 ), medium = ( 0x7A, 0x7A, 0x7A ), dark = ( 0x47, 0x47, 0x47 ) }
, green = { light = ( 0xC9, 0xC9, 0xC9 ), medium = ( 0x8D, 0x8D, 0x8D ), dark = ( 0x5E, 0x5E, 0x5E ) }
, yellow = { light = ( 0xE2, 0xE2, 0xE2 ), medium = ( 0xBD, 0xBD, 0xBD ), dark = ( 0x9D, 0x9D, 0x9D ) }
, orange = { light = ( 0xCB, 0xCB, 0xCB ), medium = ( 0xA2, 0xA2, 0xA2 ), dark = ( 0x81, 0x81, 0x81 ) }
, red = { light = ( 0x42, 0x42, 0x42 ), medium = ( 0x35, 0x35, 0x35 ), dark = ( 0x2A, 0x2A, 0x2A ) }
, black = { light = ( 0x2F, 0x2F, 0x2F ), medium = ( 0x1F, 0x1F, 0x1F ), dark = ( 0x00, 0x00, 0x00 ) }
, white = { light = ( 0xFF, 0xFF, 0xFF ), medium = ( 0xFB, 0xFB, 0xFB ), dark = ( 0xEF, 0xEF, 0xEF ) }
}
{-| Blue cone monochromacy
-}
blueConeMonochromacy : BlindnessPalette
blueConeMonochromacy =
{ blue = { light = ( 0x69, 0x83, 0xAE ), medium = ( 0x66, 0x7C, 0xA5 ), dark = ( 0x2D, 0x4C, 0x72 ) }
, green = { light = ( 0xB1, 0xD5, 0xCC ), medium = ( 0x7C, 0x95, 0x8F ), dark = ( 0x52, 0x63, 0x5F ) }
, yellow = { light = ( 0xEB, 0xEA, 0x9F ), medium = ( 0xC5, 0xC4, 0x85 ), dark = ( 0xA4, 0xA3, 0x6F ) }
, orange = { light = ( 0xDE, 0xC5, 0xB7 ), medium = ( 0xB1, 0x9D, 0x92 ), dark = ( 0x8D, 0x7D, 0x74 ) }
, red = { light = ( 0x7A, 0x2A, 0x2A ), medium = ( 0x62, 0x22, 0x22 ), dark = ( 0x4E, 0x1B, 0x1B ) }
, black = { light = ( 0x2E, 0x2E, 0x38 ), medium = ( 0x1E, 0x1E, 0x25 ), dark = ( 0x00, 0x00, 0x00 ) }
, white = { light = ( 0xFF, 0xFF, 0xFF ), medium = ( 0xFC, 0xFB, 0xF9 ), dark = ( 0xF0, 0xEF, 0xED ) }
}
svgFill : Color -> Svg.Attribute msg
svgFill =
Color.toCssString >> fill
svgStroke : Color -> Svg.Attribute msg
svgStroke =
Color.toCssString >> Svg.Attributes.stroke
font : Color -> Element.Attribute msg
font =
Color.toRgba >> Element.fromRgb >> Element.Font.color
background : Color -> Element.Attribute msg
background =
Color.toRgba >> Element.fromRgb >> Element.Background.color
transparent : Color
transparent =
Color.rgba 0 0 0 0

251
dev/DocsDisplay.elm Normal file
View File

@ -0,0 +1,251 @@
module DocsDisplay exposing (..)
import Internal.Tools.Json as Json exposing (Docs(..))
import Element exposing (Element)
import Element.Font as Font
import Widget
import Widget.Material as Material
import Widget.Material.Typography as Typography
import Colors as C
import Internal.Tools.Json as Json
import Internal.Tools.Json as Json
import Internal.Tools.Json as Json
import FastDict as Dict exposing (Dict)
type alias DObject =
{ name : String
, description : List String
, keys :
List
{ field : String
, description : List String
, required : Json.RequiredField
, content : Docs
}
}
render : Dict String Bool -> Docs -> Element (String, Bool)
render dict docs =
docs
|> findObjects
|> List.map
(\dobject ->
Element.column []
[ Element.el Typography.h3
( Element.text dobject.name )
, dobject.description
|> List.map (Element.text >> List.singleton >> Element.paragraph [])
|> Element.column []
, toTable (Dict.get dobject.name dict |> Maybe.withDefault True) dobject
|> Element.map (Tuple.pair dobject.name)
]
)
|> List.append
[ Element.paragraph []
[ Element.text "This coder decodes to "
, Element.el
[ Font.family [ Font.monospace ]
, C.background C.stdPicker.medium.white
]
( Element.text <| toString docs )
]
]
|> Element.column []
findObjects : Docs -> List DObject
findObjects docs =
bfs [ docs ] []
bfs : List Docs -> List DObject -> List DObject
bfs queue acc =
case queue of
[] ->
acc
head :: tail ->
case head of
DocsBool ->
bfs tail acc
DocsDict d ->
bfs (d :: tail) acc
DocsFloat ->
bfs tail acc
DocsInt ->
bfs tail acc
DocsLazy f ->
bfs (f () :: tail) acc
DocsList d ->
bfs (d :: tail) acc
DocsMap { content } ->
bfs (content :: tail) acc
DocsObject dobject ->
if List.any (\item -> item.name == dobject.name) acc then
bfs tail acc
else
bfs
(List.append tail (List.map .content dobject.keys))
(List.append acc [ dobject ])
DocsOptional d ->
bfs (d :: tail) acc
DocsRiskyMap { content } ->
bfs (content :: tail) acc
DocsString ->
bfs tail acc
DocsValue ->
bfs tail acc
toTable : Bool -> DObject -> Element Bool
toTable asc dobject =
Widget.sortTableV2 (Material.sortTable <| C.defaultPalette C.stdPicker)
{ content = dobject.keys
, columns =
[ Widget.stringColumnV2
{ title = "Field"
, value = .field
, toString = identity
, width = Element.fillPortion 1
}
, Widget.customColumnV2
{ title = "Type"
, value =
(\item ->
item.content
|> toString
|> Element.text
|> Element.el
[ Font.family [Font.monospace]
, C.background C.stdPicker.dark.white
, Element.padding 3
, Element.centerX
]
)
, width = Element.fillPortion 1
}
, Widget.customColumnV2
{ title = "Description"
, value = showDescription
, width = Element.fillPortion 5
}
]
, asc = asc
, sortBy = "Field"
, onChange =
(\f ->
if f == "Field" then
not asc
else
asc
)
}
{-| Show the description of a field in a table column.
-}
showDescription : { a | description : List String, required : Json.RequiredField } -> Element msg
showDescription { description, required } =
case description of
[] ->
Element.column []
[ Element.paragraph []
[ "WARNING: "
|> Element.text
|> Element.el [ Font.bold ]
, "This field has no documentation yet!"
|> Element.text
]
, case required of
Json.RequiredField ->
Element.paragraph []
[ "This field is required."
|> Element.text
]
Json.OptionalField ->
Element.paragraph []
[ "This field is optional."
|> Element.text
]
Json.OptionalFieldWithDefault default ->
Element.paragraph []
[ "This field is optional. If it is not there, a default value of \"" ++ default ++ "\" will be taken."
|> Element.text
]
]
head :: tail ->
case required of
Json.RequiredField ->
( Element.paragraph []
[ Element.el [ Font.bold ] (Element.text "Required: ")
, Element.text head
]
)
::
( List.map (Element.text >> List.singleton >> Element.paragraph []) tail)
|> Element.column []
Json.OptionalField ->
description
|> List.map (Element.text >> List.singleton >> Element.paragraph [])
|> Element.column []
Json.OptionalFieldWithDefault default ->
Element.paragraph []
[ Element.el [ Font.bold] (Element.text "Defaults to: ")
, Element.text default
]
|> List.singleton
|> List.append (List.map (Element.text >> List.singleton >> Element.paragraph []) description)
|> Element.column []
{-| Write JSON type as a string.
-}
toString : Docs -> String
toString docs =
case docs of
DocsBool ->
"bool"
DocsDict d ->
"{string:" ++ (toString d) ++ "}"
DocsFloat ->
"float"
DocsInt ->
"int"
DocsLazy f ->
toString (f ())
DocsList d ->
"[" ++ (toString d) ++ "]"
DocsMap { content } ->
"f(" ++ (toString content) ++ ")"
DocsObject { name } ->
name
DocsOptional d ->
toString d
DocsRiskyMap { content } ->
"f(" ++ (toString content) ++ ")"
DocsString ->
"string"
DocsValue ->
"<json>"

100
dev/Main.elm Normal file
View File

@ -0,0 +1,100 @@
module Main exposing (main)
{-| This module creates a browser document that allows users to look at various
documentation elements of the Elm Matrix SDK.
-}
import Browser
import Browser.Navigation as Navigation
import Route exposing (Route(..))
import Url
import FastDict as Dict
import DocsDisplay as Display
import Internal.Values.StateManager
import Element
import Internal.Tools.Json as Json
main : Program () Model Msg
main =
Browser.application
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
, onUrlChange = OnUrlChange
, onUrlRequest = OnUrlRequest
}
type alias Model =
{ key : Navigation.Key
, page : Route.Route
}
type Msg
= OnTableSwitch ( String, Bool )
| OnUrlChange Url.Url
| OnUrlRequest Browser.UrlRequest
-- INIT
init : () -> Url.Url -> Navigation.Key -> ( Model, Cmd Msg )
init () url key =
( { key = key
, page = Route.toRoute url
}
, Cmd.none
)
-- UPDATE
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
OnTableSwitch _ ->
( model, Cmd.none )
OnUrlChange url ->
init () url model.key
OnUrlRequest (Browser.Internal url) ->
( model, Navigation.pushUrl model.key (Url.toString url) )
OnUrlRequest (Browser.External url) ->
( model, Navigation.load url )
-- SUBSCRIPTIONS
subscriptions : Model -> Sub Msg
subscriptions _ =
Sub.none
-- VIEW
view : Model -> Browser.Document Msg
view model =
{ title = Route.toString model.page ++ " | Elm Matrix SDK Docs"
, body =
case model.page of
_ ->
Internal.Values.StateManager.coder
|> Json.toDocs
|> Display.render Dict.empty
|> Element.map OnTableSwitch
|> Element.layout []
|> List.singleton
}

52
dev/Route.elm Normal file
View File

@ -0,0 +1,52 @@
module Route exposing (..)
{-| This module helps parse the URL route into explicable data.
-}
import Url
import Url.Parser as P exposing ((</>))
type Route
= Home
| NotFound
| ViewObject String
toRoute : Url.Url -> Route
toRoute url =
P.parse routeParser url |> Maybe.withDefault NotFound
toString : Route -> String
toString route =
case route of
Home ->
"Home"
NotFound ->
"404"
ViewObject o ->
o
routeParser : P.Parser (Route -> a) a
routeParser =
P.oneOf
[ P.top
|> P.map Home
, P.s "home"
|> P.map Home
, P.s "index"
|> P.map Home
, P.s "dev"
</> (P.s "Main.elm")
|> P.map Home
, P.s "object"
</> P.string
|> P.map ViewObject
, P.s "object"
</> P.top
|> P.map (ViewObject "")
]

40
elm-dev.json Normal file
View File

@ -0,0 +1,40 @@
{
"type": "application",
"source-directories": [
"src",
"dev"
],
"elm-version": "0.19.1",
"dependencies": {
"direct": {
"Orasund/elm-ui-widgets": "3.4.0",
"avh4/elm-color": "1.0.0",
"elm/browser": "1.0.2",
"elm/core": "1.0.5",
"elm/html": "1.0.0",
"elm/json": "1.1.3",
"elm/svg": "1.0.1",
"elm/time": "1.0.0",
"elm/url": "1.0.0",
"mdgriffith/elm-ui": "1.1.8",
"miniBill/elm-fast-dict": "1.1.0"
},
"indirect": {
"elm/regex": "1.0.0",
"elm/virtual-dom": "1.0.3",
"elm-community/intdict": "3.0.0",
"fredcy/elm-parseint": "2.0.1",
"noahzgordon/elm-color-extra": "1.0.2",
"turboMaCk/queue": "1.1.0"
}
},
"test-dependencies": {
"direct": {
"elm-explorations/test": "2.2.0"
},
"indirect": {
"elm/bytes": "1.0.8",
"elm/random": "1.0.0"
}
}
}

87
tests/Dev/Route.elm Normal file
View File

@ -0,0 +1,87 @@
module Dev.Route exposing (..)
{-| This module tests whether routes are translated correctly.
-}
import Expect
import Fuzz exposing (Fuzzer)
import Route exposing (Route(..), toRoute)
import Test exposing (..)
import Url
customPath : String -> Fuzzer Url.Url
customPath path =
Fuzz.map (\url -> { url | path = path }) fuzzer
-- TODO: Create a more valid URL fuzzer
fuzzer : Fuzzer Url.Url
fuzzer =
Fuzz.map6 Url.Url
(Fuzz.oneOfValues [ Url.Http, Url.Https ])
Fuzz.string
(Fuzz.maybe Fuzz.int)
Fuzz.string
(Fuzz.maybe Fuzz.string)
(Fuzz.maybe Fuzz.string)
-- urlCheck : Test
-- urlCheck =
-- describe "URL fuzzer tests"
-- [ fuzz fuzzer"Index always parses to url"
-- (\url ->
-- url
-- |> Url.toString
-- |> Url.fromString
-- |> Expect.equal (Just url)
-- )
-- ]
suite : Test
suite =
describe "Route conversion"
[ fuzz (customPath "/")
"/ --> Home"
(\url ->
url
|> toRoute
|> Expect.equal Home
)
, fuzz (customPath "/home")
"/home --> Home"
(\url ->
url
|> toRoute
|> Expect.equal Home
)
, fuzz (customPath "/index")
"/index --> Home"
(\url ->
url
|> toRoute
|> Expect.equal Home
)
, fuzz
(Fuzz.asciiString
|> Fuzz.filter (not << String.contains "/")
|> Fuzz.andThen
(\o ->
Fuzz.pair
(Fuzz.constant o)
(customPath ("/object/" ++ o))
)
)
"Object can be seen"
(\( o, url ) ->
url
|> toRoute
|> Expect.equal (ViewObject o)
)
]