Skip to content
Newer
Older
100644 296 lines (233 sloc) 7.84 KB
994c91e @mikeabdullah And the real star of our show arrives: KSHTMLWriter!
mikeabdullah authored Jul 16, 2010
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 @mikeabdullah Documenting .isXHTML generation better.
mikeabdullah authored Jul 16, 2010
14 #pragma mark Creating an HTML Writer
15
994c91e @mikeabdullah And the real star of our show arrives: KSHTMLWriter!
mikeabdullah authored Jul 16, 2010
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 @mikeabdullah Documenting .isXHTML generation better.
mikeabdullah authored Jul 16, 2010
33 #pragma mark XHTML
34
35 @synthesize XHTML = _isXHTML;
36
994c91e @mikeabdullah And the real star of our show arrives: KSHTMLWriter!
mikeabdullah authored Jul 16, 2010
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 @mikeabdullah Simpler method for pulling in an external script.
mikeabdullah authored Jul 21, 2010
152 #pragma mark Scripts
153
37c85e9 @mikeabdullah -writeJavascriptWithSrc: actually makes more sense.
mikeabdullah authored Jul 21, 2010
154 - (void)writeJavascriptWithSrc:(NSString *)src;
60c7e89 @mikeabdullah Simpler method for pulling in an external script.
mikeabdullah authored Jul 21, 2010
155 {
27cf398 @mikeabdullah Assertion.
mikeabdullah authored Jul 21, 2010
156 NSParameterAssert(src);
157
1ca811e @mikeabdullah Split out -startJavascriptElementWithSrc:
mikeabdullah authored Jul 21, 2010
158 [self startJavascriptElementWithSrc:src];
60c7e89 @mikeabdullah Simpler method for pulling in an external script.
mikeabdullah authored Jul 21, 2010
159 [self endElement];
160 }
de567f7 added method to output JavaScript (via Dan)
Terrence Talbot authored Jul 20, 2010
161
4d9ca24 @mikeabdullah -writeJavascript:useCDATA: convenience method.
mikeabdullah authored Jul 21, 2010
162 - (void)writeJavascript:(NSString *)script useCDATA:(BOOL)useCDATA;
163 {
1ca811e @mikeabdullah Split out -startJavascriptElementWithSrc:
mikeabdullah authored Jul 21, 2010
164 [self startJavascriptElementWithSrc:nil];
4d9ca24 @mikeabdullah -writeJavascript:useCDATA: convenience method.
mikeabdullah authored Jul 21, 2010
165
166 if (useCDATA) [self startJavascriptCDATA];
167
168 [self writeString:@"\n"];
169 [self writeString:script];
170 [self writeString:@"\n"];
171
172 if (useCDATA) [self endJavascriptCDATA];
173
174 [self endElement];
175 }
176
1ca811e @mikeabdullah Split out -startJavascriptElementWithSrc:
mikeabdullah authored Jul 21, 2010
177 - (void)startJavascriptElementWithSrc:(NSString *)src; // src may be nil
178 {
179 [self openTag:@"script"];
180 [self writeAttribute:@"type" value:@"text/javascript"]; // in theory, HTML5 pages could omit this
181 if (src) [self writeAttribute:@"src" value:src];
182 [self didStartElement];
8a9783e @mikeabdullah Embedded scripts should start on a newline.
mikeabdullah authored Jul 21, 2010
183
184 // Embedded scripts should start on their own line for clarity
2d68556 @mikeabdullah Embedded scripts should also write their end tag on a new line.
mikeabdullah authored Jul 21, 2010
185 if (!src)
186 {
187 [self writeString:@"\n"];
188 [self stopWritingInline];
189 }
1ca811e @mikeabdullah Split out -startJavascriptElementWithSrc:
mikeabdullah authored Jul 21, 2010
190 }
191
f241869 @mikeabdullah Split out -startJavascriptCDATA and -endJavascriptCDATA.
mikeabdullah authored Jul 21, 2010
192 - (void)startJavascriptCDATA;
193 {
194 [self writeString:@"\n/* "];
195 [self startCDATA];
196 [self writeString:@" */"];
197 }
198
199 - (void)endJavascriptCDATA;
200 {
201 [self writeString:@"\n/* "];
202 [self endCDATA];
203 [self writeString:@" */\n"];
204 }
205
994c91e @mikeabdullah And the real star of our show arrives: KSHTMLWriter!
mikeabdullah authored Jul 16, 2010
206 #pragma mark Style
207
208 - (void)startStyleElementWithType:(NSString *)type;
209 {
210 [self openTag:@"style"];
211 if (type) [self writeAttribute:@"type" value:type];
212 [self didStartElement];
213 }
214
215 #pragma mark Elements Stack
216
217 - (BOOL)topElementIsList;
218 {
219 NSString *tagName = [self topElement];
220 BOOL result = [tagName isEqualToString:@"UL"] || [tagName isEqualToString:@"OL"];
221 return result;
222 }
223
c35c721 @mikeabdullah Only a handful of HTML elements are allowed to be empty.
mikeabdullah authored Jul 21, 2010
224 #pragma mark (X)HTML
225
226 - (BOOL)elementCanBeEmpty:(NSString *)tagName;
227 {
228 if ([tagName caseInsensitiveCompare:@"BR"] == NSOrderedSame ||
229 [tagName caseInsensitiveCompare:@"IMG"] == NSOrderedSame ||
230 [tagName caseInsensitiveCompare:@"HR"] == NSOrderedSame ||
231 [tagName caseInsensitiveCompare:@"META"] == NSOrderedSame ||
232 [tagName caseInsensitiveCompare:@"LINK"] == NSOrderedSame ||
233 [tagName caseInsensitiveCompare:@"INPUT"] == NSOrderedSame ||
234 [tagName caseInsensitiveCompare:@"BASE"] == NSOrderedSame ||
235 [tagName caseInsensitiveCompare:@"BASEFONT"] == NSOrderedSame ||
236 [tagName caseInsensitiveCompare:@"PARAM"] == NSOrderedSame ||
237 [tagName caseInsensitiveCompare:@"AREA"] == NSOrderedSame) return YES;
238
239 return NO;
240 }
994c91e @mikeabdullah And the real star of our show arrives: KSHTMLWriter!
mikeabdullah authored Jul 16, 2010
241
242 - (BOOL)canWriteElementInline:(NSString *)tagName;
243 {
244 switch ([tagName length])
245 {
246 case 1:
247 if ([tagName caseInsensitiveCompare:@"A"] == NSOrderedSame ||
248 [tagName caseInsensitiveCompare:@"B"] == NSOrderedSame ||
249 [tagName caseInsensitiveCompare:@"I"] == NSOrderedSame) return YES;
250 break;
251
252 case 2:
253 if ([tagName caseInsensitiveCompare:@"BR"] == NSOrderedSame ||
254 [tagName caseInsensitiveCompare:@"EM"] == NSOrderedSame) return YES;
255 break;
256
257 case 3:
258 if ([tagName caseInsensitiveCompare:@"IMG"] == NSOrderedSame ||
259 [tagName caseInsensitiveCompare:@"SUP"] == NSOrderedSame ||
260 [tagName caseInsensitiveCompare:@"SUB"] == NSOrderedSame ||
261 [tagName caseInsensitiveCompare:@"BIG"] == NSOrderedSame) return YES;
262 break;
263
264 case 4:
265 if ([tagName caseInsensitiveCompare:@"SPAN"] == NSOrderedSame ||
266 [tagName caseInsensitiveCompare:@"FONT"] == NSOrderedSame) return YES;
267 break;
268
269 case 5:
270 if ([tagName caseInsensitiveCompare:@"SMALL"] == NSOrderedSame) return YES;
271 break;
272
273 case 6:
274 if ([tagName caseInsensitiveCompare:@"STRONG"] == NSOrderedSame) return YES;
275 break;
276 }
277
278 return [super canWriteElementInline:tagName];
279 }
280
281 #pragma mark Element Primitives
282
283 - (void)closeEmptyElementTag; // /> OR > depending on -isXHTML
284 {
285 if ([self isXHTML])
286 {
287 [super closeEmptyElementTag];
288 }
289 else
290 {
291 [self writeString:@">"];
292 }
293 }
294
295 @end
Something went wrong with that request. Please try again.