svg.escobar.life

Unnamed repository; edit this file 'description' to name the repository.

commit f6e575e795989ab7013871c6a6f6d4db05a55363
parent f62c6cb5683b638662387fbe711f3487f140d381
Author: Gark Garcia <37553739+GarkGarcia@users.noreply.github.com>
Date:   Sun, 21 Jul 2019 10:41:04 -0300

Finished implementing syntax-highlighting.

Diffstat:
Asrc/Editor.elm | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/Main.elm | 6+++---
Msrc/Types.elm | 9+++------
Msrc/View.elm | 37++-----------------------------------
Mstyles.css | 86++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
5 files changed, 119 insertions(+), 73 deletions(-)
diff --git a/src/Editor.elm b/src/Editor.elm
@@ -0,0 +1,53 @@
+module Editor exposing (editor)
+
+import Types exposing (..)
+import Html exposing (Html, Attribute, div, pre, code, text, textarea)
+import Html.Attributes exposing (id, value, style, spellcheck)
+import Html.Events exposing (onInput, on)
+import Json.Decode
+import SyntaxHighlight exposing (xml, toBlockHtml)
+
+editor : Model -> Html Msg
+editor model =
+    div [ id "editor" ]
+        [ div [ translate model.editorScroll ]
+            [ codeDisplay model ]
+        , textarea model
+        ]
+
+textarea : Model -> Html Msg
+textarea model =
+    Html.textarea
+        [ value model.image
+        , onInput Update
+        , onScroll Scroll
+        , spellcheck False
+        ] []
+
+codeDisplay : Model -> Html Msg
+codeDisplay model =
+    xml (if model.image == "" then placeholder else model.image)
+        |> Result.map (toBlockHtml Nothing)
+        |> Result.withDefault
+            (pre [] [ code [] [ text model.image ] ])
+
+onScroll : ((Int, Int) -> msg) -> Attribute msg
+onScroll f = 
+    on "scroll"
+        (Json.Decode.map2 (\x -> \y -> (x, y))
+            (Json.Decode.at [ "target", "scrollLeft" ] Json.Decode.int)
+            (Json.Decode.at [ "target", "scrollTop" ]  Json.Decode.int)
+            |> Json.Decode.map f
+        )
+
+transform : String -> Attribute msg
+transform str =
+    style "transform" str
+
+translate : (Int, Int) -> Attribute Msg
+translate (x, y) =
+    transform ("translate(" ++ (String.fromInt -x) ++ "px, " ++ (String.fromInt -y) ++ "px)")
+
+placeholder : String
+placeholder =
+    "<svg ...> ... </svg>"+
\ No newline at end of file
diff --git a/src/Main.elm b/src/Main.elm
@@ -44,8 +44,8 @@ update msg model =
         Upload upl ->
             upload model upl
 
-        Scroll offset ->
-            ({model | offset = offset}, Cmd.none)
+        Scroll scroll ->
+            ({model | editorScroll = scroll}, Cmd.none)
 
 load : Result Http.Error String -> Cmd Msg
 load result =
@@ -77,7 +77,7 @@ init =
     , darkMode = False
     , uriEncoder = Maybe.withDefault Regex.never <| Regex.fromString "!|#|\\$|%|&|'|\\(|\\)|\\*|\\+|,|\\/|:|;|=|\\?|@|\\[|\\]"
     , fileName = "example.svg"
-    , offset = { top = 0, left = 0 }
+    , editorScroll = (0, 0)
     }
 
 loadExample : Cmd Msg
diff --git a/src/Types.elm b/src/Types.elm
@@ -10,14 +10,11 @@ type alias Model =
     , darkMode : Bool
     , uriEncoder : Regex
     , fileName : String
-    , offset : Offset
+    , editorScroll : (Int, Int)
     }
 
 type Upload = Requested | Selected File
 
-type alias Offset =
-    { top : Int, left : Int }
-
 type Msg
     = Update String
     | Load (Result Http.Error String)
@@ -25,4 +22,4 @@ type Msg
     | DarkModeToggle
     | Download
     | Upload Upload
-    | Scroll Offset-
\ No newline at end of file
+    | Scroll (Int, Int)+
\ No newline at end of file
diff --git a/src/View.elm b/src/View.elm
@@ -1,6 +1,7 @@
 module View exposing (view)
 
 import Types exposing (..)
+import Editor exposing (editor)
 import Html exposing (Html, div, img, button, a, textarea, pre, code, text)
 import Html.Events exposing (onClick, onInput, on)
 import Html.Attributes exposing (id, class, src, href, value, style, spellcheck, placeholder, target, rel)
@@ -9,7 +10,6 @@ import Svg exposing (svg, path)
 import Svg.Attributes exposing (d, viewBox, fill)
 import Json.Decode
 import Regex exposing (Regex, Match, replace)
-import SyntaxHighlight exposing (useTheme, xml, oneDark, toBlockHtml)
 
 
 view : Model -> Document Msg
@@ -19,7 +19,7 @@ view model =
         [ div [ id "container", class (if model.isValid then "" else "error") ]
             [ div [ id "title" ] [ logo, githubLink ]
             , display model
-            , texteditor model
+            , editor model
             ]
         ]
     }
@@ -40,39 +40,6 @@ display model =
             [ if model.darkMode then sunIcon else moonIcon ]
         ]
 
-texteditor : Model -> Html Msg
-texteditor model =
-    div [ id "editor", onInput Update ]
-        [ useTheme oneDark
-        , xml (model.image ++ (String.fromInt model.offset.left))
-            |> Result.map (toBlockHtml Nothing)
-            |> Result.withDefault
-                (pre (translate model.offset)
-                    [ code [] [ text model.image ]]
-                )
-        , viewTextarea model
-        ]
-
-translate : Offset -> List (Html.Attribute Msg)
-translate { top, left } =
-    [ style "left" ((String.fromInt -top) ++ "px")
-    , style "top"  ((String.fromInt -left) ++ "px")
-    ]
-
-viewTextarea : Model -> Html Msg
-viewTextarea model =
-    textarea
-        [ value model.image
-        , onInput Update
-        , spellcheck False
-        , on "scroll"
-            (Json.Decode.map2 Offset
-                (Json.Decode.at [ "target", "scrollTop" ] Json.Decode.int)
-                (Json.Decode.at [ "target", "scrollLeft" ] Json.Decode.int)
-                |> Json.Decode.map Scroll
-            )
-        ] []
-
 uri : Model -> String
 uri model =
     "data:image/svg+xml;utf8," ++ (replace model.uriEncoder percentEscape model.image)
diff --git a/styles.css b/styles.css
@@ -14,10 +14,21 @@
     scrollbar-width: none; /* Firefox */
     -ms-overflow-style: none; /* IE + Edge */
 
+    transition: background-color .5s ease, color .5s ease;
+
     --background: #450e79;
-    --mid: #7b2c9b;
+    --selection: #3b3ee040;
     --light: #e0ebe0;
     --dark: #1c0531;
+
+    --hl1: #d19a66;
+    --hl2: #f3a47f;
+    --hl3: #f852a5;
+    --hl4: var(--hl3);
+    --hl5: #5da7fc;
+    --hl6: #d19a66;
+
+    --comm: #95ee61;
 }
 
 @media (pointer: fine) {
@@ -44,19 +55,6 @@
     width: 0px; /*Chrome + Safari + Opera*/
 }
 
-textarea::selection {
-    background: var(--mid);
-}
-
-textarea::-moz-selection {
-    background: var(--mid);
-}
-
-textarea::placeholder {
-    color: var(--light);
-    opacity: 1;
-}
-
 svg {
     fill: none;
     fill-rule: evenodd;
@@ -158,9 +156,16 @@ body > div#container, body > div#container > * {
 
 body > div#container.error {
     --background: #96162c;
-    --mid: #b33748;
-
+    --selection: #e03b5140;
     --light: #eec6df;
+
+    --hl1: #d17666;
+    --hl2: #f38d7f;
+    --hl3: #fd5b5b;
+    --hl5: #fc5db4;
+    --hl6: #d19a66;
+
+    --comm: #ee6180;
 }
 
 body > div#container img {
@@ -187,7 +192,6 @@ body > div#container > div#display {
     border-radius: var(--tiny);
 
     box-shadow: 0 0 calc(.25 * var(--small)) .5vmax #00000015;
-    transition: background .5s ease;
 }
 
 @media (pointer: fine), (pointer: coarse) and (orientation: landscape) {
@@ -249,15 +253,17 @@ body > div#container > div#editor {
 }
 
 body > div#container > div#editor * {
-    background: transparent !important;
-
-    font-family: 'B612 Mono', monospace !important;
-    font-style: italic !important;
+    font-family: 'B612 Mono', monospace;
 }
 
 body > div#container > div#editor > * {
     position: absolute;
+    will-change: transform;
+}
+
+body > div#container > div#editor > *, body > div#container > div#editor > * > * {
     margin: 0 !important;
+    font-size: 1rem !important;
 }
 
 body > div#container > div#editor > textarea {
@@ -269,16 +275,38 @@ body > div#container > div#editor > textarea {
     width: 100%;
     height: 100%;
 
-    margin: 0;
-
-    background: transparent;
     border: none;
-    
+    background: transparent;
 
-    font-family: 'B612 Mono', monospace;
     color: transparent;
-    font-style: italic;
+    caret-color: var(--light);
 
     scrollbar-width: none; /*For Firefox*/
     -ms-overflow-style: none; /*For IE and Edge*/
-}-
\ No newline at end of file
+}
+
+body > div#container > div#editor > textarea::selection {
+    background: var(--selection);
+}
+
+body > div#container > div#editor > textarea::-moz-selection {
+    background: var(--selection);
+}
+
+.elmsh {color: var(--light);}
+.elmsh-hl {background: rgba(229, 231,235, 0.1);}
+.elmsh-add {background: rgba(40, 124,82, 0.4);}
+.elmsh-del {background: rgba(136, 64,67, 0.4);}
+
+.elmsh-comm {
+    font-style: italic;
+    color: var(--comm);
+}
+
+.elmsh1 { color: var(--hl1); }
+.elmsh2 { color: var(--hl2); }
+.elmsh3 { color: var(--hl3); }
+.elmsh4 { color: var(--hl4); }
+.elmsh5 { color: var(--hl5); }
+.elmsh6 { color: var(--hl6); }
+.elmsh7 { color: var(--light); }+
\ No newline at end of file