mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-02-11 16:44:07 +08:00
Preserve subsequent Markdown cells in .livemd (#469)
* Add import/export tests * Implement live markdown annotation for breaking Markdown cells
This commit is contained in:
parent
049cf3b5a0
commit
7dd80489a3
5 changed files with 117 additions and 4 deletions
lib/livebook
test/livebook/live_markdown
|
@ -27,9 +27,18 @@ defmodule Livebook.LiveMarkdown do
|
|||
# using Markdown, in such case the JSON contains a "livebook_object" field
|
||||
#
|
||||
# * a metadata that may appear anywhere and applies to the element
|
||||
# it directly precedes, for instance `<!-- livebook:{"force_markdown":true} -->`
|
||||
# forces the next Markdown block to be treated as part of Markdown cell
|
||||
# (even if it's Elixir code block)
|
||||
# it directly precedes, recognised metadatas are:
|
||||
#
|
||||
# - `{"force_markdown":true}` - an annotation forcing the next Markdown
|
||||
# block to be treated as part of Markdown cell (relevant for Elixir code
|
||||
# blocks, which otherwise are interpreted as Elixir cells)
|
||||
#
|
||||
# - `{"break_markdown":true}` - an annotation splitting the markdown content
|
||||
# into separate Markdown cells
|
||||
#
|
||||
# - section metadata, recognised keys `branch_parent_index`
|
||||
#
|
||||
# - cell metadata, recognised keys: `disable_formatting`
|
||||
#
|
||||
# ## Example
|
||||
#
|
||||
|
|
|
@ -24,7 +24,20 @@ defmodule Livebook.LiveMarkdown.Export do
|
|||
|
||||
defp render_section(section, notebook) do
|
||||
name = "## #{section.name}"
|
||||
cells = Enum.map(section.cells, &render_cell/1)
|
||||
|
||||
{cells, _} =
|
||||
Enum.map_reduce(section.cells, nil, fn cell, prev_cell ->
|
||||
separator =
|
||||
if is_struct(cell, Cell.Markdown) and is_struct(prev_cell, Cell.Markdown) do
|
||||
[~s/<!-- livebook:{"break_markdown":true} -->\n\n/]
|
||||
else
|
||||
[]
|
||||
end
|
||||
|
||||
rendered = separator ++ [render_cell(cell)]
|
||||
{rendered, cell}
|
||||
end)
|
||||
|
||||
metadata = section_metadata(section, notebook)
|
||||
|
||||
[name | cells]
|
||||
|
|
|
@ -141,6 +141,13 @@ defmodule Livebook.LiveMarkdown.Import do
|
|||
group_elements(ast, [{:cell, :markdown, [ast_node]} | elems])
|
||||
end
|
||||
|
||||
defp group_elements(
|
||||
[{:comment, _, [~s/livebook:{"break_markdown":true}/], %{comment: true}} | ast],
|
||||
elems
|
||||
) do
|
||||
group_elements(ast, [{:cell, :markdown, []} | elems])
|
||||
end
|
||||
|
||||
defp group_elements(
|
||||
[{:comment, _, ["livebook:" <> json], %{comment: true}} | ast],
|
||||
elems
|
||||
|
|
|
@ -504,4 +504,51 @@ defmodule Livebook.LiveMarkdown.ExportTest do
|
|||
|
||||
assert expected_document == document
|
||||
end
|
||||
|
||||
test "separates consecutive markdown cells by a break annotation" do
|
||||
notebook = %{
|
||||
Notebook.new()
|
||||
| name: "My Notebook",
|
||||
metadata: %{},
|
||||
sections: [
|
||||
%{
|
||||
Notebook.Section.new()
|
||||
| name: "Section 1",
|
||||
metadata: %{},
|
||||
cells: [
|
||||
%{
|
||||
Notebook.Cell.new(:markdown)
|
||||
| metadata: %{},
|
||||
source: """
|
||||
Cell 1\
|
||||
"""
|
||||
},
|
||||
%{
|
||||
Notebook.Cell.new(:markdown)
|
||||
| metadata: %{},
|
||||
source: """
|
||||
Cell 2\
|
||||
"""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
expected_document = """
|
||||
# My Notebook
|
||||
|
||||
## Section 1
|
||||
|
||||
Cell 1
|
||||
|
||||
<!-- livebook:{"break_markdown":true} -->
|
||||
|
||||
Cell 2
|
||||
"""
|
||||
|
||||
document = Export.notebook_to_markdown(notebook)
|
||||
|
||||
assert expected_document == document
|
||||
end
|
||||
end
|
||||
|
|
|
@ -502,4 +502,41 @@ defmodule Livebook.LiveMarkdown.ImportTest do
|
|||
]
|
||||
} = notebook
|
||||
end
|
||||
|
||||
test "imports markdown content into separate cells when a break annotation is encountered" do
|
||||
markdown = """
|
||||
# My Notebook
|
||||
|
||||
## Section 1
|
||||
|
||||
Cell 1
|
||||
|
||||
<!-- livebook:{"break_markdown":true} -->
|
||||
|
||||
Cell 2
|
||||
"""
|
||||
|
||||
{notebook, []} = Import.notebook_from_markdown(markdown)
|
||||
|
||||
assert %Notebook{
|
||||
name: "My Notebook",
|
||||
sections: [
|
||||
%Notebook.Section{
|
||||
name: "Section 1",
|
||||
cells: [
|
||||
%Cell.Markdown{
|
||||
source: """
|
||||
Cell 1\
|
||||
"""
|
||||
},
|
||||
%Cell.Markdown{
|
||||
source: """
|
||||
Cell 2\
|
||||
"""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
} = notebook
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue