- Commit
- f62c6cb5683b638662387fbe711f3487f140d381
- Parent
- 22809cfba84311ef77dee35c0e0653306a329d6a
- Author
- Gark Garcia <37553739+GarkGarcia@users.noreply.github.com>
- Date
Started working on a syntax-highlighted editor.
A simple SVG markup editor for the web
Started working on a syntax-highlighted editor.
5 files changed, 79 insertions, 24 deletions
Status | File Name | N° Changes | Insertions | Deletions |
Modified | elm.json | 4 | 3 | 1 |
Modified | src/Main.elm | 4 | 4 | 0 |
Modified | src/Types.elm | 16 | 13 | 3 |
Modified | src/View.elm | 35 | 30 | 5 |
Modified | styles.css | 44 | 29 | 15 |
diff --git a/elm.json b/elm.json @@ -13,10 +13,12 @@ "elm/http": "2.0.0", "elm/json": "1.1.3", "elm/regex": "1.0.0", - "elm/svg": "1.0.1" + "elm/svg": "1.0.1", + "pablohirafuji/elm-syntax-highlight": "3.1.0" }, "indirect": { "elm/bytes": "1.0.8", + "elm/parser": "1.1.0", "elm/time": "1.0.0", "elm/url": "1.0.0", "elm/virtual-dom": "1.0.2"
diff --git a/src/Main.elm b/src/Main.elm @@ -44,6 +44,9 @@ update msg model = Upload upl -> upload model upl + Scroll offset -> + ({model | offset = offset}, Cmd.none) + load : Result Http.Error String -> Cmd Msg load result = case result of @@ -74,6 +77,7 @@ init = , darkMode = False , uriEncoder = Maybe.withDefault Regex.never <| Regex.fromString "!|#|\\$|%|&|'|\\(|\\)|\\*|\\+|,|\\/|:|;|=|\\?|@|\\[|\\]" , fileName = "example.svg" + , offset = { top = 0, left = 0 } } loadExample : Cmd Msg
diff --git a/src/Types.elm b/src/Types.elm @@ -5,14 +5,24 @@ import Regex exposing (Regex) import Http type alias Model = - { image : String, isValid : Bool, darkMode : Bool, uriEncoder : Regex, fileName : String } + { image : String + , isValid : Bool + , darkMode : Bool + , uriEncoder : Regex + , fileName : String + , offset : Offset + } type Upload = Requested | Selected File +type alias Offset = + { top : Int, left : Int } + type Msg = Update String | Load (Result Http.Error String) | Validation Bool | DarkModeToggle | Download - | Upload Upload- \ No newline at end of file + | Upload Upload + | Scroll Offset+ \ No newline at end of file
diff --git a/src/View.elm b/src/View.elm @@ -1,14 +1,15 @@ module View exposing (view) import Types exposing (..) -import Html exposing (Html, div, img, button, a, textarea) +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, spellcheck, placeholder, target, rel) +import Html.Attributes exposing (id, class, src, href, value, style, spellcheck, placeholder, target, rel) import Browser exposing (Document) 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 @@ -41,11 +42,35 @@ display model = texteditor : Model -> Html Msg texteditor model = - textarea + 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 - , placeholder "<svg ...> ... </svg>" + , onInput Update , spellcheck False - , onInput (\input -> Update input) + , 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
diff --git a/styles.css b/styles.css @@ -4,7 +4,6 @@ align-self: center; align-content: center; align-items: center; - text-align: center; cursor: default; -webkit-user-select: none; /* Safari */ @@ -26,6 +25,8 @@ --large: 10vmax; --small: 2.5vmax; --tiny: 1vmax; + + font-size: .175in; } } @@ -34,6 +35,8 @@ --large: 15vmax; --small: 3vmax; --tiny: 2vmax; + + font-size: .25in; } } @@ -235,8 +238,31 @@ body > div#container.error > div#display > svg#error { display: block; } -body > div#container > textarea { +body > div#container > div#editor { grid-area: text; + position: relative; + + width: 100%; + height: 100%; + + overflow: hidden; +} + +body > div#container > div#editor * { + background: transparent !important; + + font-family: 'B612 Mono', monospace !important; + font-style: italic !important; +} + +body > div#container > div#editor > * { + position: absolute; + margin: 0 !important; +} + +body > div#container > div#editor > textarea { + z-index: 1; + resize: none; white-space: pre; @@ -250,21 +276,9 @@ body > div#container > textarea { font-family: 'B612 Mono', monospace; - color: var(--light); + color: transparent; font-style: italic; scrollbar-width: none; /*For Firefox*/ -ms-overflow-style: none; /*For IE and Edge*/ -} - -@media (hover: hover) { - body > div#container > textarea { - font-size: .175in; - } -} - -@media (hover: none) { - body > div#container > textarea { - font-size: .25in; - } } \ No newline at end of file