-
-
Save jonatanklosko/20e28aa772a888a25a829337a4b805e1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This script automatically converts notebooks using the legacy images/ | |
# directory to use notebook files introduced in Livebook v0.11.0. | |
# | |
# Usage: elixir convert_notebook_images.exs <notebooks-dir> | |
Mix.install([ | |
{:jason, "~> 1.4.0"} | |
]) | |
dir = | |
case System.argv() do | |
[path] -> | |
Path.expand(path) | |
_ -> | |
IO.puts("Usage: elixir convert_notebook_images.exs <notebooks-dir>") | |
System.halt(1) | |
end | |
case System.shell("git status --porcelain", cd: dir, stderr_to_stdout: true) do | |
{"", 0} -> | |
:ok | |
{_, 0} -> | |
IO.puts("Please commit all the changes before running this script") | |
System.halt(1) | |
{_, _} -> | |
IO.puts( | |
"Please run this script only in git repositories. You can initialize a fresh" <> | |
" git repo and then remove .git directory if the conversion is successful" | |
) | |
System.halt(1) | |
end | |
# Copy all images to the files directory | |
File.cp_r!(Path.join(dir, "images"), Path.join(dir, "files")) | |
for notebook_path <- Path.wildcard(Path.join(dir, "*.livemd")) do | |
source = File.read!(notebook_path) | |
image_names = | |
Regex.scan(~r{!\[.*?\]\(images/(.*?)\)}, source, capture: :all_but_first) |> List.flatten() | |
if image_names != [] do | |
# Update Markdown images to point to the files directory | |
source = | |
Regex.replace(~r{!\[(.*?)\]\(images/(.*?)\)}, source, fn _, alt, name -> | |
"![#{alt}](files/#{name})" | |
end) | |
# Update metadata to include the used files | |
file_entries = | |
for name <- Enum.sort(image_names) do | |
Jason.OrderedObject.new(name: name, type: :attachment) | |
end | |
source = | |
source | |
|> String.split("\n") | |
|> Enum.split_while(fn line -> | |
not String.starts_with?(line, "# ") and not String.starts_with?(line, "<!-- livebook:") | |
end) | |
|> case do | |
{leading, ["# " <> _ | _] = rest} -> | |
json = Jason.encode!(%{file_entries: file_entries}) | |
leading ++ ["", "<!-- livebook:#{json} -->", ""] ++ rest | |
{leading, ["<!-- livebook:" <> meta_rest | rest]} -> | |
meta = meta_rest |> String.replace_trailing(" -->", "") |> Jason.decode!() | |
json = | |
meta | |
|> Map.put(:file_entries, file_entries) | |
|> Enum.sort() | |
|> Jason.OrderedObject.new() | |
|> Jason.encode!() | |
leading ++ ["", "<!-- livebook:#{json} -->", ""] ++ rest | |
end | |
|> Enum.join("\n") | |
|> String.trim_leading("\n") | |
File.write!(notebook_path, source) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment