diva.js 7.2.4 → 7.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -11
- package/build/diva.debug.js +29165 -0
- package/build/diva.esm.js +17 -0
- package/build/diva.js +17 -0
- package/package.json +16 -3
- package/.clang-format +0 -7
- package/.github/workflows/npm-publish.yml +0 -45
- package/Makefile +0 -75
- package/elm.json +0 -32
- package/review/elm.json +0 -52
- package/review/src/ReviewConfig.elm +0 -87
- package/scripts/elm-esm.sh +0 -40
- package/scripts/minify-css.mjs +0 -31
- package/src/Filters.elm +0 -1044
- package/src/Main.elm +0 -1217
- package/src/Model.elm +0 -213
- package/src/Msg.elm +0 -59
- package/src/Utilities.elm +0 -46
- package/src/View/CollectionExplorer.elm +0 -172
- package/src/View/Helpers.elm +0 -86
- package/src/View/HtmlRenderer.elm +0 -136
- package/src/View/Icons.elm +0 -159
- package/src/View/ManifestInfoModal.elm +0 -363
- package/src/View/PageViewModal.elm +0 -1046
- package/src/View/Sidebar.elm +0 -786
- package/src/View/Toolbar.elm +0 -189
- package/src/View.elm +0 -244
- package/src/diva.ts +0 -802
- package/src/filters.ts +0 -1843
- package/src/styles/app.css +0 -328
- package/src/styles/collection.css +0 -75
- package/src/styles/modal.css +0 -388
- package/src/styles/sidebar.css +0 -215
- package/src/styles/theme.css +0 -39
- package/src/styles/toolbar.css +0 -154
- package/src/viewer-element.ts +0 -1307
- package/testing/index.html +0 -52
- package/testing/testing.html +0 -231
- package/tsconfig.json +0 -12
package/src/Model.elm
DELETED
|
@@ -1,213 +0,0 @@
|
|
|
1
|
-
module Model exposing (CollectionState, ContentsView(..), Model, Page, PageImage, ResourceResponse(..), Response(..), SidebarState(..), ViewMode(..), currentManifest, getPageAt, manifestToPages, pageViewStartIndex, primaryImage)
|
|
2
|
-
|
|
3
|
-
import Dict exposing (Dict)
|
|
4
|
-
import Filters exposing (Filters)
|
|
5
|
-
import IIIF.Image exposing (createImageAddress, thumbnailUrlFromInfo)
|
|
6
|
-
import IIIF.Language exposing (Language, extractLabelFromLanguageMap)
|
|
7
|
-
import IIIF.Presentation exposing (Canvas, IIIFCollection, IIIFManifest, Image, ImageType(..), canvasAspect, canvasLabel, toCanvases)
|
|
8
|
-
import Set exposing (Set)
|
|
9
|
-
import Utilities exposing (find, isNothing)
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
type alias CollectionState =
|
|
13
|
-
{ collection : IIIFCollection
|
|
14
|
-
, expandedIds : Set String
|
|
15
|
-
, selectedManifestId : Maybe String
|
|
16
|
-
, loadingCollectionIds : Set String
|
|
17
|
-
, loadedCollectionIds : Set String
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
type ContentsView
|
|
22
|
-
= ContentsIndex
|
|
23
|
-
| ContentsPages
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
type alias Model =
|
|
27
|
-
{ rootElementId : String
|
|
28
|
-
, manifestUrl : String
|
|
29
|
-
, acceptHeaders : List String
|
|
30
|
-
, initialZoom : Maybe Float
|
|
31
|
-
, currentZoom : Maybe Float
|
|
32
|
-
, hasTileSources : Bool
|
|
33
|
-
, pages : List Page
|
|
34
|
-
, selectedIndex : Maybe Int
|
|
35
|
-
, selectedRangeId : Maybe String
|
|
36
|
-
, rangeIndexMap : Dict String (Maybe Int)
|
|
37
|
-
, thumbsInstantScroll : Bool
|
|
38
|
-
, pendingThumbScroll : Maybe Int
|
|
39
|
-
, pageViewOpen : Bool
|
|
40
|
-
, pageViewFullscreen : Bool
|
|
41
|
-
, pageViewSidebarVisible : Bool
|
|
42
|
-
, pageViewImageIndex : Int
|
|
43
|
-
, manifestInfoOpen : Bool
|
|
44
|
-
, filters : Filters
|
|
45
|
-
, filtersJsonInput : String
|
|
46
|
-
, filtersJsonError : Maybe String
|
|
47
|
-
, fullscreen : Bool
|
|
48
|
-
, viewMode : ViewMode
|
|
49
|
-
, shiftByOne : Bool
|
|
50
|
-
, sidebarState : SidebarState
|
|
51
|
-
, mobileSidebarOpen : Bool
|
|
52
|
-
, isMobile : Bool
|
|
53
|
-
, showTitle : Bool
|
|
54
|
-
, isViewerLoading : Bool
|
|
55
|
-
, response : Response
|
|
56
|
-
, sidebarWidth : Int
|
|
57
|
-
, sidebarDrag : Maybe { startX : Int, startWidth : Int }
|
|
58
|
-
, resourceResponse : ResourceResponse
|
|
59
|
-
, collectionSidebarWidth : Int
|
|
60
|
-
, collectionSidebarVisible : Bool
|
|
61
|
-
, collectionSidebarDrag : Maybe { startX : Int, startWidth : Int }
|
|
62
|
-
, filterGroupExpanded : Set String
|
|
63
|
-
, contentsView : ContentsView
|
|
64
|
-
, detectedLanguage : Language
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
type alias Page =
|
|
69
|
-
{ aspect : Float
|
|
70
|
-
, label : String
|
|
71
|
-
, images : List PageImage
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
type alias PageImage =
|
|
76
|
-
{ tileSource : String
|
|
77
|
-
, thumbUrl : String
|
|
78
|
-
, label : String
|
|
79
|
-
, isPrimary : Bool
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
type ResourceResponse
|
|
84
|
-
= ResourceLoading
|
|
85
|
-
| ResourceLoadedManifest IIIFManifest
|
|
86
|
-
| ResourceLoadedCollection CollectionState
|
|
87
|
-
| ResourceFailed String
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
type Response
|
|
91
|
-
= NotRequested
|
|
92
|
-
| Loading
|
|
93
|
-
| Loaded IIIFManifest
|
|
94
|
-
| Failed String
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
type SidebarState
|
|
98
|
-
= SidebarHidden
|
|
99
|
-
| SidebarThumbnails
|
|
100
|
-
| SidebarMetadata
|
|
101
|
-
| SidebarContents
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
type ViewMode
|
|
105
|
-
= OneUp
|
|
106
|
-
| TwoUp
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
currentManifest : Model -> Maybe IIIFManifest
|
|
110
|
-
currentManifest model =
|
|
111
|
-
case model.resourceResponse of
|
|
112
|
-
ResourceLoadedManifest manifest ->
|
|
113
|
-
Just manifest
|
|
114
|
-
|
|
115
|
-
ResourceLoadedCollection _ ->
|
|
116
|
-
case model.response of
|
|
117
|
-
Loaded manifest ->
|
|
118
|
-
Just manifest
|
|
119
|
-
|
|
120
|
-
_ ->
|
|
121
|
-
Nothing
|
|
122
|
-
|
|
123
|
-
_ ->
|
|
124
|
-
Nothing
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
getPageAt : Int -> List Page -> Maybe Page
|
|
128
|
-
getPageAt index pageList =
|
|
129
|
-
List.drop index pageList |> List.head
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
manifestToPages : Language -> IIIFManifest -> List Page
|
|
133
|
-
manifestToPages language iiifManifest =
|
|
134
|
-
toCanvases iiifManifest
|
|
135
|
-
|> List.filterMap (canvasToPage language)
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
pageViewStartIndex : ViewMode -> Bool -> Int -> Int
|
|
139
|
-
pageViewStartIndex viewMode shiftByOne index =
|
|
140
|
-
case viewMode of
|
|
141
|
-
OneUp ->
|
|
142
|
-
index
|
|
143
|
-
|
|
144
|
-
TwoUp ->
|
|
145
|
-
if shiftByOne then
|
|
146
|
-
if index == 0 then
|
|
147
|
-
0
|
|
148
|
-
|
|
149
|
-
else if modBy 2 index == 1 then
|
|
150
|
-
index
|
|
151
|
-
|
|
152
|
-
else
|
|
153
|
-
index - 1
|
|
154
|
-
|
|
155
|
-
else
|
|
156
|
-
index - modBy 2 index
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
primaryImage : Page -> Maybe PageImage
|
|
160
|
-
primaryImage page =
|
|
161
|
-
case find .isPrimary page.images of
|
|
162
|
-
Just image ->
|
|
163
|
-
Just image
|
|
164
|
-
|
|
165
|
-
Nothing ->
|
|
166
|
-
List.head page.images
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
canvasToPage : Language -> Canvas -> Maybe Page
|
|
170
|
-
canvasToPage language canvas =
|
|
171
|
-
let
|
|
172
|
-
images =
|
|
173
|
-
List.map (iiifImageToPageImage language canvas.images) canvas.images
|
|
174
|
-
in
|
|
175
|
-
if List.isEmpty images then
|
|
176
|
-
Nothing
|
|
177
|
-
|
|
178
|
-
else
|
|
179
|
-
Just
|
|
180
|
-
{ aspect = canvasAspect canvas
|
|
181
|
-
, label = canvasLabel canvas
|
|
182
|
-
, images = images
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
iiifImageToPageImage : Language -> List Image -> Image -> PageImage
|
|
187
|
-
iiifImageToPageImage language allImages image =
|
|
188
|
-
let
|
|
189
|
-
tileSource =
|
|
190
|
-
createImageAddress image.id
|
|
191
|
-
|
|
192
|
-
thumbUrl =
|
|
193
|
-
thumbnailUrlFromInfo tileSource
|
|
194
|
-
|
|
195
|
-
label =
|
|
196
|
-
Maybe.map (extractLabelFromLanguageMap language) image.label
|
|
197
|
-
|> Maybe.withDefault "Image"
|
|
198
|
-
|
|
199
|
-
isFirst =
|
|
200
|
-
Just image == List.head allImages
|
|
201
|
-
|
|
202
|
-
isPrimaryImage =
|
|
203
|
-
find (\img -> img.imageType == PrimaryImage) allImages
|
|
204
|
-
|> isNothing
|
|
205
|
-
|
|
206
|
-
isPrimary =
|
|
207
|
-
image.imageType == PrimaryImage || (isPrimaryImage && isFirst)
|
|
208
|
-
in
|
|
209
|
-
{ tileSource = tileSource
|
|
210
|
-
, thumbUrl = thumbUrl
|
|
211
|
-
, label = label
|
|
212
|
-
, isPrimary = isPrimary
|
|
213
|
-
}
|
package/src/Msg.elm
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
module Msg exposing (Msg(..))
|
|
2
|
-
|
|
3
|
-
import Filters exposing (FilterFloatValue, FilterIntValue, FilterStringValue, FilterToggle)
|
|
4
|
-
import Http
|
|
5
|
-
import IIIF.Presentation exposing (IIIFManifest, IIIFResource)
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
type Msg
|
|
9
|
-
= ClientNotifiedFullscreenChanged Bool
|
|
10
|
-
| ClientNotifiedPageChanged Int
|
|
11
|
-
| ClientNotifiedPageChangedInstant Int
|
|
12
|
-
| ClientNotifiedScrollThumbs
|
|
13
|
-
| ServerRespondedWithCollectionItem String (Result Http.Error IIIFResource)
|
|
14
|
-
| ServerRespondedWithManifestFromCollection String (Result Http.Error IIIFManifest)
|
|
15
|
-
| ServerRespondedWithResource (Result Http.Error IIIFResource)
|
|
16
|
-
| UserAppliedFilterJson
|
|
17
|
-
| UserChangedZoomLevel Float
|
|
18
|
-
| UserClickedCloseManifestInfo
|
|
19
|
-
| UserClickedClosePageView
|
|
20
|
-
| UserClickedCollectionItem String
|
|
21
|
-
| UserClickedManifestItem String String
|
|
22
|
-
| UserClickedOpenManifestInfo
|
|
23
|
-
| UserClickedOpenPageView
|
|
24
|
-
| UserClickedPageViewImageChoice Int
|
|
25
|
-
| UserClickedPageViewNext
|
|
26
|
-
| UserClickedPageViewPrev
|
|
27
|
-
| UserClickedRange String (Maybe Int)
|
|
28
|
-
| UserClickedSaveFilteredImage
|
|
29
|
-
| UserClickedThumbnail Int
|
|
30
|
-
| UserClickedZoomIn
|
|
31
|
-
| UserClickedZoomOut
|
|
32
|
-
| UserCopiedFilterJson
|
|
33
|
-
| UserDraggedCollectionSidebarResize Int
|
|
34
|
-
| UserDraggedSidebarResize Int
|
|
35
|
-
| UserEndedCollectionSidebarResize
|
|
36
|
-
| UserEndedSidebarResize
|
|
37
|
-
| UserResetAllFilters
|
|
38
|
-
| UserResetAltColourAdjust
|
|
39
|
-
| UserSelectedContentsIndex
|
|
40
|
-
| UserSelectedContentsPages
|
|
41
|
-
| UserStartedCollectionSidebarResize Int
|
|
42
|
-
| UserStartedSidebarResize Int
|
|
43
|
-
| UserToggledContents
|
|
44
|
-
| UserToggledFilter FilterToggle Bool
|
|
45
|
-
| UserToggledFilterGroup String
|
|
46
|
-
| UserToggledFullscreen
|
|
47
|
-
| UserToggledMetadata
|
|
48
|
-
| UserToggledPageViewFullscreen
|
|
49
|
-
| UserToggledPageViewSidebar
|
|
50
|
-
| UserToggledShiftByOne
|
|
51
|
-
| UserToggledSidebar
|
|
52
|
-
| UserToggledThumbnails
|
|
53
|
-
| UserToggledTwoUp
|
|
54
|
-
| UserUpdatedFilterFloat FilterFloatValue String
|
|
55
|
-
| UserUpdatedFilterInt FilterIntValue String
|
|
56
|
-
| UserUpdatedFilterJsonInput String
|
|
57
|
-
| UserUpdatedFilterString FilterStringValue String
|
|
58
|
-
| ViewerLoadingChanged Bool
|
|
59
|
-
| ViewportChanged Int Int
|
package/src/Utilities.elm
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
module Utilities exposing (disabledIf, find, isNothing)
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
disabledIf : Bool -> msg -> Maybe msg
|
|
5
|
-
disabledIf disabled msg =
|
|
6
|
-
if disabled then
|
|
7
|
-
Nothing
|
|
8
|
-
|
|
9
|
-
else
|
|
10
|
-
Just msg
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
{-| Find the first element that satisfies a predicate and return
|
|
14
|
-
Just that element. If none match, return Nothing.
|
|
15
|
-
|
|
16
|
-
find (\num -> num > 5) [ 2, 4, 6, 8 ]
|
|
17
|
-
--> Just 6
|
|
18
|
-
|
|
19
|
-
-}
|
|
20
|
-
find : (a -> Bool) -> List a -> Maybe a
|
|
21
|
-
find predicate list =
|
|
22
|
-
case list of
|
|
23
|
-
[] ->
|
|
24
|
-
Nothing
|
|
25
|
-
|
|
26
|
-
first :: rest ->
|
|
27
|
-
if predicate first then
|
|
28
|
-
Just first
|
|
29
|
-
|
|
30
|
-
else
|
|
31
|
-
find predicate rest
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
isNothing : Maybe a -> Bool
|
|
35
|
-
isNothing maybeVal =
|
|
36
|
-
isJust maybeVal |> not
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
isJust : Maybe a -> Bool
|
|
40
|
-
isJust maybeVal =
|
|
41
|
-
case maybeVal of
|
|
42
|
-
Just _ ->
|
|
43
|
-
True
|
|
44
|
-
|
|
45
|
-
Nothing ->
|
|
46
|
-
False
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
module View.CollectionExplorer exposing (viewCollectionResizer, viewCollectionSidebar)
|
|
2
|
-
|
|
3
|
-
import Html exposing (Html, button, div, li, text, ul)
|
|
4
|
-
import Html.Attributes as HA exposing (classList, type_)
|
|
5
|
-
import Html.Events as Events
|
|
6
|
-
import Html.Lazy as Lazy
|
|
7
|
-
import IIIF.Language exposing (Language, extractLabelFromLanguageMap)
|
|
8
|
-
import IIIF.Presentation exposing (Collection, CollectionItem(..), IIIFCollection(..), Manifest)
|
|
9
|
-
import Json.Decode as Decode
|
|
10
|
-
import Model exposing (CollectionState, Model, ResourceResponse(..))
|
|
11
|
-
import Msg exposing (Msg(..))
|
|
12
|
-
import Set
|
|
13
|
-
import View.Helpers exposing (emptyHtml, viewMaybe)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
viewCollectionResizer : Model -> Html Msg
|
|
17
|
-
viewCollectionResizer model =
|
|
18
|
-
case model.resourceResponse of
|
|
19
|
-
ResourceLoadedCollection _ ->
|
|
20
|
-
div
|
|
21
|
-
[ classList
|
|
22
|
-
[ ( "collection-resizer", True )
|
|
23
|
-
, ( "is-hidden", not model.collectionSidebarVisible )
|
|
24
|
-
]
|
|
25
|
-
, Events.on "mousedown"
|
|
26
|
-
(Decode.field "clientX" Decode.int
|
|
27
|
-
|> Decode.map UserStartedCollectionSidebarResize
|
|
28
|
-
)
|
|
29
|
-
]
|
|
30
|
-
[ text "⋮" ]
|
|
31
|
-
|
|
32
|
-
_ ->
|
|
33
|
-
emptyHtml
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
viewCollectionSidebar : Model -> Html Msg
|
|
37
|
-
viewCollectionSidebar model =
|
|
38
|
-
case model.resourceResponse of
|
|
39
|
-
ResourceLoadedCollection collectionState ->
|
|
40
|
-
viewCollectionPanel model collectionState
|
|
41
|
-
|
|
42
|
-
_ ->
|
|
43
|
-
emptyHtml
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
viewCollectionItem : Language -> CollectionState -> CollectionItem -> Html Msg
|
|
47
|
-
viewCollectionItem language collectionState item =
|
|
48
|
-
case item of
|
|
49
|
-
NestedCollection collection ->
|
|
50
|
-
viewNestedCollection language collectionState collection
|
|
51
|
-
|
|
52
|
-
ManifestItem manifest ->
|
|
53
|
-
viewManifestItem language collectionState manifest
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
viewCollectionPanel : Model -> CollectionState -> Html Msg
|
|
57
|
-
viewCollectionPanel model collectionState =
|
|
58
|
-
let
|
|
59
|
-
(IIIFCollection _ collection) =
|
|
60
|
-
collectionState.collection
|
|
61
|
-
|
|
62
|
-
labelText =
|
|
63
|
-
extractLabelFromLanguageMap model.detectedLanguage collection.label
|
|
64
|
-
in
|
|
65
|
-
div
|
|
66
|
-
[ classList
|
|
67
|
-
[ ( "collection-panel", True )
|
|
68
|
-
, ( "is-fullscreen", model.fullscreen )
|
|
69
|
-
, ( "is-hidden", not model.collectionSidebarVisible )
|
|
70
|
-
]
|
|
71
|
-
, HA.style "width"
|
|
72
|
-
(if model.collectionSidebarVisible then
|
|
73
|
-
String.fromInt model.collectionSidebarWidth ++ "px"
|
|
74
|
-
|
|
75
|
-
else
|
|
76
|
-
"0px"
|
|
77
|
-
)
|
|
78
|
-
]
|
|
79
|
-
[ div
|
|
80
|
-
[ HA.class "collection-header" ]
|
|
81
|
-
[ div [ HA.class "collection-title" ] [ text labelText ]
|
|
82
|
-
, viewMaybe
|
|
83
|
-
(\summary ->
|
|
84
|
-
div [ HA.class "collection-summary" ] [ text (extractLabelFromLanguageMap model.detectedLanguage summary) ]
|
|
85
|
-
)
|
|
86
|
-
collection.summary
|
|
87
|
-
]
|
|
88
|
-
, div
|
|
89
|
-
[ HA.class "sidebar-content" ]
|
|
90
|
-
[ div
|
|
91
|
-
[ HA.class "sidebar-pane is-scroll" ]
|
|
92
|
-
[ viewCollectionTree model.detectedLanguage collectionState collection.items ]
|
|
93
|
-
]
|
|
94
|
-
]
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
viewCollectionTree : Language -> CollectionState -> List CollectionItem -> Html Msg
|
|
98
|
-
viewCollectionTree language collectionState items =
|
|
99
|
-
ul
|
|
100
|
-
[ HA.class "collection-list list-reset" ]
|
|
101
|
-
(List.map (Lazy.lazy3 viewCollectionItem language collectionState) items)
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
viewManifestItem : Language -> CollectionState -> Manifest -> Html Msg
|
|
105
|
-
viewManifestItem language collectionState manifest =
|
|
106
|
-
let
|
|
107
|
-
labelText =
|
|
108
|
-
extractLabelFromLanguageMap language manifest.label
|
|
109
|
-
|
|
110
|
-
isActive =
|
|
111
|
-
collectionState.selectedManifestId == Just manifest.id
|
|
112
|
-
in
|
|
113
|
-
li []
|
|
114
|
-
[ button
|
|
115
|
-
[ classList
|
|
116
|
-
[ ( "manifest-tree-item", True )
|
|
117
|
-
, ( "ui-button", True )
|
|
118
|
-
, ( "is-active", isActive )
|
|
119
|
-
]
|
|
120
|
-
, type_ "button"
|
|
121
|
-
, Events.onClick (UserClickedManifestItem manifest.id manifest.id)
|
|
122
|
-
]
|
|
123
|
-
[ text labelText ]
|
|
124
|
-
]
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
viewNestedCollection : Language -> CollectionState -> Collection -> Html Msg
|
|
128
|
-
viewNestedCollection language collectionState collection =
|
|
129
|
-
let
|
|
130
|
-
isExpanded =
|
|
131
|
-
Set.member collection.id collectionState.expandedIds
|
|
132
|
-
|
|
133
|
-
labelText =
|
|
134
|
-
extractLabelFromLanguageMap language collection.label
|
|
135
|
-
|
|
136
|
-
expandIcon =
|
|
137
|
-
if isExpanded then
|
|
138
|
-
"▼"
|
|
139
|
-
|
|
140
|
-
else
|
|
141
|
-
"▶"
|
|
142
|
-
|
|
143
|
-
childrenView =
|
|
144
|
-
if isExpanded then
|
|
145
|
-
let
|
|
146
|
-
isLoading =
|
|
147
|
-
Set.member collection.id collectionState.loadingCollectionIds
|
|
148
|
-
|
|
149
|
-
loadingView =
|
|
150
|
-
if isLoading then
|
|
151
|
-
[ div [ HA.class "contents-empty" ] [ text "Loading…" ] ]
|
|
152
|
-
|
|
153
|
-
else
|
|
154
|
-
[]
|
|
155
|
-
in
|
|
156
|
-
viewCollectionTree language collectionState collection.items :: loadingView
|
|
157
|
-
|
|
158
|
-
else
|
|
159
|
-
[]
|
|
160
|
-
in
|
|
161
|
-
li
|
|
162
|
-
[ HA.class "collection-tree-item" ]
|
|
163
|
-
(button
|
|
164
|
-
[ HA.class "collection-node-button ui-button"
|
|
165
|
-
, type_ "button"
|
|
166
|
-
, Events.onClick (UserClickedCollectionItem collection.id)
|
|
167
|
-
]
|
|
168
|
-
[ div [ HA.class "collection-expand-icon" ] [ text expandIcon ]
|
|
169
|
-
, text labelText
|
|
170
|
-
]
|
|
171
|
-
:: childrenView
|
|
172
|
-
)
|
package/src/View/Helpers.elm
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
module View.Helpers exposing (ButtonConfig, emptyHtml, viewButton, viewIf, viewMaybe)
|
|
2
|
-
|
|
3
|
-
import Html exposing (Html, button, div, text)
|
|
4
|
-
import Html.Attributes as HA exposing (classList, type_)
|
|
5
|
-
import Html.Events as Events
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
type alias ButtonConfig msg =
|
|
9
|
-
{ label : String
|
|
10
|
-
, icon : Html msg
|
|
11
|
-
, onClickMsg : Maybe msg
|
|
12
|
-
, isFullscreen : Bool
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
emptyHtml : Html msg
|
|
17
|
-
emptyHtml =
|
|
18
|
-
text ""
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
viewButton : ButtonConfig msg -> Html msg
|
|
22
|
-
viewButton config =
|
|
23
|
-
let
|
|
24
|
-
buttonAttrs =
|
|
25
|
-
let
|
|
26
|
-
isDisabled =
|
|
27
|
-
config.onClickMsg == Nothing
|
|
28
|
-
|
|
29
|
-
baseAttrs =
|
|
30
|
-
[ classList
|
|
31
|
-
[ ( "canvas-toolbar-button", True )
|
|
32
|
-
, ( "is-disabled", isDisabled )
|
|
33
|
-
, ( "is-fullscreen", config.isFullscreen )
|
|
34
|
-
]
|
|
35
|
-
, type_ "button"
|
|
36
|
-
, HA.title config.label
|
|
37
|
-
]
|
|
38
|
-
in
|
|
39
|
-
case config.onClickMsg of
|
|
40
|
-
Just msg ->
|
|
41
|
-
Events.onClick msg :: baseAttrs
|
|
42
|
-
|
|
43
|
-
Nothing ->
|
|
44
|
-
HA.disabled True :: baseAttrs
|
|
45
|
-
in
|
|
46
|
-
div
|
|
47
|
-
[ HA.class "canvas-toolbar-item" ]
|
|
48
|
-
[ button buttonAttrs [ config.icon ]
|
|
49
|
-
, div
|
|
50
|
-
[ classList
|
|
51
|
-
[ ( "canvas-toolbar-label", True )
|
|
52
|
-
, ( "is-fullscreen", config.isFullscreen )
|
|
53
|
-
]
|
|
54
|
-
]
|
|
55
|
-
[ text config.label ]
|
|
56
|
-
]
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
viewIf : Html msg -> Bool -> Html msg
|
|
60
|
-
viewIf view condition =
|
|
61
|
-
if condition then
|
|
62
|
-
view
|
|
63
|
-
|
|
64
|
-
else
|
|
65
|
-
emptyHtml
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
{-|
|
|
69
|
-
|
|
70
|
-
A view helper that will either render the value of
|
|
71
|
-
'body' with a given `viewFunc`, or return `Element.none`
|
|
72
|
-
indicating nothing should be rendered.
|
|
73
|
-
|
|
74
|
-
`viewFunc` can be partially applied with a `language` value
|
|
75
|
-
allowing the body to be rendered in response to the user's
|
|
76
|
-
selected language parameter.
|
|
77
|
-
|
|
78
|
-
-}
|
|
79
|
-
viewMaybe : (a -> Html msg) -> Maybe a -> Html msg
|
|
80
|
-
viewMaybe viewFunc maybeBody =
|
|
81
|
-
case maybeBody of
|
|
82
|
-
Just a ->
|
|
83
|
-
viewFunc a
|
|
84
|
-
|
|
85
|
-
Nothing ->
|
|
86
|
-
emptyHtml
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
module View.HtmlRenderer exposing (renderHtml)
|
|
2
|
-
|
|
3
|
-
import Html exposing (Html, text)
|
|
4
|
-
import Html.Parser as HtmlParser
|
|
5
|
-
import Html.Parser.Util as HtmlParserUtil
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
renderHtml : String -> List (Html msg)
|
|
9
|
-
renderHtml rawHtml =
|
|
10
|
-
let
|
|
11
|
-
normalized =
|
|
12
|
-
normalizeHtml rawHtml
|
|
13
|
-
|
|
14
|
-
renderNodes nodes =
|
|
15
|
-
sanitizeNodes nodes
|
|
16
|
-
|> HtmlParserUtil.toVirtualDom
|
|
17
|
-
in
|
|
18
|
-
case HtmlParser.run normalized of
|
|
19
|
-
Ok nodes ->
|
|
20
|
-
renderNodes nodes
|
|
21
|
-
|
|
22
|
-
Err _ ->
|
|
23
|
-
case HtmlParser.run ("<div>" ++ normalized ++ "</div>") of
|
|
24
|
-
Ok nodes ->
|
|
25
|
-
unwrapRootDiv nodes
|
|
26
|
-
|> renderNodes
|
|
27
|
-
|
|
28
|
-
Err _ ->
|
|
29
|
-
[ text rawHtml ]
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
ensureAnchorDefaults : List HtmlParser.Attribute -> List HtmlParser.Attribute
|
|
33
|
-
ensureAnchorDefaults attrs =
|
|
34
|
-
let
|
|
35
|
-
hasTarget =
|
|
36
|
-
List.any (\attr -> Tuple.first attr == "target") attrs
|
|
37
|
-
|
|
38
|
-
hasRel =
|
|
39
|
-
List.any (\attr -> Tuple.first attr == "rel") attrs
|
|
40
|
-
in
|
|
41
|
-
attrs
|
|
42
|
-
|> (\current ->
|
|
43
|
-
if hasTarget then
|
|
44
|
-
current
|
|
45
|
-
|
|
46
|
-
else
|
|
47
|
-
( "target", "_blank" ) :: current
|
|
48
|
-
)
|
|
49
|
-
|> (\current ->
|
|
50
|
-
if hasRel then
|
|
51
|
-
current
|
|
52
|
-
|
|
53
|
-
else
|
|
54
|
-
( "rel", "noopener noreferrer" ) :: current
|
|
55
|
-
)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
isAllowedTag : String -> Bool
|
|
59
|
-
isAllowedTag tag =
|
|
60
|
-
List.member tag [ "p", "br", "em", "i", "strong", "b", "a", "ul", "ol", "li", "span", "img" ]
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
normalizeHtml : String -> String
|
|
64
|
-
normalizeHtml rawHtml =
|
|
65
|
-
String.replace "<br>" "<br/>" rawHtml
|
|
66
|
-
|> String.replace "<br />" "<br/>"
|
|
67
|
-
|> String.replace "</p></p>" "</p>"
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
sanitizeAnchorAttr : HtmlParser.Attribute -> Maybe HtmlParser.Attribute
|
|
71
|
-
sanitizeAnchorAttr attr =
|
|
72
|
-
case Tuple.first attr of
|
|
73
|
-
"href" ->
|
|
74
|
-
Just attr
|
|
75
|
-
|
|
76
|
-
_ ->
|
|
77
|
-
Nothing
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
sanitizeAttrs : String -> List HtmlParser.Attribute -> List HtmlParser.Attribute
|
|
81
|
-
sanitizeAttrs tag attrs =
|
|
82
|
-
case tag of
|
|
83
|
-
"a" ->
|
|
84
|
-
List.filterMap sanitizeAnchorAttr attrs
|
|
85
|
-
|> ensureAnchorDefaults
|
|
86
|
-
|
|
87
|
-
"img" ->
|
|
88
|
-
List.filterMap sanitizeImageAttr attrs
|
|
89
|
-
|
|
90
|
-
_ ->
|
|
91
|
-
[]
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
sanitizeImageAttr : HtmlParser.Attribute -> Maybe HtmlParser.Attribute
|
|
95
|
-
sanitizeImageAttr attr =
|
|
96
|
-
case Tuple.first attr of
|
|
97
|
-
"alt" ->
|
|
98
|
-
Just attr
|
|
99
|
-
|
|
100
|
-
"src" ->
|
|
101
|
-
Just attr
|
|
102
|
-
|
|
103
|
-
_ ->
|
|
104
|
-
Nothing
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
sanitizeNode : HtmlParser.Node -> List HtmlParser.Node
|
|
108
|
-
sanitizeNode node =
|
|
109
|
-
case node of
|
|
110
|
-
HtmlParser.Text textValue ->
|
|
111
|
-
[ HtmlParser.Text textValue ]
|
|
112
|
-
|
|
113
|
-
HtmlParser.Element tag attrs children ->
|
|
114
|
-
if isAllowedTag tag then
|
|
115
|
-
[ HtmlParser.Element tag (sanitizeAttrs tag attrs) (sanitizeNodes children) ]
|
|
116
|
-
|
|
117
|
-
else
|
|
118
|
-
sanitizeNodes children
|
|
119
|
-
|
|
120
|
-
HtmlParser.Comment _ ->
|
|
121
|
-
[]
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
sanitizeNodes : List HtmlParser.Node -> List HtmlParser.Node
|
|
125
|
-
sanitizeNodes nodes =
|
|
126
|
-
List.concatMap sanitizeNode nodes
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
unwrapRootDiv : List HtmlParser.Node -> List HtmlParser.Node
|
|
130
|
-
unwrapRootDiv nodes =
|
|
131
|
-
case nodes of
|
|
132
|
-
[ HtmlParser.Element "div" _ children ] ->
|
|
133
|
-
children
|
|
134
|
-
|
|
135
|
-
_ ->
|
|
136
|
-
nodes
|