aboutsummaryrefslogtreecommitdiff
path: root/editor/editor.ml
diff options
context:
space:
mode:
Diffstat (limited to 'editor/editor.ml')
-rwxr-xr-xeditor/editor.ml263
1 files changed, 130 insertions, 133 deletions
diff --git a/editor/editor.ml b/editor/editor.ml
index aeb96c1..be15718 100755
--- a/editor/editor.ml
+++ b/editor/editor.ml
@@ -1,132 +1,11 @@
+open Js_of_ocaml
open Brr
open Note
-module Prop
- : sig
- type ('a, 'b) prop
-
- val prop
- : string -> ('a, 'b) prop
-
- val get
- : 'a -> ('a, 'b) prop -> 'b option
-
- val set
- : 'a -> ('a, 'b) prop -> 'b -> unit
- end
-
-= struct
-
- type ('a, 'b) prop = Jv.prop'
-
- let prop
- : string -> ('a, 'b) prop
- = Jstr.of_string
-
- let get
- : 'a -> ('a, 'b) prop -> 'b option
- = fun obj prop ->
- Jv.get' (Jv.Id.to_jv obj) prop
- |> Jv.to_option Jv.Id.of_jv
-
- let set
- : 'a -> ('a, 'b) prop -> 'b -> unit
- = fun obj prop value ->
- Jv.set'
- (Jv.Id.to_jv obj)
- prop
- (Jv.Id.to_jv value)
-
-end
-
-module Quill = struct
-
- type t = Jv.t
-
- type options
-
- let bounds
- : (options, El.t) Prop.prop
- = Prop.prop "bounds"
-
- let debug
- : (options, Jstr.t) Prop.prop
- = Prop.prop "debug"
-
- let placeholder
- : (options, Jstr.t) Prop.prop
- = Prop.prop "placeholder"
-
- let readonly
- : (options, Jstr.t) Prop.prop
- = Prop.prop "readonly"
-
- let theme
- : (options, Jstr.t) Prop.prop
- = Prop.prop "theme"
-
- let scrollingContainer
- : (options, El.t) Prop.prop
- = Prop.prop "scrollingContainer"
-
- let options
- : unit -> options
- = Jv.Id.of_jv @@ Jv.obj' [||]
-
- (* Constructor.
-
- [quill element] will create the editor inside the given element
-
- *)
- let quill
- : ?options:options -> El.t -> (t, Jv.Error.t) Result.t
- = fun ?options element ->
- let quill = Jv.get Jv.global "Quill" in
-
- let options = Jv.of_option ~none:Jv.undefined Jv.Id.to_jv options in
-
- match Jv.new' quill Jv.Id.[| to_jv element; options |] with
- | exception Jv.Error e -> Error e
- | v -> Ok v
-
-
- type delta = Jv.t
-
- (* Operations is an array *)
- type operations = Jv.t
-
- let ops
- : (delta, operations) Prop.prop
- = Prop.prop "ops"
-
-
- (** Return the editor content *)
- let get_contents
- : t -> delta
- = fun t ->
- Jv.call t "getContents" [||]
-
- let set_contents
- : t -> delta -> unit
- = fun t contents ->
- ignore @@ Jv.call t "setContents" [|contents|]
-
- (** [extract_content index length] return the content starting from index, with length elements *)
- let extract_contents
- : t -> int -> int -> delta
- = fun t index length ->
- Jv.call t "getContents" [|Jv.of_int index; Jv.of_int length|]
-
- let on_text_change
- : t -> (string -> string -> string -> unit) -> unit
- = fun t callback ->
- ignore @@ Jv.call t "on" [|Jv.Id.to_jv @@ Jstr.v "text-change" ; Jv.repr callback|]
-
-
-end
let storage_key = (Jstr.v "content")
+(** Save the text into the local storage *)
let save_contents
: Quill.t -> unit
= fun editor ->
@@ -135,9 +14,12 @@ let save_contents
Brr_io.Storage.set_item
storage
storage_key
- (Json.encode @@ Jv.Id.of_jv @@ contents)
+ (Json.encode @@ Quill.delta_to_json @@ contents)
|> Console.log_if_error ~use:()
+
+
+(** Load the content from the cache storage *)
let load_contents
: Quill.t -> unit
= fun editor ->
@@ -146,24 +28,21 @@ let load_contents
storage
storage_key
|> Option.iter (fun contents ->
-
-
Json.decode contents
|> Result.map (fun json ->
- Quill.set_contents editor json
+ Quill.delta_of_json json
+ |> Quill.set_contents editor
)
|> Console.log_if_error ~use:()
)
-
-
-let page_main id =
+let quill id =
begin match (Jv.is_none id) with
| true -> Console.(error [str "No element with id '%s' found"; id])
| false ->
let options = Quill.options () in
- Prop.set options Quill.placeholder (Jstr.v "Nouvelle note…");
- Prop.set options Quill.theme (Jstr.v "snow");
+ J.set options Quill.placeholder (Jstr.v "Nouvelle note…");
+ J.set options Quill.theme (Jstr.v "snow");
(* Create the editor with the configuration *)
Quill.quill ~options (Jv.Id.of_jv id)
@@ -193,11 +72,129 @@ let page_main id =
)
end
+let create_new_state pm pm_model pm_state mySchema content =
+ let module PM = Prosemirror in
+
+ let doc = PM.Model.(
+ DOMParser.parse
+ (DOMParser.from_schema pm_model mySchema)
+ (Jv.Id.of_jv content)) in
+
+ let props = PM.State.creation_prop () in
+ props##.doc := Js.some doc;
+ props##.plugins := Js.some (PM.example_setup pm mySchema);
+
+ PM.State.create
+ pm_state
+ props
+
+let storage_key = (Jstr.v "editor")
+let prosemirror id content =
+ begin match (Jv.is_none id), (Jv.is_none content) with
+ | false, false ->
+
+ let module PM = Prosemirror in
+ let pm = PM.v () in
+
+ let ( let+ ) o f = Option.iter f o
+ and ( and+ ) a b =
+ match a, b with
+ | Some a, Some b -> Some (a, b)
+ | _ -> None
+
+ in
+
+ let+ pm_state = J.get pm PM.state
+ and+ pm_view = J.get pm PM.view
+ and+ pm_model = J.get pm PM.model
+ and+ schema_basic = J.get pm PM.schema_basic
+ and+ schema_list = J.get pm PM.schema_list
+
+ in
+
+ let _ = schema_basic
+ and _ = schema_list in
+
+ let mySchema = Js_of_ocaml.Js.Unsafe.eval_string {|new PM.model.Schema({
+ nodes: PM.schema_list.addListNodes(PM.schema_basic.schema.spec.nodes, "paragraph block*", "block"),
+ marks: PM.schema_basic.schema.spec.marks
+ })|} in
+
+
+ (* Create the initial state *)
+ let storage = Brr_io.Storage.local G.window in
+ let opt_data = Brr_io.Storage.get_item storage storage_key in
+ let state = match opt_data with
+ | None -> create_new_state pm pm_model pm_state mySchema content
+ | Some contents ->
+ (* Try to load from the storage *)
+ begin match Json.decode contents with
+ | Error _ -> create_new_state pm pm_model pm_state mySchema content
+ | Ok json ->
+ Console.(log [Jstr.v "Loading json"]);
+
+ let history = PM.History.(history pm (history_prop ()) ) in
+ Console.(log [history]);
+ let _ = history in
+
+ let obj = PM.State.configuration_prop () in
+ obj##.plugins := Js.some (PM.example_setup pm mySchema);
+ obj##.schema := mySchema;
+ PM.State.fromJSON pm_state obj json
+ end
+ in
+
+ let props = PM.View.direct_editor_props () in
+ props##.dispatchTransaction := (Js.wrap_meth_callback (fun view transaction ->
+ Console.(log [ Jstr.v "Document size went from"
+ ; transaction##.before##.content##.size ]);
+ let state = view##.state##apply transaction in
+ view##updateState state
+ ));
+ props##.state := state;
+
+
+ let view = PM.View.editor_view
+ pm_view
+ (Jv.Id.of_jv id)
+ props in
+
+
+ view##setProps props;
+
+ (* Attach an event on focus out *)
+ let _out_event = Brr_note.Evr.on_el
+ (Ev.focusout)
+ (fun _ ->
+ let contents = view##.state##toJSON () in
+
+ let storage = Brr_io.Storage.local G.window in
+ Brr_io.Storage.set_item
+ storage
+ storage_key
+ (Json.encode @@ contents)
+ |> Console.log_if_error ~use:()
+
+
+
+ )
+ (Jv.Id.of_jv id) in
+ ()
+
+ | _, _-> Console.(error [str "No element with id '%s' '%s' found"; id ; content])
+
+
+
+ end
+
+
+
let () =
let open Jv in
let editor = obj
- [| "attach", (repr page_main)
+ [| "attach_quill", (repr quill)
+ ; "attach_prosemirror", (repr prosemirror)
|] in
set global "editor" editor