diff --git a/package-lock.json b/package-lock.json index 768536731..d617caddb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1656,6 +1656,7 @@ "arm64" ], "dev": true, + "license": "BSD-3-Clause", "optional": true, "os": [ "darwin" @@ -1669,6 +1670,7 @@ "x64" ], "dev": true, + "license": "BSD-3-Clause", "optional": true, "os": [ "darwin" @@ -1695,6 +1697,7 @@ "x64" ], "dev": true, + "license": "BSD-3-Clause", "optional": true, "os": [ "win32" @@ -2116,6 +2119,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -2129,6 +2133,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -2142,6 +2147,7 @@ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -2155,6 +2161,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -2180,6 +2187,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -2206,6 +2214,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -2219,6 +2228,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -2232,6 +2242,7 @@ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -2245,6 +2256,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -2271,6 +2283,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -5014,9 +5027,7 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.11", "dev": true, "license": "MIT", "dependencies": { @@ -7521,6 +7532,7 @@ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -9253,6 +9265,7 @@ "arm64" ], "dev": true, + "license": "MPL-2.0", "optional": true, "os": [ "darwin" @@ -9273,6 +9286,7 @@ "x64" ], "dev": true, + "license": "MPL-2.0", "optional": true, "os": [ "darwin" @@ -9293,6 +9307,7 @@ "arm" ], "dev": true, + "license": "MPL-2.0", "optional": true, "os": [ "linux" @@ -9313,6 +9328,7 @@ "arm64" ], "dev": true, + "license": "MPL-2.0", "optional": true, "os": [ "linux" @@ -9333,6 +9349,7 @@ "arm64" ], "dev": true, + "license": "MPL-2.0", "optional": true, "os": [ "linux" @@ -9393,6 +9410,7 @@ "x64" ], "dev": true, + "license": "MPL-2.0", "optional": true, "os": [ "win32" @@ -9448,9 +9466,7 @@ } }, "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "version": "4.17.21", "dev": true, "license": "MIT" }, diff --git a/package.json b/package.json index 9aec292e0..5e064772a 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,8 @@ "watch:app": "npx parcel serve src/entry/app/index.html --open", "build:indexeddb": "npm run clean && npx parcel build --no-source-maps --public-url . src/entry/indexeddb/index.html", "watch:indexeddb": "npx parcel serve src/entry/indexeddb/index.html --open", + "build:pdf": "npm run clean && npx parcel build --no-source-maps --public-url . src/entry/pdf/index.html", + "watch:pdf": "npx parcel serve src/entry/pdf/index.html --open", "watch:base": "npx parcel serve src/entry/base/index.html", "build:base": "npm run clean && npx parcel build --no-source-maps --public-url . src/entry/base/index.html", "build:dev": "npm run clean && npx parcel build --no-source-maps --public-url . src/entry/dev/index.html && npm run sw", diff --git a/src/elm/Lia/Markdown/Chart/View.elm b/src/elm/Lia/Markdown/Chart/View.elm index 28b6534b0..42930c57f 100644 --- a/src/elm/Lia/Markdown/Chart/View.elm +++ b/src/elm/Lia/Markdown/Chart/View.elm @@ -1497,15 +1497,7 @@ toolbox : -> ( String, JE.Value ) toolbox position config = ( "toolbox" - , JE.object - [ ( "bottom", JE.int 8 ) - , ( "left" - , position - |> Maybe.withDefault "center" - |> JE.string - ) - , feature config - ] + , JE.null ) diff --git a/src/elm/Lia/Markdown/Code/Events.elm b/src/elm/Lia/Markdown/Code/Events.elm index 968af9bfb..b6427468f 100644 --- a/src/elm/Lia/Markdown/Code/Events.elm +++ b/src/elm/Lia/Markdown/Code/Events.elm @@ -35,8 +35,8 @@ input projectID value = |> toProject projectID -eval : Array Sync -> Int -> Scripts a -> Project -> Event -eval sync projectID scripts project = +eval : Maybe Int -> Array Sync -> Int -> Scripts a -> Project -> Event +eval delay sync projectID scripts project = let files = if project.syncMode then @@ -49,7 +49,7 @@ eval sync projectID scripts project = in files |> Array.toList - |> Service.Script.eval project.evaluation (outputs scripts) + |> Service.Script.eval delay project.evaluation (outputs scripts) -- navigate the evaluation within the Code module |> toProject projectID diff --git a/src/elm/Lia/Markdown/Code/Update.elm b/src/elm/Lia/Markdown/Code/Update.elm index d64c6cc1d..dfe43b2b1 100644 --- a/src/elm/Lia/Markdown/Code/Update.elm +++ b/src/elm/Lia/Markdown/Code/Update.elm @@ -1,6 +1,7 @@ port module Lia.Markdown.Code.Update exposing ( Msg(..) , handle + , runAll , update ) @@ -47,6 +48,25 @@ handle = Handle +runAll : Maybe Int -> Scripts a -> Model -> Return Model msg sub +runAll sectionID scripts model = + model.evaluate + |> Array.foldl + (\_ ( id, return ) -> + let + ret = + execute (Just (id * 1000)) Array.empty sectionID scripts return.value id + in + ( id + 1 + , ret + |> Return.batchEvents return.events + |> Return.batchCmd [ return.command ] + ) + ) + ( 0, Return.val model ) + |> Tuple.second + + restore : Maybe Int -> JE.Value -> Model -> Return Model msg sub restore sectionID json model = case @@ -79,7 +99,7 @@ update : Array Sync -> Maybe Int -> Scripts a -> Msg -> Model -> Return Model ms update sync sectionID scripts msg model = case msg of Eval idx -> - execute sync sectionID scripts model idx + execute Nothing sync sectionID scripts model idx --|> Return.sync (PEvent.initWithId "eval" idx JE.null) Update id_1 id_2 code_str -> @@ -479,8 +499,8 @@ update_terminal msg project = ( project, Nothing ) -eval : Array Sync -> Int -> Scripts a -> Project -> Return Project msg sub -eval sync id scripts project = +eval : Maybe Int -> Array Sync -> Int -> Scripts a -> Project -> Return Project msg sub +eval delay sync id scripts project = (if project.syncMode then { project | running = True, syncLog = Log.empty } @@ -488,7 +508,7 @@ eval sync id scripts project = { project | running = True, log = Log.empty } ) |> Return.val - |> Return.batchEvent (Event.eval sync id scripts project) + |> Return.batchEvent (Event.eval delay sync id scripts project) maybe_project : Int -> (Project -> x) -> Model -> Maybe (Return x cmd sub) @@ -672,10 +692,10 @@ flipHigh model id_1 id_2 = |> Return.val -execute : Array Sync -> Maybe Int -> Scripts a -> Model -> Int -> Return Model msg sub -execute sync sectionID scripts model id = +execute : Maybe Int -> Array Sync -> Maybe Int -> Scripts a -> Model -> Int -> Return Model msg sub +execute delay sync sectionID scripts model id = model - |> maybe_project id (eval sync id scripts) + |> maybe_project id (eval delay sync id scripts) |> Maybe.map (.value >> is_version_new sectionID id) |> maybe_update id model diff --git a/src/elm/Lia/Markdown/Code/View.elm b/src/elm/Lia/Markdown/Code/View.elm index 6747665d7..0cca19bef 100644 --- a/src/elm/Lia/Markdown/Code/View.elm +++ b/src/elm/Lia/Markdown/Code/View.elm @@ -253,7 +253,7 @@ viewCode { isExecutable, lang, theme, isRunning, errors, sync, id_1, cursors } i , A11y_Aria.label <| file.name ++ " " - ++ (if file.visible then + ++ (if True then codeMinimize lang else @@ -262,7 +262,7 @@ viewCode { isExecutable, lang, theme, isRunning, errors, sync, id_1, cursors } i ] [ btnIcon { title = - if file.visible then + if True then codeMinimize lang else @@ -278,7 +278,7 @@ viewCode { isExecutable, lang, theme, isRunning, errors, sync, id_1, cursors } i ) id_2 , icon = - if file.visible then + if True then "icon-plus" else @@ -300,18 +300,11 @@ viewCode { isExecutable, lang, theme, isRunning, errors, sync, id_1, cursors } i , Html.div [ Attr.classList [ ( "lia-accordion__content", True ) - , ( "active", file.visible ) + , ( "active", True ) ] ] - [ Html.div - [ Attr.class "lia-code__input" - , if file.visible then - Attr.class "" - - else - Attr.attribute "inert" "true" - ] - [ if file.visible && isExecutable then + [ Html.div [ Attr.class "lia-code__input" ] + [ if True && isExecutable then btnIcon { title = if file.fullscreen then @@ -360,6 +353,7 @@ toStyle visible pix = else "0px" , Attr.style "transition" "min-height 0.25s ease-out" + , Attr.style "break-inside" "avoid" ] @@ -442,16 +436,15 @@ evaluate { isExecutable, theme, attr, isRunning, id_1, id_2, file, errors, sync, total_lines = lines code + -- XXX: Changed to comply with pdf max_lines = - if file.fullscreen then - total_lines - - else if total_lines > 16 then - 16 - - else - total_lines + --if file.fullscreen then + total_lines + --else if total_lines > 16 then + -- 16 + --else + -- total_lines readOnly = if isExecutable then if isRunning then @@ -492,15 +485,15 @@ evaluate { isExecutable, theme, attr, isRunning, id_1, id_2, file, errors, sync, |> Params.get "data-theme" |> Maybe.withDefault theme |> Editor.theme - , Editor.maxLines - (if max_lines > 16 then - -1 - else - max_lines - ) - , Editor.readOnly readOnly - , Editor.highlightActiveLine (not readOnly) + --, Editor.maxLines + -- (if max_lines > 16 then + -- -1 + -- else + -- max_lines + -- ) + , Editor.readOnly True + , Editor.highlightActiveLine False , attr |> Params.get "data-tabSize" |> Maybe.andThen String.toInt @@ -528,10 +521,12 @@ evaluate { isExecutable, theme, attr, isRunning, id_1, id_2, file, errors, sync, isExecutable , Editor.useSoftTabs False , Editor.annotations errors - , Editor.enableBasicAutocompletion isExecutable - , Editor.enableLiveAutocompletion isExecutable - , Editor.enableSnippets isExecutable + + --, Editor.enableBasicAutocompletion isExecutable + --, Editor.enableLiveAutocompletion isExecutable + --, Editor.enableSnippets isExecutable , Editor.extensions [ "language_tools" ] + , Editor.useWrapMode True , Editor.onCtrlEnter (Eval id_1) ] ) diff --git a/src/elm/Lia/Markdown/Config.elm b/src/elm/Lia/Markdown/Config.elm index d18d94f2f..3a4237101 100644 --- a/src/elm/Lia/Markdown/Config.elm +++ b/src/elm/Lia/Markdown/Config.elm @@ -61,7 +61,7 @@ init lang translations settings sync screen id formula media section = sync in Config - settings.mode + Textbook (viewer main >> List.map (Html.map Script)) section settings.editor diff --git a/src/elm/Lia/Markdown/Inline/Multimedia.elm b/src/elm/Lia/Markdown/Inline/Multimedia.elm index 887af68ae..1158ae35d 100644 --- a/src/elm/Lia/Markdown/Inline/Multimedia.elm +++ b/src/elm/Lia/Markdown/Inline/Multimedia.elm @@ -1,6 +1,7 @@ module Lia.Markdown.Inline.Multimedia exposing ( audio , movie + , reverseMovie , website ) @@ -9,7 +10,7 @@ import Lia.Parser.UrlPattern.Generic exposing (root) website = - { youtube = "https://www.youtube-nocookie.com/embed/" + { youtube = "https://www.youtube.com/embed/" } @@ -56,6 +57,94 @@ movie = |> replace +{-| Reverse transformation of embed URLs back to original website URLs. + + reverseMovie "https://www.youtube.com/embed/dQw4w9WgXcQ" + == Just "https://www.youtube.com/watch?v=dQw4w9WgXcQ" + + reverseMovie "https://player.vimeo.com/video/123456" + == Just "https://vimeo.com/123456" + + reverseMovie "https://example.com/unknown" + == Nothing + +-} +reverseMovie : String -> Maybe String +reverseMovie url = + case + [ { by = + \u w -> + "https://www.youtube.com/watch?v=" + ++ w + ++ reversePreserve u + , pattern = root "(?:www\\.)?youtube\\.com/embed/([^\\?&\"'<> #]+)" + } + , { by = + \u w -> + "https://vimeo.com/" + ++ w + ++ reversePreserve u + , pattern = root "player\\.vimeo\\.com/video/(\\d+)" + } + , { by = + \u w -> + "https://www.dailymotion.com/video/" + ++ w + ++ reversePreserve u + , pattern = root "(?:www\\.)?dailymotion\\.com/embed/video/(.+)" + } + , { by = \_ w -> "https://peertube.tv/videos/watch/" ++ w + , pattern = root "peertube\\.tv/videos/embed/(.+)" + } + , { by = + \u w -> + "https://www.teachertube.com/video/" + ++ w + ++ reversePreserve u + , pattern = root "(?:www\\.)?teachertube\\.com/embed/video/(\\d+.*)" + } + ] + |> replace + |> (\f -> f url) + of + ( True, result ) -> + Just result + + ( False, _ ) -> + Nothing + + +{-| Preserve query parameters and fragment from the original URL for reverse transformation. +-} +reversePreserve : String -> String +reversePreserve url = + let + params = + url + |> String.split "?" + |> List.tail + |> Maybe.andThen List.head + |> Maybe.map (String.split "#") + |> Maybe.andThen List.head + |> Maybe.withDefault "" + + frag = + url + |> String.split "#" + |> List.tail + |> Maybe.andThen List.head + |> Maybe.map ((++) "#") + |> Maybe.withDefault "" + in + (if String.isEmpty params then + "" + + else + "&" ++ params + ) + ++ frag + + audio : String -> ( Bool, String ) audio = [ { by = diff --git a/src/elm/Lia/Markdown/Inline/View.elm b/src/elm/Lia/Markdown/Inline/View.elm index 99528a51e..d36e12959 100644 --- a/src/elm/Lia/Markdown/Inline/View.elm +++ b/src/elm/Lia/Markdown/Inline/View.elm @@ -30,7 +30,7 @@ import Lia.Markdown.HTML.Attributes exposing (Parameters, annotation, toAttribut import Lia.Markdown.HTML.Types exposing (Node) import Lia.Markdown.HTML.View as HTML import Lia.Markdown.Inline.Config as Config exposing (Config) -import Lia.Markdown.Inline.Multimedia exposing (website) +import Lia.Markdown.Inline.Multimedia exposing (reverseMovie, website) import Lia.Markdown.Inline.Stringify exposing (stringify_) import Lia.Markdown.Inline.Types exposing (Inline(..), Inlines, Reference(..), combine) import Lia.Markdown.Quiz.Block.Types exposing (State(..)) @@ -797,7 +797,7 @@ img config attr alt_ url_ title_ width = ) |> CList.addIf (width == Nothing) (load url_) |> CList.addWhen (title config title_) - |> addLazyLoading config.visible + --|> addLazyLoading config.visible ) [] @@ -855,10 +855,9 @@ reference config ref attr = |> figure config title_ width "image" Audio alt_ ( tube, url_ ) title_ -> - figure config title_ Nothing "audio" <| - Html.div [] - [ printLink config alt_ title_ url_ - , if tube then + Html.a [ Attr.href url_ ] + [ figure config title_ Nothing "audio" <| + if tube then Html.iframe (Attr.src url_ :: Attr.attribute "allowfullscreen" "" @@ -867,13 +866,14 @@ reference config ref attr = :: annotation "lia-audio" attr |> CList.addWhen (title config title_) |> CList.addWhen (alt config alt_) - |> addLazyLoading config.visible + --|> addLazyLoading config.visible ) [] - else + else audio - (toAttribute attr + (attr + |> annotation "lia-audio" |> CList.addWhen (title config title_) |> CList.addWhen (alt config alt_) ) @@ -882,37 +882,42 @@ reference config ref attr = , preload = "none" , errorHandling = True } - ] + ] Movie alt_ ( tube, url_ ) title_ -> - if tube then - figure config title_ Nothing "iframe" <| - Html.div [ Attr.class "lia-iframe-wrapper" ] - [ printLink config alt_ title_ url_ - , Html.iframe - ((url_ - |> addTranslation config - |> Attr.src - ) - :: Attr.attribute "allowfullscreen" "" - :: Attr.attribute "allow" "accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" - :: toAttribute attr - |> CList.addWhen (title config title_) - |> CList.addWhen (alt config alt_) - |> addLazyLoading config.visible - ) - (viewer config alt_) - ] + Html.a + [ url_ + |> reverseMovie + |> Maybe.withDefault url_ + |> Attr.href + , Attr.target "_blank" + ] + [ if tube then + figure config title_ Nothing "iframe" <| + Html.div [ Attr.class "lia-iframe-wrapper" ] + [ Html.iframe + ((url_ + |> addTranslation config + |> Attr.src + ) + :: Attr.attribute "allowfullscreen" "" + -- :: Attr.attribute "loading" "lazy" + :: Attr.style "pointer-events" "none" + :: Attr.attribute "allow" "accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" + :: toAttribute attr + |> CList.addWhen (title config title_) + |> CList.addWhen (alt config alt_) + ) + (viewer config alt_) + ] - else - figure config title_ Nothing "movie" <| - -- This fixes if multiple videos appear on different sites, but on the same - -- position, then only the attributes are changed, which does not affect the - -- video at all. By using Html.Keyed the system is forced to update the - -- entire video tag. - Html.div [] - [ printLink config alt_ title_ url_ - , Html.Keyed.node "div" + else + figure config title_ Nothing "movie" <| + -- This fixes if multiple videos appear on different sites, but on the same + -- position, then only the attributes are changed, which does not affect the + -- video at all. By using Html.Keyed the system is forced to update the + -- entire video tag. + Html.Keyed.node "div" [ Attr.class "lia-video-wrapper" ] [ ( url_ , Html.video @@ -925,26 +930,28 @@ reference config ref attr = [ Html.source [ Attr.src url_, onError "video" url_ ] [] ] ) ] - ] + ] Embed alt_ url title_ -> - Html.figure [ Attr.class "lia-figure", Attr.style "height" "auto", Attr.style "width" "100%" ] <| - [ Html.div [ Attr.class "lia-figure__media" ] <| - [ printLink config alt_ title_ url - , oembed config.oEmbed attr url - , Html.figcaption [ Attr.class "lia-figure__caption" ] <| - case title_ of - Just sub -> - viewer config sub - - Nothing -> - [ Html.a - [ Attr.class "lia-link" - , Attr.href url - , Attr.target "blank_" + Html.a [ Attr.href url ] + [ Html.figure [ Attr.class "lia-figure", Attr.style "height" "auto", Attr.style "width" "100%" ] <| + [ Html.div [ Attr.class "lia-figure__media" ] <| + [ printLink config alt_ title_ url + , oembed config.oEmbed attr url + , Html.figcaption [ Attr.class "lia-figure__caption" ] <| + case title_ of + Just sub -> + viewer config sub + + Nothing -> + [ Html.a + [ Attr.href url + , Attr.target "blank_" + , Attr.class "lia-link" + ] + [ Html.text url ] ] - [ Html.text url ] - ] + ] ] ] @@ -959,11 +966,11 @@ reference config ref attr = [] QR_Link url title_ -> - [ url - |> QRCode.fromString - |> Result.map (QRCode.toSvg [ A11y_Aria.label <| Translations.qrCode config.lang ++ ": " ++ url ]) - |> Result.withDefault (Html.text (Translations.qrErr config.lang)) - ] + [ [ url + |> QRCode.fromString + |> Result.map (QRCode.toSvg [ A11y_Aria.label <| Translations.qrCode config.lang ++ ": " ++ url ]) + |> Result.withDefault (Html.text (Translations.qrErr config.lang)) + ] |> Html.a (Attr.href url :: Attr.style "width" "300px" @@ -973,6 +980,8 @@ reference config ref attr = |> CList.addWhen (title config title_) ) |> figure config title_ (Just 300) "image" + ] + |> Html.a [ Attr.href url ] audio : diff --git a/src/elm/Lia/Markdown/Quiz/Update.elm b/src/elm/Lia/Markdown/Quiz/Update.elm index 0c76fe9ea..2a73e163a 100644 --- a/src/elm/Lia/Markdown/Quiz/Update.elm +++ b/src/elm/Lia/Markdown/Quiz/Update.elm @@ -97,7 +97,7 @@ update sync sectionID scripts msg vector = (case code of Just c -> [ [ toString e.state ] - |> Service.Script.eval c (outputs scripts) + |> Service.Script.eval Nothing c (outputs scripts) |> Event.pushWithId "eval" id ] diff --git a/src/elm/Lia/Markdown/Survey/Update.elm b/src/elm/Lia/Markdown/Survey/Update.elm index c173e25e2..21caa569b 100644 --- a/src/elm/Lia/Markdown/Survey/Update.elm +++ b/src/elm/Lia/Markdown/Survey/Update.elm @@ -122,7 +122,7 @@ update sync sectionID scripts msg vector = of Just code -> [ toString element.state ] - |> Service.Script.eval code (outputs scripts) + |> Service.Script.eval Nothing code (outputs scripts) |> Event.pushWithId "eval" id Nothing -> diff --git a/src/elm/Lia/Markdown/Task/Update.elm b/src/elm/Lia/Markdown/Task/Update.elm index a8a4f2f35..4ce648a69 100644 --- a/src/elm/Lia/Markdown/Task/Update.elm +++ b/src/elm/Lia/Markdown/Task/Update.elm @@ -69,7 +69,7 @@ update sectionID scripts msg vector = Just code -> [ toString element ] - |> Service.Script.eval code (outputs scripts) + |> Service.Script.eval Nothing code (outputs scripts) |> Event.pushWithId "eval" x ) |> store sectionID diff --git a/src/elm/Lia/Markdown/Update.elm b/src/elm/Lia/Markdown/Update.elm index 130ccb082..6efac48dc 100644 --- a/src/elm/Lia/Markdown/Update.elm +++ b/src/elm/Lia/Markdown/Update.elm @@ -332,8 +332,21 @@ initEffect : -> Bool -> Section -> Return Section Msg Msg -initEffect sync globals run_all_javascript sound = - update sync globals (UpdateEffect sound (Effect.init run_all_javascript)) +initEffect sync globals run_all_javascript sound section = + let + return = + update sync globals (UpdateEffect sound (Effect.init run_all_javascript)) section + + return2 = + return.value.code_model + |> Code.runAll (Just section.id) section.effect_model.javascript + |> Return.mapVal (\v -> { section | code_model = v }) + |> Return.mapEvents "code" section.id + |> updateScript + in + return2 + |> Return.batchEvents return.events + |> Return.batchCmd [ return.command ] subHandle : Scripts SubSection -> JE.Value -> SubSection -> Return SubSection Msg Msg diff --git a/src/elm/Lia/Model.elm b/src/elm/Lia/Model.elm index 419aca7f6..00942691b 100644 --- a/src/elm/Lia/Model.elm +++ b/src/elm/Lia/Model.elm @@ -133,7 +133,7 @@ init : init { seed, hasShareApi, openTOC, isFullscreen, settings, backends, url, readme, origin, anchor } = let default = - Settings.init hasShareApi isFullscreen Settings.Presentation + Settings.init hasShareApi isFullscreen Settings.Textbook in { url = url , repositoryUrl = repo readme diff --git a/src/elm/Lia/Script.elm b/src/elm/Lia/Script.elm index 803e3a99b..808d5bd81 100644 --- a/src/elm/Lia/Script.elm +++ b/src/elm/Lia/Script.elm @@ -15,6 +15,7 @@ module Lia.Script exposing , subscriptions , update , view + , viewFullPage ) {-| This module defines the basic interface to LiaScript. In order to implement @@ -451,6 +452,13 @@ init = Lia.Model.init +{-| Alias for global LiaScript view defined in `Lia.View.viewFullPage` +-} +viewFullPage : Screen -> Model -> List (Html Msg) +viewFullPage = + Lia.View.viewFullPage + + {-| Alias for global LiaScript view defined in `Lia.View.view` -} view : Screen -> Bool -> Model -> Html Msg diff --git a/src/elm/Lia/Settings/Json.elm b/src/elm/Lia/Settings/Json.elm index 409356aff..c11acdfe3 100644 --- a/src/elm/Lia/Settings/Json.elm +++ b/src/elm/Lia/Settings/Json.elm @@ -38,17 +38,19 @@ maybeFloat = fromMode : Mode -> JE.Value -fromMode mode = - JE.string <| - case mode of - Textbook -> - "Textbook" +fromMode _ = + {- JE.string <| + case mode of + Textbook -> + "Textbook" - Presentation -> - "Presentation" + Presentation -> + "Presentation" - Slides -> - "Slides" + Slides -> + "Slides" + -} + JE.string "Textbook" settings : @@ -117,16 +119,18 @@ toModel model = toMode : String -> JD.Decoder Mode -toMode str = - case str of - "Textbook" -> - JD.succeed Textbook +toMode _ = + {- case str of + "Textbook" -> + JD.succeed Textbook - "Presentation" -> - JD.succeed Presentation + "Presentation" -> + JD.succeed Presentation - "Slides" -> - JD.succeed Slides + "Slides" -> + JD.succeed Slides - _ -> - JD.fail "unknown presentation mode" + _ -> + JD.fail "unknown presentation mode" + -} + JD.succeed Textbook diff --git a/src/elm/Lia/Settings/Types.elm b/src/elm/Lia/Settings/Types.elm index 6105eac7f..db9be670c 100644 --- a/src/elm/Lia/Settings/Types.elm +++ b/src/elm/Lia/Settings/Types.elm @@ -61,6 +61,7 @@ type Mode = Slides -- Underline Comments and Effects | Presentation -- Only effects | Textbook -- Render Comments and Effects at ones + | Full type Audio diff --git a/src/elm/Lia/Settings/View.elm b/src/elm/Lia/Settings/View.elm index db46a0c0f..31b668ec5 100644 --- a/src/elm/Lia/Settings/View.elm +++ b/src/elm/Lia/Settings/View.elm @@ -83,6 +83,9 @@ design model = Slides -> "lia-mode--slides" + + Full -> + "lia-mode--textbook" ] @@ -268,6 +271,15 @@ viewModes grouping lang tabbable settings = "lia-mode-slides" "icon-slides" "" + , viewMode + grouping + lang + tabbable + Full + settings.mode + "lia-mode-full" + "icon-full" + "" ] @@ -302,6 +314,9 @@ modeToString show = Textbook -> Trans.modeTextbook + Full -> + always "TODO" + viewSizing : (List (Attribute Msg) -> List (Attribute Msg)) -> Lang -> Bool -> Int -> Html Msg viewSizing grouping lang tabbable size = @@ -866,6 +881,9 @@ menuMode lang tabbable settings = Textbook -> ( "icon-book", Trans.modeTextbook lang ) + + Full -> + ( "icon-book", "TODO" ) in [ actionBtn { grouping = grouping diff --git a/src/elm/Lia/Update.elm b/src/elm/Lia/Update.elm index 26b23da79..6bf052cea 100644 --- a/src/elm/Lia/Update.elm +++ b/src/elm/Lia/Update.elm @@ -29,6 +29,7 @@ import Return exposing (Return) import Service.Console import Service.Database import Service.Event as Event exposing (Event) +import Service.Script import Service.Slide import Session exposing (Session) @@ -146,6 +147,16 @@ update session msg model = } } ) + |> Return.batchEvent + (if idx == Array.length model.sections - 1 then + Service.Script.exec + 5000 + False + "console.log(\"__RENDER_DONE__\"); window.dispatchEvent( new CustomEvent(\"puppeteer:ready\", { detail: { status: \"done\", ts: Date.now() }}));" + + else + Event.none + ) else { model @@ -392,6 +403,25 @@ update session msg model = return |> Return.mapValCmd (set_active_section { model | to_do = [] }) UpdateMarkdown |> Return.batchEvents (initializeSlide model :: model.to_do) + |> Return.batchEvent + (if model.section_active < Array.length model.sections then + Service.Script.exec + (if model.section_active == 0 then + -- Add timeout so that first slide, so that scripts can be loaded + 5000 + + else + 1000 + ) + False + <| + "window.LIA.goto(" + ++ String.fromInt (model.section_active + 1) + ++ ")" + + else + Event.none + ) ( JumpToFragment id, Just sec ) -> if (model.settings.mode == Textbook) || sec.effect_model.visible == id then diff --git a/src/elm/Lia/View.elm b/src/elm/Lia/View.elm index 519878ee1..0bc8a0bea 100644 --- a/src/elm/Lia/View.elm +++ b/src/elm/Lia/View.elm @@ -1,4 +1,4 @@ -module Lia.View exposing (view) +module Lia.View exposing (view, viewFullPage) import Accessibility.Aria as A11y_Aria import Accessibility.Key as A11y_Key @@ -67,6 +67,28 @@ view screen hasIndex model = ) +viewFullPage : Screen -> Model -> List (Html Msg) +viewFullPage screen model = + model.sections + |> Array.toList + |> List.indexedMap (viewSection screen model) + + +viewSection screen model section_active sec = + Config.init + model.translation + { old = model.langCodeOriginal, new = model.langCode, name = model.langName } + model.settings + model.sync + screen + section_active + (Just model.definition.formulas) + model.media + sec + |> Markdown.view False True + |> Html.map UpdateMarkdown + + {-| **@private:** Display the side section that contains the document search, table of contents and the home button. -} @@ -254,11 +276,24 @@ viewPanes screen model = viewConfig (model.sections |> Array.toIndexedList - |> List.map (showSection model screen) + |> List.map + (\( i, sec ) -> + showSection + { model + | section_active = + if model.settings.mode == Full then + i + + else + model.section_active + } + screen + ( i, sec ) + ) |> Html.div [ Attr.style "width" "100%" , Attr.style "overflow-y" "auto" - , Attr.style "display" "flex" + , Attr.style "display" "block" , Attr.style "justify-content" "center" , Attr.class "lia-slide__container" , Attr.style "margin-block-start" "0px" @@ -295,7 +330,8 @@ initConfig screen model = showSection : Model -> Screen -> ( Int, Section ) -> Html Msg showSection model screen ( id, section ) = initConfig screen model section - |> Markdown.view (model.section_active /= id) (Maybe.withDefault model.persistent section.persistent) + |> Markdown.view (model.section_active /= id) + (Maybe.withDefault model.persistent section.persistent) |> Html.map UpdateMarkdown diff --git a/src/elm/Main.elm b/src/elm/Main.elm index a78bd2cdb..e4aee9f32 100644 --- a/src/elm/Main.elm +++ b/src/elm/Main.elm @@ -70,6 +70,7 @@ type alias Flags = { support : List String , enabled : Bool } + , fullPage : Maybe Bool , hideURL : Bool } @@ -93,7 +94,9 @@ init : Flags -> Url.Url -> Nav.Key -> ( Model, Cmd Msg ) init flags url key = let model url_ state_ lia_ = - Model 0 + Model + (Maybe.withDefault False flags.fullPage) + 0 flags.hasIndex Nothing Index.init diff --git a/src/elm/Model.elm b/src/elm/Model.elm index 8764516da..cf86dd744 100644 --- a/src/elm/Model.elm +++ b/src/elm/Model.elm @@ -50,7 +50,8 @@ import Session exposing (Session) -} type alias Model = - { size : Float + { fullPage : Bool + , size : Float , hasIndex : Bool , code : Maybe String , index : Index.Model diff --git a/src/elm/Service/Script.elm b/src/elm/Service/Script.elm index a07a0f3c2..b520bbf6a 100644 --- a/src/elm/Service/Script.elm +++ b/src/elm/Service/Script.elm @@ -12,6 +12,7 @@ module Service.Script exposing , stop ) +import Html exposing (del) import Json.Decode as JD import Json.Encode as JE import Lia.Utils exposing (toEscapeString) @@ -166,8 +167,8 @@ input string = which is used to replace numbered input macros => `@input(id)` -} -eval : String -> List ( String, String ) -> List String -> Event -eval code scripts inputs = +eval : Maybe Int -> String -> List ( String, String ) -> List String -> Event +eval delay code scripts inputs = let -- the first input parameter is also used as the default -- one to replace the `@input` without parenthesis @@ -182,11 +183,20 @@ eval code scripts inputs = code_ = List.foldl replace_inputKey code scripts in - inputs - |> List.indexedMap Tuple.pair - |> List.foldl replace_inputID code_ - |> replace_input default - |> JE.string + [ ( "code" + , inputs + |> List.indexedMap Tuple.pair + |> List.foldl replace_inputID code_ + |> replace_input default + |> JE.string + ) + , ( "delay" + , delay + |> Maybe.withDefault 0 + |> JE.int + ) + ] + |> JE.object |> event "eval" diff --git a/src/elm/View.elm b/src/elm/View.elm index adf993f69..8095d6558 100644 --- a/src/elm/View.elm +++ b/src/elm/View.elm @@ -22,12 +22,21 @@ view model = , body = case model.state of Running -> - [ model.lia - |> Lia.Script.view - model.session.screen - model.hasIndex - |> Html.map LiaScript - ] + if model.fullPage then + [ model.lia + |> Lia.Script.viewFullPage + model.session.screen + |> Html.div [] + |> Html.map LiaScript + ] + + else + [ model.lia + |> Lia.Script.view + model.session.screen + model.hasIndex + |> Html.map LiaScript + ] Idle -> [ Html.map UpdateIndex <| Index.view model.session model.lia.settings model.index diff --git a/src/entry/pdf/index.html b/src/entry/pdf/index.html new file mode 100644 index 000000000..a1887f83a --- /dev/null +++ b/src/entry/pdf/index.html @@ -0,0 +1,79 @@ + + + +
+