A lean XML builder for Gleam

I think im almost ready, just need to write tests

Changed files
+37 -31
src
+11 -10
src/xmleam.gleam
··· 1 1 import gleam/io 2 - import gleam/result.{unwrap} 3 - import xmleam/builder.{Opt, basic_tag, opts_tag} 2 + import xmleam/xml_builder.{block_tag, new, tag} 4 3 5 4 pub fn main() { 6 5 let document = { 7 - builder.xml("1.0", "UTF-8", [ 8 - unwrap(basic_tag("Hello", ["World"]), "ENCODING ERROR"), 9 - unwrap( 10 - opts_tag("link", [Opt("href", "https://example.com")]), 11 - "ENCODING ERROR", 12 - ), 13 - ]) 6 + xml_builder.new_document() 7 + |> block_tag( 8 + "hello", 9 + new() 10 + |> tag("world", "Earth") 11 + |> xml_builder.end, 12 + ) 13 + |> xml_builder.end_xml() 14 14 } 15 - io.debug(result.unwrap(document, "ENCODING Error")) 15 + 16 + io.debug(document) 16 17 }
+26 -21
src/xmleam/xml_builder.gleam
··· 76 76 /// ie. new_document() 77 77 /// |> tag("hello", "world") 78 78 /// Throws an error if anything is left blank 79 - pub fn tag(label: String, contents: String, document: XmlBuilder) -> XmlBuilder { 79 + pub fn tag(document: XmlBuilder, label: String, contents: String) -> XmlBuilder { 80 80 let label_empty = string.is_empty(label) 81 81 use <- bool.guard(when: label_empty, return: Error(LabelEmpty)) 82 82 let contents_empty = string.is_empty(contents) 83 83 use <- bool.guard(when: contents_empty, return: Error(ContentsEmpty)) 84 - let documents_empty = 85 - string_builder.is_empty(result.unwrap(document, string_builder.new())) 86 - use <- bool.guard(when: documents_empty, return: Error(TagPlacedBeforeNew)) 87 84 88 85 case result.is_error(document) { 89 86 True -> Error(result.unwrap_error(document, NOTAPPLICABLE)) ··· 105 102 /// This is for a tag with options and content 106 103 /// ie. <hello world="hi"> ?? <hello> 107 104 pub fn option_content_tag( 105 + document: XmlBuilder, 108 106 label: String, 109 107 contents: String, 110 108 options: List(Option), 111 - document: XmlBuilder, 112 109 ) { 113 110 let label_empty = string.is_empty(label) 114 111 use <- bool.guard(when: label_empty, return: Error(LabelEmpty)) 115 112 let contents_empty = string.is_empty(contents) 116 113 use <- bool.guard(when: contents_empty, return: Error(ContentsEmpty)) 117 - let documents_empty = 118 - string_builder.is_empty(result.unwrap(document, string_builder.new())) 119 - use <- bool.guard(when: documents_empty, return: Error(TagPlacedBeforeNew)) 120 114 let options_empty = list.is_empty(options) 121 115 use <- bool.guard(when: options_empty, return: Error(OptionsEmpty)) 122 116 ··· 140 134 141 135 ///This is a tag with options that self-closes 142 136 /// ie. <link href="https://example.com" /> 143 - pub fn option_tag(label: String, options: List(Option), document: XmlBuilder) { 137 + pub fn option_tag(document: XmlBuilder, label: String, options: List(Option)) { 144 138 let label_empty = string.is_empty(label) 145 139 use <- bool.guard(when: label_empty, return: Error(LabelEmpty)) 146 - let documents_empty = 147 - string_builder.is_empty(result.unwrap(document, string_builder.new())) 148 - use <- bool.guard(when: documents_empty, return: Error(TagPlacedBeforeNew)) 149 140 let options_empty = list.is_empty(options) 150 141 use <- bool.guard(when: options_empty, return: Error(OptionsEmpty)) 151 142 ··· 181 172 /// new() 182 173 /// |> tag("email", "example@example.com") 183 174 /// }) 184 - pub fn block_tag(label: String, inner: XmlBuilder, document: XmlBuilder) { 175 + pub fn block_tag(document: XmlBuilder, label: String, inner: XmlBuilder) { 185 176 let label_empty = string.is_empty(label) 186 177 use <- bool.guard(when: label_empty, return: Error(LabelEmpty)) 187 178 let inner_empty = ··· 221 212 let inner_empty = 222 213 string_builder.is_empty(result.unwrap(inner, string_builder.new())) 223 214 use <- bool.guard(when: inner_empty, return: Error(InnerEmpty)) 224 - let documents_empty = 225 - string_builder.is_empty(result.unwrap(document, string_builder.new())) 226 - use <- bool.guard(when: documents_empty, return: Error(TagPlacedBeforeNew)) 227 215 let options_empty = list.is_empty(options) 228 216 use <- bool.guard(when: options_empty, return: Error(OptionsEmpty)) 229 217 ··· 249 237 /// takes in the Xml Document and outputs 250 238 /// a Result(String, BuilderError) 251 239 pub fn end_xml(document: XmlBuilder) -> Result(String, BuilderError) { 252 - let document_empty = 253 - string_builder.is_empty(result.unwrap(document, string_builder.new())) 254 - use <- bool.guard(when: document_empty, return: Error(EmptyDocument)) 240 + case result.is_error(document) { 241 + True -> Error(result.unwrap_error(document, NOTAPPLICABLE)) 242 + 243 + False -> 244 + case 245 + string_builder.is_empty(result.unwrap(document, string_builder.new())) 246 + { 247 + True -> Error(EmptyDocument) 248 + 249 + False -> 250 + result.unwrap(document, string_builder.new()) 251 + |> string_builder.to_string 252 + |> Ok 253 + } 254 + } 255 + } 256 + 257 + pub fn end(inner: XmlBuilder) -> XmlBuilder { 258 + let inner_empty = 259 + string_builder.is_empty(result.unwrap(inner, string_builder.new())) 260 + use <- bool.guard(when: inner_empty, return: Error(EmptyDocument)) 255 261 256 - result.unwrap(document, string_builder.new()) 257 - |> string_builder.to_string 262 + result.unwrap(inner, string_builder.new()) 258 263 |> Ok 259 264 }