1 module ddoc.types; 2 3 import ddoc.lexer; 4 import ddoc.sections; 5 6 struct Comment 7 { 8 bool isDitto() const @property 9 { 10 import std..string : strip, toLower; 11 12 return sections.length == 2 && sections[0].content.strip().toLower() == "ditto"; 13 } 14 15 Section[] sections; 16 17 /** 18 * Creates a Comment object without expanding the sections. 19 * 20 * Use $(LREF parse) with a function pointer to $(REF highlight, ddoc,highlight) 21 * or $(REF parseComment, ddoc,comments) to parse a comment while also 22 * expanding sections. 23 */ 24 static Comment parseUnexpanded(string text) 25 { 26 import ddoc.unhighlight : unhighlight; 27 28 return parse(text, null, false, &unhighlight); 29 } 30 31 static Comment parse(string text, string[string] macros, bool removeUnknown, 32 string function(string) highlightFn) 33 { 34 import std.functional : toDelegate; 35 36 return parse(text, macros, removeUnknown, toDelegate(highlightFn)); 37 } 38 39 static Comment parse(string text, string[string] macros, bool removeUnknown, 40 string delegate(string) highlightFn) 41 out(retVal) 42 { 43 assert(retVal.sections.length >= 2); 44 } 45 do 46 { 47 import std.algorithm : find; 48 import ddoc.macros : expand; 49 50 auto sections = splitSections(text); 51 string[string] sMacros = macros; 52 auto m = sections.find!(p => p.name == "Macros"); 53 const e = sections.find!(p => p.name == "Escapes"); 54 auto p = sections.find!(p => p.name == "Params"); 55 if (m.length) 56 { 57 if (!doMapping(m[0])) 58 throw new DdocParseException("Unable to parse Key/Value pairs", m[0].content); 59 foreach (kv; m[0].mapping) 60 sMacros[kv[0]] = kv[1]; 61 } 62 if (e.length) 63 { 64 assert(0, "Escapes not handled yet"); 65 } 66 if (p.length) 67 { 68 if (!doMapping(p[0])) 69 throw new DdocParseException("Unable to parse Key/Value pairs", p[0].content); 70 foreach (ref kv; p[0].mapping) 71 kv[1] = expand(Lexer(highlightFn(kv[1])), sMacros, removeUnknown); 72 } 73 74 foreach (ref Section sec; sections) 75 { 76 if (sec.name != "Macros" && sec.name != "Escapes" && sec.name != "Params") 77 sec.content = expand(Lexer(highlightFn(sec.content)), sMacros, removeUnknown); 78 } 79 return Comment(sections); 80 } 81 } 82 83 private: 84 bool doMapping(ref Section s) 85 { 86 import ddoc.macros : KeyValuePair, parseKeyValuePair; 87 88 auto lex = Lexer(s.content); 89 KeyValuePair[] pairs; 90 if (parseKeyValuePair(lex, pairs)) 91 { 92 foreach (idx, kv; pairs) 93 s.mapping ~= kv; 94 return true; 95 } 96 return false; 97 }