Remove untyped metadata (#484)

This commit is contained in:
Jonatan Kłosko 2021-07-30 13:04:07 +02:00 committed by GitHub
parent 42463c7cb1
commit 37b6a1aa40
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 111 additions and 121 deletions

View file

@ -26,9 +26,15 @@ defmodule Livebook.LiveMarkdown.Export do
name = ["# ", notebook.name] name = ["# ", notebook.name]
sections = Enum.map(notebook.sections, &render_section(&1, notebook, ctx)) sections = Enum.map(notebook.sections, &render_section(&1, notebook, ctx))
metadata = notebook_metadata(notebook)
[name | sections] [name | sections]
|> Enum.intersperse("\n\n") |> Enum.intersperse("\n\n")
|> prepend_metadata(notebook.metadata) |> prepend_metadata(metadata)
end
defp notebook_metadata(_notebook) do
%{}
end end
defp render_section(section, notebook, ctx) do defp render_section(section, notebook, ctx) do
@ -54,19 +60,21 @@ defmodule Livebook.LiveMarkdown.Export do
|> prepend_metadata(metadata) |> prepend_metadata(metadata)
end end
defp section_metadata(%{parent_id: nil} = section, _notebook) do defp section_metadata(%{parent_id: nil} = _section, _notebook) do
section.metadata %{}
end end
defp section_metadata(section, notebook) do defp section_metadata(section, notebook) do
parent_idx = Notebook.section_index(notebook, section.parent_id) parent_idx = Notebook.section_index(notebook, section.parent_id)
Map.put(section.metadata, "branch_parent_index", parent_idx) %{"branch_parent_index" => parent_idx}
end end
defp render_cell(%Cell.Markdown{} = cell, _ctx) do defp render_cell(%Cell.Markdown{} = cell, _ctx) do
metadata = cell_metadata(cell)
cell.source cell.source
|> format_markdown_source() |> format_markdown_source()
|> prepend_metadata(cell.metadata) |> prepend_metadata(metadata)
end end
defp render_cell(%Cell.Elixir{} = cell, ctx) do defp render_cell(%Cell.Elixir{} = cell, ctx) do
@ -74,9 +82,11 @@ defmodule Livebook.LiveMarkdown.Export do
code = get_elixir_cell_code(cell) code = get_elixir_cell_code(cell)
outputs = if ctx.include_outputs?, do: render_outputs(cell), else: [] outputs = if ctx.include_outputs?, do: render_outputs(cell), else: []
metadata = cell_metadata(cell)
cell = cell =
[delimiter, "elixir\n", code, "\n", delimiter] [delimiter, "elixir\n", code, "\n", delimiter]
|> prepend_metadata(cell.metadata) |> prepend_metadata(metadata)
if outputs == [] do if outputs == [] do
cell cell
@ -98,10 +108,18 @@ defmodule Livebook.LiveMarkdown.Export do
|> put_unless_implicit(reactive: cell.reactive, props: cell.props) |> put_unless_implicit(reactive: cell.reactive, props: cell.props)
|> Jason.encode!() |> Jason.encode!()
metadata = cell_metadata(cell)
"<!-- livebook:#{json} -->" "<!-- livebook:#{json} -->"
|> prepend_metadata(cell.metadata) |> prepend_metadata(metadata)
end end
defp cell_metadata(%Cell.Elixir{} = cell) do
put_unless_implicit(%{}, disable_formatting: cell.disable_formatting)
end
defp cell_metadata(_cell), do: %{}
defp render_outputs(cell) do defp render_outputs(cell) do
cell.outputs cell.outputs
|> Enum.reverse() |> Enum.reverse()
@ -125,7 +143,7 @@ defmodule Livebook.LiveMarkdown.Export do
defp render_output(_output), do: :ignored defp render_output(_output), do: :ignored
defp get_elixir_cell_code(%{source: source, metadata: %{"disable_formatting" => true}}), defp get_elixir_cell_code(%{source: source, disable_formatting: true}),
do: source do: source
defp get_elixir_cell_code(%{source: source}), do: format_code(source) defp get_elixir_cell_code(%{source: source}), do: format_code(source)

View file

@ -200,29 +200,31 @@ defmodule Livebook.LiveMarkdown.Import do
defp build_notebook([{:cell, :elixir, source, outputs} | elems], cells, sections) do defp build_notebook([{:cell, :elixir, source, outputs} | elems], cells, sections) do
{metadata, elems} = grab_metadata(elems) {metadata, elems} = grab_metadata(elems)
attrs = cell_metadata_to_attrs(:elixir, metadata)
outputs = Enum.map(outputs, &{:text, &1}) outputs = Enum.map(outputs, &{:text, &1})
cell = %{Notebook.Cell.new(:elixir) | source: source, metadata: metadata, outputs: outputs} cell = %{Notebook.Cell.new(:elixir) | source: source, outputs: outputs} |> Map.merge(attrs)
build_notebook(elems, [cell | cells], sections) build_notebook(elems, [cell | cells], sections)
end end
defp build_notebook([{:cell, :markdown, md_ast} | elems], cells, sections) do defp build_notebook([{:cell, :markdown, md_ast} | elems], cells, sections) do
{metadata, elems} = grab_metadata(elems) {metadata, elems} = grab_metadata(elems)
attrs = cell_metadata_to_attrs(:markdown, metadata)
source = md_ast |> Enum.reverse() |> MarkdownHelpers.markdown_from_ast() source = md_ast |> Enum.reverse() |> MarkdownHelpers.markdown_from_ast()
cell = %{Notebook.Cell.new(:markdown) | source: source, metadata: metadata} cell = %{Notebook.Cell.new(:markdown) | source: source} |> Map.merge(attrs)
build_notebook(elems, [cell | cells], sections) build_notebook(elems, [cell | cells], sections)
end end
defp build_notebook([{:cell, :input, data} | elems], cells, sections) do defp build_notebook([{:cell, :input, data} | elems], cells, sections) do
{metadata, elems} = grab_metadata(elems)
attrs = parse_input_attrs(data) attrs = parse_input_attrs(data)
cell = %{Notebook.Cell.new(:input) | metadata: metadata} |> Map.merge(attrs) cell = Notebook.Cell.new(:input) |> Map.merge(attrs)
build_notebook(elems, [cell | cells], sections) build_notebook(elems, [cell | cells], sections)
end end
defp build_notebook([{:section_name, content} | elems], cells, sections) do defp build_notebook([{:section_name, content} | elems], cells, sections) do
name = MarkdownHelpers.text_from_ast(content) name = MarkdownHelpers.text_from_ast(content)
{metadata, elems} = grab_metadata(elems) {metadata, elems} = grab_metadata(elems)
section = %{Notebook.Section.new() | name: name, cells: cells, metadata: metadata} attrs = section_metadata_to_attrs(metadata)
section = %{Notebook.Section.new() | name: name, cells: cells} |> Map.merge(attrs)
build_notebook(elems, [], [section | sections]) build_notebook(elems, [], [section | sections])
end end
@ -242,7 +244,8 @@ defmodule Livebook.LiveMarkdown.Import do
defp build_notebook([{:notebook_name, content} | elems], [], sections) do defp build_notebook([{:notebook_name, content} | elems], [], sections) do
name = MarkdownHelpers.text_from_ast(content) name = MarkdownHelpers.text_from_ast(content)
{metadata, []} = grab_metadata(elems) {metadata, []} = grab_metadata(elems)
%{Notebook.new() | name: name, sections: sections, metadata: metadata} attrs = notebook_metadata_to_attrs(metadata)
%{Notebook.new() | name: name, sections: sections} |> Map.merge(attrs)
end end
# If there's no explicit notebook heading, use the defaults. # If there's no explicit notebook heading, use the defaults.
@ -279,13 +282,48 @@ defmodule Livebook.LiveMarkdown.Import do
end) end)
end end
defp notebook_metadata_to_attrs(_metadata) do
%{}
end
defp section_metadata_to_attrs(metadata) do
Enum.reduce(metadata, %{}, fn
{"branch_parent_index", parent_idx}, attrs ->
# At this point we cannot extract other section id,
# so we temporarily keep the index
Map.put(attrs, :parent_id, {:idx, parent_idx})
_entry, attrs ->
attrs
end)
end
defp cell_metadata_to_attrs(:elixir, metadata) do
Enum.reduce(metadata, %{}, fn
{"disable_formatting", disable_formatting}, attrs ->
Map.put(attrs, :disable_formatting, disable_formatting)
_entry, attrs ->
attrs
end)
end
defp cell_metadata_to_attrs(_type, _metadata) do
%{}
end
defp postprocess_notebook(notebook) do defp postprocess_notebook(notebook) do
sections = sections =
Enum.map(notebook.sections, fn section -> Enum.map(notebook.sections, fn section ->
# Set parent_id based on the persisted branch_parent_index if present # Set parent_id based on the persisted branch_parent_index if present
{parent_idx, metadata} = Map.pop(section.metadata, "branch_parent_index") case section.parent_id do
parent = parent_idx && Enum.at(notebook.sections, parent_idx) nil ->
%{section | metadata: metadata, parent_id: parent && parent.id} section
{:idx, parent_idx} ->
parent = Enum.at(notebook.sections, parent_idx)
%{section | parent_id: parent.id}
end
end) end)
%{notebook | sections: sections} %{notebook | sections: sections}

View file

@ -13,19 +13,16 @@ defmodule Livebook.Notebook do
# A notebook is divided into a number of *sections*, each # A notebook is divided into a number of *sections*, each
# containing a number of *cells*. # containing a number of *cells*.
defstruct [:name, :version, :sections, :metadata] defstruct [:name, :version, :sections]
alias Livebook.Notebook.{Section, Cell} alias Livebook.Notebook.{Section, Cell}
alias Livebook.Utils.Graph alias Livebook.Utils.Graph
import Livebook.Utils, only: [access_by_id: 1] import Livebook.Utils, only: [access_by_id: 1]
@type metadata :: %{String.t() => term()}
@type t :: %__MODULE__{ @type t :: %__MODULE__{
name: String.t(), name: String.t(),
version: String.t(), version: String.t(),
sections: list(Section.t()), sections: list(Section.t())
metadata: metadata()
} }
@version "1.0" @version "1.0"
@ -38,8 +35,7 @@ defmodule Livebook.Notebook do
%__MODULE__{ %__MODULE__{
name: "Untitled notebook", name: "Untitled notebook",
version: @version, version: @version,
sections: [], sections: []
metadata: %{}
} }
end end

View file

@ -12,16 +12,6 @@ defmodule Livebook.Notebook.Cell do
@type id :: Utils.id() @type id :: Utils.id()
@typedoc """
Arbitrary cell information persisted as part of the notebook.
## Recognised entries
* `disable_formatting` - whether this particular cell should
not be automatically formatted. Relevant for Elixir cells only.
"""
@type metadata :: %{String.t() => term()}
@type t :: Cell.Elixir.t() | Cell.Markdown.t() | Cell.Input.t() @type t :: Cell.Elixir.t() | Cell.Markdown.t() | Cell.Input.t()
@type type :: :markdown | :elixir | :input @type type :: :markdown | :elixir | :input

View file

@ -6,16 +6,16 @@ defmodule Livebook.Notebook.Cell.Elixir do
# It consists of text content that the user can edit # It consists of text content that the user can edit
# and produces some output once evaluated. # and produces some output once evaluated.
defstruct [:id, :metadata, :source, :outputs] defstruct [:id, :source, :outputs, :disable_formatting]
alias Livebook.Utils alias Livebook.Utils
alias Livebook.Notebook.Cell alias Livebook.Notebook.Cell
@type t :: %__MODULE__{ @type t :: %__MODULE__{
id: Cell.id(), id: Cell.id(),
metadata: Cell.metadata(),
source: String.t(), source: String.t(),
outputs: list(output()) outputs: list(output()),
disable_formatting: boolean()
} }
@typedoc """ @typedoc """
@ -47,9 +47,9 @@ defmodule Livebook.Notebook.Cell.Elixir do
def new() do def new() do
%__MODULE__{ %__MODULE__{
id: Utils.random_id(), id: Utils.random_id(),
metadata: %{},
source: "", source: "",
outputs: [] outputs: [],
disable_formatting: false
} }
end end
end end

View file

@ -6,14 +6,13 @@ defmodule Livebook.Notebook.Cell.Input do
# It consists of an input that the user may fill # It consists of an input that the user may fill
# and then read during code evaluation. # and then read during code evaluation.
defstruct [:id, :metadata, :type, :name, :value, :reactive, :props] defstruct [:id, :type, :name, :value, :reactive, :props]
alias Livebook.Utils alias Livebook.Utils
alias Livebook.Notebook.Cell alias Livebook.Notebook.Cell
@type t :: %__MODULE__{ @type t :: %__MODULE__{
id: Cell.id(), id: Cell.id(),
metadata: Cell.metadata(),
type: type(), type: type(),
name: String.t(), name: String.t(),
value: String.t(), value: String.t(),
@ -36,7 +35,6 @@ defmodule Livebook.Notebook.Cell.Input do
def new() do def new() do
%__MODULE__{ %__MODULE__{
id: Utils.random_id(), id: Utils.random_id(),
metadata: %{},
type: :text, type: :text,
name: "input", name: "input",
value: "", value: "",

View file

@ -6,14 +6,13 @@ defmodule Livebook.Notebook.Cell.Markdown do
# It consists of Markdown content that the user can edit # It consists of Markdown content that the user can edit
# and which is then rendered on the page. # and which is then rendered on the page.
defstruct [:id, :metadata, :source] defstruct [:id, :source]
alias Livebook.Utils alias Livebook.Utils
alias Livebook.Notebook.Cell alias Livebook.Notebook.Cell
@type t :: %__MODULE__{ @type t :: %__MODULE__{
id: Cell.id(), id: Cell.id(),
metadata: Cell.metadata(),
source: String.t() source: String.t()
} }
@ -24,7 +23,6 @@ defmodule Livebook.Notebook.Cell.Markdown do
def new() do def new() do
%__MODULE__{ %__MODULE__{
id: Utils.random_id(), id: Utils.random_id(),
metadata: %{},
source: "" source: ""
} }
end end

View file

@ -65,7 +65,7 @@ defmodule Livebook.Notebook.Export.Elixir do
defp comment_out(""), do: "" defp comment_out(""), do: ""
defp comment_out(line), do: ["# ", line] defp comment_out(line), do: ["# ", line]
defp get_elixir_cell_code(%{source: source, metadata: %{"disable_formatting" => true}}), defp get_elixir_cell_code(%{source: source, disable_formatting: true}),
do: source do: source
defp get_elixir_cell_code(%{source: source}), do: format_code(source) defp get_elixir_cell_code(%{source: source}), do: format_code(source)

View file

@ -10,20 +10,18 @@ defmodule Livebook.Notebook.Section do
# a branching section. Such section logically follows its # a branching section. Such section logically follows its
# parent section and has no impact on any further sections. # parent section and has no impact on any further sections.
defstruct [:id, :name, :cells, :parent_id, :metadata] defstruct [:id, :name, :cells, :parent_id]
alias Livebook.Notebook.Cell alias Livebook.Notebook.Cell
alias Livebook.Utils alias Livebook.Utils
@type id :: Utils.id() @type id :: Utils.id()
@type metadata :: %{String.t() => term()}
@type t :: %__MODULE__{ @type t :: %__MODULE__{
id: id(), id: id(),
name: String.t(), name: String.t(),
cells: list(Cell.t()), cells: list(Cell.t()),
parent_id: id() | nil, parent_id: id() | nil
metadata: metadata()
} }
@doc """ @doc """
@ -35,8 +33,7 @@ defmodule Livebook.Notebook.Section do
id: Utils.random_id(), id: Utils.random_id(),
name: "Section", name: "Section",
cells: [], cells: [],
parent_id: nil, parent_id: nil
metadata: %{}
} }
end end
end end

View file

@ -5,12 +5,14 @@ defmodule LivebookWeb.SessionLive.ElixirCellSettingsComponent do
@impl true @impl true
def update(assigns, socket) do def update(assigns, socket) do
metadata = assigns.cell.metadata cell = assigns.cell
assigns = socket =
Map.merge(assigns, %{disable_formatting: Map.get(metadata, "disable_formatting", false)}) socket
|> assign(assigns)
|> assign_new(:disable_formatting, fn -> cell.disable_formatting end)
{:ok, assign(socket, assigns)} {:ok, socket}
end end
@impl true @impl true
@ -39,21 +41,13 @@ defmodule LivebookWeb.SessionLive.ElixirCellSettingsComponent do
end end
@impl true @impl true
def handle_event("save", params, socket) do def handle_event("save", %{"disable_formatting" => disable_formatting}, socket) do
metadata = update_metadata(socket.assigns.cell.metadata, params) disable_formatting = disable_formatting == "true"
Session.set_cell_attributes(socket.assigns.session_id, socket.assigns.cell.id, %{ Session.set_cell_attributes(socket.assigns.session_id, socket.assigns.cell.id, %{
metadata: metadata disable_formatting: disable_formatting
}) })
{:noreply, push_patch(socket, to: socket.assigns.return_to)} {:noreply, push_patch(socket, to: socket.assigns.return_to)}
end end
defp update_metadata(metadata, form_data) do
if form_data["disable_formatting"] == "true" do
Map.put(metadata, "disable_formatting", true)
else
Map.delete(metadata, "disable_formatting")
end
end
end end

View file

@ -8,17 +8,14 @@ defmodule Livebook.LiveMarkdown.ExportTest do
notebook = %{ notebook = %{
Notebook.new() Notebook.new()
| name: "My Notebook", | name: "My Notebook",
metadata: %{"author" => "Sherlock Holmes"},
sections: [ sections: [
%{ %{
Notebook.Section.new() Notebook.Section.new()
| name: "Section 1", | name: "Section 1",
metadata: %{"created_at" => "2021-02-15"},
cells: [ cells: [
%{ %{
Notebook.Cell.new(:markdown) Notebook.Cell.new(:markdown)
| metadata: %{"updated_at" => "2021-02-15"}, | source: """
source: """
Make sure to install: Make sure to install:
* Erlang * Erlang
@ -28,7 +25,7 @@ defmodule Livebook.LiveMarkdown.ExportTest do
}, },
%{ %{
Notebook.Cell.new(:elixir) Notebook.Cell.new(:elixir)
| metadata: %{"readonly" => true}, | disable_formatting: true,
source: """ source: """
Enum.to_list(1..10)\ Enum.to_list(1..10)\
""" """
@ -85,23 +82,17 @@ defmodule Livebook.LiveMarkdown.ExportTest do
} }
expected_document = """ expected_document = """
<!-- livebook:{"author":"Sherlock Holmes"} -->
# My Notebook # My Notebook
<!-- livebook:{"created_at":"2021-02-15"} -->
## Section 1 ## Section 1
<!-- livebook:{"updated_at":"2021-02-15"} -->
Make sure to install: Make sure to install:
* Erlang * Erlang
* Elixir * Elixir
* PostgreSQL * PostgreSQL
<!-- livebook:{"readonly":true} --> <!-- livebook:{"disable_formatting":true} -->
```elixir ```elixir
Enum.to_list(1..10) Enum.to_list(1..10)
@ -355,7 +346,7 @@ defmodule Livebook.LiveMarkdown.ExportTest do
assert expected_document == document assert expected_document == document
end end
test "does not format code in Elixir cells which explicitly state so in metadata" do test "does not format code in Elixir cells which have formatting disabled" do
notebook = %{ notebook = %{
Notebook.new() Notebook.new()
| name: "My Notebook", | name: "My Notebook",
@ -366,7 +357,7 @@ defmodule Livebook.LiveMarkdown.ExportTest do
cells: [ cells: [
%{ %{
Notebook.Cell.new(:elixir) Notebook.Cell.new(:elixir)
| metadata: %{"disable_formatting" => true}, | disable_formatting: true,
source: """ source: """
[1,2,3] # Comment\ [1,2,3] # Comment\
""" """

View file

@ -7,23 +7,17 @@ defmodule Livebook.LiveMarkdown.ImportTest do
test "acceptance" do test "acceptance" do
markdown = """ markdown = """
<!-- livebook:{"author":"Sherlock Holmes"} -->
# My Notebook # My Notebook
<!-- livebook:{"created_at":"2021-02-15"} -->
## Section 1 ## Section 1
<!-- livebook:{"updated_at":"2021-02-15"} -->
Make sure to install: Make sure to install:
* Erlang * Erlang
* Elixir * Elixir
* PostgreSQL * PostgreSQL
<!-- livebook:{"readonly":true} --> <!-- livebook:{"disable_formatting": true} -->
```elixir ```elixir
Enum.to_list(1..10) Enum.to_list(1..10)
@ -56,14 +50,11 @@ defmodule Livebook.LiveMarkdown.ImportTest do
assert %Notebook{ assert %Notebook{
name: "My Notebook", name: "My Notebook",
metadata: %{"author" => "Sherlock Holmes"},
sections: [ sections: [
%Notebook.Section{ %Notebook.Section{
name: "Section 1", name: "Section 1",
metadata: %{"created_at" => "2021-02-15"},
cells: [ cells: [
%Cell.Markdown{ %Cell.Markdown{
metadata: %{"updated_at" => "2021-02-15"},
source: """ source: """
Make sure to install: Make sure to install:
@ -73,13 +64,12 @@ defmodule Livebook.LiveMarkdown.ImportTest do
""" """
}, },
%Cell.Elixir{ %Cell.Elixir{
metadata: %{"readonly" => true}, disable_formatting: true,
source: """ source: """
Enum.to_list(1..10)\ Enum.to_list(1..10)\
""" """
}, },
%Cell.Markdown{ %Cell.Markdown{
metadata: %{},
source: """ source: """
This is it for this section.\ This is it for this section.\
""" """
@ -89,23 +79,19 @@ defmodule Livebook.LiveMarkdown.ImportTest do
%Notebook.Section{ %Notebook.Section{
id: section2_id, id: section2_id,
name: "Section 2", name: "Section 2",
metadata: %{},
cells: [ cells: [
%Cell.Input{ %Cell.Input{
metadata: %{},
type: :text, type: :text,
name: "length", name: "length",
value: "100", value: "100",
reactive: true reactive: true
}, },
%Cell.Elixir{ %Cell.Elixir{
metadata: %{},
source: """ source: """
IO.gets("length: ")\ IO.gets("length: ")\
""" """
}, },
%Cell.Input{ %Cell.Input{
metadata: %{},
type: :range, type: :range,
name: "length", name: "length",
value: "100", value: "100",
@ -115,11 +101,9 @@ defmodule Livebook.LiveMarkdown.ImportTest do
}, },
%Notebook.Section{ %Notebook.Section{
name: "Section 3", name: "Section 3",
metadata: %{},
parent_id: section2_id, parent_id: section2_id,
cells: [ cells: [
%Cell.Elixir{ %Cell.Elixir{
metadata: %{},
source: """ source: """
Process.info()\ Process.info()\
""" """
@ -152,10 +136,8 @@ defmodule Livebook.LiveMarkdown.ImportTest do
sections: [ sections: [
%Notebook.Section{ %Notebook.Section{
name: "Section 1", name: "Section 1",
metadata: %{},
cells: [ cells: [
%Cell.Markdown{ %Cell.Markdown{
metadata: %{},
source: """ source: """
Line 1.\\ Line 1.\\
Line 2. Line 2.
@ -213,7 +195,6 @@ defmodule Livebook.LiveMarkdown.ImportTest do
name: "Probably section 1", name: "Probably section 1",
cells: [ cells: [
%Cell.Markdown{ %Cell.Markdown{
metadata: %{},
source: """ source: """
### Heading ### Heading
@ -226,7 +207,6 @@ defmodule Livebook.LiveMarkdown.ImportTest do
name: "Probably section 2", name: "Probably section 2",
cells: [ cells: [
%Cell.Markdown{ %Cell.Markdown{
metadata: %{},
source: """ source: """
**Tiny heading**\ **Tiny heading**\
""" """
@ -330,7 +310,6 @@ defmodule Livebook.LiveMarkdown.ImportTest do
assert %Notebook{ assert %Notebook{
name: "My Notebook", name: "My Notebook",
metadata: %{"author" => "Sherlock Holmes"},
sections: [ sections: [
%Notebook.Section{ %Notebook.Section{
name: "Section", name: "Section",

View file

@ -8,17 +8,14 @@ defmodule Livebook.Notebook.Export.ElixirTest do
notebook = %{ notebook = %{
Notebook.new() Notebook.new()
| name: "My Notebook", | name: "My Notebook",
metadata: %{"author" => "Sherlock Holmes"},
sections: [ sections: [
%{ %{
Notebook.Section.new() Notebook.Section.new()
| name: "Section 1", | name: "Section 1",
metadata: %{"created_at" => "2021-02-15"},
cells: [ cells: [
%{ %{
Notebook.Cell.new(:markdown) Notebook.Cell.new(:markdown)
| metadata: %{"updated_at" => "2021-02-15"}, | source: """
source: """
Make sure to install: Make sure to install:
* Erlang * Erlang
@ -28,15 +25,14 @@ defmodule Livebook.Notebook.Export.ElixirTest do
}, },
%{ %{
Notebook.Cell.new(:elixir) Notebook.Cell.new(:elixir)
| metadata: %{"readonly" => true}, | disable_formatting: true,
source: """ source: """
Enum.to_list(1..10)\ Enum.to_list(1..10)\
""" """
}, },
%{ %{
Notebook.Cell.new(:markdown) Notebook.Cell.new(:markdown)
| metadata: %{}, | source: """
source: """
This is it for this section.\ This is it for this section.\
""" """
} }
@ -46,7 +42,6 @@ defmodule Livebook.Notebook.Export.ElixirTest do
Notebook.Section.new() Notebook.Section.new()
| id: "s2", | id: "s2",
name: "Section 2", name: "Section 2",
metadata: %{},
cells: [ cells: [
%{ %{
Notebook.Cell.new(:input) Notebook.Cell.new(:input)
@ -57,8 +52,7 @@ defmodule Livebook.Notebook.Export.ElixirTest do
}, },
%{ %{
Notebook.Cell.new(:elixir) Notebook.Cell.new(:elixir)
| metadata: %{}, | source: """
source: """
IO.gets("length: ")\ IO.gets("length: ")\
""" """
}, },
@ -74,13 +68,11 @@ defmodule Livebook.Notebook.Export.ElixirTest do
%{ %{
Notebook.Section.new() Notebook.Section.new()
| name: "Section 3", | name: "Section 3",
metadata: %{},
parent_id: "s2", parent_id: "s2",
cells: [ cells: [
%{ %{
Notebook.Cell.new(:elixir) Notebook.Cell.new(:elixir)
| metadata: %{}, | source: """
source: """
Process.info()\ Process.info()\
""" """
} }

View file

@ -2782,14 +2782,13 @@ defmodule Livebook.Session.DataTest do
{:insert_cell, self(), "s1", 0, :elixir, "c1"} {:insert_cell, self(), "s1", 0, :elixir, "c1"}
]) ])
metadata = %{"disable_formatting" => true} attrs = %{disable_formatting: true}
attrs = %{metadata: metadata}
operation = {:set_cell_attributes, self(), "c1", attrs} operation = {:set_cell_attributes, self(), "c1", attrs}
assert {:ok, assert {:ok,
%{ %{
notebook: %{ notebook: %{
sections: [%{cells: [%{metadata: ^metadata}]}] sections: [%{cells: [%{disable_formatting: true}]}]
} }
}, _} = Data.apply_operation(data, operation) }, _} = Data.apply_operation(data, operation)
end end

View file

@ -173,7 +173,7 @@ defmodule Livebook.SessionTest do
pid = self() pid = self()
{_section_id, cell_id} = insert_section_and_cell(session_id) {_section_id, cell_id} = insert_section_and_cell(session_id)
attrs = %{metadata: %{"disable_formatting" => true}} attrs = %{disable_formatting: true}
Session.set_cell_attributes(session_id, cell_id, attrs) Session.set_cell_attributes(session_id, cell_id, attrs)
assert_receive {:operation, {:set_cell_attributes, ^pid, ^cell_id, ^attrs}} assert_receive {:operation, {:set_cell_attributes, ^pid, ^cell_id, ^attrs}}