Skip to main content

forge_rsx/
lib.rs

1#![doc = include_str!("../README.md")]
2
3/// ### Rules Module
4///
5/// A module that encapsulates the rules and functionalities of the `rsx` macro.
6///
7/// A macro to generate HTML-like markup with different indentation styles.
8/// 
9/// Usage:
10/// ```rust
11/// use forge_rsx::{rsx, get_char};
12/// 
13/// fn main() {
14///     // 1. Component defined with 'lined' (minified single line)
15///     let apple = "🍎 Apple";
16///     let apple_component = rsx!(lined, span { {&apple} });
17/// 
18///     // 2. Full HTML Document using 'doctype_html' and 'btfy4'
19///     let html_doc = rsx! {
20///         btfy4,
21///         doctype_html
22///         html {
23///             head {
24///                 meta { charset: "UTF-8" } // No comma needed here
25///                 meta { name: "viewport", content: "width=device-width, initial-scale=1.0" }
26///                 title { "Forge RSX Demo" }
27///             }
28///             body {
29///                 "x-data": "{ open: false }", ":class": "bg-white",
30///                 h1 { "Welcome to Forge RSX" }
31///                 br {}
32///                 div { 
33///                     class: "container",
34///                     "x-show": "open",
35///                     "Alpine.js integration demo"
36///                 }
37///                 "id": "my-id", "style": "color: #4f4f4f; font-size: 2rem;" // No comma needed here
38///             }
39///         }
40///     };
41/// 
42///     // 3. Formatting Samples: Demonstrating 0 and 2-space indentation styles
43///     let span = rsx!(btfy0, span { "..." });
44///     let empty_p = rsx!(tabed, p { });
45///     let p = rsx!(btfy2, p {"..."});
46/// 
47///     // 4. Complex section with 'for' loops and logic
48///     let fruits = vec!["🍇", "mango", "orange"];
49///     let section = rsx!(btfy4, section { 
50///         div { 
51///             ol { 
52///                 for fruit in &fruits => {
53///                     li {
54///                         span {
55///                             {
56///                                 if fruit == &"🍇" {
57///                                     &format!("{} {}", fruit.to_string(), "Grapes")
58///                                 } else if fruit == &"mango" {
59///                                     &format!("{} {}", "🥭", fruit.to_lowercase())
60///                                 } else {
61///                                     &fruit.to_uppercase()
62///                                 }
63///                             }
64///                         }
65///                     }
66///                 }
67///                 li { 
68///                     {"<!-- How to join RSX component -->"}
69///                     {&apple_component.to_string()} 
70///                     {
71///                         if get_char(&apple, 1).to_string() == "🍎" {
72///                             "🍎".to_string()
73///                         } else {
74///                             apple_component.to_string()
75///                         }
76///                     }
77///                 }
78///             } 
79///         } 
80///     });
81/// 
82///     // 5. Printing all results
83///     println!("--- FULL HTML DOCUMENT ---\n{}\n", html_doc);
84///     println!("--- MINIFIED SPAN ---\n{}\n", span);
85///     println!("--- EMPTY P ---\n{}\n", empty_p);
86///     println!("--- P WITH CONTENT ---\n{}\n", p);
87///     println!("--- FRUIT SECTION ---\n{}", section);
88/// 
89///     // --- FULL HTML DOCUMENT ---
90///     // <!DOCTYPE html>
91///     // <html>
92///     //     <head>
93///     //         <meta charset="UTF-8">
94///     //         <meta name="viewport" content="width=device-width, initial-scale=1.0">
95///     //         <title>
96///     //             Forge RSX Demo
97///     //         </title>
98///     //     </head>
99///     //     <body x-data="{ open: false }" :class="bg-white" id="my-id" style="color: #4f4f4f; font-size: 2rem;">
100///     //         <h1>
101///     //             Welcome to Forge RSX
102///     //         </h1>
103///     //         <br>
104///     //         <div class="container" x-show="open">
105///     //             Alpine.js integration demo
106///     //         </div>
107///     //     </body>
108///     // </html>
109/// 
110///     // --- MINIFIED SPAN ---
111///     // <span>
112///     // ...
113///     // </span>
114/// 
115///     // --- EMPTY P ---
116///     // <p></p>
117/// 
118///     // --- P WITH CONTENT ---
119///     // <p>
120///     // ...
121///     // </p>
122/// 
123///     // --- FRUIT SECTION ---
124///     // <section>
125///     //     <div>
126///     //         <ol>
127///     //             <li>
128///     //                 <span>
129///     //                     🍇 Grapes
130///     //                 </span>
131///     //             </li>
132///     //             <li>
133///     //                 <span>
134///     //                     🥭 mango
135///     //                 </span>
136///     //             </li>
137///     //             <li>
138///     //                 <span>
139///     //                     ORANGE
140///     //                 </span>
141///     //             </li>
142///     //             <li>
143///     //                 <!-- How to join RSX component -->
144///     //                 <span>🍎 Apple</span>
145///     //                 🍎
146///     //             </li>
147///     //         </ol>
148///     //     </div>
149///     // </section>
150/// }
151/// ```
152/// 
153/// - `lined`: produces HTML without indentation or line breaks (single-line output)
154/// - `btfy0`: uses 0 spaces (no indentation, minified output)
155/// - `btfy2`: uses 2 spaces indentation
156/// - `btfy4`: uses 4 spaces indentation
157pub mod rules;
158
159/// Returns the character at the specified 1-based index `n` from the input string `s`.
160///
161/// If `n` exceeds the number of characters in `s`, the function returns an empty string.
162///
163/// # Arguments
164///
165/// * `s` - A string slice from which to extract a character.
166/// * `n` - The 1-based position of the character to retrieve.
167///
168/// # Examples
169///
170/// ```rust
171/// use forge_rsx::get_char;
172/// let s = "Hello, forge-rsx!";
173/// assert_eq!(get_char(s, 0), ""); // Out of bounds, returns empty
174/// assert_eq!(get_char(s, 1), "H"); // First character
175/// assert_eq!(get_char(s, 50), ""); // Out of bounds, returns empty
176/// ```
177///
178/// Note: `n` starts at 1 for the first character.
179pub fn get_char(s: &str, index: usize) -> String {
180    if index == 0 || index > s.chars().count() {
181        "".to_string()
182    } else {
183        // Convert 1-based index to 0-based
184        let char_index = index - 1;
185        // Get the char at the position
186        s.chars().nth(char_index).unwrap().to_string()
187    }
188}