Skip to content

Commit

Permalink
Markdown export of hlist boxes; make line_of_length style-sensitive
Browse files Browse the repository at this point in the history
  • Loading branch information
lukstafi committed Jan 25, 2024
1 parent dcdf99e commit 261f5cb
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 51 deletions.
74 changes: 59 additions & 15 deletions src/printbox-md/PrintBox_md.ml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ module Config = struct
type t = {
tables: [`Text | `Html];
vlists: [`Line_break | `List | `As_table];
hlists: [`Minimal | `Stylized | `As_table];
foldable_trees: bool;
multiline_preformatted: preformatted;
one_line_preformatted: preformatted;
Expand All @@ -18,6 +19,7 @@ module Config = struct
let default = {
tables=`Text;
vlists=`List;
hlists=`Minimal;
foldable_trees=false;
multiline_preformatted=Code_block;
one_line_preformatted=Code_quote;
Expand All @@ -28,6 +30,7 @@ module Config = struct
let uniform = {
tables=`Html;
vlists=`Line_break;
hlists=`Stylized;
foldable_trees=true;
multiline_preformatted=Stylized;
one_line_preformatted=Stylized;
Expand All @@ -38,7 +41,9 @@ module Config = struct

let html_tables c = {c with tables=`Html}
let text_tables c = {c with tables=`Text}
let non_preformatted x c = {c with non_preformatted=x}
let vlists x c = {c with vlists=x}
let hlists x c = {c with hlists=x}
let foldable_trees c = {c with foldable_trees=true}
let unfolded_trees c = {c with foldable_trees=false}
let multiline_preformatted x c = {c with multiline_preformatted=x}
Expand Down Expand Up @@ -187,26 +192,33 @@ let rec multiline_heuristic b =
Array.length children > 0 || multiline_heuristic header
| B.Link {inner; _} -> multiline_heuristic inner
let rec line_of_length_exn b =
let rec line_of_length_heuristic_exn c b =
match B.view b with
| B.Empty | B.Text {l=[]; _} -> 0
| B.Text {l=[s]; _} ->
if String.contains s '\n' then raise Not_found else String.length s
| B.Text _ -> raise Not_found
| B.Frame b -> line_of_length_exn b + 39
| B.Frame b when c.Config.frames = `Stylized ->
(* "<span style="border:thin solid"></span>" *)
line_of_length_heuristic_exn c b + 39
| B.Frame b ->
(* "> " *)
line_of_length_heuristic_exn c b + 2
| B.Pad (_, _) -> raise Not_found
| B.Align {inner; _} -> line_of_length_exn inner
| B.Align {inner; _} -> line_of_length_heuristic_exn c inner
| B.Grid (_, [||]) | B.Grid (_, [|[||]|]) -> 0
| B.Grid (`None, [|row|]) ->
(* "&nbsp;" *)
(Array.length row - 1) * 6 + Array.fold_left (+) 0 (Array.map line_of_length_exn row)
| B.Grid (`Bars, [|row|]) ->
| B.Grid (`None, [|row|]) when c.Config.hlists = `Minimal ->
(* " &nbsp; " *)
(Array.length row - 1) * 8 +
Array.fold_left (+) 0 (Array.map (line_of_length_heuristic_exn c) row)
| B.Grid (`Bars, [|row|]) when c.Config.hlists = `Minimal ->
(* " | " *)
(Array.length row - 1) * 3 + Array.fold_left (+) 0 (Array.map line_of_length_exn row)
(Array.length row - 1) * 3 +
Array.fold_left (+) 0 (Array.map (line_of_length_heuristic_exn c) row)
| B.Grid _ -> raise Not_found
| B.Tree (_, header, [||]) -> line_of_length_exn header
| B.Tree (_, header, [||]) -> line_of_length_heuristic_exn c header
| B.Tree _ -> raise Not_found
| B.Link {inner; uri} -> line_of_length_exn inner + String.length uri + 4
| B.Link {inner; uri} -> line_of_length_heuristic_exn c inner + String.length uri + 4
let is_native_table rows =
let rec header h =
Expand Down Expand Up @@ -275,6 +287,38 @@ let pp c out b =
| B.Align {h = _; v=_; inner} ->
(* NOT IMPLEMENTED YET *)
loop ~in_span ~prefix inner
| B.Grid (bars, [|row|])
when c.Config.hlists <> `As_table &&
Array.for_all (Fun.negate multiline_heuristic) row -> (
let len = Array.length row in
match c.Config.hlists, c.Config.non_preformatted with
| `As_table, _ -> assert false
| `Minimal, `Minimal ->
Array.iteri (fun i r ->
loop ~in_span ~prefix r;
if i < len - 1 then (
if bars = `Bars then fprintf out " | " else fprintf out " &nbsp; "))
row
| _, `Stylized | `Stylized, _ ->
let spec_pre, spec_post =
if in_span
then {|<span style="|}, "</span>"
else {|<div style="|}, "</div>" in
fprintf out {|%swhite-space: pre">|} spec_pre;
if not in_span then fprintf out "@,%s@,%s" prefix prefix;
Array.iteri (fun i r ->
if i < len - 1 && bars = `Bars && c.Config.hlists = `Stylized
then fprintf out {|<span style="border-right: thin solid">|};
loop ~in_span ~prefix r;
if i < len - 1 then (
if bars = `Bars && c.Config.hlists = `Stylized
then fprintf out "</span>"
else if bars = `Bars then fprintf out " | "
else fprintf out " &nbsp; "))
row;
if not in_span then fprintf out "@,%s" prefix;
pp_print_string out spec_post
)
| B.Grid (bars, rows)
when c.Config.vlists <> `As_table &&
Array.for_all (fun row -> Array.length row = 1) rows -> (
Expand All @@ -300,13 +344,13 @@ let pp c out b =
| B.Grid (_, [||]) -> ()
| B.Grid (bars, rows) when bars <> `None && is_native_table rows ->
let lengths =
Array.fold_left (Array.map2 (fun len b -> max len @@ line_of_length_exn b))
Array.fold_left (Array.map2 (fun len b -> max len @@ line_of_length_heuristic_exn c b))
(Array.map (fun _ -> 0) rows.(0)) rows in
let n_rows = Array.length rows and n_cols = Array.length rows.(0) in
Array.iteri (fun i header ->
loop ~in_span:true ~prefix:"" @@ remove_bold header;
if i < n_rows - 1 then
let len = line_of_length_exn header in
let len = line_of_length_heuristic_exn c header in
fprintf out "%s|" (String.make (lengths.(i) - len) ' ')
) rows.(0);
fprintf out "@,%s" prefix;
Expand All @@ -315,10 +359,10 @@ let pp c out b =
if j < n_cols - 1 then pp_print_char out '|'
) rows.(0);
Array.iteri (fun i row ->
if i > 0 then Array.iteri (fun j c ->
loop ~in_span:true ~prefix:"" c;
if i > 0 then Array.iteri (fun j b ->
loop ~in_span:true ~prefix:"" b;
if j < n_cols - 1 then
let len = line_of_length_exn c in
let len = line_of_length_heuristic_exn c b in
fprintf out "%s|" (String.make (lengths.(j) - len) ' ')
) row;
if i < n_rows - 1 then fprintf out "@,%s" prefix;
Expand Down
21 changes: 17 additions & 4 deletions src/printbox-md/PrintBox_md.mli
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,26 @@ module Config : sig

val text_tables : t -> t
(** Output tables via {!PrintBox_text}. Already the case for the {!default} config. *)

val non_preformatted : [`Minimal | `Stylized] -> t -> t

val vlists : [`Line_break | `List | `As_table] -> t -> t
(** How to output {!PrintBox.vlist} boxes, i.e. single-column grids.
[`Line_break] is used in the {!uniform} config; when the {!PrintBox.vlist} has bars,
it puts a bottom border div around a row.
[`List] is used in the {!default} config; when the {!PrintBox.vlist} has bars,
it puts a quoted horizontal rule ["> ---"] at the bottom of a row. *)
- [`Line_break] is set in the {!uniform} config; when the {!PrintBox.vlist} has bars,
it puts a bottom border div around a row.
- [`List] is set in the {!default} config; when the {!PrintBox.vlist} has bars,
it puts a quoted horizontal rule ["> ---"] at the bottom of a row.
- [`As_table] falls back to the general table printing mechanism. *)

val hlists : [`Minimal | `Stylized | `As_table] -> t -> t
(** How to output {!PrintBox.hlist} boxes, i.e. single-row grids, curently only if they fit
in one line.
- [`Minimal] uses spaces and a horizontal bar ["|"] to separate columns.
If {!Config.non_preformatted} is [`Stylized], it also uses the ["white-space: pre"] style
to prevent line breaks. It is set in the {!default} config.
- [`Stylized] uses ["white-space: pre"] style to prevent line breaks, and instead of ["|"]
it uses the border style to provide grid bars. It is set in the {!uniform} config.
- [`As_table] falls back to the general table printing mechanism. *)

val foldable_trees : t -> t
(** Output trees so every node with children is foldable.
Expand Down
60 changes: 44 additions & 16 deletions test/test_md.expected
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ Test default:
b row 2.2
> ---
- b row 3
- a longiiish column 1 &nbsp; a longiiish column 2 &nbsp; > a longiiish column 3 &nbsp; a longiiish column 4
- b longiiish column 1 | b longiiish column 2 | b longiiish column 3 | > b longiiish column 4
- > - c row 1
> > ---
> - c row 2.1<br>
Expand Down Expand Up @@ -55,14 +57,14 @@ Test default:
> > │
> > ```
> >
- header 1 |header 2 |<span style="border:thin solid">header 3</span>
-----------------------------------------------|-----------------------------------------------|-----------------------------------------------
cell 1.1 |<span style="border:thin solid">cell 1.2</span>|cell 1.3
<span style="border:thin solid">cell 2.1</span>|cell 2.2 |cell 2.3
- > header 1 |header 2 |<span style="border:thin solid">header 3</span>
> -----------------------------------------------|-----------------------------------------------|-----------------------------------------------
> cell 1.1 |<span style="border:thin solid">cell 1.2</span>|cell 1.3
> <span style="border:thin solid">cell 2.1</span>|cell 2.2 |cell 2.3
- header 1 |header 2 |<span style="border:thin solid">header 3</span>
----------|----------|----------
cell 1.1 |<span style="border:thin solid">cell 1.2</span>|cell 1.3
<span style="border:thin solid">cell 2.1</span>|cell 2.2 |cell 2.3
- > header 1 |header 2 |<span style="border:thin solid">header 3</span>
> ----------|----------|----------
> cell 1.1 |<span style="border:thin solid">cell 1.2</span>|cell 1.3
> <span style="border:thin solid">cell 2.1</span>|cell 2.2 |cell 2.3

Test uniform unfolded:

Expand All @@ -82,6 +84,14 @@ Test uniform unfolded:
<div style="white-space: pre">b row 2.1
b row 2.2</div></div>
<span style="white-space: pre">b row 3</span>
- <div style="white-space: pre">

<span style="white-space: pre">a longiiish column 1</span> &nbsp; <span style="white-space: pre">a longiiish column 2</span> &nbsp; <span style="border:thin solid"><span style="white-space: pre">a longiiish column 3</span></span> &nbsp; <span style="white-space: pre">a longiiish column 4</span>
</div>
- <div style="white-space: pre">

<span style="border-right: thin solid"><span style="white-space: pre">b longiiish column 1</span></span><span style="border-right: thin solid"><span style="white-space: pre">b longiiish column 2</span></span><span style="border-right: thin solid"><span style="white-space: pre">b longiiish column 3</span></span><span style="border:thin solid"><span style="white-space: pre">b longiiish column 4</span></span>
</div>
- <div style="border:thin solid">

<div style="border-bottom:thin solid">
Expand Down Expand Up @@ -187,6 +197,8 @@ Test foldable:
b row 2.2
> ---
- b row 3
- a longiiish column 1 &nbsp; a longiiish column 2 &nbsp; > a longiiish column 3 &nbsp; a longiiish column 4
- b longiiish column 1 | b longiiish column 2 | b longiiish column 3 | > b longiiish column 4
- > - c row 1
> > ---
> - c row 2.1<br>
Expand Down Expand Up @@ -239,14 +251,14 @@ Test foldable:
> > │
> > ```
> >
- header 1 |header 2 |<span style="border:thin solid">header 3</span>
-----------------------------------------------|-----------------------------------------------|-----------------------------------------------
cell 1.1 |<span style="border:thin solid">cell 1.2</span>|cell 1.3
<span style="border:thin solid">cell 2.1</span>|cell 2.2 |cell 2.3
- > header 1 |header 2 |<span style="border:thin solid">header 3</span>
> -----------------------------------------------|-----------------------------------------------|-----------------------------------------------
> cell 1.1 |<span style="border:thin solid">cell 1.2</span>|cell 1.3
> <span style="border:thin solid">cell 2.1</span>|cell 2.2 |cell 2.3
- header 1 |header 2 |<span style="border:thin solid">header 3</span>
----------|----------|----------
cell 1.1 |<span style="border:thin solid">cell 1.2</span>|cell 1.3
<span style="border:thin solid">cell 2.1</span>|cell 2.2 |cell 2.3
- > header 1 |header 2 |<span style="border:thin solid">header 3</span>
> ----------|----------|----------
> cell 1.1 |<span style="border:thin solid">cell 1.2</span>|cell 1.3
> <span style="border:thin solid">cell 2.1</span>|cell 2.2 |cell 2.3
</details>

Test uniform tab=2, text tables:
Expand All @@ -267,6 +279,14 @@ Test uniform tab=2, text tables:
<div style="white-space: pre">b row 2.1
b row 2.2</div></div>
<span style="white-space: pre">b row 3</span>
- <div style="white-space: pre">

<span style="white-space: pre">a longiiish column 1</span> &nbsp; <span style="white-space: pre">a longiiish column 2</span> &nbsp; <span style="border:thin solid"><span style="white-space: pre">a longiiish column 3</span></span> &nbsp; <span style="white-space: pre">a longiiish column 4</span>
</div>
- <div style="white-space: pre">

<span style="border-right: thin solid"><span style="white-space: pre">b longiiish column 1</span></span><span style="border-right: thin solid"><span style="white-space: pre">b longiiish column 2</span></span><span style="border-right: thin solid"><span style="white-space: pre">b longiiish column 3</span></span><span style="border:thin solid"><span style="white-space: pre">b longiiish column 4</span></span>
</div>
- <div style="border:thin solid">

<div style="border-bottom:thin solid">
Expand Down Expand Up @@ -363,6 +383,14 @@ Test single quote tab=2, text tables:
<div style="white-space: pre">b row 2.1
b row 2.2</div></div>
<span style="white-space: pre">b row 3</span>
- <div style="white-space: pre">

<span style="white-space: pre">a longiiish column 1</span> &nbsp; <span style="white-space: pre">a longiiish column 2</span> &nbsp; <span style="border:thin solid"><span style="white-space: pre">a longiiish column 3</span></span> &nbsp; <span style="white-space: pre">a longiiish column 4</span>
</div>
- <div style="white-space: pre">

<span style="border-right: thin solid"><span style="white-space: pre">b longiiish column 1</span></span><span style="border-right: thin solid"><span style="white-space: pre">b longiiish column 2</span></span><span style="border-right: thin solid"><span style="white-space: pre">b longiiish column 3</span></span><span style="border:thin solid"><span style="white-space: pre">b longiiish column 4</span></span>
</div>
- <div style="border:thin solid">

<div style="border-bottom:thin solid">
Expand Down
Loading

0 comments on commit 261f5cb

Please sign in to comment.