documents¶
In [ ]:
open file_system_operators
open sm'_operators
open rust.rust_operators
open rust
In [ ]:
///- --test static
open testing
args¶
In [ ]:
inl get_args () =
{
source_dir = "source-dir", 's'
dist_dir = "dist-dir", 'd'
cache_dir = "cache-dir", 'c'
hangul_spec = "hangul-spec", 'H'
filter = "filter", 'f'
transcribe_only = "transcribe-only", 't'
}
get_command¶
In [ ]:
let get_command () =
###"command"
|> runtime.new_command
|> runtime.command_init_arg (get_args () .source_dir) (
runtime.arg_required true
)
|> runtime.command_init_arg (get_args () .dist_dir) (
runtime.arg_required true
)
|> runtime.command_init_arg (get_args () .cache_dir) (
runtime.arg_required true
)
|> runtime.command_init_arg (get_args () .hangul_spec) (
id
)
|> runtime.command_init_arg (get_args () .filter) (
id
)
|> runtime.command_init_arg (get_args () .transcribe_only) (
runtime.arg_default_value "false"
>> runtime.arg_action runtime.SetTrue
)
crowbook¶
In [ ]:
let crowbook hangul { ext dist_dir dist_path output_path } =
inl exit_code, result =
inl args =
inl default ext =
$'$" rendering.num_depth 6"'
++# $'$" rendering.highlight.theme \\\\\\"Solarized (dark)\\\\\\""'
match ext with
| "html" =>
$'$"--set"'
++# $'$" html.css.add \\\\\\"\'"'
++# $'$" body {{ color: \#e8e6e3; background-color: \#202324; }}"'
++# $'$" a {{ color: \#989693; }}"'
++# $'$" pre {{ background-color: \#1b1b1b; padding: 10px; }}"'
++# $'$" \'\\\\\\""'
++# default ext
| "pdf" =>
$'$"--set"'
++# $'$" tex.paper.size a4paper"'
++# $'$" tex.command tectonic"'
++# $'$" tex.template.add \\\"\\\\pagenumbering{{gobble}}\\\""'
++# (
if hangul |> not
then ""
else
$'$" tex.template.add \\\"\\\\usepackage{{polyglossia}}\\\""'
++# $'$" tex.template.add \\\"\\\\setmainlanguage{{korean}}\\\""'
++# $'$" tex.template.add \\\"\\\\setmainfont{{NanumGothicCoding}}\\\""'
++# $'$" tex.font.size 13"'
)
++# default ext
| "epub" =>
$'$"--set"'
++# $'$" epub.version 3"'
++# $'$" html.css.add \\\\\\"\' "'
++# $'$" body {{ color: \#e8e6e3; background-color: \#202324; }} "'
++# $'$" a {{ color: \#989693; }} "'
++# $'$" \'\\\\\\""'
++# default ext
| _ => ""
inl exit_code, result =
runtime.execution_options fun x => { x with
command =
$'$"crowbook --verbose --to {!ext}"'
++# $'$" --single \\\"{!dist_path}\\\" --output \\\"{!output_path}\\\" {!args}"'
working_directory = dist_dir |> Some |> optionm'.box
}
|> runtime.execute_with_options
if exit_code = 0
then exit_code, result
else
trace Warning
fun () => "documents.crowbook / attempt error"
fun () => { exit_code output_path result }
runtime.execution_options fun x => { x with
command =
$'$"crowbook --verbose --to {!ext}"'
++# $'$" --single \\\"{!dist_path}\\\" --output \\\"{!output_path}\\\""'
++# (if ext = "pdf" then $'$" --set tex.command tectonic"' else "")
working_directory = dist_dir |> Some |> optionm'.box
}
|> runtime.execute_with_options
if result |> sm'.contains "ERROR" |> not
then (exit_code, result) |> Ok
else
trace Warning
fun () => "documents.crowbook / result contains ERROR"
fun () => { exit_code output_path result }
(exit_code, result) |> Error
hangul¶
In [ ]:
let hangul workspace_root hangul_spec transcribe_only { ext dist_dir dist_path output_path } =
inl lines =
dist_path
|> file_system.read_all_text
|> sm'.split "\n"
|> fun x => a x : _ int _
|> am.map sm'.trim
inl text =
lines
|> am.filter fun line => line <>. ""
|> seq.of_array'
|> sm'.concat "\n"
|> fun x => $'$"{!x}\n\n"'
inl hangul_spec =
if (text |> sm'.contains " the ")
&& (text |> sm'.contains " and ")
then "eng"
else hangul_spec
inl exit_code, result =
runtime.execution_options fun x => { x with
command =
inl hangulize_path =
workspace_root </> $'$"../alphabet/deps/hangulize/cmd/hangulize/hangulize{!(platform.get_executable_suffix ())}"'
$'$"{!hangulize_path} {!hangul_spec}"'
stdin =
fun stdin =>
inl stdin =
stdin
|> threading.arc_mutex_lock
|> resultm.unwrap'
text |> runtime.stdin_write_all stdin
|> Some |> optionm'.box
}
|> runtime.execute_with_options
inl result =
inl result =
result
|> sm'.split "\n"
|> fun x => a x : _ int _
inl result_len = result |> am'.length
(("", (0, 0), false), lines)
||> am.fold fun (acc, (i, n), in_code_block) line =>
if line = ""
then acc ++# "\n", (i + 1, n + 1), in_code_block
else
inl code_fence = line |> sm'.starts_with "```"
inl acc =
inl i = i - n
if i >= result_len
then acc
elif code_fence || in_code_block
then
inl result = acc ++# line
if i = result_len - 1
then result
else result ++# "\n"
else
inl new_line = result |> am'.index i
inl new_line =
if new_line |> sm'.contains "://"
then line
else new_line
inl result = acc ++# new_line
inl result =
if transcribe_only
then result
else result ++# "\n" ++# line
if i = result_len - 1
then result
else result ++# "\n"
acc, (i + 1, n), (if code_fence then in_code_block |> not else in_code_block)
|> fun (acc, _, _) => acc
result |> file_system.write_all_text output_path
trace Info
fun () => "documents.hangul"
fun () => { exit_code result_len = ##result; output_path }
(exit_code, result) |> Ok
|> fun x => x : result (int * string) (int * string)
fix_paths¶
In [ ]:
let fix_paths { cache_dir dist_path ext } =
inl file_name = dist_path |> file_system.get_file_name
inl cache_path = cache_dir </> file_name
inl dist_path_no_ext =
dist_path
|> sm'.slice 0 ((dist_path |> sm'.last_index_of ".") - 1)
inl cache_path_no_ext =
cache_path
|> sm'.slice 0 ((cache_path |> sm'.last_index_of ".") - 1)
inl is_md = ext |> sm'.ends_with ".md"
inl output_path : string =
if is_md |> not
then $'$"{!dist_path}.{!ext}"'
else $'$"{!dist_path_no_ext}.{!ext}"'
inl output_cache_path : string =
if is_md |> not
then $'$"{!cache_path}.{!ext}"'
else $'$"{!cache_path_no_ext}.{!ext}"'
{ output_path output_cache_path }
files_fn¶
In [ ]:
inl files_fn { dist_dir cache_dir } fn dist_path ext =
inl { output_path output_cache_path } = fix_paths { cache_dir dist_path ext }
inl equal =
if (output_path |> file_system.file_exists |> not)
|| (output_cache_path |> file_system.file_exists |> not)
then false
else
inl output_hash =
output_path
|> crypto.get_file_hash
|> resultm.map_error' sm'.format'
|> resultm.unbox'
|> resultm.get
inl output_cache_hash =
output_cache_path
|> crypto.get_file_hash
|> resultm.map_error' sm'.format'
|> resultm.unbox'
|> resultm.get
output_hash = output_cache_hash
if equal
then None
else
match fn { ext dist_dir dist_path output_path } with
| Ok (exit_code, result) when exit_code <>. 0 =>
trace Info
fun () => "documents.files_fn / error"
fun () => { exit_code result }
new_pair output_path result |> Error |> resultm.box |> Some
| Error (exit_code, result) =>
new_pair output_path result |> Error |> resultm.box |> Some
| _ =>
if output_path |> file_system.file_exists
then output_path |> file_system.file_copy output_cache_path
else failwith $'$"documents.files_fn / {!output_path} should exist"'
output_path |> Ok |> resultm.box |> Some
run¶
In [ ]:
let run { source_dir dist_dir cache_dir hangul_spec filter transcribe_only }
: async.future_pin (
resultm.result'
(am'.vec (
resultm.result'
(pair string (am'.vec (optionm'.option' (resultm.result' string (pair string string)))))
sm'.std_string
))
sm'.std_string
)
=
inl workspace_root = file_system.get_workspace_root ()
inl source_dir = source_dir |> file_system.get_full_path
inl dist_dir = dist_dir |> file_system.get_full_path
inl cache_dir = cache_dir |> file_system.get_full_path
trace Debug
fun () => "documents.run"
fun () => { source_dir dist_dir cache_dir hangul_spec filter transcribe_only }
fun () =>
inl files =
run_target function
| Rust => fun () =>
inl filter, has_filter = match filter with Some filter => filter, true | None => "", false
$'{ let mut out: Vec<Rc<str>> = Vec::new(); let mut stack = vec\![std::path::PathBuf::from(&*!dist_dir)]; while let Some(dir) = stack.pop() { if let Ok(entries) = std::fs::read_dir(&dir) { for entry in entries.flatten() { let path = entry.path(); if path.is_dir() { stack.push(path) } else { let s = path.display().to_string(); if s.ends_with(".md") && \!s.ends_with(".hangul.md") && (\!!has_filter || s.contains(&*!filter)) { out.push(Rc::from(s.as_str())) } } } } } out }' : am'.vec string
| _ => fun () =>
dist_dir
|> file_system.new_walk_dir
|> file_system.walk_dir_filter fun entry => async.new_future_move_send fun () =>
entry
|> file_system.dir_entry_file_type
|> async.await_send
|> resultm.map_error' sm'.format'
|> resultm.unbox
|> function
| Ok file_type when file_type |> file_system.file_type_is_dir =>
file_system.Ignore
| _ =>
inl path =
entry
|> file_system.dir_entry_path
|> file_system.path_buf_display
|> sm'.format'
|> sm'.from_std_string
if (path |> sm'.ends_with ".md" |> not)
|| (
match filter with
| Some filter => path |> sm'.contains filter |> not
| None => false
)
|| (path |> sm'.ends_with ".hangul.md")
then file_system.Ignore
else file_system.Continue
|> async.stream_filter_map_futures fun (entry : _ _ file_system.async_walkdir_error) =>
match entry |> resultm.map_error' sm'.format' |> resultm.unbox with
| Ok entry =>
entry
|> file_system.dir_entry_path
|> file_system.path_buf_display
|> sm'.format'
|> sm'.from_std_string
|> Some
| Error error =>
trace Critical
fun () => "documents.run / stream_filter_map"
fun () => { error }
None
|> optionm'.box
|> async.stream_collect_futures
|> async.await
trace Debug
fun () => "documents.run"
fun () => { files_len = files |> am'.vec_len }
files
|> async.into_par_iter
|> async.par_map fun file =>
inl file = file |> file_system.get_full_path
inl relative_path =
file
|> sm'.to_std_string
|> file_system.new_path_buf
|> file_system.path_buf_display
|> sm'.format'
|> sm'.from_std_string
|> sm'.replace dist_dir (join "")
|> sm'.replace "\\" "/"
|> fun s => $'$".{!s}"'
inl file = file |> file_system.normalize_path
inl real_path = source_dir </> relative_path |> file_system.standardize_path
inl origin_hash_exit_code, origin_hash =
runtime.execution_options fun x => { x with
command =
$'$"git ls-tree --format=\'%%(objectname)\' origin/gh-pages \\"{!real_path}\\""'
working_directory = source_dir |> Some |> optionm'.box
}
|> runtime.execute_with_options
inl dist_path = dist_dir </> relative_path |> file_system.standardize_path
inl local_git_hash_exit_code, local_git_hash =
runtime.execution_options fun x => { x with
command = $'$"git hash-object \\"{!dist_path}\\""'
working_directory = dist_dir |> Some |> optionm'.box
}
|> runtime.execute_with_options
inl cache_path = cache_dir </> relative_path |> file_system.standardize_path
inl files =
inl files_fn = files_fn { dist_dir cache_dir }
inl files = [
"hangul.md", dist_path, hangul workspace_root hangul_spec transcribe_only |> files_fn
]
inl { output_path } = fix_paths { dist_path cache_dir ext = "hangul.md" }
inl files' = [
"html", dist_path, crowbook false |> files_fn
"pdf", dist_path, crowbook false |> files_fn
"epub", dist_path, crowbook false |> files_fn
"html", output_path, crowbook true |> files_fn
"pdf", output_path, crowbook true |> files_fn
"epub", output_path, crowbook true |> files_fn
]
[ files; files' ]
inl files' =
if origin_hash |> sm'.contains local_git_hash
then []
else
inl hash1 =
dist_path
|> crypto.get_file_hash
|> resultm.map_error' sm'.format'
|> resultm.unbox'
|> resultm.get
inl hash2 =
if cache_path |> file_system.file_exists |> not
then None
else
cache_path
|> crypto.get_file_hash
|> resultm.map_error' sm'.format'
|> resultm.unbox'
|> resultm.ok
match hash2 with
| Some hash2 when hash1 = hash2 => []
| _ =>
trace Info
fun () =>
"documents.run / par_map"
++# " / origin_hash |> sm\'.contains local_git_hash |> not"
++# " / Some hash2 when hash1 = hash2"
fun () => {
file
real_path
relative_path
origin_hash_exit_code
origin_hash
local_git_hash_exit_code
local_git_hash
hash1
hash2
dist_path
cache_path
}
dist_path |> file_system.file_copy cache_path
files
inl files' =
if files' <> []
then files'
else
files
|> listm.map fun files =>
files
|> listm'.filter fun ext, path, fn =>
inl { output_path output_cache_path } =
fix_paths { cache_dir dist_path = path; ext }
if output_path |> file_system.file_exists
then true
elif output_cache_path |> file_system.file_exists |> not
then true
else
trace Info
fun () => "documents.run / par_map / files\' = [] / listm.iter"
fun () => { output_path output_cache_path }
output_cache_path |> file_system.file_copy output_path
false
files'
|> listm'.box
|> listm'.to_array'
|> am'.to_vec
|> am'.vec_collect fun files =>
files
|> listm'.box
|> listm'.to_array'
|> am'.to_vec
|> async.into_par_iter
|> async.par_map fun ext, path, fn =>
fn path ext |> optionm'.box
|> async.par_collect
|> new_pair file
|> Ok
|> resultm.box
|> async.par_collect
|> Ok
|> resultm.box
|> async.new_future_move
In [1]:
///- --test
///> rust -d async-walkdir encoding_rs encoding_rs_io futures futures-lite rayon regex sha2
inl workspace_root = file_system.get_workspace_root ()
inl source_dir = workspace_root </> "../alphabet/target/documents"
inl dist_dir = source_dir </> "dist"
inl cache_dir = source_dir </> "cache"
inl file_name_no_ext = "test"
inl file_name = join $'$"{!file_name_no_ext}.md"'
source_dir |> file_system.directory_delete true
dist_dir |> file_system.directory_delete true
cache_dir |> file_system.directory_delete true
source_dir |> file_system.create_dir |> ignore
dist_dir |> file_system.create_dir |> ignore
cache_dir |> file_system.create_dir |> ignore
inl text = """
# a
## b
---
abc
abc
abc
http://abc.com
abc
"""
text |> file_system.write_all_text (source_dir </> file_name)
text |> file_system.write_all_text (dist_dir </> file_name)
inl html_path = dist_dir </> $'$"{!file_name}.html"' |> file_system.absolute_path
inl pdf_path = dist_dir </> $'$"{!file_name}.pdf"' |> file_system.absolute_path
inl epub_path = dist_dir </> $'$"{!file_name}.epub"' |> file_system.absolute_path
inl hangul_path = dist_dir </> $'$"{!file_name_no_ext}.hangul.md"' |> file_system.absolute_path
inl hangul_html_path = dist_dir </> $'$"{!file_name_no_ext}.hangul.md.html"' |> file_system.absolute_path
inl hangul_pdf_path = dist_dir </> $'$"{!file_name_no_ext}.hangul.md.pdf"' |> file_system.absolute_path
inl hangul_epub_path = dist_dir </> $'$"{!file_name_no_ext}.hangul.md.epub"' |> file_system.absolute_path
run {
source_dir
dist_dir
cache_dir
hangul_spec = "por-br"
filter = None
transcribe_only = false
}
|> async.block_on_futures
|> resultm.unwrap'
|> sm'.format_debug'
|> sm'.from_std_string
|> _assert_eq (
;[
Ok (
(dist_dir </> file_name |> file_system.absolute_path),
;[
hangul_path
html_path
pdf_path
epub_path
hangul_html_path
hangul_pdf_path
hangul_epub_path
]
|> am'.to_vec |> am'.vec_map (Ok >> resultm.box >> Some >> optionm'.box)
|> fun x => x : _ (_ (_ _ sm'.std_string))
)
]
|> am'.to_vec
|> am'.vec_map resultm.box
|> fun x => x : _ (_ _ sm'.std_string)
|> sm'.format_debug'
|> sm'.from_std_string
)
dist_dir |> file_system.directory_delete true
dist_dir |> file_system.create_dir |> ignore
text |> file_system.write_all_text (dist_dir </> file_name)
run {
source_dir = source_dir
dist_dir = dist_dir
cache_dir = cache_dir
hangul_spec = "por-br"
filter = None
transcribe_only = false
}
|> async.block_on_futures
|> resultm.unwrap'
|> sm'.format_debug'
|> sm'.from_std_string
|> _assert_eq (
;[
Ok (
(dist_dir </> file_name |> file_system.absolute_path),
;[]
|> am'.to_vec |> am'.vec_map ((optionm.map resultm.box) >> optionm'.box)
)
]
|> am'.to_vec
|> am'.vec_map resultm.box
|> fun x =>
x : am'.vec (
resultm.result'
(string * am'.vec (optionm'.option' (resultm.result' string string)))
sm'.std_string
)
|> sm'.format_debug'
|> sm'.from_std_string
)
run {
source_dir = source_dir
dist_dir = dist_dir
cache_dir = cache_dir
hangul_spec = "por-br"
filter = None
transcribe_only = false
}
|> async.block_on_futures
|> resultm.unwrap'
|> sm'.format_debug'
|> sm'.from_std_string
|> _assert_eq (
;[
Ok (
(dist_dir </> file_name |> file_system.absolute_path),
;[ None; None; None; None; None; None; None ]
|> am'.to_vec |> am'.vec_map ((optionm.map resultm.box) >> optionm'.box)
)
]
|> am'.to_vec
|> am'.vec_map resultm.box
|> fun x =>
x : am'.vec (
resultm.result'
(string * am'.vec (optionm'.option' (resultm.result' string string)))
sm'.std_string
)
|> sm'.format_debug'
|> sm'.from_std_string
)
hangul_path
|> file_system.read_all_text
|> _assert_eq (
"# 아"
++\# "# a"
++\# ""
++\# "## 브"
++\# "## b"
++\# ""
++\# "---"
++\# "---"
++\# ""
++\# "아브크"
++\# "abc"
++\# "아브크"
++\# "abc"
++\# ""
++\# "아브크"
++\# "abc"
++\# ""
++\# "http://abc.com"
++\# "http://abc.com"
++\# "아브크"
++\# "abc"
++\# ""
)
html_path
|> file_system.read_all_text
|> sm'.contains "<p class = \"rule\">***</p>\n<p id = \"para-1\">abc abc</p>"
|> _assert_eq true
pdf_path
|> file_system.read_all_bytes
|> sm'.slice_contains "%PDF-1.5"
|> _assert_eq true
epub_path
|> file_system.read_all_bytes
|> sm'.slice_contains "application/epub+zip"
|> _assert_eq true
hangul_html_path
|> file_system.read_all_text
|> sm'.contains "<p class = \"rule\">***</p>\n<p id = \"para-1\">아브크 abc 아브크 abc</p>"
|> _assert_eq true
hangul_pdf_path
|> file_system.read_all_bytes
|> sm'.slice_contains "%PDF-1.5"
|> _assert_eq true
hangul_epub_path
|> file_system.read_all_bytes
|> sm'.slice_contains "application/epub+zip"
|> _assert_eq true
16:30:19 1v file_system.create_dir / { dir = /home/runner/work/alphabet/spiral/../alphabet/target/documents } 16:30:19 2v file_system.create_dir / { dir = /home/runner/work/alphabet/spiral/../alphabet/target/documents/dist } 16:30:19 3v file_system.create_dir / { dir = /home/runner/work/alphabet/spiral/../alphabet/target/documents/cache } 16:30:19 4d documents.run / { source_dir = /home/runner/work/alphabet/alphabet/target/documents; dist_dir = /home/runner/work/alphabet/alphabet/target/documents/dist; cache_dir = /home/runner/work/alphabet/alphabet/target/documents/cache; hangul_spec = por-br; filter = None; transcribe_only = false } 16:30:19 5d documents.run / { files_len = 1 } 16:30:19 6d runtime.execute_with_options / { file_name = git; arguments = ["ls-tree", "--format='%(objectname)'", "origin/gh-pages", "/home/runner/work/alphabet/alphabet/target/documents/test.md"] } 16:30:19 7v ! fatal: Not a valid object name origin/gh-pages 16:30:19 8v runtime.execute_with_options / result / { file_name = git; exit_code = 128; std_trace_len = 56 } 16:30:19 9d runtime.execute_with_options / { file_name = git; arguments = ["hash-object", "/home/runner/work/alphabet/alphabet/target/documents/dist/test.md"] } 16:30:19 10v > 6358eb3bcf1cbb2b0cdddbd569507e44386e02c3 16:30:19 11v runtime.execute_with_options / result / { file_name = git; exit_code = 0; std_trace_len = 40 } 16:30:19 12i documents.run / par_map / origin_hash |> sm'.contains local_git_hash |> not / Some hash2 when hash1 = hash2 / { file = /home/runner/work/alphabet/alphabet/target/documents/dist/test.md; real_path = /home/runner/work/alphabet/alphabet/target/documents/test.md; relative_path = ./test.md; origin_hash_exit_code = 128; origin_hash = fatal: Not a valid object name origin/gh-pages; local_git_hash_exit_code = 0; local_git_hash = 6358eb3bcf1cbb2b0cdddbd569507e44386e02c3; hash1 = e75e7fe031d4e828aadbec1ce37f56969e7da7baa427b6866c0ed8ac1a86b107; hash2 = None; dist_path = /home/runner/work/alphabet/alphabet/target/documents/dist/test.md; cache_path = /home/runner/work/alphabet/alphabet/target/documents/cache/test.md } 16:30:19 13d file_system.file_copy / { old_path = /home/runner/work/alphabet/alphabet/target/documents/dist/test.md; new_path = /home/runner/work/alphabet/alphabet/target/documents/cache/test.md; result = 49 } 16:30:19 14d runtime.execute_with_options / { file_name = /home/runner/work/alphabet/spiral/../alphabet/deps/hangulize/cmd/hangulize/hangulize; arguments = ["por-br"] } 16:30:19 15v > # 아 16:30:19 16v > ## 브 16:30:19 17v > --- 16:30:19 18v > 아브크 16:30:19 19v > 아브크 16:30:19 20v > 아브크 16:30:19 21v > 트프://아브크.콩 16:30:19 22v > 아브크 16:30:19 23v runtime.execute_with_options / result / { file_name = /home/runner/work/alphabet/spiral/../alphabet/deps/hangulize/cmd/hangulize/hangulize; exit_code = 0; std_trace_len = 79 } 16:30:19 24i documents.hangul / { exit_code = 0; result_len = 121; output_path = /home/runner/work/alphabet/alphabet/target/documents/dist/test.hangul.md } 16:30:19 25d file_system.file_copy / { old_path = /home/runner/work/alphabet/alphabet/target/documents/dist/test.hangul.md; new_path = /home/runner/work/alphabet/alphabet/target/documents/cache/test.hangul.md; result = 121 } 16:30:19 26d runtime.execute_with_options / { file_name = crowbook; arguments = ["--verbose", "--to", "html", "--single", "/home/runner/work/alphabet/alphabet/target/documents/dist/test.md", "--output", "/home/runner/work/alphabet/alphabet/target/documents/dist/test.md.html", "--set", "html.css.add", "' body { color: #e8e6e3; background-color: #202324; } a { color: #989693; } pre { background-color: #1b1b1b; padding: 10px; } '", "rendering.num_depth", "6", "rendering.highlight.theme", "Solarized (dark)"] } 16:30:19 27v ! CROWBOOK 0.17.1 16:30:19 28v ! 16:30:19 [DEBUG] (1) crowbook::book: Ignoring YAML block: 16:30:19 29v ! 16:30:19 30v ! 16:30:19 [DEBUG] (1) crowbook::book: Attempting to generate html... 16:30:19 31v ! 16:30:19 [DEBUG] (1) epub_builder::toc: rendered elem: "<li>\n <a href=\"#link-1\">1. a</a>\n <ul>\n <li><a href=\"#link-2\">1.1. b</a></li>\n </ul>\n</li>" 16:30:19 32v ! 16:30:19 [INFO] crowbook::book: Succesfully generated HTML (standalone page): test.md.html 16:30:19 33v runtime.execute_with_options / result / { file_name = crowbook; exit_code = 0; std_trace_len = 456 } 16:30:19 34d file_system.file_copy / { old_path = /home/runner/work/alphabet/alphabet/target/documents/dist/test.md.html; new_path = /home/runner/work/alphabet/alphabet/target/documents/cache/test.md.html; result = 11691 } 16:30:19 35d runtime.execute_with_options / { file_name = crowbook; arguments = ["--verbose", "--to", "pdf", "--single", "/home/runner/work/alphabet/alphabet/target/documents/dist/test.md", "--output", "/home/runner/work/alphabet/alphabet/target/documents/dist/test.md.pdf", "--set", "tex.paper.size", "a4paper", "tex.command", "tectonic", "tex.template.add", "\\pagenumbering{gobble}", "rendering.num_depth", "6", "rendering.highlight.theme", "Solarized (dark)"] } 16:30:19 36v ! CROWBOOK 0.17.1 16:30:19 37v ! 16:30:19 [DEBUG] (1) crowbook::book: Ignoring YAML block: 16:30:19 38v ! 16:30:19 39v ! 16:30:19 [DEBUG] (1) crowbook::book: Attempting to generate pdf... 16:30:19 40v ! 16:30:19 [DEBUG] (1) crowbook::latex: Attempting to run LaTeX on generated file 16:31:28 41v ! 16:31:28 [INFO] crowbook::book: Succesfully generated PDF: test.md.pdf 16:31:28 42v runtime.execute_with_options / result / { file_name = crowbook; exit_code = 0; std_trace_len = 352 } 16:31:28 43d file_system.file_copy / { old_path = /home/runner/work/alphabet/alphabet/target/documents/dist/test.md.pdf; new_path = /home/runner/work/alphabet/alphabet/target/documents/cache/test.md.pdf; result = 6594 } 16:31:28 44d runtime.execute_with_options / { file_name = crowbook; arguments = ["--verbose", "--to", "epub", "--single", "/home/runner/work/alphabet/alphabet/target/documents/dist/test.md", "--output", "/home/runner/work/alphabet/alphabet/target/documents/dist/test.md.epub", "--set", "epub.version", "3", "html.css.add", "' body { color: #e8e6e3; background-color: #202324; } a { color: #989693; } '", "rendering.num_depth", "6", "rendering.highlight.theme", "Solarized (dark)"] } 16:31:28 45v ! CROWBOOK 0.17.1 16:31:28 46v ! 16:31:28 [DEBUG] (1) crowbook::book: Ignoring YAML block: 16:31:28 47v ! 16:31:28 48v ! 16:31:28 [DEBUG] (1) crowbook::book: Attempting to generate epub... 16:31:28 49v ! 16:31:28 [DEBUG] (1) epub_builder::epub: Add resource: "stylesheet.css" 16:31:28 50v ! 16:31:28 [DEBUG] (1) epub_builder::epub: render_opf... 16:31:28 51v ! 16:31:28 [DEBUG] (1) epub_builder::epub: id="id_title_page.xhtml", mime="application/xhtml+xml" 16:31:28 52v ! 16:31:28 [DEBUG] (1) epub_builder::epub: content = Content { file: "title_page.xhtml", mime: "application/xhtml+xml", itemref: true, cover: false, reftype: Some(TitlePage), title: "Title" } 16:31:28 53v ! 16:31:28 [DEBUG] (1) epub_builder::epub: id="id_chapter_000.xhtml", mime="application/xhtml+xml" 16:31:28 54v ! 16:31:28 [DEBUG] (1) epub_builder::epub: content = Content { file: "chapter_000.xhtml", mime: "application/xhtml+xml", itemref: true, cover: false, reftype: Some(Text), title: "1. a" } 16:31:28 55v ! 16:31:28 [DEBUG] (1) epub_builder::epub: id="id_stylesheet.css", mime="text/css" 16:31:28 56v ! 16:31:28 [DEBUG] (1) epub_builder::toc: rendered elem: "<li><a href=\"title_page.xhtml\">Title</a></li>" 16:31:28 57v ! 16:31:28 [DEBUG] (1) epub_builder::toc: rendered elem: "<li>\n <a href=\"chapter_000.xhtml\">1. a</a>\n <ol>\n <li><a href=\"chapter_000.xhtml#link-2\">1.1. b</a></li>\n </ol>\n</li>" 16:31:28 58v ! 16:31:28 [INFO] crowbook::book: Succesfully generated EPUB: test.md.epub 16:31:28 59v runtime.execute_with_options / result / { file_name = crowbook; exit_code = 0; std_trace_len = 1426 } 16:31:28 60d file_system.file_copy / { old_path = /home/runner/work/alphabet/alphabet/target/documents/dist/test.md.epub; new_path = /home/runner/work/alphabet/alphabet/target/documents/cache/test.md.epub; result = 5043 } 16:31:28 61d runtime.execute_with_options / { file_name = crowbook; arguments = ["--verbose", "--to", "html", "--single", "/home/runner/work/alphabet/alphabet/target/documents/dist/test.hangul.md", "--output", "/home/runner/work/alphabet/alphabet/target/documents/dist/test.hangul.md.html", "--set", "html.css.add", "' body { color: #e8e6e3; background-color: #202324; } a { color: #989693; } pre { background-color: #1b1b1b; padding: 10px; } '", "rendering.num_depth", "6", "rendering.highlight.theme", "Solarized (dark)"] } 16:31:28 62v ! CROWBOOK 0.17.1 16:31:28 63v ! 16:31:28 [DEBUG] (1) crowbook::book: Ignoring YAML block: 16:31:28 64v ! 16:31:28 65v ! 16:31:28 [DEBUG] (1) crowbook::book: Attempting to generate html... 16:31:28 66v ! 16:31:28 [DEBUG] (1) epub_builder::toc: rendered elem: "<li><a href=\"#link-1\">1. 아</a></li>" 16:31:28 67v ! 16:31:28 [DEBUG] (1) epub_builder::toc: rendered elem: "<li>\n <a href=\"#link-2\">2. a</a>\n <ul>\n <li><a href=\"#link-3\">2.1. 브</a></li>\n <li><a href=\"#link-4\">2.2. b</a></li>\n </ul>\n</li>" 16:31:28 68v ! 16:31:28 [INFO] crowbook::book: Succesfully generated HTML (standalone page): test.hangul.md.html 16:31:28 69v runtime.execute_with_options / result / { file_name = crowbook; exit_code = 0; std_trace_len = 617 } 16:31:28 70d file_system.file_copy / { old_path = /home/runner/work/alphabet/alphabet/target/documents/dist/test.hangul.md.html; new_path = /home/runner/work/alphabet/alphabet/target/documents/cache/test.hangul.md.html; result = 16077 } 16:31:28 71d runtime.execute_with_options / { file_name = crowbook; arguments = ["--verbose", "--to", "pdf", "--single", "/home/runner/work/alphabet/alphabet/target/documents/dist/test.hangul.md", "--output", "/home/runner/work/alphabet/alphabet/target/documents/dist/test.hangul.md.pdf", "--set", "tex.paper.size", "a4paper", "tex.command", "tectonic", "tex.template.add", "\\pagenumbering{gobble}", "tex.template.add", "\\usepackage{polyglossia}", "tex.template.add", "\\setmainlanguage{korean}", "tex.template.add", "\\setmainfont{NanumGothicCoding}", "tex.font.size", "13", "rendering.num_depth", "6", "rendering.highlight.theme", "Solarized (dark)"] } 16:31:28 72v ! CROWBOOK 0.17.1 16:31:28 73v ! 16:31:28 [DEBUG] (1) crowbook::book: Ignoring YAML block: 16:31:28 74v ! 16:31:28 75v ! 16:31:28 [DEBUG] (1) crowbook::book: Attempting to generate pdf... 16:31:28 76v ! 16:31:28 [DEBUG] (1) crowbook::latex: Attempting to run LaTeX on generated file 16:31:31 77v ! 16:31:31 [INFO] crowbook::book: Succesfully generated PDF: test.hangul.md.pdf 16:31:31 78v runtime.execute_with_options / result / { file_name = crowbook; exit_code = 0; std_trace_len = 359 } 16:31:31 79d file_system.file_copy / { old_path = /home/runner/work/alphabet/alphabet/target/documents/dist/test.hangul.md.pdf; new_path = /home/runner/work/alphabet/alphabet/target/documents/cache/test.hangul.md.pdf; result = 12243 } 16:31:31 80d runtime.execute_with_options / { file_name = crowbook; arguments = ["--verbose", "--to", "epub", "--single", "/home/runner/work/alphabet/alphabet/target/documents/dist/test.hangul.md", "--output", "/home/runner/work/alphabet/alphabet/target/documents/dist/test.hangul.md.epub", "--set", "epub.version", "3", "html.css.add", "' body { color: #e8e6e3; background-color: #202324; } a { color: #989693; } '", "rendering.num_depth", "6", "rendering.highlight.theme", "Solarized (dark)"] } 16:31:31 81v ! CROWBOOK 0.17.1 16:31:31 82v ! 16:31:31 [DEBUG] (1) crowbook::book: Ignoring YAML block: 16:31:31 83v ! 16:31:31 84v ! 16:31:31 [DEBUG] (1) crowbook::book: Attempting to generate epub... 16:31:31 85v ! 16:31:31 [WARN] crowbook::epub: EPUB (test.hangul.md): detected two chapters inside the same markdown file. 16:31:31 86v ! 16:31:31 [WARN] crowbook::epub: EPUB ({source}): conflict between: 1. 아 and 2. a 16:31:31 87v ! 16:31:31 [DEBUG] (1) epub_builder::epub: Add resource: "stylesheet.css" 16:31:31 88v ! 16:31:31 [DEBUG] (1) epub_builder::epub: render_opf... 16:31:31 89v ! 16:31:31 [DEBUG] (1) epub_builder::epub: id="id_title_page.xhtml", mime="application/xhtml+xml" 16:31:31 90v ! 16:31:31 [DEBUG] (1) epub_builder::epub: content = Content { file: "title_page.xhtml", mime: "application/xhtml+xml", itemref: true, cover: false, reftype: Some(TitlePage), title: "Title" } 16:31:31 91v ! 16:31:31 [DEBUG] (1) epub_builder::epub: id="id_chapter_000.xhtml", mime="application/xhtml+xml" 16:31:31 92v ! 16:31:31 [DEBUG] (1) epub_builder::epub: content = Content { file: "chapter_000.xhtml", mime: "application/xhtml+xml", itemref: true, cover: false, reftype: Some(Text), title: "1. 아" } 16:31:31 93v ! 16:31:31 [DEBUG] (1) epub_builder::epub: id="id_stylesheet.css", mime="text/css" 16:31:31 94v ! 16:31:31 [DEBUG] (1) epub_builder::toc: rendered elem: "<li><a href=\"title_page.xhtml\">Title</a></li>" 16:31:31 95v ! 16:31:31 [DEBUG] (1) epub_builder::toc: rendered elem: "<li><a href=\"chapter_000.xhtml\">1. 아</a></li>" 16:31:31 96v ! 16:31:31 [INFO] crowbook::book: Succesfully generated EPUB: test.hangul.md.epub 16:31:31 97v runtime.execute_with_options / result / { file_name = crowbook; exit_code = 0; std_trace_len = 1563 } 16:31:31 98d file_system.file_copy / { old_path = /home/runner/work/alphabet/alphabet/target/documents/dist/test.hangul.md.epub; new_path = /home/runner/work/alphabet/alphabet/target/documents/cache/test.hangul.md.epub; result = 5048 } __assert_eq { expected = [Ok(("/home/runner/work/alphabet/alphabet/target/documents/dist/test.md", [Some(Ok("/home/runner/work/alphabet/alphabet/target/documents/dist/test.hangul.md")), Some(Ok("/home/runner/work/alphabet/alphabet/target/documents/dist/test.md.html")), Some(Ok("/home/runner/work/alphabet/alphabet/target/documents/dist/test.md.pdf")), Some(Ok("/home/runner/work/alphabet/alphabet/target/documents/dist/test.md.epub")), Some(Ok("/home/runner/work/alphabet/alphabet/target/documents/dist/test.hangul.md.html")), Some(Ok("/home/runner/work/alphabet/alphabet/target/documents/dist/test.hangul.md.pdf")), Some(Ok("/home/runner/work/alphabet/alphabet/target/documents/dist/test.hangul.md.epub"))]))] } 16:31:31 99v file_system.create_dir / { dir = /home/runner/work/alphabet/spiral/../alphabet/target/documents/dist } 16:31:31 100d documents.run / { source_dir = /home/runner/work/alphabet/alphabet/target/documents; dist_dir = /home/runner/work/alphabet/alphabet/target/documents/dist; cache_dir = /home/runner/work/alphabet/alphabet/target/documents/cache; hangul_spec = por-br; filter = None; transcribe_only = false } 16:31:31 101d documents.run / { files_len = 1 } 16:31:31 102d runtime.execute_with_options / { file_name = git; arguments = ["ls-tree", "--format='%(objectname)'", "origin/gh-pages", "/home/runner/work/alphabet/alphabet/target/documents/test.md"] } 16:31:31 103v ! fatal: Not a valid object name origin/gh-pages 16:31:31 104v runtime.execute_with_options / result / { file_name = git; exit_code = 128; std_trace_len = 56 } 16:31:31 105d runtime.execute_with_options / { file_name = git; arguments = ["hash-object", "/home/runner/work/alphabet/alphabet/target/documents/dist/test.md"] } 16:31:31 106v > 6358eb3bcf1cbb2b0cdddbd569507e44386e02c3 16:31:31 107v runtime.execute_with_options / result / { file_name = git; exit_code = 0; std_trace_len = 40 } 16:31:31 108i documents.run / par_map / files' = [] / listm.iter / { output_path = /home/runner/work/alphabet/alphabet/target/documents/dist/test.hangul.md.epub; output_cache_path = /home/runner/work/alphabet/alphabet/target/documents/cache/test.hangul.md.epub } 16:31:31 109d file_system.file_copy / { old_path = /home/runner/work/alphabet/alphabet/target/documents/cache/test.hangul.md.epub; new_path = /home/runner/work/alphabet/alphabet/target/documents/dist/test.hangul.md.epub; result = 5048 } 16:31:31 110i documents.run / par_map / files' = [] / listm.iter / { output_path = /home/runner/work/alphabet/alphabet/target/documents/dist/test.hangul.md.pdf; output_cache_path = /home/runner/work/alphabet/alphabet/target/documents/cache/test.hangul.md.pdf } 16:31:31 111d file_system.file_copy / { old_path = /home/runner/work/alphabet/alphabet/target/documents/cache/test.hangul.md.pdf; new_path = /home/runner/work/alphabet/alphabet/target/documents/dist/test.hangul.md.pdf; result = 12243 } 16:31:31 112i documents.run / par_map / files' = [] / listm.iter / { output_path = /home/runner/work/alphabet/alphabet/target/documents/dist/test.hangul.md.html; output_cache_path = /home/runner/work/alphabet/alphabet/target/documents/cache/test.hangul.md.html } 16:31:31 113d file_system.file_copy / { old_path = /home/runner/work/alphabet/alphabet/target/documents/cache/test.hangul.md.html; new_path = /home/runner/work/alphabet/alphabet/target/documents/dist/test.hangul.md.html; result = 16077 } 16:31:31 114i documents.run / par_map / files' = [] / listm.iter / { output_path = /home/runner/work/alphabet/alphabet/target/documents/dist/test.md.epub; output_cache_path = /home/runner/work/alphabet/alphabet/target/documents/cache/test.md.epub } 16:31:31 115d file_system.file_copy / { old_path = /home/runner/work/alphabet/alphabet/target/documents/cache/test.md.epub; new_path = /home/runner/work/alphabet/alphabet/target/documents/dist/test.md.epub; result = 5043 } 16:31:31 116i documents.run / par_map / files' = [] / listm.iter / { output_path = /home/runner/work/alphabet/alphabet/target/documents/dist/test.md.pdf; output_cache_path = /home/runner/work/alphabet/alphabet/target/documents/cache/test.md.pdf } 16:31:31 117d file_system.file_copy / { old_path = /home/runner/work/alphabet/alphabet/target/documents/cache/test.md.pdf; new_path = /home/runner/work/alphabet/alphabet/target/documents/dist/test.md.pdf; result = 6594 } 16:31:31 118i documents.run / par_map / files' = [] / listm.iter / { output_path = /home/runner/work/alphabet/alphabet/target/documents/dist/test.md.html; output_cache_path = /home/runner/work/alphabet/alphabet/target/documents/cache/test.md.html } 16:31:31 119d file_system.file_copy / { old_path = /home/runner/work/alphabet/alphabet/target/documents/cache/test.md.html; new_path = /home/runner/work/alphabet/alphabet/target/documents/dist/test.md.html; result = 11691 } 16:31:31 120i documents.run / par_map / files' = [] / listm.iter / { output_path = /home/runner/work/alphabet/alphabet/target/documents/dist/test.hangul.md; output_cache_path = /home/runner/work/alphabet/alphabet/target/documents/cache/test.hangul.md } 16:31:31 121d file_system.file_copy / { old_path = /home/runner/work/alphabet/alphabet/target/documents/cache/test.hangul.md; new_path = /home/runner/work/alphabet/alphabet/target/documents/dist/test.hangul.md; result = 121 } __assert_eq { expected = [Ok(("/home/runner/work/alphabet/alphabet/target/documents/dist/test.md", []))] } 16:31:31 122d documents.run / { source_dir = /home/runner/work/alphabet/alphabet/target/documents; dist_dir = /home/runner/work/alphabet/alphabet/target/documents/dist; cache_dir = /home/runner/work/alphabet/alphabet/target/documents/cache; hangul_spec = por-br; filter = None; transcribe_only = false } 16:31:31 123d documents.run / { files_len = 1 } 16:31:31 124d runtime.execute_with_options / { file_name = git; arguments = ["ls-tree", "--format='%(objectname)'", "origin/gh-pages", "/home/runner/work/alphabet/alphabet/target/documents/test.md"] } 16:31:31 125v ! fatal: Not a valid object name origin/gh-pages 16:31:31 126v runtime.execute_with_options / result / { file_name = git; exit_code = 128; std_trace_len = 56 } 16:31:31 127d runtime.execute_with_options / { file_name = git; arguments = ["hash-object", "/home/runner/work/alphabet/alphabet/target/documents/dist/test.md"] } 16:31:31 128v > 6358eb3bcf1cbb2b0cdddbd569507e44386e02c3 16:31:31 129v runtime.execute_with_options / result / { file_name = git; exit_code = 0; std_trace_len = 40 } __assert_eq { expected = [Ok(("/home/runner/work/alphabet/alphabet/target/documents/dist/test.md", [None, None, None, None, None, None, None]))] } __assert_eq { expected = # 아 # a ## 브 ## b --- --- 아브크 abc 아브크 abc 아브크 abc http://abc.com http://abc.com 아브크 abc } __assert_eq { expected = true } __assert_eq { expected = true } __assert_eq { expected = true } __assert_eq { expected = true } __assert_eq { expected = true } __assert_eq { expected = true }
tests¶
In [2]:
inl tests () =
testing.run_tests {
verify_app = get_command >> runtime.command_debug_assert
}
main¶
In [ ]:
///> _
inl main (args : array_base string) =
Info |> Some |> init_trace_state
trace Info
fun () => "documents.main"
fun () => { args }
inl command = get_command ()
inl arg_matches = command |> runtime.command_get_matches
inl source_dir =
arg_matches
|> runtime.matches_get_one (get_args () .source_dir |> fst)
|> optionm'.unbox
|> optionm.value
|> sm'.from_std_string
inl dist_dir =
arg_matches
|> runtime.matches_get_one (get_args () .dist_dir |> fst)
|> optionm'.unbox
|> optionm.value
|> sm'.from_std_string
inl cache_dir =
arg_matches
|> runtime.matches_get_one (get_args () .cache_dir |> fst)
|> optionm'.unbox
|> optionm.value
|> sm'.from_std_string
inl hangul_spec =
arg_matches
|> runtime.matches_get_one (get_args () .hangul_spec |> fst)
|> optionm'.unbox
|> optionm.map sm'.from_std_string
|> optionm'.default_value "por-br"
inl filter =
arg_matches
|> runtime.matches_get_one (get_args () .filter |> fst)
|> optionm'.unbox
|> optionm.map sm'.from_std_string
inl transcribe_only =
arg_matches
|> runtime.matches_get_flag (get_args () .transcribe_only |> fst)
inl result =
run { source_dir dist_dir cache_dir hangul_spec filter transcribe_only }
|> async.block_on_futures
|> resultm.unbox
match result with
| Ok result =>
trace Info
fun () => "documents.main"
fun () => { result_len = result |> am'.vec_len }
0i32
| Error error =>
trace Critical
fun () => "documents.main"
fun () => { error }
1i32
inl main () =
backend_switch {
Fsharp = fun () =>
$'let tests () = !tests ()' : ()
$'let main args = !main args' : ()
Rust = fun () =>
inl args =
$'Rc::new(RefCell::new(std::env::args().skip(1).map(|x| Rc::<str>::from(x)).collect::<Vec<Rc<str>>>()))'
: array_base string
inl exit_code = main args
$'if !exit_code \!= 0 { std::process::exit(!exit_code) }' : ()
} : ()