reflex-dom-ace: Basic support for using the Ace editor with Reflex.

[ bsd3, library, web ] [ Propose Tags ]

Provides basic support for using the Ace editor with Reflex-DOM web apps.

Ace editor: https://ace.c9.io/.


[Skip to Readme]

Modules

[Index] [Quick Jump]

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

  • No Candidates
Versions [RSS] 0.3.0.0, 0.3.0.1, 0.3.0.2, 0.3.0.3
Dependencies base (>=4.7 && <4.15), containers (>=0.6 && <0.7), data-default (>=0.5 && <0.8), ghcjs-dom (>=0.9.1.0 && <0.10), jsaddle (>=0.9.0.0 && <0.10), lens (>=4.7 && <5), mtl (>=2.1 && <2.3), reflex-dom-core (>=0.6.1.0 && <0.7), text (>=1.2 && <1.3) [details]
License BSD-3-Clause
Author Doug Beardsley, Tim Johns
Maintainer slimtim10@gmail.com
Category Web
Source repo head: git clone https://github.com/SlimTim10/reflex-dom-ace
Uploaded by SlimTim10 at 2021-05-27T17:44:40Z
Distributions
Downloads 506 total (16 in the last 30 days)
Rating (no votes yet) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs available [build log]
Last success reported on 2021-05-27 [all 1 reports]

Readme for reflex-dom-ace-0.3.0.3

[back to package description]

reflex-dom-ace

Overview

Basic support for using the Ace editor with Reflex.

This package provides a Reflex wrapper around the Ace editor. It is somewhat incomplete and was derived from code written for hsnippet.

This is also intended to serve as an example of how to structure FFI packages that rely on external JS packages.

Example Usage with Obelisk

Add Dependency to Obelisk

Hackage

As per the Obelisk FAQ, modify default.nix to look like:

# ...
project ./. ({ pkgs, ... }: {
# ...
  overrides = self: super:
  {
    reflex-dom-ace = self.callHackageDirect {
      pkg = "reflex-dom-ace";
      ver = "0.3.0.1";
      sha256 = "0kbd3kqmsx4115a39a984m62kgc9s96586c5yx80nijman8j0zlw";
    } {};
  };
# ...

Change the ver to match the desired version and leave the sha256. Then let ob run fail with the expected sha256 and update the value accordingly.

NOTE: It may be necessary to run nix-collect-garbage to clear the cache before ob run.

GitHub

As per the Obelisk FAQ, modify default.nix to look like:

# ...
project ./. ({ pkgs, ... }: {
# ...
  overrides = self: super: let
    aceSrc = pkgs.fetchFromGitHub {
      owner = "SlimTim10";
      repo = "reflex-dom-ace";
      rev = "5d086c871892b9ebf7c66ad2d4d4f84023bea9b2";
      sha256 = "0vizlf691s1rbkilhf23c79vkb6pns2x4b6b94szn9wd8mjizxyc";
    };
  in
  {
    reflex-dom-ace = self.callCabal2nix "reflex-dom-ace" aceSrc {};
  };
# ...

Change the rev to match the latest commit hash and leave the sha256. Then let ob run fail with the expected sha256 and update the value accordingly.

NOTE: It may be necessary to run nix-collect-garbage to clear the cache before ob run.

Get Ace Editor

Get the src-noconflict package from ace-builds (tested with package version 06.7.20). Move the src-noconflict contents to the project directory static/ace/.

E.g.,

$ cd ~
$ git clone https://github.com/ajaxorg/ace-builds
$ mv ~/ace-builds/src-noconflict ~/my-obelisk-project/static/ace

Editor.hs

module Editor
  ( widget
  ) where

import Data.Text (Text)
import Control.Monad (void)
import Data.Functor ((<&>))

import qualified Language.Javascript.JSaddle.Types as JS
import qualified Reflex.Dom.Ace as Ace
import qualified Reflex.Dom.Core as R
import Reflex.Dom.Core ((=:))

widget
  :: forall t m.
     ( R.DomBuilder t m
     , R.TriggerEvent t m
     , JS.MonadJSM (R.Performable m)
     , JS.MonadJSM m
     , R.PerformEvent t m
     , R.PostBuild t m
     , R.MonadHold t m
     )
  => m (R.Dynamic t Text)
widget = do
  let containerId = "editor"
  void $ R.elAttr "div" (
    "id" =: containerId
    ) R.blank
  (script, _) <- R.elAttr' "script" (
    "src" =: "/static/ace/ace.js"
    <> "type" =: "text/javascript"
    <> "charset" =: "utf-8"
    ) R.blank
  let scriptLoaded = () <$ R.domEvent R.Load script
  let loading = R.el "p" $ R.text "Loading editor..." <&> const (R.constDyn "")
  dt :: R.Dynamic t (R.Dynamic t Text) <- R.widgetHold loading
    $ R.ffor scriptLoaded
    $ const $ do
      ace <- do
        let
          cfg = R.def
            { Ace._aceConfigMode = Just "latex"
            }
        Ace.aceWidget cfg (Ace.AceDynConfig (Just Ace.AceTheme_Clouds)) R.never containerId "" R.never
      return $ Ace.aceValue ace
  R.holdDyn "" . R.switchDyn $ R.updated <$> dt

Frontend.hs

module Frontend where

import Obelisk.Frontend
import Obelisk.Configs
import Obelisk.Route
import Obelisk.Generated.Static

import Reflex.Dom.Core

import Common.Api
import Common.Route

import qualified Editor

frontend :: Frontend (R FrontendRoute)
frontend = Frontend
  { _frontend_head = do
      el "title" $ text "Obelisk Minimal Example"
      elAttr "link" ("href" =: static @"main.css" <> "type" =: "text/css" <> "rel" =: "stylesheet") blank
  , _frontend_body = do
      prerender_ blank $ do
        editorContents :: Dynamic t Text <- Editor.widget
        -- Do something with editorContents
        return ()
  }

Important Notes

This currently does not work if your app is using reflex-dom's mainWidgetWithHead or mainWidgetWithCss.