Permalink
Browse files

And the real star of our show arrives: KSHTMLWriter!

  • Loading branch information...
1 parent 09261e3 commit 994c91ecd404826821249a6d97e787e3ab3cbd51 @mikeabdullah mikeabdullah committed Jul 16, 2010
Showing with 320 additions and 0 deletions.
  1. +99 −0 KSHTMLWriter.h
  2. +221 −0 KSHTMLWriter.m
View
@@ -0,0 +1,99 @@
+//
+// KSHTMLWriter.h
+// Sandvox
+//
+// Created by Mike on 23/02/2010.
+// Copyright 2010 Karelia Software. All rights reserved.
+//
+
+
+#import "KSXMLWriter.h"
+
+
+@interface KSHTMLWriter : KSXMLWriter
+{
+ @private
+ BOOL _isXHTML;
+}
+
+#pragma mark Creating an HTML Writer
+// For if you desperately need to set a doctype before calling -startDocument:isXHTML:
+- (id)initWithOutputWriter:(id <KSWriter>)stream isXHTML:(BOOL)isXHTML;
+
+
+#pragma mark Document
+// It doesn't make sense to change from isXHTML mid-write, so is only supported when initialising or when starting document.
+- (void)startDocument:(NSString *)DTD isXHTML:(BOOL)isXHTML;
+@property(nonatomic, readonly, getter=isXHTML) BOOL XHTML;
+
+
+#pragma mark HTML Fragments
+- (void)writeHTMLString:(NSString *)html;
+- (void)writeHTMLFormat:(NSString *)format , ...;
+
+
+#pragma mark General
+
+// <tagName id="idName" class="className">
+// Pretty standard convenience methods
+
+- (void)startElement:(NSString *)tagName;
+- (void)startElement:(NSString *)tagName className:(NSString *)className;
+
+- (void)startElement:(NSString *)tagName
+ idName:(NSString *)idName
+ className:(NSString *)className;
+
+
+#pragma mark Line Break
+// <br /> OR <br>
+// depends on isXHTML
+- (void)writeLineBreak;
+
+
+#pragma mark Links
+// <a href="...." target="..." rel="nofollow">
+- (void)startAnchorElementWithHref:(NSString *)href title:(NSString *)titleString target:(NSString *)targetString rel:(NSString *)relString;
+
+
+#pragma mark Images
+// <img src="..." alt="..." width="..." height="..." />
+- (void)writeImageWithIdName:(NSString *)idName
+ className:(NSString *)className
+ src:(NSString *)src
+ alt:(NSString *)alt
+ width:(NSString *)width
+ height:(NSString *)height;
+
+
+#pragma mark Link
+
+// <link>
+// Goes in <head> to link to scripts, CSS, etc.
+- (void)writeLinkWithHref:(NSString *)href
+ type:(NSString *)type
+ rel:(NSString *)rel
+ title:(NSString *)title
+ media:(NSString *)media;
+
+- (void)writeLinkToStylesheet:(NSString *)href
+ title:(NSString *)title
+ media:(NSString *)media;
+
+
+#pragma mark Style
+- (void)startStyleElementWithType:(NSString *)type;
+
+
+#pragma mark Elements Stack
+- (BOOL)topElementIsList;
+
+
+#pragma mark Element Primitives
+// /> OR >
+// Which is used depends on -isXHTML
+- (void)closeEmptyElementTag;
+
+
+@end
+
View
@@ -0,0 +1,221 @@
+//
+// KSHTMLWriter.m
+// Sandvox
+//
+// Created by Mike on 23/02/2010.
+// Copyright 2010 Karelia Software. All rights reserved.
+//
+
+#import "KSHTMLWriter.h"
+
+
+@implementation KSHTMLWriter
+
+- (id)initWithOutputWriter:(id <KSWriter>)stream;
+{
+ [super initWithOutputWriter:stream];
+ _isXHTML = YES;
+ return self;
+}
+
+- (id)initWithOutputWriter:(id <KSWriter>)stream isXHTML:(BOOL)isXHTML;
+{
+ if (self = [self initWithOutputWriter:stream])
+ {
+ _isXHTML = isXHTML;
+ }
+
+ return self;
+}
+
+#pragma mark Document
+
+- (void)startDocument:(NSString *)DTD isXHTML:(BOOL)isXHTML;
+{
+ _isXHTML = isXHTML;
+ [self startDocument:DTD];
+}
+
+@synthesize XHTML = _isXHTML;
+
+#pragma mark HTML Fragments
+
+- (void)writeHTMLString:(NSString *)html;
+{
+ [self writeString:html];
+}
+
+- (void)writeHTMLFormat:(NSString *)format , ...
+{
+ va_list argList;
+ va_start(argList, format);
+ NSString *aString = [[[NSString alloc] initWithFormat:format arguments:argList] autorelease];
+ va_end(argList);
+
+ [self writeHTMLString:aString];
+}
+
+#pragma mark General
+
+- (void)startElement:(NSString *)tagName;
+{
+ [self startElement:tagName className:nil];
+}
+
+- (void)startElement:(NSString *)tagName className:(NSString *)className;
+{
+ [self startElement:tagName idName:nil className:className];
+}
+
+- (void)startElement:(NSString *)tagName idName:(NSString *)idName className:(NSString *)className;
+{
+ [self openTag:tagName];
+ if (idName) [self writeAttribute:@"id" value:idName];
+ if (className) [self writeAttribute:@"class" value:className];
+ [self didStartElement];
+}
+
+#pragma mark Line Break
+
+- (void)writeLineBreak;
+{
+ [self startElement:@"br"];
+ [self endElement];
+}
+
+#pragma mark Higher-level Tag Writing
+
+- (void)startAnchorElementWithHref:(NSString *)href title:(NSString *)titleString target:(NSString *)targetString rel:(NSString *)relString;
+{
+ [self openTag:@"a"];
+ if (href) [self writeAttribute:@"href" value:href];
+ if (targetString) [self writeAttribute:@"target" value:targetString];
+ if (titleString) [self writeAttribute:@"title" value:titleString];
+ if (relString) [self writeAttribute:@"rel" value:relString];
+ [self didStartElement];
+}
+
+- (void)writeImageWithIdName:(NSString *)idName
+ className:(NSString *)className
+ src:(NSString *)src
+ alt:(NSString *)alt
+ width:(NSString *)width
+ height:(NSString *)height;
+{
+ [self openTag:@"img"];
+
+ if (idName) [self writeAttribute:@"id" value:idName];
+ if (className) [self writeAttribute:@"class" value:className];
+
+ [self writeAttribute:@"src" value:src];
+ [self writeAttribute:@"alt" value:alt];
+ if (width) [self writeAttribute:@"width" value:width];
+ if (height) [self writeAttribute:@"height" value:height];
+
+ [self didStartElement];
+ [self endElement];
+}
+
+// TODO: disable indentation & newlines when we are in an anchor tag, somehow.
+
+#pragma mark Link
+
+- (void)writeLinkWithHref:(NSString *)href
+ type:(NSString *)type
+ rel:(NSString *)rel
+ title:(NSString *)title
+ media:(NSString *)media;
+{
+ [self openTag:@"link"];
+
+ if (rel) [self writeAttribute:@"rel" value:rel];
+ if (type) [self writeAttribute:@"type" value:type];
+ [self writeAttribute:@"href" value:href];
+ if (title) [self writeAttribute:@"title" value:title];
+ if (media) [self writeAttribute:@"media" value:media];
+
+ [self didStartElement];
+ [self endElement];
+}
+
+- (void)writeLinkToStylesheet:(NSString *)href
+ title:(NSString *)title
+ media:(NSString *)media;
+{
+ [self writeLinkWithHref:href type:@"text/css" rel:@"stylesheet" title:title media:media];
+}
+
+#pragma mark Style
+
+- (void)startStyleElementWithType:(NSString *)type;
+{
+ [self openTag:@"style"];
+ if (type) [self writeAttribute:@"type" value:type];
+ [self didStartElement];
+}
+
+#pragma mark Elements Stack
+
+- (BOOL)topElementIsList;
+{
+ NSString *tagName = [self topElement];
+ BOOL result = [tagName isEqualToString:@"UL"] || [tagName isEqualToString:@"OL"];
+ return result;
+}
+
+#pragma mark Inline Writing
+
+- (BOOL)canWriteElementInline:(NSString *)tagName;
+{
+ switch ([tagName length])
+ {
+ case 1:
+ if ([tagName caseInsensitiveCompare:@"A"] == NSOrderedSame ||
+ [tagName caseInsensitiveCompare:@"B"] == NSOrderedSame ||
+ [tagName caseInsensitiveCompare:@"I"] == NSOrderedSame) return YES;
+ break;
+
+ case 2:
+ if ([tagName caseInsensitiveCompare:@"BR"] == NSOrderedSame ||
+ [tagName caseInsensitiveCompare:@"EM"] == NSOrderedSame) return YES;
+ break;
+
+ case 3:
+ if ([tagName caseInsensitiveCompare:@"IMG"] == NSOrderedSame ||
+ [tagName caseInsensitiveCompare:@"SUP"] == NSOrderedSame ||
+ [tagName caseInsensitiveCompare:@"SUB"] == NSOrderedSame ||
+ [tagName caseInsensitiveCompare:@"BIG"] == NSOrderedSame) return YES;
+ break;
+
+ case 4:
+ if ([tagName caseInsensitiveCompare:@"SPAN"] == NSOrderedSame ||
+ [tagName caseInsensitiveCompare:@"FONT"] == NSOrderedSame) return YES;
+ break;
+
+ case 5:
+ if ([tagName caseInsensitiveCompare:@"SMALL"] == NSOrderedSame) return YES;
+ break;
+
+ case 6:
+ if ([tagName caseInsensitiveCompare:@"STRONG"] == NSOrderedSame) return YES;
+ break;
+ }
+
+ return [super canWriteElementInline:tagName];
+}
+
+#pragma mark Element Primitives
+
+- (void)closeEmptyElementTag; // /> OR > depending on -isXHTML
+{
+ if ([self isXHTML])
+ {
+ [super closeEmptyElementTag];
+ }
+ else
+ {
+ [self writeString:@">"];
+ }
+}
+
+@end

0 comments on commit 994c91e

Please sign in to comment.