Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 308 lines (244 sloc) 8.449 kb
994c91e Mike Abdullah And the real star of our show arrives: KSHTMLWriter!
mikeabdullah authored
1 //
2 // KSHTMLWriter.m
3 // Sandvox
4 //
5 // Created by Mike on 23/02/2010.
6 // Copyright 2010 Karelia Software. All rights reserved.
7 //
8
9 #import "KSHTMLWriter.h"
10
11
12 @implementation KSHTMLWriter
13
72adfa1 Mike Abdullah Documenting .isXHTML generation better.
mikeabdullah authored
14 #pragma mark Creating an HTML Writer
15
994c91e Mike Abdullah And the real star of our show arrives: KSHTMLWriter!
mikeabdullah authored
16 - (id)initWithOutputWriter:(id <KSWriter>)stream;
17 {
18 [super initWithOutputWriter:stream];
19 _isXHTML = YES;
20 return self;
21 }
22
23 - (id)initWithOutputWriter:(id <KSWriter>)stream isXHTML:(BOOL)isXHTML;
24 {
25 if (self = [self initWithOutputWriter:stream])
26 {
27 _isXHTML = isXHTML;
28 }
29
30 return self;
31 }
32
72adfa1 Mike Abdullah Documenting .isXHTML generation better.
mikeabdullah authored
33 #pragma mark XHTML
34
35 @synthesize XHTML = _isXHTML;
36
994c91e Mike Abdullah And the real star of our show arrives: KSHTMLWriter!
mikeabdullah authored
37 #pragma mark Document
38
39 - (void)startDocument:(NSString *)DTD isXHTML:(BOOL)isXHTML;
40 {
41 _isXHTML = isXHTML;
42 [self startDocument:DTD];
43 }
44
45 #pragma mark HTML Fragments
46
47 - (void)writeHTMLString:(NSString *)html;
48 {
49 [self writeString:html];
50 }
51
52 - (void)writeHTMLFormat:(NSString *)format , ...
53 {
54 va_list argList;
55 va_start(argList, format);
56 NSString *aString = [[[NSString alloc] initWithFormat:format arguments:argList] autorelease];
57 va_end(argList);
58
59 [self writeHTMLString:aString];
60 }
61
62 #pragma mark General
63
64 - (void)startElement:(NSString *)tagName;
65 {
66 [self startElement:tagName className:nil];
67 }
68
69 - (void)startElement:(NSString *)tagName className:(NSString *)className;
70 {
71 [self startElement:tagName idName:nil className:className];
72 }
73
74 - (void)startElement:(NSString *)tagName idName:(NSString *)idName className:(NSString *)className;
75 {
76 [self openTag:tagName];
77 if (idName) [self writeAttribute:@"id" value:idName];
78 if (className) [self writeAttribute:@"class" value:className];
79 [self didStartElement];
80 }
81
82 #pragma mark Line Break
83
84 - (void)writeLineBreak;
85 {
86 [self startElement:@"br"];
87 [self endElement];
88 }
89
90 #pragma mark Higher-level Tag Writing
91
92 - (void)startAnchorElementWithHref:(NSString *)href title:(NSString *)titleString target:(NSString *)targetString rel:(NSString *)relString;
93 {
94 [self openTag:@"a"];
95 if (href) [self writeAttribute:@"href" value:href];
96 if (targetString) [self writeAttribute:@"target" value:targetString];
97 if (titleString) [self writeAttribute:@"title" value:titleString];
98 if (relString) [self writeAttribute:@"rel" value:relString];
99 [self didStartElement];
100 }
101
102 - (void)writeImageWithIdName:(NSString *)idName
103 className:(NSString *)className
104 src:(NSString *)src
105 alt:(NSString *)alt
106 width:(NSString *)width
107 height:(NSString *)height;
108 {
109 [self openTag:@"img"];
110
111 if (idName) [self writeAttribute:@"id" value:idName];
112 if (className) [self writeAttribute:@"class" value:className];
113
114 [self writeAttribute:@"src" value:src];
115 [self writeAttribute:@"alt" value:alt];
116 if (width) [self writeAttribute:@"width" value:width];
117 if (height) [self writeAttribute:@"height" value:height];
118
119 [self didStartElement];
120 [self endElement];
121 }
122
123 // TODO: disable indentation & newlines when we are in an anchor tag, somehow.
124
125 #pragma mark Link
126
127 - (void)writeLinkWithHref:(NSString *)href
128 type:(NSString *)type
129 rel:(NSString *)rel
130 title:(NSString *)title
131 media:(NSString *)media;
132 {
133 [self openTag:@"link"];
134
135 if (rel) [self writeAttribute:@"rel" value:rel];
136 if (type) [self writeAttribute:@"type" value:type];
137 [self writeAttribute:@"href" value:href];
138 if (title) [self writeAttribute:@"title" value:title];
139 if (media) [self writeAttribute:@"media" value:media];
140
141 [self didStartElement];
142 [self endElement];
143 }
144
145 - (void)writeLinkToStylesheet:(NSString *)href
146 title:(NSString *)title
147 media:(NSString *)media;
148 {
149 [self writeLinkWithHref:href type:@"text/css" rel:@"stylesheet" title:title media:media];
150 }
151
60c7e89 Mike Abdullah Simpler method for pulling in an external script.
mikeabdullah authored
152 #pragma mark Scripts
153
37c85e9 Mike Abdullah -writeJavascriptWithSrc: actually makes more sense.
mikeabdullah authored
154 - (void)writeJavascriptWithSrc:(NSString *)src;
60c7e89 Mike Abdullah Simpler method for pulling in an external script.
mikeabdullah authored
155 {
37c85e9 Mike Abdullah -writeJavascriptWithSrc: actually makes more sense.
mikeabdullah authored
156 [self openTag:@"script"];
157 [self writeAttribute:@"type" value:@"text/javascript"]; // in theory, HTML5 pages could omit this
158 [self writeAttribute:@"src" value:src];
159 [self didStartElement];
160
60c7e89 Mike Abdullah Simpler method for pulling in an external script.
mikeabdullah authored
161 [self endElement];
162 }
de567f7 added method to output JavaScript (via Dan)
Terrence Talbot authored
163
f241869 Mike Abdullah Split out -startJavascriptCDATA and -endJavascriptCDATA.
mikeabdullah authored
164 - (void)startJavascriptCDATA;
165 {
166 [self writeString:@"\n/* "];
167 [self startCDATA];
168 [self writeString:@" */"];
169 }
170
171 - (void)endJavascriptCDATA;
172 {
173 [self writeString:@"\n/* "];
174 [self endCDATA];
175 [self writeString:@" */\n"];
176 }
177
de567f7 added method to output JavaScript (via Dan)
Terrence Talbot authored
178 - (void)writeScriptSrc:(NSString *)src // Note: You should either use src OR contents, not both.
179 orContents:(NSString *)contents // However you can specify contents for comments, which is OK.
180 useCDATA:(BOOL)useCDATA;
181 {
60c7e89 Mike Abdullah Simpler method for pulling in an external script.
mikeabdullah authored
182 // Use clean API when possible…
37c85e9 Mike Abdullah -writeJavascriptWithSrc: actually makes more sense.
mikeabdullah authored
183 if (src && !contents) return [self writeJavascriptWithSrc:src];
60c7e89 Mike Abdullah Simpler method for pulling in an external script.
mikeabdullah authored
184
185
186 // …otherwise bodge it:
187
de567f7 added method to output JavaScript (via Dan)
Terrence Talbot authored
188 [self openTag:@"script"];
189
190 [self writeAttribute:@"type" value:@"text/javascript"];
191 if (src) [self writeAttribute:@"src" value:src];
192 [self didStartElement];
193 if (contents)
194 {
195 // DO NOT USE startNewline since we don't want indentation
58fe1d1 Mike Abdullah Use CDATA API for script writing.
mikeabdullah authored
196 if (useCDATA)
197 {
198 [self writeString:@"\n/* "];
199 [self startCDATA];
200 [self writeString:@" */"];
201 }
202
203 [self writeString:@"\n"];
de567f7 added method to output JavaScript (via Dan)
Terrence Talbot authored
204 [self writeString:contents];
58fe1d1 Mike Abdullah Use CDATA API for script writing.
mikeabdullah authored
205 [self writeString:@"\n"];
206
207 if (useCDATA)
208 {
209 [self writeString:@"\n/* "];
210 [self endCDATA];
211 [self writeString:@" */\n"];
212 }
de567f7 added method to output JavaScript (via Dan)
Terrence Talbot authored
213 }
214
215 [self endElement];
216 }
217
994c91e Mike Abdullah And the real star of our show arrives: KSHTMLWriter!
mikeabdullah authored
218 #pragma mark Style
219
220 - (void)startStyleElementWithType:(NSString *)type;
221 {
222 [self openTag:@"style"];
223 if (type) [self writeAttribute:@"type" value:type];
224 [self didStartElement];
225 }
226
227 #pragma mark Elements Stack
228
229 - (BOOL)topElementIsList;
230 {
231 NSString *tagName = [self topElement];
232 BOOL result = [tagName isEqualToString:@"UL"] || [tagName isEqualToString:@"OL"];
233 return result;
234 }
235
c35c721 Mike Abdullah Only a handful of HTML elements are allowed to be empty.
mikeabdullah authored
236 #pragma mark (X)HTML
237
238 - (BOOL)elementCanBeEmpty:(NSString *)tagName;
239 {
240 if ([tagName caseInsensitiveCompare:@"BR"] == NSOrderedSame ||
241 [tagName caseInsensitiveCompare:@"IMG"] == NSOrderedSame ||
242 [tagName caseInsensitiveCompare:@"HR"] == NSOrderedSame ||
243 [tagName caseInsensitiveCompare:@"META"] == NSOrderedSame ||
244 [tagName caseInsensitiveCompare:@"LINK"] == NSOrderedSame ||
245 [tagName caseInsensitiveCompare:@"INPUT"] == NSOrderedSame ||
246 [tagName caseInsensitiveCompare:@"BASE"] == NSOrderedSame ||
247 [tagName caseInsensitiveCompare:@"BASEFONT"] == NSOrderedSame ||
248 [tagName caseInsensitiveCompare:@"PARAM"] == NSOrderedSame ||
249 [tagName caseInsensitiveCompare:@"AREA"] == NSOrderedSame) return YES;
250
251 return NO;
252 }
994c91e Mike Abdullah And the real star of our show arrives: KSHTMLWriter!
mikeabdullah authored
253
254 - (BOOL)canWriteElementInline:(NSString *)tagName;
255 {
256 switch ([tagName length])
257 {
258 case 1:
259 if ([tagName caseInsensitiveCompare:@"A"] == NSOrderedSame ||
260 [tagName caseInsensitiveCompare:@"B"] == NSOrderedSame ||
261 [tagName caseInsensitiveCompare:@"I"] == NSOrderedSame) return YES;
262 break;
263
264 case 2:
265 if ([tagName caseInsensitiveCompare:@"BR"] == NSOrderedSame ||
266 [tagName caseInsensitiveCompare:@"EM"] == NSOrderedSame) return YES;
267 break;
268
269 case 3:
270 if ([tagName caseInsensitiveCompare:@"IMG"] == NSOrderedSame ||
271 [tagName caseInsensitiveCompare:@"SUP"] == NSOrderedSame ||
272 [tagName caseInsensitiveCompare:@"SUB"] == NSOrderedSame ||
273 [tagName caseInsensitiveCompare:@"BIG"] == NSOrderedSame) return YES;
274 break;
275
276 case 4:
277 if ([tagName caseInsensitiveCompare:@"SPAN"] == NSOrderedSame ||
278 [tagName caseInsensitiveCompare:@"FONT"] == NSOrderedSame) return YES;
279 break;
280
281 case 5:
282 if ([tagName caseInsensitiveCompare:@"SMALL"] == NSOrderedSame) return YES;
283 break;
284
285 case 6:
286 if ([tagName caseInsensitiveCompare:@"STRONG"] == NSOrderedSame) return YES;
287 break;
288 }
289
290 return [super canWriteElementInline:tagName];
291 }
292
293 #pragma mark Element Primitives
294
295 - (void)closeEmptyElementTag; // /> OR > depending on -isXHTML
296 {
297 if ([self isXHTML])
298 {
299 [super closeEmptyElementTag];
300 }
301 else
302 {
303 [self writeString:@">"];
304 }
305 }
306
307 @end
Something went wrong with that request. Please try again.