defmodule LiveMonacoEditor do @external_resource "README.md" @moduledoc "README.md" |> File.read!() |> String.split("") |> Enum.fetch!(1) use Phoenix.Component import Phoenix.LiveView, only: [push_event: 3] alias Phoenix.LiveView.Socket @default_path "file" @default_opts %{ # editor "language" => "markdown", "tabSize" => 2, "formatOnType" => true, "formatOnPaste" => true, "tabIndex" => -1, # visual "theme" => "default", "fontFamily" => "JetBrains Mono, monospace", "fontSize" => 14, "guides" => %{ "indentation" => false }, "occurrencesHighlight" => false, "minimap" => %{ "enabled" => false }, # behavior "scrollbar" => %{ "alwaysConsumeMouseWheel" => false }, "scrollBeyondLastLine" => false, # auto complete "renderLineHighlight" => "none", "suggestSelection" => "first", "parameterHints" => true, # TODO: enable with intellisense implementation # "wordBasedSuggestions" => !this.intellisense, "tabCompletion" => "on" } @doc """ Renders a monaco editor [model](https://microsoft.github.io/monaco-editor/docs.html#functions/editor.createModel.html). ## Examples Render a simple editor using default options: Or merge with custom options: "on"} ) } /> """ attr :path, :string, default: @default_path, doc: "file identifier, pass unique names to render multiple editors" attr :value, :string, default: "", doc: "initial content" attr :change, :string, default: "", doc: "event name to capture editor content changes, see https://github.com/BeaconCMS/live_monaco_editor#inside-forms for more info" attr :target, :string, default: "", doc: "target for editor events in order to use with LiveComponent, see https://github.com/BeaconCMS/live_monaco_editor#inside-forms for more info" attr :opts, :map, default: @default_opts, doc: """ options for the monaco editor instance ## Example %{ "language" => "markdown", "fontSize" => 12, "wordWrap" => "on" } See all available options at https://microsoft.github.io/monaco-editor/docs.html#interfaces/editor.IStandaloneEditorConstructionOptions.html """ attr :style, :string, default: "min-height: 100px; width: 100%;" attr :rest, :global, doc: "the arbitrary HTML attributes to add to the editor container element" def code_editor(assigns) do opts = assigns |> Map.get(:opts, %{}) |> Jason.encode!() assigns = assign(assigns, :opts, opts) ~H"""
""" end @doc """ The default Monaco Editor opts passed to `<.code_editor>` """ def default_opts, do: @default_opts # https://github.com/phoenixframework/phoenix_live_view/blob/c3c21d6de55315adea04e28f7a461a91e46497bb/lib/phoenix_live_view/utils.ex#L176-L183 defp random_encoded_bytes do binary = << System.system_time(:nanosecond)::64, :erlang.phash2({node(), self()})::16, :erlang.unique_integer()::16 >> Base.url_encode64(binary) end defp random_id do String.replace(random_encoded_bytes(), ["/", "+"], "-") end @doc """ Change the editor's language. ## Examples LiveMonacoEditor.change_language(socket, "markdown", to: "my_file.md") ## Options * `:to` - the editor's `path` name that will get the language changed. Defaults to "#{@default_path}". See https://microsoft.github.io/monaco-editor/docs.html#functions/editor.setModelLanguage.html for more info. """ @spec change_language(Socket.t(), String.t(), keyword()) :: Socket.t() def change_language(socket, mime_type_or_language_id, opts \\ []) when is_binary(mime_type_or_language_id) do to = Keyword.get(opts, :to, @default_path) push_event(socket, "lme:change_language:#{to}", %{ "mimeTypeOrLanguageId" => mime_type_or_language_id }) end @doc """ Change the editor's `value` (content). ## Examples LiveMonacoEditor.set_value(socket, "Enum.all?([1, 2, 3])", to: "my_script.exs") ## Options * `:to` - the editor's `path` name that will get the value updated. Defaults to "#{@default_path}". See https://microsoft.github.io/monaco-editor/docs.html#interfaces/editor.IStandaloneCodeEditor.html#setValue for more info. """ @spec set_value(Socket.t(), String.t(), keyword()) :: Socket.t() def set_value(socket, value, opts \\ []) when is_binary(value) do to = Keyword.get(opts, :to, @default_path) push_event(socket, "lme:set_value:#{to}", %{"value" => value}) end end