1 /**
2 * Copyright © DiamondMVC 2019
3 * License: MIT (https://github.com/DiamondMVC/Diamond/blob/master/LICENSE)
4 * Author: Jacob Jensen (bausshf)
5 */
6 module diamond.dom.domparsersettings;
7 
8 import std..string : toLower;
9 
10 import diamond.core.collections;
11 
12 /// Wrapper around dom parser settings.
13 abstract class DomParserSettings
14 {
15   private:
16   /// Boolean determining whether the parser is strict or not.
17   bool _strictParsing;
18   /// HashSet of tags that can has flexible content, such as the HTML <script> tag.
19   HashSet!string _flexibleTags;
20   /// Boolean determining whether the parser allows self-closing tags or not.
21   bool _allowSelfClosingTags;
22   /// HashSet of self-closing tags.
23   HashSet!string _selfClosingTags;
24   /// HashSet of standard tags.
25   HashSet!string _standardTags;
26   /// Tags to repair within the head section.
27   HashSet!string _headRepairTags;
28   /// Tags to repair within the body section.
29   HashSet!string _bodyRepairTags;
30 
31   protected
32   {
33     /**
34     * Creates a new dom parser setting.
35     * Params:
36     *   strictParsing =         Boolean determining whether the parser is strict or not.
37     *   flexibleTags =          An array of tags that can has flexible content, such as the HTML <script> tag.
38     *   allowSelfClosingTags =  Boolean determining whether the parser allows self-closing tags or not.
39     *   selfClosingTags =       An array of tags that can be self-closed.
40     *   standardTags =          An array of standard tags. These are only relevant if self-closing tags are allowed.
41     *   headRepairTags =        An array of tags that can be repaired within the head section.
42     *   bodyRepairTags =        An array of tags that can be repaired within the body section.
43     */
44     this
45     (
46       bool strictParsing,
47       string[] flexibleTags,
48       bool allowSelfClosingTags,
49       string[] selfClosingTags,
50       string[] standardTags,
51       string[] headRepairTags,
52       string[] bodyRepairTags
53     ) @safe
54     {
55       _strictParsing = strictParsing;
56 
57       _flexibleTags = new HashSet!string;
58 
59       if (flexibleTags && flexibleTags.length)
60       {
61         foreach (tag; flexibleTags)
62         {
63           _flexibleTags.add(tag.toLower);
64         }
65       }
66 
67       _allowSelfClosingTags = allowSelfClosingTags;
68 
69       if (_allowSelfClosingTags)
70       {
71         _selfClosingTags = new HashSet!string;
72 
73         if (selfClosingTags && selfClosingTags.length)
74         {
75           foreach (tag; selfClosingTags)
76           {
77             _selfClosingTags.add(tag.toLower);
78           }
79         }
80 
81         _standardTags = new HashSet!string;
82 
83         if (standardTags && standardTags.length)
84         {
85           foreach (tag; standardTags)
86           {
87             _standardTags.add(tag.toLower);
88           }
89         }
90       }
91 
92       _headRepairTags = new HashSet!string;
93 
94       if (headRepairTags && headRepairTags.length)
95       {
96         foreach (tag; headRepairTags)
97         {
98           _headRepairTags.add(tag.toLower);
99         }
100       }
101 
102       _bodyRepairTags = new HashSet!string;
103 
104       if (bodyRepairTags && bodyRepairTags.length)
105       {
106         foreach (tag; bodyRepairTags)
107         {
108           _bodyRepairTags.add(tag.toLower);
109         }
110       }
111     }
112   }
113 
114   public:
115   final:
116   @property
117   {
118     /// Gets a boolean determining whether the parser is strict or not.
119     bool strictParsing() @safe { return _strictParsing; }
120 
121     /// Gets a boolean determining whether the parser allwos self-closing tags or not.
122     bool allowSelfClosingTags() @safe { return _allowSelfClosingTags; }
123   }
124 
125   /**
126   * Checks whether a specific tag is flexible or not.
127   * Params:
128   *   tagName = The name of the tag to validate.
129   * Returns:
130   *   True if the tag is flexible, false otherwise.
131   */
132   bool isFlexibleTag(string tagName) @safe
133   {
134     if (!_flexibleTags)
135     {
136       return false;
137     }
138 
139     return _flexibleTags.has(tagName.toLower);
140   }
141 
142   /**
143   * Checks whether a specific tag is self-closing or not.
144   * Params:
145   *   tagName = The name of the tag to validate.
146   * Returns:
147   *   True if the tag is self-closing, false otherwise.
148   */
149   bool isSelfClosingTag(string tagName) @safe
150   {
151     if (!_selfClosingTags)
152     {
153       return false;
154     }
155 
156     return _selfClosingTags.has(tagName.toLower);
157   }
158 
159   /**
160   * Checks whether a specific tag is standard or not.
161   * Params:
162   *   tagName = The name of the tag to validate.
163   * Returns:
164   *   True if the tag is standard, false otherwise.
165   */
166   bool isStandardTag(string tagName) @safe
167   {
168     if (!_standardTags)
169     {
170       return false;
171     }
172 
173     return _standardTags.has(tagName.toLower);
174   }
175 
176   /**
177   * Checks whether a specific tag is located in the head section or not.
178   * Params:
179   *   tagName = The name of the tag to validate.
180   * Returns:
181   *   True if the tag is located in the head section, false otherwise.
182   */
183   bool isHeadTag(string tagName) @safe
184   {
185     if (!_headRepairTags)
186     {
187       return false;
188     }
189 
190     return _headRepairTags.has(tagName);
191   }
192 
193   /**
194   * Checks whether a specific tag is located in the body section or not.
195   * Params:
196   *   tagName = The name of the tag to validate.
197   * Returns:
198   *   True if the tag is located in the body section, false otherwise.
199   */
200   bool isBodyTag(string tagName) @safe
201   {
202     if (!_bodyRepairTags)
203     {
204       return false;
205     }
206 
207     return _bodyRepairTags.has(tagName);
208   }
209 }