Skip to main content

inkferro_core/render/
cli_boxes.rs

1//! Vendored cli-boxes character table.
2//!
3//! Source: cli-boxes@4.0.1 (node_modules/cli-boxes/boxes.json in the ink@7 fork).
4//! Regenerate by: `cat node_modules/cli-boxes/boxes.json` and transcribing the
5//! eight fields (topLeft/top/topRight/right/bottomRight/bottom/bottomLeft/left)
6//! for each named style into the constants below.
7//!
8//! Only the styles that `dom::BorderStyle::Named` can produce are included here.
9//! Custom box-drawing characters are handled by `BoxChars::from_custom`.
10
11use std::borrow::Cow;
12
13/// All eight box-drawing characters for one border style.
14///
15/// Uses `Cow<'static, str>` so named-style constants are zero-copy (`Borrowed`)
16/// while `Custom` border styles use `Owned` strings without leaking memory.
17#[derive(Debug, Clone)]
18pub struct BoxChars {
19    pub top_left: Cow<'static, str>,
20    pub top: Cow<'static, str>,
21    pub top_right: Cow<'static, str>,
22    pub right: Cow<'static, str>,
23    pub bottom_right: Cow<'static, str>,
24    pub bottom: Cow<'static, str>,
25    pub bottom_left: Cow<'static, str>,
26    pub left: Cow<'static, str>,
27}
28
29/// Construct a `BoxChars` from eight `&'static str` literals (named styles).
30macro_rules! static_chars {
31    ($tl:expr, $t:expr, $tr:expr, $r:expr, $br:expr, $b:expr, $bl:expr, $l:expr) => {
32        BoxChars {
33            top_left: Cow::Borrowed($tl),
34            top: Cow::Borrowed($t),
35            top_right: Cow::Borrowed($tr),
36            right: Cow::Borrowed($r),
37            bottom_right: Cow::Borrowed($br),
38            bottom: Cow::Borrowed($b),
39            bottom_left: Cow::Borrowed($bl),
40            left: Cow::Borrowed($l),
41        }
42    };
43}
44
45/// Owned strings for a `BorderStyle::Custom` box — input to `BoxChars::from_custom`.
46///
47/// Keeping the fields in a struct avoids the 8-argument clippy lint and makes
48/// call sites self-documenting.
49pub struct CustomChars {
50    pub top_left: String,
51    pub top: String,
52    pub top_right: String,
53    pub right: String,
54    pub bottom_right: String,
55    pub bottom: String,
56    pub bottom_left: String,
57    pub left: String,
58}
59
60impl BoxChars {
61    /// Build from a `CustomChars` (for `BorderStyle::Custom`).
62    ///
63    /// No leaking: the strings are moved into `Cow::Owned` and freed when the
64    /// `BoxChars` value is dropped at the end of each `render_border` call.
65    pub fn from_custom(c: CustomChars) -> Self {
66        Self {
67            top_left: Cow::Owned(c.top_left),
68            top: Cow::Owned(c.top),
69            top_right: Cow::Owned(c.top_right),
70            right: Cow::Owned(c.right),
71            bottom_right: Cow::Owned(c.bottom_right),
72            bottom: Cow::Owned(c.bottom),
73            bottom_left: Cow::Owned(c.bottom_left),
74            left: Cow::Owned(c.left),
75        }
76    }
77}
78
79// ─── Named styles from cli-boxes@4.0.1 ───────────────────────────────────────
80
81fn single() -> BoxChars {
82    static_chars!("┌", "─", "┐", "│", "┘", "─", "└", "│")
83}
84fn double() -> BoxChars {
85    static_chars!("╔", "═", "╗", "║", "╝", "═", "╚", "║")
86}
87fn round() -> BoxChars {
88    static_chars!("╭", "─", "╮", "│", "╯", "─", "╰", "│")
89}
90fn bold() -> BoxChars {
91    static_chars!("┏", "━", "┓", "┃", "┛", "━", "┗", "┃")
92}
93fn single_double() -> BoxChars {
94    static_chars!("╓", "─", "╖", "║", "╜", "─", "╙", "║")
95}
96fn double_single() -> BoxChars {
97    static_chars!("╒", "═", "╕", "│", "╛", "═", "╘", "│")
98}
99fn classic() -> BoxChars {
100    static_chars!("+", "-", "+", "|", "+", "-", "+", "|")
101}
102fn arrow() -> BoxChars {
103    static_chars!("↘", "↓", "↙", "←", "↖", "↑", "↗", "→")
104}
105
106/// Resolve a named style string to `BoxChars`.
107///
108/// Returns `None` for unknown style names — the caller falls back to a default.
109/// Mirrors render-border.ts:32-34:
110/// ```ts
111/// const box = typeof node.style.borderStyle === 'string'
112///   ? cliBoxes[node.style.borderStyle]
113///   : node.style.borderStyle;
114/// ```
115pub fn named(style: &str) -> Option<BoxChars> {
116    match style {
117        "single" => Some(single()),
118        "double" => Some(double()),
119        "round" => Some(round()),
120        "bold" => Some(bold()),
121        "singleDouble" => Some(single_double()),
122        "doubleSingle" => Some(double_single()),
123        "classic" => Some(classic()),
124        "arrow" => Some(arrow()),
125        _ => None,
126    }
127}