1 /** 2 HTML character entity escaping. 3 4 TODO: Make things @safe once Appender is. 5 6 Copyright: © 2012-2014 RejectedSoftware e.K. 7 License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. 8 Authors: Sönke Ludwig 9 */ 10 module dmarkdown.html; 11 12 import std.array; 13 import std.conv; 14 import std.range; 15 16 17 package: 18 19 20 /** Writes the HTML escaped version of a given string to an output range. 21 */ 22 void filterHTMLEscape(R, S)(ref R dst, S str, HTMLEscapeFlags flags = HTMLEscapeFlags.escapeNewline) 23 if (isOutputRange!(R, dchar) && isInputRange!S) 24 { 25 for (;!str.empty;str.popFront()) 26 filterHTMLEscape(dst, str.front, flags); 27 } 28 29 /** Writes the HTML escaped version of a given string to an output range (also escapes double quotes). 30 */ 31 void filterHTMLAttribEscape(R, S)(ref R dst, S str) 32 if (isOutputRange!(R, dchar) && isInputRange!S) 33 { 34 for (; !str.empty; str.popFront()) 35 filterHTMLEscape(dst, str.front, HTMLEscapeFlags.escapeNewline|HTMLEscapeFlags.escapeQuotes); 36 } 37 38 /** Writes the HTML escaped version of a given string to an output range (escapes every character). 39 */ 40 void filterHTMLAllEscape(R, S)(ref R dst, S str) 41 if (isOutputRange!(R, dchar) && isInputRange!S) 42 { 43 for (; !str.empty; str.popFront()) { 44 dst.put("&#"); 45 dst.put(to!string(cast(uint)str.front)); 46 dst.put(';'); 47 } 48 } 49 50 /** 51 Writes the HTML escaped version of a character to an output range. 52 */ 53 void filterHTMLEscape(R)(ref R dst, dchar ch, HTMLEscapeFlags flags = HTMLEscapeFlags.escapeNewline ) 54 { 55 switch (ch) { 56 default: 57 if (flags & HTMLEscapeFlags.escapeUnknown) { 58 dst.put("&#"); 59 dst.put(to!string(cast(uint)ch)); 60 dst.put(';'); 61 } else dst.put(ch); 62 break; 63 case '"': 64 if (flags & HTMLEscapeFlags.escapeQuotes) dst.put("""); 65 else dst.put('"'); 66 break; 67 case '\'': 68 if (flags & HTMLEscapeFlags.escapeQuotes) dst.put("'"); 69 else dst.put('\''); 70 break; 71 case '\r', '\n': 72 if (flags & HTMLEscapeFlags.escapeNewline) { 73 dst.put("&#"); 74 dst.put(to!string(cast(uint)ch)); 75 dst.put(';'); 76 } else dst.put(ch); 77 break; 78 case 'a': .. case 'z': goto case; 79 case 'A': .. case 'Z': goto case; 80 case '0': .. case '9': goto case; 81 case ' ', '\t', '-', '_', '.', ':', ',', ';', 82 '#', '+', '*', '?', '=', '(', ')', '/', '!', 83 '%' , '{', '}', '[', ']', '`', '´', '$', '^', '~': 84 dst.put(cast(char)ch); 85 break; 86 case '<': dst.put("<"); break; 87 case '>': dst.put(">"); break; 88 case '&': dst.put("&"); break; 89 } 90 } 91 92 93 enum HTMLEscapeFlags { 94 escapeMinimal = 0, 95 escapeQuotes = 1<<0, 96 escapeNewline = 1<<1, 97 escapeUnknown = 1<<2 98 }